editor.rs

    1pub mod display_map;
    2mod element;
    3mod highlight_matching_bracket;
    4mod hover_popover;
    5pub mod items;
    6mod link_go_to_definition;
    7mod mouse_context_menu;
    8pub mod movement;
    9mod multi_buffer;
   10pub mod selections_collection;
   11
   12#[cfg(any(test, feature = "test-support"))]
   13pub mod test;
   14
   15use aho_corasick::AhoCorasick;
   16use anyhow::Result;
   17use clock::ReplicaId;
   18use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   19pub use display_map::DisplayPoint;
   20use display_map::*;
   21pub use element::*;
   22use futures::FutureExt;
   23use fuzzy::{StringMatch, StringMatchCandidate};
   24use gpui::{
   25    actions,
   26    color::Color,
   27    elements::*,
   28    executor,
   29    fonts::{self, HighlightStyle, TextStyle},
   30    geometry::vector::{vec2f, Vector2F},
   31    impl_actions, impl_internal_actions,
   32    platform::CursorStyle,
   33    serde_json::json,
   34    text_layout, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox,
   35    Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View,
   36    ViewContext, ViewHandle, WeakViewHandle,
   37};
   38use highlight_matching_bracket::refresh_matching_bracket_highlights;
   39use hover_popover::{hide_hover, HoverState};
   40pub use items::MAX_TAB_TITLE_LEN;
   41pub use language::{char_kind, CharKind};
   42use language::{
   43    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic,
   44    DiagnosticSeverity, IndentKind, IndentSize, Language, OffsetRangeExt, OffsetUtf16, Point,
   45    Selection, SelectionGoal, TransactionId,
   46};
   47use link_go_to_definition::{hide_link_definition, LinkGoToDefinitionState};
   48pub use multi_buffer::{
   49    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   50    ToPoint,
   51};
   52use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
   53use ordered_float::OrderedFloat;
   54use project::{FormatTrigger, LocationLink, Project, ProjectPath, ProjectTransaction};
   55use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   56use serde::{Deserialize, Serialize};
   57use settings::Settings;
   58use smallvec::SmallVec;
   59use smol::Timer;
   60use snippet::Snippet;
   61use std::{
   62    any::TypeId,
   63    borrow::Cow,
   64    cmp::{self, Ordering, Reverse},
   65    mem,
   66    num::NonZeroU32,
   67    ops::{Deref, DerefMut, Range, RangeInclusive},
   68    sync::Arc,
   69    time::{Duration, Instant},
   70};
   71pub use sum_tree::Bias;
   72use theme::{DiagnosticStyle, Theme};
   73use util::{post_inc, ResultExt, TryFutureExt};
   74use workspace::{ItemNavHistory, Workspace};
   75
   76const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
   77const MAX_LINE_LEN: usize = 1024;
   78const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
   79const MAX_SELECTION_HISTORY_LEN: usize = 1024;
   80
   81pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
   82
   83#[derive(Clone, Deserialize, PartialEq, Default)]
   84pub struct SelectNext {
   85    #[serde(default)]
   86    pub replace_newest: bool,
   87}
   88
   89#[derive(Clone, PartialEq)]
   90pub struct Scroll(pub Vector2F);
   91
   92#[derive(Clone, PartialEq)]
   93pub struct Select(pub SelectPhase);
   94
   95#[derive(Clone, Debug, PartialEq)]
   96pub struct Jump {
   97    path: ProjectPath,
   98    position: Point,
   99    anchor: language::Anchor,
  100}
  101
  102#[derive(Clone, Deserialize, PartialEq)]
  103pub struct SelectToBeginningOfLine {
  104    #[serde(default)]
  105    stop_at_soft_wraps: bool,
  106}
  107
  108#[derive(Clone, Deserialize, PartialEq)]
  109pub struct SelectToEndOfLine {
  110    #[serde(default)]
  111    stop_at_soft_wraps: bool,
  112}
  113
  114#[derive(Clone, Deserialize, PartialEq)]
  115pub struct ToggleCodeActions {
  116    #[serde(default)]
  117    pub deployed_from_indicator: bool,
  118}
  119
  120#[derive(Clone, Default, Deserialize, PartialEq)]
  121pub struct ConfirmCompletion {
  122    #[serde(default)]
  123    pub item_ix: Option<usize>,
  124}
  125
  126#[derive(Clone, Default, Deserialize, PartialEq)]
  127pub struct ConfirmCodeAction {
  128    #[serde(default)]
  129    pub item_ix: Option<usize>,
  130}
  131
  132actions!(
  133    editor,
  134    [
  135        Cancel,
  136        Backspace,
  137        Delete,
  138        Newline,
  139        NewlineBelow,
  140        GoToDiagnostic,
  141        GoToPrevDiagnostic,
  142        Indent,
  143        Outdent,
  144        DeleteLine,
  145        DeleteToPreviousWordStart,
  146        DeleteToPreviousSubwordStart,
  147        DeleteToNextWordEnd,
  148        DeleteToNextSubwordEnd,
  149        DeleteToBeginningOfLine,
  150        DeleteToEndOfLine,
  151        CutToEndOfLine,
  152        DuplicateLine,
  153        MoveLineUp,
  154        MoveLineDown,
  155        Transpose,
  156        Cut,
  157        Copy,
  158        Paste,
  159        Undo,
  160        Redo,
  161        MoveUp,
  162        MoveDown,
  163        MoveLeft,
  164        MoveRight,
  165        MoveToPreviousWordStart,
  166        MoveToPreviousSubwordStart,
  167        MoveToNextWordEnd,
  168        MoveToNextSubwordEnd,
  169        MoveToBeginningOfLine,
  170        MoveToEndOfLine,
  171        MoveToBeginning,
  172        MoveToEnd,
  173        SelectUp,
  174        SelectDown,
  175        SelectLeft,
  176        SelectRight,
  177        SelectToPreviousWordStart,
  178        SelectToPreviousSubwordStart,
  179        SelectToNextWordEnd,
  180        SelectToNextSubwordEnd,
  181        SelectToBeginning,
  182        SelectToEnd,
  183        SelectAll,
  184        SelectLine,
  185        SplitSelectionIntoLines,
  186        AddSelectionAbove,
  187        AddSelectionBelow,
  188        Tab,
  189        TabPrev,
  190        ToggleComments,
  191        ShowCharacterPalette,
  192        SelectLargerSyntaxNode,
  193        SelectSmallerSyntaxNode,
  194        GoToDefinition,
  195        GoToTypeDefinition,
  196        MoveToEnclosingBracket,
  197        UndoSelection,
  198        RedoSelection,
  199        FindAllReferences,
  200        Rename,
  201        ConfirmRename,
  202        PageUp,
  203        PageDown,
  204        Fold,
  205        UnfoldLines,
  206        FoldSelectedRanges,
  207        ShowCompletions,
  208        OpenExcerpts,
  209        RestartLanguageServer,
  210        Hover,
  211        Format,
  212    ]
  213);
  214
  215impl_actions!(
  216    editor,
  217    [
  218        SelectNext,
  219        SelectToBeginningOfLine,
  220        SelectToEndOfLine,
  221        ToggleCodeActions,
  222        ConfirmCompletion,
  223        ConfirmCodeAction,
  224    ]
  225);
  226
  227impl_internal_actions!(editor, [Scroll, Select, Jump]);
  228
  229enum DocumentHighlightRead {}
  230enum DocumentHighlightWrite {}
  231enum InputComposition {}
  232
  233#[derive(Copy, Clone, PartialEq, Eq)]
  234pub enum Direction {
  235    Prev,
  236    Next,
  237}
  238
  239pub fn init(cx: &mut MutableAppContext) {
  240    cx.add_action(Editor::new_file);
  241    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
  242    cx.add_action(Editor::select);
  243    cx.add_action(Editor::cancel);
  244    cx.add_action(Editor::newline);
  245    cx.add_action(Editor::newline_below);
  246    cx.add_action(Editor::backspace);
  247    cx.add_action(Editor::delete);
  248    cx.add_action(Editor::tab);
  249    cx.add_action(Editor::tab_prev);
  250    cx.add_action(Editor::indent);
  251    cx.add_action(Editor::outdent);
  252    cx.add_action(Editor::delete_line);
  253    cx.add_action(Editor::delete_to_previous_word_start);
  254    cx.add_action(Editor::delete_to_previous_subword_start);
  255    cx.add_action(Editor::delete_to_next_word_end);
  256    cx.add_action(Editor::delete_to_next_subword_end);
  257    cx.add_action(Editor::delete_to_beginning_of_line);
  258    cx.add_action(Editor::delete_to_end_of_line);
  259    cx.add_action(Editor::cut_to_end_of_line);
  260    cx.add_action(Editor::duplicate_line);
  261    cx.add_action(Editor::move_line_up);
  262    cx.add_action(Editor::move_line_down);
  263    cx.add_action(Editor::transpose);
  264    cx.add_action(Editor::cut);
  265    cx.add_action(Editor::copy);
  266    cx.add_action(Editor::paste);
  267    cx.add_action(Editor::undo);
  268    cx.add_action(Editor::redo);
  269    cx.add_action(Editor::move_up);
  270    cx.add_action(Editor::move_down);
  271    cx.add_action(Editor::move_left);
  272    cx.add_action(Editor::move_right);
  273    cx.add_action(Editor::move_to_previous_word_start);
  274    cx.add_action(Editor::move_to_previous_subword_start);
  275    cx.add_action(Editor::move_to_next_word_end);
  276    cx.add_action(Editor::move_to_next_subword_end);
  277    cx.add_action(Editor::move_to_beginning_of_line);
  278    cx.add_action(Editor::move_to_end_of_line);
  279    cx.add_action(Editor::move_to_beginning);
  280    cx.add_action(Editor::move_to_end);
  281    cx.add_action(Editor::select_up);
  282    cx.add_action(Editor::select_down);
  283    cx.add_action(Editor::select_left);
  284    cx.add_action(Editor::select_right);
  285    cx.add_action(Editor::select_to_previous_word_start);
  286    cx.add_action(Editor::select_to_previous_subword_start);
  287    cx.add_action(Editor::select_to_next_word_end);
  288    cx.add_action(Editor::select_to_next_subword_end);
  289    cx.add_action(Editor::select_to_beginning_of_line);
  290    cx.add_action(Editor::select_to_end_of_line);
  291    cx.add_action(Editor::select_to_beginning);
  292    cx.add_action(Editor::select_to_end);
  293    cx.add_action(Editor::select_all);
  294    cx.add_action(Editor::select_line);
  295    cx.add_action(Editor::split_selection_into_lines);
  296    cx.add_action(Editor::add_selection_above);
  297    cx.add_action(Editor::add_selection_below);
  298    cx.add_action(Editor::select_next);
  299    cx.add_action(Editor::toggle_comments);
  300    cx.add_action(Editor::select_larger_syntax_node);
  301    cx.add_action(Editor::select_smaller_syntax_node);
  302    cx.add_action(Editor::move_to_enclosing_bracket);
  303    cx.add_action(Editor::undo_selection);
  304    cx.add_action(Editor::redo_selection);
  305    cx.add_action(Editor::go_to_diagnostic);
  306    cx.add_action(Editor::go_to_prev_diagnostic);
  307    cx.add_action(Editor::go_to_definition);
  308    cx.add_action(Editor::go_to_type_definition);
  309    cx.add_action(Editor::page_up);
  310    cx.add_action(Editor::page_down);
  311    cx.add_action(Editor::fold);
  312    cx.add_action(Editor::unfold_lines);
  313    cx.add_action(Editor::fold_selected_ranges);
  314    cx.add_action(Editor::show_completions);
  315    cx.add_action(Editor::toggle_code_actions);
  316    cx.add_action(Editor::open_excerpts);
  317    cx.add_action(Editor::jump);
  318    cx.add_async_action(Editor::format);
  319    cx.add_action(Editor::restart_language_server);
  320    cx.add_action(Editor::show_character_palette);
  321    cx.add_async_action(Editor::confirm_completion);
  322    cx.add_async_action(Editor::confirm_code_action);
  323    cx.add_async_action(Editor::rename);
  324    cx.add_async_action(Editor::confirm_rename);
  325    cx.add_async_action(Editor::find_all_references);
  326
  327    hover_popover::init(cx);
  328    link_go_to_definition::init(cx);
  329    mouse_context_menu::init(cx);
  330
  331    workspace::register_project_item::<Editor>(cx);
  332    workspace::register_followable_item::<Editor>(cx);
  333}
  334
  335trait InvalidationRegion {
  336    fn ranges(&self) -> &[Range<Anchor>];
  337}
  338
  339#[derive(Clone, Debug, PartialEq)]
  340pub enum SelectPhase {
  341    Begin {
  342        position: DisplayPoint,
  343        add: bool,
  344        click_count: usize,
  345    },
  346    BeginColumnar {
  347        position: DisplayPoint,
  348        goal_column: u32,
  349    },
  350    Extend {
  351        position: DisplayPoint,
  352        click_count: usize,
  353    },
  354    Update {
  355        position: DisplayPoint,
  356        goal_column: u32,
  357        scroll_position: Vector2F,
  358    },
  359    End,
  360}
  361
  362#[derive(Clone, Debug)]
  363pub enum SelectMode {
  364    Character,
  365    Word(Range<Anchor>),
  366    Line(Range<Anchor>),
  367    All,
  368}
  369
  370#[derive(PartialEq, Eq)]
  371pub enum Autoscroll {
  372    Fit,
  373    Center,
  374    Newest,
  375}
  376
  377#[derive(Copy, Clone, PartialEq, Eq)]
  378pub enum EditorMode {
  379    SingleLine,
  380    AutoHeight { max_lines: usize },
  381    Full,
  382}
  383
  384#[derive(Clone)]
  385pub enum SoftWrap {
  386    None,
  387    EditorWidth,
  388    Column(u32),
  389}
  390
  391#[derive(Clone)]
  392pub struct EditorStyle {
  393    pub text: TextStyle,
  394    pub placeholder_text: Option<TextStyle>,
  395    pub theme: theme::Editor,
  396}
  397
  398type CompletionId = usize;
  399
  400pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor;
  401
  402type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  403
  404pub struct Editor {
  405    handle: WeakViewHandle<Self>,
  406    buffer: ModelHandle<MultiBuffer>,
  407    display_map: ModelHandle<DisplayMap>,
  408    pub selections: SelectionsCollection,
  409    columnar_selection_tail: Option<Anchor>,
  410    add_selections_state: Option<AddSelectionsState>,
  411    select_next_state: Option<SelectNextState>,
  412    selection_history: SelectionHistory,
  413    autoclose_regions: Vec<AutocloseRegion>,
  414    snippet_stack: InvalidationStack<SnippetState>,
  415    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  416    ime_transaction: Option<TransactionId>,
  417    active_diagnostics: Option<ActiveDiagnosticGroup>,
  418    scroll_position: Vector2F,
  419    scroll_top_anchor: Anchor,
  420    autoscroll_request: Option<(Autoscroll, bool)>,
  421    soft_wrap_mode_override: Option<settings::SoftWrap>,
  422    get_field_editor_theme: Option<GetFieldEditorTheme>,
  423    override_text_style: Option<Box<OverrideTextStyle>>,
  424    project: Option<ModelHandle<Project>>,
  425    focused: bool,
  426    show_local_cursors: bool,
  427    show_local_selections: bool,
  428    blink_epoch: usize,
  429    blinking_paused: bool,
  430    mode: EditorMode,
  431    vertical_scroll_margin: f32,
  432    placeholder_text: Option<Arc<str>>,
  433    highlighted_rows: Option<Range<u32>>,
  434    #[allow(clippy::type_complexity)]
  435    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
  436    nav_history: Option<ItemNavHistory>,
  437    context_menu: Option<ContextMenu>,
  438    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
  439    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  440    next_completion_id: CompletionId,
  441    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
  442    code_actions_task: Option<Task<()>>,
  443    document_highlights_task: Option<Task<()>>,
  444    pending_rename: Option<RenameState>,
  445    searchable: bool,
  446    cursor_shape: CursorShape,
  447    keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
  448    input_enabled: bool,
  449    leader_replica_id: Option<u16>,
  450    hover_state: HoverState,
  451    link_go_to_definition_state: LinkGoToDefinitionState,
  452    _subscriptions: Vec<Subscription>,
  453}
  454
  455pub struct EditorSnapshot {
  456    pub mode: EditorMode,
  457    pub display_snapshot: DisplaySnapshot,
  458    pub placeholder_text: Option<Arc<str>>,
  459    is_focused: bool,
  460    scroll_position: Vector2F,
  461    scroll_top_anchor: Anchor,
  462}
  463
  464#[derive(Clone, Debug)]
  465struct SelectionHistoryEntry {
  466    selections: Arc<[Selection<Anchor>]>,
  467    select_next_state: Option<SelectNextState>,
  468    add_selections_state: Option<AddSelectionsState>,
  469}
  470
  471enum SelectionHistoryMode {
  472    Normal,
  473    Undoing,
  474    Redoing,
  475}
  476
  477impl Default for SelectionHistoryMode {
  478    fn default() -> Self {
  479        Self::Normal
  480    }
  481}
  482
  483#[derive(Default)]
  484struct SelectionHistory {
  485    #[allow(clippy::type_complexity)]
  486    selections_by_transaction:
  487        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  488    mode: SelectionHistoryMode,
  489    undo_stack: VecDeque<SelectionHistoryEntry>,
  490    redo_stack: VecDeque<SelectionHistoryEntry>,
  491}
  492
  493impl SelectionHistory {
  494    fn insert_transaction(
  495        &mut self,
  496        transaction_id: TransactionId,
  497        selections: Arc<[Selection<Anchor>]>,
  498    ) {
  499        self.selections_by_transaction
  500            .insert(transaction_id, (selections, None));
  501    }
  502
  503    #[allow(clippy::type_complexity)]
  504    fn transaction(
  505        &self,
  506        transaction_id: TransactionId,
  507    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  508        self.selections_by_transaction.get(&transaction_id)
  509    }
  510
  511    #[allow(clippy::type_complexity)]
  512    fn transaction_mut(
  513        &mut self,
  514        transaction_id: TransactionId,
  515    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  516        self.selections_by_transaction.get_mut(&transaction_id)
  517    }
  518
  519    fn push(&mut self, entry: SelectionHistoryEntry) {
  520        if !entry.selections.is_empty() {
  521            match self.mode {
  522                SelectionHistoryMode::Normal => {
  523                    self.push_undo(entry);
  524                    self.redo_stack.clear();
  525                }
  526                SelectionHistoryMode::Undoing => self.push_redo(entry),
  527                SelectionHistoryMode::Redoing => self.push_undo(entry),
  528            }
  529        }
  530    }
  531
  532    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  533        if self
  534            .undo_stack
  535            .back()
  536            .map_or(true, |e| e.selections != entry.selections)
  537        {
  538            self.undo_stack.push_back(entry);
  539            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  540                self.undo_stack.pop_front();
  541            }
  542        }
  543    }
  544
  545    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  546        if self
  547            .redo_stack
  548            .back()
  549            .map_or(true, |e| e.selections != entry.selections)
  550        {
  551            self.redo_stack.push_back(entry);
  552            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  553                self.redo_stack.pop_front();
  554            }
  555        }
  556    }
  557}
  558
  559#[derive(Clone, Debug)]
  560struct AddSelectionsState {
  561    above: bool,
  562    stack: Vec<usize>,
  563}
  564
  565#[derive(Clone, Debug)]
  566struct SelectNextState {
  567    query: AhoCorasick,
  568    wordwise: bool,
  569    done: bool,
  570}
  571
  572#[derive(Debug)]
  573struct AutocloseRegion {
  574    selection_id: usize,
  575    range: Range<Anchor>,
  576    pair: BracketPair,
  577}
  578
  579#[derive(Debug)]
  580struct SnippetState {
  581    ranges: Vec<Vec<Range<Anchor>>>,
  582    active_index: usize,
  583}
  584
  585pub struct RenameState {
  586    pub range: Range<Anchor>,
  587    pub old_name: Arc<str>,
  588    pub editor: ViewHandle<Editor>,
  589    block_id: BlockId,
  590}
  591
  592struct InvalidationStack<T>(Vec<T>);
  593
  594enum ContextMenu {
  595    Completions(CompletionsMenu),
  596    CodeActions(CodeActionsMenu),
  597}
  598
  599impl ContextMenu {
  600    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
  601        if self.visible() {
  602            match self {
  603                ContextMenu::Completions(menu) => menu.select_prev(cx),
  604                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  605            }
  606            true
  607        } else {
  608            false
  609        }
  610    }
  611
  612    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
  613        if self.visible() {
  614            match self {
  615                ContextMenu::Completions(menu) => menu.select_next(cx),
  616                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  617            }
  618            true
  619        } else {
  620            false
  621        }
  622    }
  623
  624    fn visible(&self) -> bool {
  625        match self {
  626            ContextMenu::Completions(menu) => menu.visible(),
  627            ContextMenu::CodeActions(menu) => menu.visible(),
  628        }
  629    }
  630
  631    fn render(
  632        &self,
  633        cursor_position: DisplayPoint,
  634        style: EditorStyle,
  635        cx: &mut RenderContext<Editor>,
  636    ) -> (DisplayPoint, ElementBox) {
  637        match self {
  638            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
  639            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
  640        }
  641    }
  642}
  643
  644struct CompletionsMenu {
  645    id: CompletionId,
  646    initial_position: Anchor,
  647    buffer: ModelHandle<Buffer>,
  648    completions: Arc<[Completion]>,
  649    match_candidates: Vec<StringMatchCandidate>,
  650    matches: Arc<[StringMatch]>,
  651    selected_item: usize,
  652    list: UniformListState,
  653}
  654
  655impl CompletionsMenu {
  656    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
  657        if self.selected_item > 0 {
  658            self.selected_item -= 1;
  659            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  660        }
  661        cx.notify();
  662    }
  663
  664    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
  665        if self.selected_item + 1 < self.matches.len() {
  666            self.selected_item += 1;
  667            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  668        }
  669        cx.notify();
  670    }
  671
  672    fn visible(&self) -> bool {
  673        !self.matches.is_empty()
  674    }
  675
  676    fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
  677        enum CompletionTag {}
  678
  679        let completions = self.completions.clone();
  680        let matches = self.matches.clone();
  681        let selected_item = self.selected_item;
  682        let container_style = style.autocomplete.container;
  683        UniformList::new(
  684            self.list.clone(),
  685            matches.len(),
  686            cx,
  687            move |_, range, items, cx| {
  688                let start_ix = range.start;
  689                for (ix, mat) in matches[range].iter().enumerate() {
  690                    let completion = &completions[mat.candidate_id];
  691                    let item_ix = start_ix + ix;
  692                    items.push(
  693                        MouseEventHandler::<CompletionTag>::new(
  694                            mat.candidate_id,
  695                            cx,
  696                            |state, _| {
  697                                let item_style = if item_ix == selected_item {
  698                                    style.autocomplete.selected_item
  699                                } else if state.hovered {
  700                                    style.autocomplete.hovered_item
  701                                } else {
  702                                    style.autocomplete.item
  703                                };
  704
  705                                Text::new(completion.label.text.clone(), style.text.clone())
  706                                    .with_soft_wrap(false)
  707                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
  708                                        &completion.label.text,
  709                                        style.text.color.into(),
  710                                        styled_runs_for_code_label(
  711                                            &completion.label,
  712                                            &style.syntax,
  713                                        ),
  714                                        &mat.positions,
  715                                    ))
  716                                    .contained()
  717                                    .with_style(item_style)
  718                                    .boxed()
  719                            },
  720                        )
  721                        .with_cursor_style(CursorStyle::PointingHand)
  722                        .on_down(MouseButton::Left, move |_, cx| {
  723                            cx.dispatch_action(ConfirmCompletion {
  724                                item_ix: Some(item_ix),
  725                            });
  726                        })
  727                        .boxed(),
  728                    );
  729                }
  730            },
  731        )
  732        .with_width_from_item(
  733            self.matches
  734                .iter()
  735                .enumerate()
  736                .max_by_key(|(_, mat)| {
  737                    self.completions[mat.candidate_id]
  738                        .label
  739                        .text
  740                        .chars()
  741                        .count()
  742                })
  743                .map(|(ix, _)| ix),
  744        )
  745        .contained()
  746        .with_style(container_style)
  747        .boxed()
  748    }
  749
  750    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
  751        let mut matches = if let Some(query) = query {
  752            fuzzy::match_strings(
  753                &self.match_candidates,
  754                query,
  755                false,
  756                100,
  757                &Default::default(),
  758                executor,
  759            )
  760            .await
  761        } else {
  762            self.match_candidates
  763                .iter()
  764                .enumerate()
  765                .map(|(candidate_id, candidate)| StringMatch {
  766                    candidate_id,
  767                    score: Default::default(),
  768                    positions: Default::default(),
  769                    string: candidate.string.clone(),
  770                })
  771                .collect()
  772        };
  773        matches.sort_unstable_by_key(|mat| {
  774            let completion = &self.completions[mat.candidate_id];
  775            (
  776                completion.lsp_completion.sort_text.as_ref(),
  777                Reverse(OrderedFloat(mat.score)),
  778                completion.sort_key(),
  779            )
  780        });
  781
  782        for mat in &mut matches {
  783            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
  784            for position in &mut mat.positions {
  785                *position += filter_start;
  786            }
  787        }
  788
  789        self.matches = matches.into();
  790    }
  791}
  792
  793#[derive(Clone)]
  794struct CodeActionsMenu {
  795    actions: Arc<[CodeAction]>,
  796    buffer: ModelHandle<Buffer>,
  797    selected_item: usize,
  798    list: UniformListState,
  799    deployed_from_indicator: bool,
  800}
  801
  802impl CodeActionsMenu {
  803    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
  804        if self.selected_item > 0 {
  805            self.selected_item -= 1;
  806            cx.notify()
  807        }
  808    }
  809
  810    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
  811        if self.selected_item + 1 < self.actions.len() {
  812            self.selected_item += 1;
  813            cx.notify()
  814        }
  815    }
  816
  817    fn visible(&self) -> bool {
  818        !self.actions.is_empty()
  819    }
  820
  821    fn render(
  822        &self,
  823        mut cursor_position: DisplayPoint,
  824        style: EditorStyle,
  825        cx: &mut RenderContext<Editor>,
  826    ) -> (DisplayPoint, ElementBox) {
  827        enum ActionTag {}
  828
  829        let container_style = style.autocomplete.container;
  830        let actions = self.actions.clone();
  831        let selected_item = self.selected_item;
  832        let element = UniformList::new(
  833            self.list.clone(),
  834            actions.len(),
  835            cx,
  836            move |_, range, items, cx| {
  837                let start_ix = range.start;
  838                for (ix, action) in actions[range].iter().enumerate() {
  839                    let item_ix = start_ix + ix;
  840                    items.push(
  841                        MouseEventHandler::<ActionTag>::new(item_ix, cx, |state, _| {
  842                            let item_style = if item_ix == selected_item {
  843                                style.autocomplete.selected_item
  844                            } else if state.hovered {
  845                                style.autocomplete.hovered_item
  846                            } else {
  847                                style.autocomplete.item
  848                            };
  849
  850                            Text::new(action.lsp_action.title.clone(), style.text.clone())
  851                                .with_soft_wrap(false)
  852                                .contained()
  853                                .with_style(item_style)
  854                                .boxed()
  855                        })
  856                        .with_cursor_style(CursorStyle::PointingHand)
  857                        .on_down(MouseButton::Left, move |_, cx| {
  858                            cx.dispatch_action(ConfirmCodeAction {
  859                                item_ix: Some(item_ix),
  860                            });
  861                        })
  862                        .boxed(),
  863                    );
  864                }
  865            },
  866        )
  867        .with_width_from_item(
  868            self.actions
  869                .iter()
  870                .enumerate()
  871                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
  872                .map(|(ix, _)| ix),
  873        )
  874        .contained()
  875        .with_style(container_style)
  876        .boxed();
  877
  878        if self.deployed_from_indicator {
  879            *cursor_position.column_mut() = 0;
  880        }
  881
  882        (cursor_position, element)
  883    }
  884}
  885
  886#[derive(Debug)]
  887struct ActiveDiagnosticGroup {
  888    primary_range: Range<Anchor>,
  889    primary_message: String,
  890    blocks: HashMap<BlockId, Diagnostic>,
  891    is_valid: bool,
  892}
  893
  894#[derive(Serialize, Deserialize)]
  895pub struct ClipboardSelection {
  896    pub len: usize,
  897    pub is_entire_line: bool,
  898    pub first_line_indent: u32,
  899}
  900
  901#[derive(Debug)]
  902pub struct NavigationData {
  903    // Matching offsets for anchor and scroll_top_anchor allows us to recreate the anchor if the buffer
  904    // has since been closed
  905    cursor_anchor: Anchor,
  906    cursor_position: Point,
  907    scroll_position: Vector2F,
  908    scroll_top_anchor: Anchor,
  909    scroll_top_row: u32,
  910}
  911
  912pub struct EditorCreated(pub ViewHandle<Editor>);
  913
  914enum GotoDefinitionKind {
  915    Symbol,
  916    Type,
  917}
  918
  919impl Editor {
  920    pub fn single_line(
  921        field_editor_style: Option<GetFieldEditorTheme>,
  922        cx: &mut ViewContext<Self>,
  923    ) -> Self {
  924        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
  925        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  926        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
  927    }
  928
  929    pub fn auto_height(
  930        max_lines: usize,
  931        field_editor_style: Option<GetFieldEditorTheme>,
  932        cx: &mut ViewContext<Self>,
  933    ) -> Self {
  934        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
  935        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  936        Self::new(
  937            EditorMode::AutoHeight { max_lines },
  938            buffer,
  939            None,
  940            field_editor_style,
  941            cx,
  942        )
  943    }
  944
  945    pub fn for_buffer(
  946        buffer: ModelHandle<Buffer>,
  947        project: Option<ModelHandle<Project>>,
  948        cx: &mut ViewContext<Self>,
  949    ) -> Self {
  950        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  951        Self::new(EditorMode::Full, buffer, project, None, cx)
  952    }
  953
  954    pub fn for_multibuffer(
  955        buffer: ModelHandle<MultiBuffer>,
  956        project: Option<ModelHandle<Project>>,
  957        cx: &mut ViewContext<Self>,
  958    ) -> Self {
  959        Self::new(EditorMode::Full, buffer, project, None, cx)
  960    }
  961
  962    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
  963        let mut clone = Self::new(
  964            self.mode,
  965            self.buffer.clone(),
  966            self.project.clone(),
  967            self.get_field_editor_theme,
  968            cx,
  969        );
  970        self.display_map.update(cx, |display_map, cx| {
  971            let snapshot = display_map.snapshot(cx);
  972            clone.display_map.update(cx, |display_map, cx| {
  973                display_map.set_state(&snapshot, cx);
  974            });
  975        });
  976        clone.selections.set_state(&self.selections);
  977        clone.scroll_position = self.scroll_position;
  978        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
  979        clone.searchable = self.searchable;
  980        clone
  981    }
  982
  983    fn new(
  984        mode: EditorMode,
  985        buffer: ModelHandle<MultiBuffer>,
  986        project: Option<ModelHandle<Project>>,
  987        get_field_editor_theme: Option<GetFieldEditorTheme>,
  988        cx: &mut ViewContext<Self>,
  989    ) -> Self {
  990        let display_map = cx.add_model(|cx| {
  991            let settings = cx.global::<Settings>();
  992            let style = build_style(&*settings, get_field_editor_theme, None, cx);
  993            DisplayMap::new(
  994                buffer.clone(),
  995                style.text.font_id,
  996                style.text.font_size,
  997                None,
  998                2,
  999                1,
 1000                cx,
 1001            )
 1002        });
 1003
 1004        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1005
 1006        let mut this = Self {
 1007            handle: cx.weak_handle(),
 1008            buffer: buffer.clone(),
 1009            display_map: display_map.clone(),
 1010            selections,
 1011            columnar_selection_tail: None,
 1012            add_selections_state: None,
 1013            select_next_state: None,
 1014            selection_history: Default::default(),
 1015            autoclose_regions: Default::default(),
 1016            snippet_stack: Default::default(),
 1017            select_larger_syntax_node_stack: Vec::new(),
 1018            ime_transaction: Default::default(),
 1019            active_diagnostics: None,
 1020            soft_wrap_mode_override: None,
 1021            get_field_editor_theme,
 1022            project,
 1023            scroll_position: Vector2F::zero(),
 1024            scroll_top_anchor: Anchor::min(),
 1025            autoscroll_request: None,
 1026            focused: false,
 1027            show_local_cursors: false,
 1028            show_local_selections: true,
 1029            blink_epoch: 0,
 1030            blinking_paused: false,
 1031            mode,
 1032            vertical_scroll_margin: 3.0,
 1033            placeholder_text: None,
 1034            highlighted_rows: None,
 1035            background_highlights: Default::default(),
 1036            nav_history: None,
 1037            context_menu: None,
 1038            mouse_context_menu: cx.add_view(context_menu::ContextMenu::new),
 1039            completion_tasks: Default::default(),
 1040            next_completion_id: 0,
 1041            available_code_actions: Default::default(),
 1042            code_actions_task: Default::default(),
 1043            document_highlights_task: Default::default(),
 1044            pending_rename: Default::default(),
 1045            searchable: true,
 1046            override_text_style: None,
 1047            cursor_shape: Default::default(),
 1048            keymap_context_layers: Default::default(),
 1049            input_enabled: true,
 1050            leader_replica_id: None,
 1051            hover_state: Default::default(),
 1052            link_go_to_definition_state: Default::default(),
 1053            _subscriptions: vec![
 1054                cx.observe(&buffer, Self::on_buffer_changed),
 1055                cx.subscribe(&buffer, Self::on_buffer_event),
 1056                cx.observe(&display_map, Self::on_display_map_changed),
 1057            ],
 1058        };
 1059        this.end_selection(cx);
 1060
 1061        let editor_created_event = EditorCreated(cx.handle());
 1062        cx.emit_global(editor_created_event);
 1063
 1064        this.report_event("open editor", cx);
 1065        this
 1066    }
 1067
 1068    pub fn new_file(
 1069        workspace: &mut Workspace,
 1070        _: &workspace::NewFile,
 1071        cx: &mut ViewContext<Workspace>,
 1072    ) {
 1073        let project = workspace.project().clone();
 1074        if project.read(cx).is_remote() {
 1075            cx.propagate_action();
 1076        } else if let Some(buffer) = project
 1077            .update(cx, |project, cx| project.create_buffer("", None, cx))
 1078            .log_err()
 1079        {
 1080            workspace.add_item(
 1081                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 1082                cx,
 1083            );
 1084        }
 1085    }
 1086
 1087    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 1088        self.buffer.read(cx).replica_id()
 1089    }
 1090
 1091    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
 1092        self.leader_replica_id
 1093    }
 1094
 1095    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
 1096        &self.buffer
 1097    }
 1098
 1099    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 1100        self.buffer().read(cx).title(cx)
 1101    }
 1102
 1103    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
 1104        EditorSnapshot {
 1105            mode: self.mode,
 1106            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1107            scroll_position: self.scroll_position,
 1108            scroll_top_anchor: self.scroll_top_anchor.clone(),
 1109            placeholder_text: self.placeholder_text.clone(),
 1110            is_focused: self
 1111                .handle
 1112                .upgrade(cx)
 1113                .map_or(false, |handle| handle.is_focused(cx)),
 1114        }
 1115    }
 1116
 1117    pub fn language_at<'a, T: ToOffset>(
 1118        &self,
 1119        point: T,
 1120        cx: &'a AppContext,
 1121    ) -> Option<Arc<Language>> {
 1122        self.buffer.read(cx).language_at(point, cx)
 1123    }
 1124
 1125    fn style(&self, cx: &AppContext) -> EditorStyle {
 1126        build_style(
 1127            cx.global::<Settings>(),
 1128            self.get_field_editor_theme,
 1129            self.override_text_style.as_deref(),
 1130            cx,
 1131        )
 1132    }
 1133
 1134    pub fn mode(&self) -> EditorMode {
 1135        self.mode
 1136    }
 1137
 1138    pub fn set_placeholder_text(
 1139        &mut self,
 1140        placeholder_text: impl Into<Arc<str>>,
 1141        cx: &mut ViewContext<Self>,
 1142    ) {
 1143        self.placeholder_text = Some(placeholder_text.into());
 1144        cx.notify();
 1145    }
 1146
 1147    pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
 1148        self.vertical_scroll_margin = margin_rows as f32;
 1149        cx.notify();
 1150    }
 1151
 1152    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
 1153        self.set_scroll_position_internal(scroll_position, true, cx);
 1154    }
 1155
 1156    fn set_scroll_position_internal(
 1157        &mut self,
 1158        scroll_position: Vector2F,
 1159        local: bool,
 1160        cx: &mut ViewContext<Self>,
 1161    ) {
 1162        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1163
 1164        if scroll_position.y() == 0. {
 1165            self.scroll_top_anchor = Anchor::min();
 1166            self.scroll_position = scroll_position;
 1167        } else {
 1168            let scroll_top_buffer_offset =
 1169                DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
 1170            let anchor = map
 1171                .buffer_snapshot
 1172                .anchor_at(scroll_top_buffer_offset, Bias::Right);
 1173            self.scroll_position = vec2f(
 1174                scroll_position.x(),
 1175                scroll_position.y() - anchor.to_display_point(&map).row() as f32,
 1176            );
 1177            self.scroll_top_anchor = anchor;
 1178        }
 1179
 1180        self.autoscroll_request.take();
 1181        hide_hover(self, cx);
 1182
 1183        cx.emit(Event::ScrollPositionChanged { local });
 1184        cx.notify();
 1185    }
 1186
 1187    fn set_scroll_top_anchor(
 1188        &mut self,
 1189        anchor: Anchor,
 1190        position: Vector2F,
 1191        cx: &mut ViewContext<Self>,
 1192    ) {
 1193        self.scroll_top_anchor = anchor;
 1194        self.scroll_position = position;
 1195        cx.emit(Event::ScrollPositionChanged { local: false });
 1196        cx.notify();
 1197    }
 1198
 1199    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 1200        self.cursor_shape = cursor_shape;
 1201        cx.notify();
 1202    }
 1203
 1204    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 1205        if self.display_map.read(cx).clip_at_line_ends != clip {
 1206            self.display_map
 1207                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1208        }
 1209    }
 1210
 1211    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: gpui::keymap::Context) {
 1212        self.keymap_context_layers
 1213            .insert(TypeId::of::<Tag>(), context);
 1214    }
 1215
 1216    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
 1217        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
 1218    }
 1219
 1220    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1221        self.input_enabled = input_enabled;
 1222    }
 1223
 1224    pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
 1225        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1226        compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
 1227    }
 1228
 1229    pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
 1230        if max < self.scroll_position.x() {
 1231            self.scroll_position.set_x(max);
 1232            true
 1233        } else {
 1234            false
 1235        }
 1236    }
 1237
 1238    pub fn autoscroll_vertically(
 1239        &mut self,
 1240        viewport_height: f32,
 1241        line_height: f32,
 1242        cx: &mut ViewContext<Self>,
 1243    ) -> bool {
 1244        let visible_lines = viewport_height / line_height;
 1245        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1246        let mut scroll_position =
 1247            compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
 1248        let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 1249            (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
 1250        } else {
 1251            display_map.max_point().row().saturating_sub(1) as f32
 1252        };
 1253        if scroll_position.y() > max_scroll_top {
 1254            scroll_position.set_y(max_scroll_top);
 1255            self.set_scroll_position(scroll_position, cx);
 1256        }
 1257
 1258        let (autoscroll, local) = if let Some(autoscroll) = self.autoscroll_request.take() {
 1259            autoscroll
 1260        } else {
 1261            return false;
 1262        };
 1263
 1264        let first_cursor_top;
 1265        let last_cursor_bottom;
 1266        if let Some(highlighted_rows) = &self.highlighted_rows {
 1267            first_cursor_top = highlighted_rows.start as f32;
 1268            last_cursor_bottom = first_cursor_top + 1.;
 1269        } else if autoscroll == Autoscroll::Newest {
 1270            let newest_selection = self.selections.newest::<Point>(cx);
 1271            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
 1272            last_cursor_bottom = first_cursor_top + 1.;
 1273        } else {
 1274            let selections = self.selections.all::<Point>(cx);
 1275            first_cursor_top = selections
 1276                .first()
 1277                .unwrap()
 1278                .head()
 1279                .to_display_point(&display_map)
 1280                .row() as f32;
 1281            last_cursor_bottom = selections
 1282                .last()
 1283                .unwrap()
 1284                .head()
 1285                .to_display_point(&display_map)
 1286                .row() as f32
 1287                + 1.0;
 1288        }
 1289
 1290        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 1291            0.
 1292        } else {
 1293            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
 1294        };
 1295        if margin < 0.0 {
 1296            return false;
 1297        }
 1298
 1299        match autoscroll {
 1300            Autoscroll::Fit | Autoscroll::Newest => {
 1301                let margin = margin.min(self.vertical_scroll_margin);
 1302                let target_top = (first_cursor_top - margin).max(0.0);
 1303                let target_bottom = last_cursor_bottom + margin;
 1304                let start_row = scroll_position.y();
 1305                let end_row = start_row + visible_lines;
 1306
 1307                if target_top < start_row {
 1308                    scroll_position.set_y(target_top);
 1309                    self.set_scroll_position_internal(scroll_position, local, cx);
 1310                } else if target_bottom >= end_row {
 1311                    scroll_position.set_y(target_bottom - visible_lines);
 1312                    self.set_scroll_position_internal(scroll_position, local, cx);
 1313                }
 1314            }
 1315            Autoscroll::Center => {
 1316                scroll_position.set_y((first_cursor_top - margin).max(0.0));
 1317                self.set_scroll_position_internal(scroll_position, local, cx);
 1318            }
 1319        }
 1320
 1321        true
 1322    }
 1323
 1324    pub fn autoscroll_horizontally(
 1325        &mut self,
 1326        start_row: u32,
 1327        viewport_width: f32,
 1328        scroll_width: f32,
 1329        max_glyph_width: f32,
 1330        layouts: &[text_layout::Line],
 1331        cx: &mut ViewContext<Self>,
 1332    ) -> bool {
 1333        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1334        let selections = self.selections.all::<Point>(cx);
 1335
 1336        let mut target_left;
 1337        let mut target_right;
 1338
 1339        if self.highlighted_rows.is_some() {
 1340            target_left = 0.0_f32;
 1341            target_right = 0.0_f32;
 1342        } else {
 1343            target_left = std::f32::INFINITY;
 1344            target_right = 0.0_f32;
 1345            for selection in selections {
 1346                let head = selection.head().to_display_point(&display_map);
 1347                if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
 1348                    let start_column = head.column().saturating_sub(3);
 1349                    let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
 1350                    target_left = target_left.min(
 1351                        layouts[(head.row() - start_row) as usize]
 1352                            .x_for_index(start_column as usize),
 1353                    );
 1354                    target_right = target_right.max(
 1355                        layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 1356                            + max_glyph_width,
 1357                    );
 1358                }
 1359            }
 1360        }
 1361
 1362        target_right = target_right.min(scroll_width);
 1363
 1364        if target_right - target_left > viewport_width {
 1365            return false;
 1366        }
 1367
 1368        let scroll_left = self.scroll_position.x() * max_glyph_width;
 1369        let scroll_right = scroll_left + viewport_width;
 1370
 1371        if target_left < scroll_left {
 1372            self.scroll_position.set_x(target_left / max_glyph_width);
 1373            true
 1374        } else if target_right > scroll_right {
 1375            self.scroll_position
 1376                .set_x((target_right - viewport_width) / max_glyph_width);
 1377            true
 1378        } else {
 1379            false
 1380        }
 1381    }
 1382
 1383    fn selections_did_change(
 1384        &mut self,
 1385        local: bool,
 1386        old_cursor_position: &Anchor,
 1387        cx: &mut ViewContext<Self>,
 1388    ) {
 1389        if self.focused && self.leader_replica_id.is_none() {
 1390            self.buffer.update(cx, |buffer, cx| {
 1391                buffer.set_active_selections(
 1392                    &self.selections.disjoint_anchors(),
 1393                    self.selections.line_mode,
 1394                    cx,
 1395                )
 1396            });
 1397        }
 1398
 1399        let display_map = self
 1400            .display_map
 1401            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1402        let buffer = &display_map.buffer_snapshot;
 1403        self.add_selections_state = None;
 1404        self.select_next_state = None;
 1405        self.select_larger_syntax_node_stack.clear();
 1406        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 1407        self.snippet_stack
 1408            .invalidate(&self.selections.disjoint_anchors(), buffer);
 1409        self.take_rename(false, cx);
 1410
 1411        let new_cursor_position = self.selections.newest_anchor().head();
 1412
 1413        self.push_to_nav_history(
 1414            old_cursor_position.clone(),
 1415            Some(new_cursor_position.to_point(buffer)),
 1416            cx,
 1417        );
 1418
 1419        if local {
 1420            let new_cursor_position = self.selections.newest_anchor().head();
 1421            let completion_menu = match self.context_menu.as_mut() {
 1422                Some(ContextMenu::Completions(menu)) => Some(menu),
 1423                _ => {
 1424                    self.context_menu.take();
 1425                    None
 1426                }
 1427            };
 1428
 1429            if let Some(completion_menu) = completion_menu {
 1430                let cursor_position = new_cursor_position.to_offset(buffer);
 1431                let (word_range, kind) =
 1432                    buffer.surrounding_word(completion_menu.initial_position.clone());
 1433                if kind == Some(CharKind::Word)
 1434                    && word_range.to_inclusive().contains(&cursor_position)
 1435                {
 1436                    let query = Self::completion_query(buffer, cursor_position);
 1437                    cx.background()
 1438                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 1439                    self.show_completions(&ShowCompletions, cx);
 1440                } else {
 1441                    self.hide_context_menu(cx);
 1442                }
 1443            }
 1444
 1445            hide_hover(self, cx);
 1446
 1447            if old_cursor_position.to_display_point(&display_map).row()
 1448                != new_cursor_position.to_display_point(&display_map).row()
 1449            {
 1450                self.available_code_actions.take();
 1451            }
 1452            self.refresh_code_actions(cx);
 1453            self.refresh_document_highlights(cx);
 1454            refresh_matching_bracket_highlights(self, cx);
 1455        }
 1456
 1457        self.pause_cursor_blinking(cx);
 1458        cx.emit(Event::SelectionsChanged { local });
 1459        cx.notify();
 1460    }
 1461
 1462    pub fn change_selections<R>(
 1463        &mut self,
 1464        autoscroll: Option<Autoscroll>,
 1465        cx: &mut ViewContext<Self>,
 1466        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 1467    ) -> R {
 1468        let old_cursor_position = self.selections.newest_anchor().head();
 1469        self.push_to_selection_history();
 1470
 1471        let (changed, result) = self.selections.change_with(cx, change);
 1472
 1473        if changed {
 1474            if let Some(autoscroll) = autoscroll {
 1475                self.request_autoscroll(autoscroll, cx);
 1476            }
 1477            self.selections_did_change(true, &old_cursor_position, cx);
 1478        }
 1479
 1480        result
 1481    }
 1482
 1483    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1484    where
 1485        I: IntoIterator<Item = (Range<S>, T)>,
 1486        S: ToOffset,
 1487        T: Into<Arc<str>>,
 1488    {
 1489        self.buffer
 1490            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 1491    }
 1492
 1493    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1494    where
 1495        I: IntoIterator<Item = (Range<S>, T)>,
 1496        S: ToOffset,
 1497        T: Into<Arc<str>>,
 1498    {
 1499        self.buffer.update(cx, |buffer, cx| {
 1500            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
 1501        });
 1502    }
 1503
 1504    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
 1505        self.hide_context_menu(cx);
 1506
 1507        match phase {
 1508            SelectPhase::Begin {
 1509                position,
 1510                add,
 1511                click_count,
 1512            } => self.begin_selection(*position, *add, *click_count, cx),
 1513            SelectPhase::BeginColumnar {
 1514                position,
 1515                goal_column,
 1516            } => self.begin_columnar_selection(*position, *goal_column, cx),
 1517            SelectPhase::Extend {
 1518                position,
 1519                click_count,
 1520            } => self.extend_selection(*position, *click_count, cx),
 1521            SelectPhase::Update {
 1522                position,
 1523                goal_column,
 1524                scroll_position,
 1525            } => self.update_selection(*position, *goal_column, *scroll_position, cx),
 1526            SelectPhase::End => self.end_selection(cx),
 1527        }
 1528    }
 1529
 1530    fn extend_selection(
 1531        &mut self,
 1532        position: DisplayPoint,
 1533        click_count: usize,
 1534        cx: &mut ViewContext<Self>,
 1535    ) {
 1536        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1537        let tail = self.selections.newest::<usize>(cx).tail();
 1538        self.begin_selection(position, false, click_count, cx);
 1539
 1540        let position = position.to_offset(&display_map, Bias::Left);
 1541        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 1542
 1543        let mut pending_selection = self
 1544            .selections
 1545            .pending_anchor()
 1546            .expect("extend_selection not called with pending selection");
 1547        if position >= tail {
 1548            pending_selection.start = tail_anchor.clone();
 1549        } else {
 1550            pending_selection.end = tail_anchor.clone();
 1551            pending_selection.reversed = true;
 1552        }
 1553
 1554        let mut pending_mode = self.selections.pending_mode().unwrap();
 1555        match &mut pending_mode {
 1556            SelectMode::Word(range) | SelectMode::Line(range) => {
 1557                *range = tail_anchor.clone()..tail_anchor
 1558            }
 1559            _ => {}
 1560        }
 1561
 1562        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 1563            s.set_pending(pending_selection, pending_mode)
 1564        });
 1565    }
 1566
 1567    fn begin_selection(
 1568        &mut self,
 1569        position: DisplayPoint,
 1570        add: bool,
 1571        click_count: usize,
 1572        cx: &mut ViewContext<Self>,
 1573    ) {
 1574        if !self.focused {
 1575            cx.focus_self();
 1576        }
 1577
 1578        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1579        let buffer = &display_map.buffer_snapshot;
 1580        let newest_selection = self.selections.newest_anchor().clone();
 1581        let position = display_map.clip_point(position, Bias::Left);
 1582
 1583        let start;
 1584        let end;
 1585        let mode;
 1586        let auto_scroll;
 1587        match click_count {
 1588            1 => {
 1589                start = buffer.anchor_before(position.to_point(&display_map));
 1590                end = start.clone();
 1591                mode = SelectMode::Character;
 1592                auto_scroll = true;
 1593            }
 1594            2 => {
 1595                let range = movement::surrounding_word(&display_map, position);
 1596                start = buffer.anchor_before(range.start.to_point(&display_map));
 1597                end = buffer.anchor_before(range.end.to_point(&display_map));
 1598                mode = SelectMode::Word(start.clone()..end.clone());
 1599                auto_scroll = true;
 1600            }
 1601            3 => {
 1602                let position = display_map
 1603                    .clip_point(position, Bias::Left)
 1604                    .to_point(&display_map);
 1605                let line_start = display_map.prev_line_boundary(position).0;
 1606                let next_line_start = buffer.clip_point(
 1607                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 1608                    Bias::Left,
 1609                );
 1610                start = buffer.anchor_before(line_start);
 1611                end = buffer.anchor_before(next_line_start);
 1612                mode = SelectMode::Line(start.clone()..end.clone());
 1613                auto_scroll = true;
 1614            }
 1615            _ => {
 1616                start = buffer.anchor_before(0);
 1617                end = buffer.anchor_before(buffer.len());
 1618                mode = SelectMode::All;
 1619                auto_scroll = false;
 1620            }
 1621        }
 1622
 1623        self.change_selections(auto_scroll.then(|| Autoscroll::Newest), cx, |s| {
 1624            if !add {
 1625                s.clear_disjoint();
 1626            } else if click_count > 1 {
 1627                s.delete(newest_selection.id)
 1628            }
 1629
 1630            s.set_pending_anchor_range(start..end, mode);
 1631        });
 1632    }
 1633
 1634    fn begin_columnar_selection(
 1635        &mut self,
 1636        position: DisplayPoint,
 1637        goal_column: u32,
 1638        cx: &mut ViewContext<Self>,
 1639    ) {
 1640        if !self.focused {
 1641            cx.focus_self();
 1642        }
 1643
 1644        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1645        let tail = self.selections.newest::<Point>(cx).tail();
 1646        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 1647
 1648        self.select_columns(
 1649            tail.to_display_point(&display_map),
 1650            position,
 1651            goal_column,
 1652            &display_map,
 1653            cx,
 1654        );
 1655    }
 1656
 1657    fn update_selection(
 1658        &mut self,
 1659        position: DisplayPoint,
 1660        goal_column: u32,
 1661        scroll_position: Vector2F,
 1662        cx: &mut ViewContext<Self>,
 1663    ) {
 1664        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1665
 1666        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 1667            let tail = tail.to_display_point(&display_map);
 1668            self.select_columns(tail, position, goal_column, &display_map, cx);
 1669        } else if let Some(mut pending) = self.selections.pending_anchor() {
 1670            let buffer = self.buffer.read(cx).snapshot(cx);
 1671            let head;
 1672            let tail;
 1673            let mode = self.selections.pending_mode().unwrap();
 1674            match &mode {
 1675                SelectMode::Character => {
 1676                    head = position.to_point(&display_map);
 1677                    tail = pending.tail().to_point(&buffer);
 1678                }
 1679                SelectMode::Word(original_range) => {
 1680                    let original_display_range = original_range.start.to_display_point(&display_map)
 1681                        ..original_range.end.to_display_point(&display_map);
 1682                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 1683                        ..original_display_range.end.to_point(&display_map);
 1684                    if movement::is_inside_word(&display_map, position)
 1685                        || original_display_range.contains(&position)
 1686                    {
 1687                        let word_range = movement::surrounding_word(&display_map, position);
 1688                        if word_range.start < original_display_range.start {
 1689                            head = word_range.start.to_point(&display_map);
 1690                        } else {
 1691                            head = word_range.end.to_point(&display_map);
 1692                        }
 1693                    } else {
 1694                        head = position.to_point(&display_map);
 1695                    }
 1696
 1697                    if head <= original_buffer_range.start {
 1698                        tail = original_buffer_range.end;
 1699                    } else {
 1700                        tail = original_buffer_range.start;
 1701                    }
 1702                }
 1703                SelectMode::Line(original_range) => {
 1704                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 1705
 1706                    let position = display_map
 1707                        .clip_point(position, Bias::Left)
 1708                        .to_point(&display_map);
 1709                    let line_start = display_map.prev_line_boundary(position).0;
 1710                    let next_line_start = buffer.clip_point(
 1711                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 1712                        Bias::Left,
 1713                    );
 1714
 1715                    if line_start < original_range.start {
 1716                        head = line_start
 1717                    } else {
 1718                        head = next_line_start
 1719                    }
 1720
 1721                    if head <= original_range.start {
 1722                        tail = original_range.end;
 1723                    } else {
 1724                        tail = original_range.start;
 1725                    }
 1726                }
 1727                SelectMode::All => {
 1728                    return;
 1729                }
 1730            };
 1731
 1732            if head < tail {
 1733                pending.start = buffer.anchor_before(head);
 1734                pending.end = buffer.anchor_before(tail);
 1735                pending.reversed = true;
 1736            } else {
 1737                pending.start = buffer.anchor_before(tail);
 1738                pending.end = buffer.anchor_before(head);
 1739                pending.reversed = false;
 1740            }
 1741
 1742            self.change_selections(None, cx, |s| {
 1743                s.set_pending(pending, mode);
 1744            });
 1745        } else {
 1746            log::error!("update_selection dispatched with no pending selection");
 1747            return;
 1748        }
 1749
 1750        self.set_scroll_position(scroll_position, cx);
 1751        cx.notify();
 1752    }
 1753
 1754    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 1755        self.columnar_selection_tail.take();
 1756        if self.selections.pending_anchor().is_some() {
 1757            let selections = self.selections.all::<usize>(cx);
 1758            self.change_selections(None, cx, |s| {
 1759                s.select(selections);
 1760                s.clear_pending();
 1761            });
 1762        }
 1763    }
 1764
 1765    fn select_columns(
 1766        &mut self,
 1767        tail: DisplayPoint,
 1768        head: DisplayPoint,
 1769        goal_column: u32,
 1770        display_map: &DisplaySnapshot,
 1771        cx: &mut ViewContext<Self>,
 1772    ) {
 1773        let start_row = cmp::min(tail.row(), head.row());
 1774        let end_row = cmp::max(tail.row(), head.row());
 1775        let start_column = cmp::min(tail.column(), goal_column);
 1776        let end_column = cmp::max(tail.column(), goal_column);
 1777        let reversed = start_column < tail.column();
 1778
 1779        let selection_ranges = (start_row..=end_row)
 1780            .filter_map(|row| {
 1781                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 1782                    let start = display_map
 1783                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 1784                        .to_point(display_map);
 1785                    let end = display_map
 1786                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 1787                        .to_point(display_map);
 1788                    if reversed {
 1789                        Some(end..start)
 1790                    } else {
 1791                        Some(start..end)
 1792                    }
 1793                } else {
 1794                    None
 1795                }
 1796            })
 1797            .collect::<Vec<_>>();
 1798
 1799        self.change_selections(None, cx, |s| {
 1800            s.select_ranges(selection_ranges);
 1801        });
 1802        cx.notify();
 1803    }
 1804
 1805    pub fn has_pending_nonempty_selection(&self) -> bool {
 1806        let pending_nonempty_selection = match self.selections.pending_anchor() {
 1807            Some(Selection { start, end, .. }) => start != end,
 1808            None => false,
 1809        };
 1810        pending_nonempty_selection || self.columnar_selection_tail.is_some()
 1811    }
 1812
 1813    pub fn has_pending_selection(&self) -> bool {
 1814        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 1815    }
 1816
 1817    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 1818        if self.take_rename(false, cx).is_some() {
 1819            return;
 1820        }
 1821
 1822        if hide_hover(self, cx) {
 1823            return;
 1824        }
 1825
 1826        if self.hide_context_menu(cx).is_some() {
 1827            return;
 1828        }
 1829
 1830        if self.snippet_stack.pop().is_some() {
 1831            return;
 1832        }
 1833
 1834        if self.mode == EditorMode::Full {
 1835            if self.active_diagnostics.is_some() {
 1836                self.dismiss_diagnostics(cx);
 1837                return;
 1838            }
 1839
 1840            if self.change_selections(Some(Autoscroll::Fit), cx, |s| s.try_cancel()) {
 1841                return;
 1842            }
 1843        }
 1844
 1845        cx.propagate_action();
 1846    }
 1847
 1848    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 1849        if !self.input_enabled {
 1850            return;
 1851        }
 1852
 1853        let text: Arc<str> = text.into();
 1854        let selections = self.selections.all_adjusted(cx);
 1855        let mut edits = Vec::new();
 1856        let mut new_selections = Vec::with_capacity(selections.len());
 1857        let mut new_autoclose_regions = Vec::new();
 1858        let snapshot = self.buffer.read(cx).read(cx);
 1859
 1860        for (selection, autoclose_region) in
 1861            self.selections_with_autoclose_regions(selections, &snapshot)
 1862        {
 1863            if let Some(language) = snapshot.language_at(selection.head()) {
 1864                // Determine if the inserted text matches the opening or closing
 1865                // bracket of any of this language's bracket pairs.
 1866                let mut bracket_pair = None;
 1867                let mut is_bracket_pair_start = false;
 1868                for pair in language.brackets() {
 1869                    if pair.start.ends_with(text.as_ref()) {
 1870                        bracket_pair = Some(pair.clone());
 1871                        is_bracket_pair_start = true;
 1872                        break;
 1873                    } else if pair.end.as_str() == text.as_ref() {
 1874                        bracket_pair = Some(pair.clone());
 1875                        break;
 1876                    }
 1877                }
 1878
 1879                if let Some(bracket_pair) = bracket_pair {
 1880                    if selection.is_empty() {
 1881                        if is_bracket_pair_start {
 1882                            let prefix_len = bracket_pair.start.len() - text.len();
 1883
 1884                            // If the inserted text is a suffix of an opening bracket and the
 1885                            // selection is preceded by the rest of the opening bracket, then
 1886                            // insert the closing bracket.
 1887                            let following_text_allows_autoclose = snapshot
 1888                                .chars_at(selection.start)
 1889                                .next()
 1890                                .map_or(true, |c| language.should_autoclose_before(c));
 1891                            let preceding_text_matches_prefix = prefix_len == 0
 1892                                || (selection.start.column >= (prefix_len as u32)
 1893                                    && snapshot.contains_str_at(
 1894                                        Point::new(
 1895                                            selection.start.row,
 1896                                            selection.start.column - (prefix_len as u32),
 1897                                        ),
 1898                                        &bracket_pair.start[..prefix_len],
 1899                                    ));
 1900                            if following_text_allows_autoclose && preceding_text_matches_prefix {
 1901                                let anchor = snapshot.anchor_before(selection.end);
 1902                                new_selections
 1903                                    .push((selection.map(|_| anchor.clone()), text.len()));
 1904                                new_autoclose_regions.push((
 1905                                    anchor.clone(),
 1906                                    text.len(),
 1907                                    selection.id,
 1908                                    bracket_pair.clone(),
 1909                                ));
 1910                                edits.push((
 1911                                    selection.range(),
 1912                                    format!("{}{}", text, bracket_pair.end).into(),
 1913                                ));
 1914                                continue;
 1915                            }
 1916                        } else if let Some(region) = autoclose_region {
 1917                            // If the selection is followed by an auto-inserted closing bracket,
 1918                            // then don't insert anything else; just move the selection past the
 1919                            // closing bracket.
 1920                            let should_skip = selection.end == region.range.end.to_point(&snapshot);
 1921                            if should_skip {
 1922                                let anchor = snapshot.anchor_after(selection.end);
 1923                                new_selections.push((
 1924                                    selection.map(|_| anchor.clone()),
 1925                                    region.pair.end.len(),
 1926                                ));
 1927                                continue;
 1928                            }
 1929                        }
 1930                    }
 1931                    // If an opening bracket is typed while text is selected, then
 1932                    // surround that text with the bracket pair.
 1933                    else if is_bracket_pair_start {
 1934                        edits.push((selection.start..selection.start, text.clone()));
 1935                        edits.push((
 1936                            selection.end..selection.end,
 1937                            bracket_pair.end.as_str().into(),
 1938                        ));
 1939                        new_selections.push((
 1940                            Selection {
 1941                                id: selection.id,
 1942                                start: snapshot.anchor_after(selection.start),
 1943                                end: snapshot.anchor_before(selection.end),
 1944                                reversed: selection.reversed,
 1945                                goal: selection.goal,
 1946                            },
 1947                            0,
 1948                        ));
 1949                        continue;
 1950                    }
 1951                }
 1952            }
 1953
 1954            // If not handling any auto-close operation, then just replace the selected
 1955            // text with the given input and move the selection to the end of the
 1956            // newly inserted text.
 1957            let anchor = snapshot.anchor_after(selection.end);
 1958            new_selections.push((selection.map(|_| anchor.clone()), 0));
 1959            edits.push((selection.start..selection.end, text.clone()));
 1960        }
 1961
 1962        drop(snapshot);
 1963        self.transact(cx, |this, cx| {
 1964            this.buffer.update(cx, |buffer, cx| {
 1965                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
 1966            });
 1967
 1968            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 1969            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 1970            let snapshot = this.buffer.read(cx).read(cx);
 1971            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
 1972                .zip(new_selection_deltas)
 1973                .map(|(selection, delta)| selection.map(|e| e + delta))
 1974                .collect::<Vec<_>>();
 1975
 1976            let mut i = 0;
 1977            for (position, delta, selection_id, pair) in new_autoclose_regions {
 1978                let position = position.to_offset(&snapshot) + delta;
 1979                let start = snapshot.anchor_before(position);
 1980                let end = snapshot.anchor_after(position);
 1981                while let Some(existing_state) = this.autoclose_regions.get(i) {
 1982                    match existing_state.range.start.cmp(&start, &snapshot) {
 1983                        Ordering::Less => i += 1,
 1984                        Ordering::Greater => break,
 1985                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
 1986                            Ordering::Less => i += 1,
 1987                            Ordering::Equal => break,
 1988                            Ordering::Greater => break,
 1989                        },
 1990                    }
 1991                }
 1992                this.autoclose_regions.insert(
 1993                    i,
 1994                    AutocloseRegion {
 1995                        selection_id,
 1996                        range: start..end,
 1997                        pair,
 1998                    },
 1999                );
 2000            }
 2001
 2002            drop(snapshot);
 2003            this.change_selections(None, cx, |s| s.select(new_selections));
 2004            this.trigger_completion_on_input(&text, cx);
 2005        });
 2006    }
 2007
 2008    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2009        self.transact(cx, |this, cx| {
 2010            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2011                let selections = this.selections.all::<usize>(cx);
 2012
 2013                let buffer = this.buffer.read(cx).snapshot(cx);
 2014                selections
 2015                    .iter()
 2016                    .map(|selection| {
 2017                        let start_point = selection.start.to_point(&buffer);
 2018                        let mut indent = buffer.indent_size_for_line(start_point.row);
 2019                        indent.len = cmp::min(indent.len, start_point.column);
 2020                        let start = selection.start;
 2021                        let end = selection.end;
 2022
 2023                        let mut insert_extra_newline = false;
 2024                        if let Some(language) = buffer.language() {
 2025                            let leading_whitespace_len = buffer
 2026                                .reversed_chars_at(start)
 2027                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2028                                .map(|c| c.len_utf8())
 2029                                .sum::<usize>();
 2030
 2031                            let trailing_whitespace_len = buffer
 2032                                .chars_at(end)
 2033                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2034                                .map(|c| c.len_utf8())
 2035                                .sum::<usize>();
 2036
 2037                            insert_extra_newline = language.brackets().iter().any(|pair| {
 2038                                let pair_start = pair.start.trim_end();
 2039                                let pair_end = pair.end.trim_start();
 2040
 2041                                pair.newline
 2042                                    && buffer
 2043                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
 2044                                    && buffer.contains_str_at(
 2045                                        (start - leading_whitespace_len)
 2046                                            .saturating_sub(pair_start.len()),
 2047                                        pair_start,
 2048                                    )
 2049                            });
 2050                        }
 2051
 2052                        let mut new_text = String::with_capacity(1 + indent.len as usize);
 2053                        new_text.push('\n');
 2054                        new_text.extend(indent.chars());
 2055                        if insert_extra_newline {
 2056                            new_text = new_text.repeat(2);
 2057                        }
 2058
 2059                        let anchor = buffer.anchor_after(end);
 2060                        let new_selection = selection.map(|_| anchor.clone());
 2061                        (
 2062                            (start..end, new_text),
 2063                            (insert_extra_newline, new_selection),
 2064                        )
 2065                    })
 2066                    .unzip()
 2067            };
 2068
 2069            this.edit_with_autoindent(edits, cx);
 2070            let buffer = this.buffer.read(cx).snapshot(cx);
 2071            let new_selections = selection_fixup_info
 2072                .into_iter()
 2073                .map(|(extra_newline_inserted, new_selection)| {
 2074                    let mut cursor = new_selection.end.to_point(&buffer);
 2075                    if extra_newline_inserted {
 2076                        cursor.row -= 1;
 2077                        cursor.column = buffer.line_len(cursor.row);
 2078                    }
 2079                    new_selection.map(|_| cursor)
 2080                })
 2081                .collect();
 2082
 2083            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
 2084        });
 2085    }
 2086
 2087    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 2088        let buffer = self.buffer.read(cx);
 2089        let snapshot = buffer.snapshot(cx);
 2090
 2091        let mut edits = Vec::new();
 2092        let mut rows = Vec::new();
 2093        let mut rows_inserted = 0;
 2094
 2095        for selection in self.selections.all_adjusted(cx) {
 2096            let cursor = selection.head();
 2097            let row = cursor.row;
 2098
 2099            let end_of_line = snapshot
 2100                .clip_point(Point::new(row, snapshot.line_len(row)), Bias::Left)
 2101                .to_point(&snapshot);
 2102
 2103            let newline = "\n".to_string();
 2104            edits.push((end_of_line..end_of_line, newline));
 2105
 2106            rows_inserted += 1;
 2107            rows.push(row + rows_inserted);
 2108        }
 2109
 2110        self.transact(cx, |editor, cx| {
 2111            editor.edit_with_autoindent(edits, cx);
 2112
 2113            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
 2114                let mut index = 0;
 2115                s.move_cursors_with(|map, _, _| {
 2116                    let row = rows[index];
 2117                    index += 1;
 2118
 2119                    let point = Point::new(row, 0);
 2120                    let boundary = map.next_line_boundary(point).1;
 2121                    let clipped = map.clip_point(boundary, Bias::Left);
 2122
 2123                    (clipped, SelectionGoal::None)
 2124                });
 2125            });
 2126        });
 2127    }
 2128
 2129    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2130        let text: Arc<str> = text.into();
 2131        self.transact(cx, |this, cx| {
 2132            let old_selections = this.selections.all_adjusted(cx);
 2133            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 2134                let anchors = {
 2135                    let snapshot = buffer.read(cx);
 2136                    old_selections
 2137                        .iter()
 2138                        .map(|s| {
 2139                            let anchor = snapshot.anchor_after(s.end);
 2140                            s.map(|_| anchor.clone())
 2141                        })
 2142                        .collect::<Vec<_>>()
 2143                };
 2144                buffer.edit(
 2145                    old_selections
 2146                        .iter()
 2147                        .map(|s| (s.start..s.end, text.clone())),
 2148                    Some(AutoindentMode::EachLine),
 2149                    cx,
 2150                );
 2151                anchors
 2152            });
 2153
 2154            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 2155                s.select_anchors(selection_anchors);
 2156            })
 2157        });
 2158    }
 2159
 2160    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2161        if !cx.global::<Settings>().show_completions_on_input {
 2162            return;
 2163        }
 2164
 2165        let selection = self.selections.newest_anchor();
 2166        if self
 2167            .buffer
 2168            .read(cx)
 2169            .is_completion_trigger(selection.head(), text, cx)
 2170        {
 2171            self.show_completions(&ShowCompletions, cx);
 2172        } else {
 2173            self.hide_context_menu(cx);
 2174        }
 2175    }
 2176
 2177    /// If any empty selections is touching the start of its innermost containing autoclose
 2178    /// region, expand it to select the brackets.
 2179    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 2180        let selections = self.selections.all::<usize>(cx);
 2181        let buffer = self.buffer.read(cx).read(cx);
 2182        let mut new_selections = Vec::new();
 2183        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
 2184            if let (Some(region), true) = (region, selection.is_empty()) {
 2185                let mut range = region.range.to_offset(&buffer);
 2186                if selection.start == range.start {
 2187                    if range.start >= region.pair.start.len() {
 2188                        range.start -= region.pair.start.len();
 2189                        if buffer.contains_str_at(range.start, &region.pair.start) {
 2190                            if buffer.contains_str_at(range.end, &region.pair.end) {
 2191                                range.end += region.pair.end.len();
 2192                                selection.start = range.start;
 2193                                selection.end = range.end;
 2194                            }
 2195                        }
 2196                    }
 2197                }
 2198            }
 2199            new_selections.push(selection);
 2200        }
 2201
 2202        drop(buffer);
 2203        self.change_selections(None, cx, |selections| selections.select(new_selections));
 2204    }
 2205
 2206    /// Iterate the given selections, and for each one, find the smallest surrounding
 2207    /// autoclose region. This uses the ordering of the selections and the autoclose
 2208    /// regions to avoid repeated comparisons.
 2209    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 2210        &'a self,
 2211        selections: impl IntoIterator<Item = Selection<D>>,
 2212        buffer: &'a MultiBufferSnapshot,
 2213    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 2214        let mut i = 0;
 2215        let mut regions = self.autoclose_regions.as_slice();
 2216        selections.into_iter().map(move |selection| {
 2217            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 2218
 2219            let mut enclosing = None;
 2220            while let Some(pair_state) = regions.get(i) {
 2221                if pair_state.range.end.to_offset(buffer) < range.start {
 2222                    regions = &regions[i + 1..];
 2223                    i = 0;
 2224                } else if pair_state.range.start.to_offset(buffer) > range.end {
 2225                    break;
 2226                } else if pair_state.selection_id == selection.id {
 2227                    enclosing = Some(pair_state);
 2228                    i += 1;
 2229                }
 2230            }
 2231
 2232            (selection.clone(), enclosing)
 2233        })
 2234    }
 2235
 2236    /// Remove any autoclose regions that no longer contain their selection.
 2237    fn invalidate_autoclose_regions(
 2238        &mut self,
 2239        mut selections: &[Selection<Anchor>],
 2240        buffer: &MultiBufferSnapshot,
 2241    ) {
 2242        self.autoclose_regions.retain(|state| {
 2243            let mut i = 0;
 2244            while let Some(selection) = selections.get(i) {
 2245                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 2246                    selections = &selections[1..];
 2247                    continue;
 2248                }
 2249                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 2250                    break;
 2251                }
 2252                if selection.id == state.selection_id {
 2253                    return true;
 2254                } else {
 2255                    i += 1;
 2256                }
 2257            }
 2258            false
 2259        });
 2260    }
 2261
 2262    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 2263        let offset = position.to_offset(buffer);
 2264        let (word_range, kind) = buffer.surrounding_word(offset);
 2265        if offset > word_range.start && kind == Some(CharKind::Word) {
 2266            Some(
 2267                buffer
 2268                    .text_for_range(word_range.start..offset)
 2269                    .collect::<String>(),
 2270            )
 2271        } else {
 2272            None
 2273        }
 2274    }
 2275
 2276    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 2277        if self.pending_rename.is_some() {
 2278            return;
 2279        }
 2280
 2281        let project = if let Some(project) = self.project.clone() {
 2282            project
 2283        } else {
 2284            return;
 2285        };
 2286
 2287        let position = self.selections.newest_anchor().head();
 2288        let (buffer, buffer_position) = if let Some(output) = self
 2289            .buffer
 2290            .read(cx)
 2291            .text_anchor_for_position(position.clone(), cx)
 2292        {
 2293            output
 2294        } else {
 2295            return;
 2296        };
 2297
 2298        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 2299        let completions = project.update(cx, |project, cx| {
 2300            project.completions(&buffer, buffer_position, cx)
 2301        });
 2302
 2303        let id = post_inc(&mut self.next_completion_id);
 2304        let task = cx.spawn_weak(|this, mut cx| {
 2305            async move {
 2306                let completions = completions.await?;
 2307                if completions.is_empty() {
 2308                    return Ok(());
 2309                }
 2310
 2311                let mut menu = CompletionsMenu {
 2312                    id,
 2313                    initial_position: position,
 2314                    match_candidates: completions
 2315                        .iter()
 2316                        .enumerate()
 2317                        .map(|(id, completion)| {
 2318                            StringMatchCandidate::new(
 2319                                id,
 2320                                completion.label.text[completion.label.filter_range.clone()].into(),
 2321                            )
 2322                        })
 2323                        .collect(),
 2324                    buffer,
 2325                    completions: completions.into(),
 2326                    matches: Vec::new().into(),
 2327                    selected_item: 0,
 2328                    list: Default::default(),
 2329                };
 2330
 2331                menu.filter(query.as_deref(), cx.background()).await;
 2332
 2333                if let Some(this) = this.upgrade(&cx) {
 2334                    this.update(&mut cx, |this, cx| {
 2335                        match this.context_menu.as_ref() {
 2336                            None => {}
 2337                            Some(ContextMenu::Completions(prev_menu)) => {
 2338                                if prev_menu.id > menu.id {
 2339                                    return;
 2340                                }
 2341                            }
 2342                            _ => return,
 2343                        }
 2344
 2345                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
 2346                        if this.focused {
 2347                            this.show_context_menu(ContextMenu::Completions(menu), cx);
 2348                        }
 2349
 2350                        cx.notify();
 2351                    });
 2352                }
 2353                Ok::<_, anyhow::Error>(())
 2354            }
 2355            .log_err()
 2356        });
 2357        self.completion_tasks.push((id, task));
 2358    }
 2359
 2360    pub fn confirm_completion(
 2361        &mut self,
 2362        action: &ConfirmCompletion,
 2363        cx: &mut ViewContext<Self>,
 2364    ) -> Option<Task<Result<()>>> {
 2365        use language::ToOffset as _;
 2366
 2367        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 2368            menu
 2369        } else {
 2370            return None;
 2371        };
 2372
 2373        let mat = completions_menu
 2374            .matches
 2375            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 2376        let buffer_handle = completions_menu.buffer;
 2377        let completion = completions_menu.completions.get(mat.candidate_id)?;
 2378
 2379        let snippet;
 2380        let text;
 2381        if completion.is_snippet() {
 2382            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 2383            text = snippet.as_ref().unwrap().text.clone();
 2384        } else {
 2385            snippet = None;
 2386            text = completion.new_text.clone();
 2387        };
 2388        let selections = self.selections.all::<usize>(cx);
 2389        let buffer = buffer_handle.read(cx);
 2390        let old_range = completion.old_range.to_offset(buffer);
 2391        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 2392
 2393        let newest_selection = self.selections.newest_anchor();
 2394        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
 2395            return None;
 2396        }
 2397
 2398        let lookbehind = newest_selection
 2399            .start
 2400            .text_anchor
 2401            .to_offset(buffer)
 2402            .saturating_sub(old_range.start);
 2403        let lookahead = old_range
 2404            .end
 2405            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 2406        let mut common_prefix_len = old_text
 2407            .bytes()
 2408            .zip(text.bytes())
 2409            .take_while(|(a, b)| a == b)
 2410            .count();
 2411
 2412        let snapshot = self.buffer.read(cx).snapshot(cx);
 2413        let mut ranges = Vec::new();
 2414        for selection in &selections {
 2415            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 2416                let start = selection.start.saturating_sub(lookbehind);
 2417                let end = selection.end + lookahead;
 2418                ranges.push(start + common_prefix_len..end);
 2419            } else {
 2420                common_prefix_len = 0;
 2421                ranges.clear();
 2422                ranges.extend(selections.iter().map(|s| {
 2423                    if s.id == newest_selection.id {
 2424                        old_range.clone()
 2425                    } else {
 2426                        s.start..s.end
 2427                    }
 2428                }));
 2429                break;
 2430            }
 2431        }
 2432        let text = &text[common_prefix_len..];
 2433
 2434        self.transact(cx, |this, cx| {
 2435            if let Some(mut snippet) = snippet {
 2436                snippet.text = text.to_string();
 2437                for tabstop in snippet.tabstops.iter_mut().flatten() {
 2438                    tabstop.start -= common_prefix_len as isize;
 2439                    tabstop.end -= common_prefix_len as isize;
 2440                }
 2441
 2442                this.insert_snippet(&ranges, snippet, cx).log_err();
 2443            } else {
 2444                this.buffer.update(cx, |buffer, cx| {
 2445                    buffer.edit(
 2446                        ranges.iter().map(|range| (range.clone(), text)),
 2447                        Some(AutoindentMode::EachLine),
 2448                        cx,
 2449                    );
 2450                });
 2451            }
 2452        });
 2453
 2454        let project = self.project.clone()?;
 2455        let apply_edits = project.update(cx, |project, cx| {
 2456            project.apply_additional_edits_for_completion(
 2457                buffer_handle,
 2458                completion.clone(),
 2459                true,
 2460                cx,
 2461            )
 2462        });
 2463        Some(cx.foreground().spawn(async move {
 2464            apply_edits.await?;
 2465            Ok(())
 2466        }))
 2467    }
 2468
 2469    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 2470        if matches!(
 2471            self.context_menu.as_ref(),
 2472            Some(ContextMenu::CodeActions(_))
 2473        ) {
 2474            self.context_menu.take();
 2475            cx.notify();
 2476            return;
 2477        }
 2478
 2479        let deployed_from_indicator = action.deployed_from_indicator;
 2480        let mut task = self.code_actions_task.take();
 2481        cx.spawn_weak(|this, mut cx| async move {
 2482            while let Some(prev_task) = task {
 2483                prev_task.await;
 2484                task = this
 2485                    .upgrade(&cx)
 2486                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
 2487            }
 2488
 2489            if let Some(this) = this.upgrade(&cx) {
 2490                this.update(&mut cx, |this, cx| {
 2491                    if this.focused {
 2492                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
 2493                            this.show_context_menu(
 2494                                ContextMenu::CodeActions(CodeActionsMenu {
 2495                                    buffer,
 2496                                    actions,
 2497                                    selected_item: Default::default(),
 2498                                    list: Default::default(),
 2499                                    deployed_from_indicator,
 2500                                }),
 2501                                cx,
 2502                            );
 2503                        }
 2504                    }
 2505                })
 2506            }
 2507            Ok::<_, anyhow::Error>(())
 2508        })
 2509        .detach_and_log_err(cx);
 2510    }
 2511
 2512    pub fn confirm_code_action(
 2513        workspace: &mut Workspace,
 2514        action: &ConfirmCodeAction,
 2515        cx: &mut ViewContext<Workspace>,
 2516    ) -> Option<Task<Result<()>>> {
 2517        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 2518        let actions_menu = if let ContextMenu::CodeActions(menu) =
 2519            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
 2520        {
 2521            menu
 2522        } else {
 2523            return None;
 2524        };
 2525        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 2526        let action = actions_menu.actions.get(action_ix)?.clone();
 2527        let title = action.lsp_action.title.clone();
 2528        let buffer = actions_menu.buffer;
 2529
 2530        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
 2531            project.apply_code_action(buffer, action, true, cx)
 2532        });
 2533        Some(cx.spawn(|workspace, cx| async move {
 2534            let project_transaction = apply_code_actions.await?;
 2535            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
 2536        }))
 2537    }
 2538
 2539    async fn open_project_transaction(
 2540        this: ViewHandle<Editor>,
 2541        workspace: ViewHandle<Workspace>,
 2542        transaction: ProjectTransaction,
 2543        title: String,
 2544        mut cx: AsyncAppContext,
 2545    ) -> Result<()> {
 2546        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
 2547
 2548        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 2549        entries.sort_unstable_by_key(|(buffer, _)| {
 2550            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
 2551        });
 2552
 2553        // If the project transaction's edits are all contained within this editor, then
 2554        // avoid opening a new editor to display them.
 2555
 2556        if let Some((buffer, transaction)) = entries.first() {
 2557            if entries.len() == 1 {
 2558                let excerpt = this.read_with(&cx, |editor, cx| {
 2559                    editor
 2560                        .buffer()
 2561                        .read(cx)
 2562                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 2563                });
 2564                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 2565                    if excerpted_buffer == *buffer {
 2566                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 2567                            let excerpt_range = excerpt_range.to_offset(buffer);
 2568                            buffer
 2569                                .edited_ranges_for_transaction(transaction)
 2570                                .all(|range| {
 2571                                    excerpt_range.start <= range.start
 2572                                        && excerpt_range.end >= range.end
 2573                                })
 2574                        });
 2575
 2576                        if all_edits_within_excerpt {
 2577                            return Ok(());
 2578                        }
 2579                    }
 2580                }
 2581            }
 2582        } else {
 2583            return Ok(());
 2584        }
 2585
 2586        let mut ranges_to_highlight = Vec::new();
 2587        let excerpt_buffer = cx.add_model(|cx| {
 2588            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
 2589            for (buffer_handle, transaction) in &entries {
 2590                let buffer = buffer_handle.read(cx);
 2591                ranges_to_highlight.extend(
 2592                    multibuffer.push_excerpts_with_context_lines(
 2593                        buffer_handle.clone(),
 2594                        buffer
 2595                            .edited_ranges_for_transaction::<usize>(transaction)
 2596                            .collect(),
 2597                        1,
 2598                        cx,
 2599                    ),
 2600                );
 2601            }
 2602            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
 2603            multibuffer
 2604        });
 2605
 2606        workspace.update(&mut cx, |workspace, cx| {
 2607            let project = workspace.project().clone();
 2608            let editor =
 2609                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 2610            workspace.add_item(Box::new(editor.clone()), cx);
 2611            editor.update(cx, |editor, cx| {
 2612                editor.highlight_background::<Self>(
 2613                    ranges_to_highlight,
 2614                    |theme| theme.editor.highlighted_line_background,
 2615                    cx,
 2616                );
 2617            });
 2618        });
 2619
 2620        Ok(())
 2621    }
 2622
 2623    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2624        let project = self.project.as_ref()?;
 2625        let buffer = self.buffer.read(cx);
 2626        let newest_selection = self.selections.newest_anchor().clone();
 2627        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 2628        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 2629        if start_buffer != end_buffer {
 2630            return None;
 2631        }
 2632
 2633        let actions = project.update(cx, |project, cx| {
 2634            project.code_actions(&start_buffer, start..end, cx)
 2635        });
 2636        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2637            let actions = actions.await;
 2638            if let Some(this) = this.upgrade(&cx) {
 2639                this.update(&mut cx, |this, cx| {
 2640                    this.available_code_actions = actions.log_err().and_then(|actions| {
 2641                        if actions.is_empty() {
 2642                            None
 2643                        } else {
 2644                            Some((start_buffer, actions.into()))
 2645                        }
 2646                    });
 2647                    cx.notify();
 2648                })
 2649            }
 2650        }));
 2651        None
 2652    }
 2653
 2654    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2655        if self.pending_rename.is_some() {
 2656            return None;
 2657        }
 2658
 2659        let project = self.project.as_ref()?;
 2660        let buffer = self.buffer.read(cx);
 2661        let newest_selection = self.selections.newest_anchor().clone();
 2662        let cursor_position = newest_selection.head();
 2663        let (cursor_buffer, cursor_buffer_position) =
 2664            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 2665        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 2666        if cursor_buffer != tail_buffer {
 2667            return None;
 2668        }
 2669
 2670        let highlights = project.update(cx, |project, cx| {
 2671            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 2672        });
 2673
 2674        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2675            let highlights = highlights.log_err().await;
 2676            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
 2677                this.update(&mut cx, |this, cx| {
 2678                    if this.pending_rename.is_some() {
 2679                        return;
 2680                    }
 2681
 2682                    let buffer_id = cursor_position.buffer_id;
 2683                    let buffer = this.buffer.read(cx);
 2684                    if !buffer
 2685                        .text_anchor_for_position(cursor_position, cx)
 2686                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 2687                    {
 2688                        return;
 2689                    }
 2690
 2691                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 2692                    let mut write_ranges = Vec::new();
 2693                    let mut read_ranges = Vec::new();
 2694                    for highlight in highlights {
 2695                        for (excerpt_id, excerpt_range) in
 2696                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 2697                        {
 2698                            let start = highlight
 2699                                .range
 2700                                .start
 2701                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 2702                            let end = highlight
 2703                                .range
 2704                                .end
 2705                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 2706                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 2707                                continue;
 2708                            }
 2709
 2710                            let range = Anchor {
 2711                                buffer_id,
 2712                                excerpt_id: excerpt_id.clone(),
 2713                                text_anchor: start,
 2714                            }..Anchor {
 2715                                buffer_id,
 2716                                excerpt_id,
 2717                                text_anchor: end,
 2718                            };
 2719                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 2720                                write_ranges.push(range);
 2721                            } else {
 2722                                read_ranges.push(range);
 2723                            }
 2724                        }
 2725                    }
 2726
 2727                    this.highlight_background::<DocumentHighlightRead>(
 2728                        read_ranges,
 2729                        |theme| theme.editor.document_highlight_read_background,
 2730                        cx,
 2731                    );
 2732                    this.highlight_background::<DocumentHighlightWrite>(
 2733                        write_ranges,
 2734                        |theme| theme.editor.document_highlight_write_background,
 2735                        cx,
 2736                    );
 2737                    cx.notify();
 2738                });
 2739            }
 2740        }));
 2741        None
 2742    }
 2743
 2744    pub fn render_code_actions_indicator(
 2745        &self,
 2746        style: &EditorStyle,
 2747        cx: &mut RenderContext<Self>,
 2748    ) -> Option<ElementBox> {
 2749        if self.available_code_actions.is_some() {
 2750            enum Tag {}
 2751            Some(
 2752                MouseEventHandler::<Tag>::new(0, cx, |_, _| {
 2753                    Svg::new("icons/bolt_8.svg")
 2754                        .with_color(style.code_actions.indicator)
 2755                        .boxed()
 2756                })
 2757                .with_cursor_style(CursorStyle::PointingHand)
 2758                .with_padding(Padding::uniform(3.))
 2759                .on_down(MouseButton::Left, |_, cx| {
 2760                    cx.dispatch_action(ToggleCodeActions {
 2761                        deployed_from_indicator: true,
 2762                    });
 2763                })
 2764                .boxed(),
 2765            )
 2766        } else {
 2767            None
 2768        }
 2769    }
 2770
 2771    pub fn context_menu_visible(&self) -> bool {
 2772        self.context_menu
 2773            .as_ref()
 2774            .map_or(false, |menu| menu.visible())
 2775    }
 2776
 2777    pub fn render_context_menu(
 2778        &self,
 2779        cursor_position: DisplayPoint,
 2780        style: EditorStyle,
 2781        cx: &mut RenderContext<Editor>,
 2782    ) -> Option<(DisplayPoint, ElementBox)> {
 2783        self.context_menu
 2784            .as_ref()
 2785            .map(|menu| menu.render(cursor_position, style, cx))
 2786    }
 2787
 2788    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
 2789        if !matches!(menu, ContextMenu::Completions(_)) {
 2790            self.completion_tasks.clear();
 2791        }
 2792        self.context_menu = Some(menu);
 2793        cx.notify();
 2794    }
 2795
 2796    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 2797        cx.notify();
 2798        self.completion_tasks.clear();
 2799        self.context_menu.take()
 2800    }
 2801
 2802    pub fn insert_snippet(
 2803        &mut self,
 2804        insertion_ranges: &[Range<usize>],
 2805        snippet: Snippet,
 2806        cx: &mut ViewContext<Self>,
 2807    ) -> Result<()> {
 2808        let tabstops = self.buffer.update(cx, |buffer, cx| {
 2809            let snippet_text: Arc<str> = snippet.text.clone().into();
 2810            buffer.edit(
 2811                insertion_ranges
 2812                    .iter()
 2813                    .cloned()
 2814                    .map(|range| (range, snippet_text.clone())),
 2815                Some(AutoindentMode::EachLine),
 2816                cx,
 2817            );
 2818
 2819            let snapshot = &*buffer.read(cx);
 2820            let snippet = &snippet;
 2821            snippet
 2822                .tabstops
 2823                .iter()
 2824                .map(|tabstop| {
 2825                    let mut tabstop_ranges = tabstop
 2826                        .iter()
 2827                        .flat_map(|tabstop_range| {
 2828                            let mut delta = 0_isize;
 2829                            insertion_ranges.iter().map(move |insertion_range| {
 2830                                let insertion_start = insertion_range.start as isize + delta;
 2831                                delta +=
 2832                                    snippet.text.len() as isize - insertion_range.len() as isize;
 2833
 2834                                let start = snapshot.anchor_before(
 2835                                    (insertion_start + tabstop_range.start) as usize,
 2836                                );
 2837                                let end = snapshot
 2838                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 2839                                start..end
 2840                            })
 2841                        })
 2842                        .collect::<Vec<_>>();
 2843                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 2844                    tabstop_ranges
 2845                })
 2846                .collect::<Vec<_>>()
 2847        });
 2848
 2849        if let Some(tabstop) = tabstops.first() {
 2850            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 2851                s.select_ranges(tabstop.iter().cloned());
 2852            });
 2853            self.snippet_stack.push(SnippetState {
 2854                active_index: 0,
 2855                ranges: tabstops,
 2856            });
 2857        }
 2858
 2859        Ok(())
 2860    }
 2861
 2862    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 2863        self.move_to_snippet_tabstop(Bias::Right, cx)
 2864    }
 2865
 2866    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 2867        self.move_to_snippet_tabstop(Bias::Left, cx)
 2868    }
 2869
 2870    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 2871        if let Some(mut snippet) = self.snippet_stack.pop() {
 2872            match bias {
 2873                Bias::Left => {
 2874                    if snippet.active_index > 0 {
 2875                        snippet.active_index -= 1;
 2876                    } else {
 2877                        self.snippet_stack.push(snippet);
 2878                        return false;
 2879                    }
 2880                }
 2881                Bias::Right => {
 2882                    if snippet.active_index + 1 < snippet.ranges.len() {
 2883                        snippet.active_index += 1;
 2884                    } else {
 2885                        self.snippet_stack.push(snippet);
 2886                        return false;
 2887                    }
 2888                }
 2889            }
 2890            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 2891                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 2892                    s.select_anchor_ranges(current_ranges.iter().cloned())
 2893                });
 2894                // If snippet state is not at the last tabstop, push it back on the stack
 2895                if snippet.active_index + 1 < snippet.ranges.len() {
 2896                    self.snippet_stack.push(snippet);
 2897                }
 2898                return true;
 2899            }
 2900        }
 2901
 2902        false
 2903    }
 2904
 2905    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 2906        self.transact(cx, |this, cx| {
 2907            this.select_all(&SelectAll, cx);
 2908            this.insert("", cx);
 2909        });
 2910    }
 2911
 2912    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 2913        self.transact(cx, |this, cx| {
 2914            this.select_autoclose_pair(cx);
 2915            let mut selections = this.selections.all::<Point>(cx);
 2916            if !this.selections.line_mode {
 2917                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 2918                for selection in &mut selections {
 2919                    if selection.is_empty() {
 2920                        let old_head = selection.head();
 2921                        let mut new_head =
 2922                            movement::left(&display_map, old_head.to_display_point(&display_map))
 2923                                .to_point(&display_map);
 2924                        if let Some((buffer, line_buffer_range)) = display_map
 2925                            .buffer_snapshot
 2926                            .buffer_line_for_row(old_head.row)
 2927                        {
 2928                            let indent_size =
 2929                                buffer.indent_size_for_line(line_buffer_range.start.row);
 2930                            let language_name = buffer.language().map(|language| language.name());
 2931                            let indent_len = match indent_size.kind {
 2932                                IndentKind::Space => {
 2933                                    cx.global::<Settings>().tab_size(language_name.as_deref())
 2934                                }
 2935                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 2936                            };
 2937                            if old_head.column <= indent_size.len && old_head.column > 0 {
 2938                                let indent_len = indent_len.get();
 2939                                new_head = cmp::min(
 2940                                    new_head,
 2941                                    Point::new(
 2942                                        old_head.row,
 2943                                        ((old_head.column - 1) / indent_len) * indent_len,
 2944                                    ),
 2945                                );
 2946                            }
 2947                        }
 2948
 2949                        selection.set_head(new_head, SelectionGoal::None);
 2950                    }
 2951                }
 2952            }
 2953
 2954            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 2955            this.insert("", cx);
 2956        });
 2957    }
 2958
 2959    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 2960        self.transact(cx, |this, cx| {
 2961            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 2962                let line_mode = s.line_mode;
 2963                s.move_with(|map, selection| {
 2964                    if selection.is_empty() && !line_mode {
 2965                        let cursor = movement::right(map, selection.head());
 2966                        selection.set_head(cursor, SelectionGoal::None);
 2967                    }
 2968                })
 2969            });
 2970            this.insert("", cx);
 2971        });
 2972    }
 2973
 2974    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 2975        if self.move_to_prev_snippet_tabstop(cx) {
 2976            return;
 2977        }
 2978
 2979        self.outdent(&Outdent, cx);
 2980    }
 2981
 2982    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 2983        if self.move_to_next_snippet_tabstop(cx) {
 2984            return;
 2985        }
 2986
 2987        let mut selections = self.selections.all_adjusted(cx);
 2988        let buffer = self.buffer.read(cx);
 2989        let snapshot = buffer.snapshot(cx);
 2990        let rows_iter = selections.iter().map(|s| s.head().row);
 2991        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 2992
 2993        let mut edits = Vec::new();
 2994        let mut prev_edited_row = 0;
 2995        let mut row_delta = 0;
 2996        for selection in &mut selections {
 2997            if selection.start.row != prev_edited_row {
 2998                row_delta = 0;
 2999            }
 3000            prev_edited_row = selection.end.row;
 3001
 3002            // If the selection is non-empty, then increase the indentation of the selected lines.
 3003            if !selection.is_empty() {
 3004                row_delta =
 3005                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 3006                continue;
 3007            }
 3008
 3009            // If the selection is empty and the cursor is in the leading whitespace before the
 3010            // suggested indentation, then auto-indent the line.
 3011            let cursor = selection.head();
 3012            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 3013                let current_indent = snapshot.indent_size_for_line(cursor.row);
 3014                if cursor.column < suggested_indent.len
 3015                    && cursor.column <= current_indent.len
 3016                    && current_indent.len <= suggested_indent.len
 3017                {
 3018                    selection.start = Point::new(cursor.row, suggested_indent.len);
 3019                    selection.end = selection.start;
 3020                    if row_delta == 0 {
 3021                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 3022                            cursor.row,
 3023                            current_indent,
 3024                            suggested_indent,
 3025                        ));
 3026                        row_delta = suggested_indent.len - current_indent.len;
 3027                    }
 3028                    continue;
 3029                }
 3030            }
 3031
 3032            // Otherwise, insert a hard or soft tab.
 3033            let settings = cx.global::<Settings>();
 3034            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
 3035            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
 3036                IndentSize::tab()
 3037            } else {
 3038                let tab_size = settings.tab_size(language_name.as_deref()).get();
 3039                let char_column = snapshot
 3040                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 3041                    .flat_map(str::chars)
 3042                    .count()
 3043                    + row_delta as usize;
 3044                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 3045                IndentSize::spaces(chars_to_next_tab_stop)
 3046            };
 3047            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 3048            selection.end = selection.start;
 3049            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 3050            row_delta += tab_size.len;
 3051        }
 3052
 3053        self.transact(cx, |this, cx| {
 3054            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 3055            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections))
 3056        });
 3057    }
 3058
 3059    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 3060        let mut selections = self.selections.all::<Point>(cx);
 3061        let mut prev_edited_row = 0;
 3062        let mut row_delta = 0;
 3063        let mut edits = Vec::new();
 3064        let buffer = self.buffer.read(cx);
 3065        let snapshot = buffer.snapshot(cx);
 3066        for selection in &mut selections {
 3067            if selection.start.row != prev_edited_row {
 3068                row_delta = 0;
 3069            }
 3070            prev_edited_row = selection.end.row;
 3071
 3072            row_delta =
 3073                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 3074        }
 3075
 3076        self.transact(cx, |this, cx| {
 3077            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 3078            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3079        });
 3080    }
 3081
 3082    fn indent_selection(
 3083        buffer: &MultiBuffer,
 3084        snapshot: &MultiBufferSnapshot,
 3085        selection: &mut Selection<Point>,
 3086        edits: &mut Vec<(Range<Point>, String)>,
 3087        delta_for_start_row: u32,
 3088        cx: &AppContext,
 3089    ) -> u32 {
 3090        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 3091        let settings = cx.global::<Settings>();
 3092        let tab_size = settings.tab_size(language_name.as_deref()).get();
 3093        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
 3094            IndentKind::Tab
 3095        } else {
 3096            IndentKind::Space
 3097        };
 3098        let mut start_row = selection.start.row;
 3099        let mut end_row = selection.end.row + 1;
 3100
 3101        // If a selection ends at the beginning of a line, don't indent
 3102        // that last line.
 3103        if selection.end.column == 0 {
 3104            end_row -= 1;
 3105        }
 3106
 3107        // Avoid re-indenting a row that has already been indented by a
 3108        // previous selection, but still update this selection's column
 3109        // to reflect that indentation.
 3110        if delta_for_start_row > 0 {
 3111            start_row += 1;
 3112            selection.start.column += delta_for_start_row;
 3113            if selection.end.row == selection.start.row {
 3114                selection.end.column += delta_for_start_row;
 3115            }
 3116        }
 3117
 3118        let mut delta_for_end_row = 0;
 3119        for row in start_row..end_row {
 3120            let current_indent = snapshot.indent_size_for_line(row);
 3121            let indent_delta = match (current_indent.kind, indent_kind) {
 3122                (IndentKind::Space, IndentKind::Space) => {
 3123                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 3124                    IndentSize::spaces(columns_to_next_tab_stop)
 3125                }
 3126                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 3127                (_, IndentKind::Tab) => IndentSize::tab(),
 3128            };
 3129
 3130            let row_start = Point::new(row, 0);
 3131            edits.push((
 3132                row_start..row_start,
 3133                indent_delta.chars().collect::<String>(),
 3134            ));
 3135
 3136            // Update this selection's endpoints to reflect the indentation.
 3137            if row == selection.start.row {
 3138                selection.start.column += indent_delta.len;
 3139            }
 3140            if row == selection.end.row {
 3141                selection.end.column += indent_delta.len;
 3142                delta_for_end_row = indent_delta.len;
 3143            }
 3144        }
 3145
 3146        if selection.start.row == selection.end.row {
 3147            delta_for_start_row + delta_for_end_row
 3148        } else {
 3149            delta_for_end_row
 3150        }
 3151    }
 3152
 3153    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 3154        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3155        let selections = self.selections.all::<Point>(cx);
 3156        let mut deletion_ranges = Vec::new();
 3157        let mut last_outdent = None;
 3158        {
 3159            let buffer = self.buffer.read(cx);
 3160            let snapshot = buffer.snapshot(cx);
 3161            for selection in &selections {
 3162                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 3163                let tab_size = cx
 3164                    .global::<Settings>()
 3165                    .tab_size(language_name.as_deref())
 3166                    .get();
 3167                let mut rows = selection.spanned_rows(false, &display_map);
 3168
 3169                // Avoid re-outdenting a row that has already been outdented by a
 3170                // previous selection.
 3171                if let Some(last_row) = last_outdent {
 3172                    if last_row == rows.start {
 3173                        rows.start += 1;
 3174                    }
 3175                }
 3176
 3177                for row in rows {
 3178                    let indent_size = snapshot.indent_size_for_line(row);
 3179                    if indent_size.len > 0 {
 3180                        let deletion_len = match indent_size.kind {
 3181                            IndentKind::Space => {
 3182                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 3183                                if columns_to_prev_tab_stop == 0 {
 3184                                    tab_size
 3185                                } else {
 3186                                    columns_to_prev_tab_stop
 3187                                }
 3188                            }
 3189                            IndentKind::Tab => 1,
 3190                        };
 3191                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 3192                        last_outdent = Some(row);
 3193                    }
 3194                }
 3195            }
 3196        }
 3197
 3198        self.transact(cx, |this, cx| {
 3199            this.buffer.update(cx, |buffer, cx| {
 3200                let empty_str: Arc<str> = "".into();
 3201                buffer.edit(
 3202                    deletion_ranges
 3203                        .into_iter()
 3204                        .map(|range| (range, empty_str.clone())),
 3205                    None,
 3206                    cx,
 3207                );
 3208            });
 3209            let selections = this.selections.all::<usize>(cx);
 3210            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3211        });
 3212    }
 3213
 3214    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 3215        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3216        let selections = self.selections.all::<Point>(cx);
 3217
 3218        let mut new_cursors = Vec::new();
 3219        let mut edit_ranges = Vec::new();
 3220        let mut selections = selections.iter().peekable();
 3221        while let Some(selection) = selections.next() {
 3222            let mut rows = selection.spanned_rows(false, &display_map);
 3223            let goal_display_column = selection.head().to_display_point(&display_map).column();
 3224
 3225            // Accumulate contiguous regions of rows that we want to delete.
 3226            while let Some(next_selection) = selections.peek() {
 3227                let next_rows = next_selection.spanned_rows(false, &display_map);
 3228                if next_rows.start <= rows.end {
 3229                    rows.end = next_rows.end;
 3230                    selections.next().unwrap();
 3231                } else {
 3232                    break;
 3233                }
 3234            }
 3235
 3236            let buffer = &display_map.buffer_snapshot;
 3237            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 3238            let edit_end;
 3239            let cursor_buffer_row;
 3240            if buffer.max_point().row >= rows.end {
 3241                // If there's a line after the range, delete the \n from the end of the row range
 3242                // and position the cursor on the next line.
 3243                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 3244                cursor_buffer_row = rows.end;
 3245            } else {
 3246                // If there isn't a line after the range, delete the \n from the line before the
 3247                // start of the row range and position the cursor there.
 3248                edit_start = edit_start.saturating_sub(1);
 3249                edit_end = buffer.len();
 3250                cursor_buffer_row = rows.start.saturating_sub(1);
 3251            }
 3252
 3253            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 3254            *cursor.column_mut() =
 3255                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 3256
 3257            new_cursors.push((
 3258                selection.id,
 3259                buffer.anchor_after(cursor.to_point(&display_map)),
 3260            ));
 3261            edit_ranges.push(edit_start..edit_end);
 3262        }
 3263
 3264        self.transact(cx, |this, cx| {
 3265            let buffer = this.buffer.update(cx, |buffer, cx| {
 3266                let empty_str: Arc<str> = "".into();
 3267                buffer.edit(
 3268                    edit_ranges
 3269                        .into_iter()
 3270                        .map(|range| (range, empty_str.clone())),
 3271                    None,
 3272                    cx,
 3273                );
 3274                buffer.snapshot(cx)
 3275            });
 3276            let new_selections = new_cursors
 3277                .into_iter()
 3278                .map(|(id, cursor)| {
 3279                    let cursor = cursor.to_point(&buffer);
 3280                    Selection {
 3281                        id,
 3282                        start: cursor,
 3283                        end: cursor,
 3284                        reversed: false,
 3285                        goal: SelectionGoal::None,
 3286                    }
 3287                })
 3288                .collect();
 3289
 3290            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3291                s.select(new_selections);
 3292            });
 3293        });
 3294    }
 3295
 3296    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 3297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3298        let buffer = &display_map.buffer_snapshot;
 3299        let selections = self.selections.all::<Point>(cx);
 3300
 3301        let mut edits = Vec::new();
 3302        let mut selections_iter = selections.iter().peekable();
 3303        while let Some(selection) = selections_iter.next() {
 3304            // Avoid duplicating the same lines twice.
 3305            let mut rows = selection.spanned_rows(false, &display_map);
 3306
 3307            while let Some(next_selection) = selections_iter.peek() {
 3308                let next_rows = next_selection.spanned_rows(false, &display_map);
 3309                if next_rows.start < rows.end {
 3310                    rows.end = next_rows.end;
 3311                    selections_iter.next().unwrap();
 3312                } else {
 3313                    break;
 3314                }
 3315            }
 3316
 3317            // Copy the text from the selected row region and splice it at the start of the region.
 3318            let start = Point::new(rows.start, 0);
 3319            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 3320            let text = buffer
 3321                .text_for_range(start..end)
 3322                .chain(Some("\n"))
 3323                .collect::<String>();
 3324            edits.push((start..start, text));
 3325        }
 3326
 3327        self.transact(cx, |this, cx| {
 3328            this.buffer.update(cx, |buffer, cx| {
 3329                buffer.edit(edits, None, cx);
 3330            });
 3331
 3332            this.request_autoscroll(Autoscroll::Fit, cx);
 3333        });
 3334    }
 3335
 3336    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 3337        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3338        let buffer = self.buffer.read(cx).snapshot(cx);
 3339
 3340        let mut edits = Vec::new();
 3341        let mut unfold_ranges = Vec::new();
 3342        let mut refold_ranges = Vec::new();
 3343
 3344        let selections = self.selections.all::<Point>(cx);
 3345        let mut selections = selections.iter().peekable();
 3346        let mut contiguous_row_selections = Vec::new();
 3347        let mut new_selections = Vec::new();
 3348
 3349        while let Some(selection) = selections.next() {
 3350            // Find all the selections that span a contiguous row range
 3351            contiguous_row_selections.push(selection.clone());
 3352            let start_row = selection.start.row;
 3353            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3354                display_map.next_line_boundary(selection.end).0.row + 1
 3355            } else {
 3356                selection.end.row
 3357            };
 3358
 3359            while let Some(next_selection) = selections.peek() {
 3360                if next_selection.start.row <= end_row {
 3361                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3362                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3363                    } else {
 3364                        next_selection.end.row
 3365                    };
 3366                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3367                } else {
 3368                    break;
 3369                }
 3370            }
 3371
 3372            // Move the text spanned by the row range to be before the line preceding the row range
 3373            if start_row > 0 {
 3374                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 3375                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 3376                let insertion_point = display_map
 3377                    .prev_line_boundary(Point::new(start_row - 1, 0))
 3378                    .0;
 3379
 3380                // Don't move lines across excerpts
 3381                if buffer
 3382                    .excerpt_boundaries_in_range((
 3383                        Bound::Excluded(insertion_point),
 3384                        Bound::Included(range_to_move.end),
 3385                    ))
 3386                    .next()
 3387                    .is_none()
 3388                {
 3389                    let text = buffer
 3390                        .text_for_range(range_to_move.clone())
 3391                        .flat_map(|s| s.chars())
 3392                        .skip(1)
 3393                        .chain(['\n'])
 3394                        .collect::<String>();
 3395
 3396                    edits.push((
 3397                        buffer.anchor_after(range_to_move.start)
 3398                            ..buffer.anchor_before(range_to_move.end),
 3399                        String::new(),
 3400                    ));
 3401                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3402                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3403
 3404                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 3405
 3406                    // Move selections up
 3407                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3408                        |mut selection| {
 3409                            selection.start.row -= row_delta;
 3410                            selection.end.row -= row_delta;
 3411                            selection
 3412                        },
 3413                    ));
 3414
 3415                    // Move folds up
 3416                    unfold_ranges.push(range_to_move.clone());
 3417                    for fold in display_map.folds_in_range(
 3418                        buffer.anchor_before(range_to_move.start)
 3419                            ..buffer.anchor_after(range_to_move.end),
 3420                    ) {
 3421                        let mut start = fold.start.to_point(&buffer);
 3422                        let mut end = fold.end.to_point(&buffer);
 3423                        start.row -= row_delta;
 3424                        end.row -= row_delta;
 3425                        refold_ranges.push(start..end);
 3426                    }
 3427                }
 3428            }
 3429
 3430            // If we didn't move line(s), preserve the existing selections
 3431            new_selections.append(&mut contiguous_row_selections);
 3432        }
 3433
 3434        self.transact(cx, |this, cx| {
 3435            this.unfold_ranges(unfold_ranges, true, cx);
 3436            this.buffer.update(cx, |buffer, cx| {
 3437                for (range, text) in edits {
 3438                    buffer.edit([(range, text)], None, cx);
 3439                }
 3440            });
 3441            this.fold_ranges(refold_ranges, cx);
 3442            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3443                s.select(new_selections);
 3444            })
 3445        });
 3446    }
 3447
 3448    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 3449        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3450        let buffer = self.buffer.read(cx).snapshot(cx);
 3451
 3452        let mut edits = Vec::new();
 3453        let mut unfold_ranges = Vec::new();
 3454        let mut refold_ranges = Vec::new();
 3455
 3456        let selections = self.selections.all::<Point>(cx);
 3457        let mut selections = selections.iter().peekable();
 3458        let mut contiguous_row_selections = Vec::new();
 3459        let mut new_selections = Vec::new();
 3460
 3461        while let Some(selection) = selections.next() {
 3462            // Find all the selections that span a contiguous row range
 3463            contiguous_row_selections.push(selection.clone());
 3464            let start_row = selection.start.row;
 3465            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3466                display_map.next_line_boundary(selection.end).0.row + 1
 3467            } else {
 3468                selection.end.row
 3469            };
 3470
 3471            while let Some(next_selection) = selections.peek() {
 3472                if next_selection.start.row <= end_row {
 3473                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3474                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3475                    } else {
 3476                        next_selection.end.row
 3477                    };
 3478                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3479                } else {
 3480                    break;
 3481                }
 3482            }
 3483
 3484            // Move the text spanned by the row range to be after the last line of the row range
 3485            if end_row <= buffer.max_point().row {
 3486                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 3487                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 3488
 3489                // Don't move lines across excerpt boundaries
 3490                if buffer
 3491                    .excerpt_boundaries_in_range((
 3492                        Bound::Excluded(range_to_move.start),
 3493                        Bound::Included(insertion_point),
 3494                    ))
 3495                    .next()
 3496                    .is_none()
 3497                {
 3498                    let mut text = String::from("\n");
 3499                    text.extend(buffer.text_for_range(range_to_move.clone()));
 3500                    text.pop(); // Drop trailing newline
 3501                    edits.push((
 3502                        buffer.anchor_after(range_to_move.start)
 3503                            ..buffer.anchor_before(range_to_move.end),
 3504                        String::new(),
 3505                    ));
 3506                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3507                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3508
 3509                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 3510
 3511                    // Move selections down
 3512                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3513                        |mut selection| {
 3514                            selection.start.row += row_delta;
 3515                            selection.end.row += row_delta;
 3516                            selection
 3517                        },
 3518                    ));
 3519
 3520                    // Move folds down
 3521                    unfold_ranges.push(range_to_move.clone());
 3522                    for fold in display_map.folds_in_range(
 3523                        buffer.anchor_before(range_to_move.start)
 3524                            ..buffer.anchor_after(range_to_move.end),
 3525                    ) {
 3526                        let mut start = fold.start.to_point(&buffer);
 3527                        let mut end = fold.end.to_point(&buffer);
 3528                        start.row += row_delta;
 3529                        end.row += row_delta;
 3530                        refold_ranges.push(start..end);
 3531                    }
 3532                }
 3533            }
 3534
 3535            // If we didn't move line(s), preserve the existing selections
 3536            new_selections.append(&mut contiguous_row_selections);
 3537        }
 3538
 3539        self.transact(cx, |this, cx| {
 3540            this.unfold_ranges(unfold_ranges, true, cx);
 3541            this.buffer.update(cx, |buffer, cx| {
 3542                for (range, text) in edits {
 3543                    buffer.edit([(range, text)], None, cx);
 3544                }
 3545            });
 3546            this.fold_ranges(refold_ranges, cx);
 3547            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
 3548        });
 3549    }
 3550
 3551    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 3552        self.transact(cx, |this, cx| {
 3553            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3554                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 3555                let line_mode = s.line_mode;
 3556                s.move_with(|display_map, selection| {
 3557                    if !selection.is_empty() || line_mode {
 3558                        return;
 3559                    }
 3560
 3561                    let mut head = selection.head();
 3562                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 3563                    if head.column() == display_map.line_len(head.row()) {
 3564                        transpose_offset = display_map
 3565                            .buffer_snapshot
 3566                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3567                    }
 3568
 3569                    if transpose_offset == 0 {
 3570                        return;
 3571                    }
 3572
 3573                    *head.column_mut() += 1;
 3574                    head = display_map.clip_point(head, Bias::Right);
 3575                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
 3576
 3577                    let transpose_start = display_map
 3578                        .buffer_snapshot
 3579                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3580                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 3581                        let transpose_end = display_map
 3582                            .buffer_snapshot
 3583                            .clip_offset(transpose_offset + 1, Bias::Right);
 3584                        if let Some(ch) =
 3585                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 3586                        {
 3587                            edits.push((transpose_start..transpose_offset, String::new()));
 3588                            edits.push((transpose_end..transpose_end, ch.to_string()));
 3589                        }
 3590                    }
 3591                });
 3592                edits
 3593            });
 3594            this.buffer
 3595                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 3596            let selections = this.selections.all::<usize>(cx);
 3597            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3598                s.select(selections);
 3599            });
 3600        });
 3601    }
 3602
 3603    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 3604        let mut text = String::new();
 3605        let buffer = self.buffer.read(cx).snapshot(cx);
 3606        let mut selections = self.selections.all::<Point>(cx);
 3607        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3608        {
 3609            let max_point = buffer.max_point();
 3610            for selection in &mut selections {
 3611                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 3612                if is_entire_line {
 3613                    selection.start = Point::new(selection.start.row, 0);
 3614                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 3615                    selection.goal = SelectionGoal::None;
 3616                }
 3617                let mut len = 0;
 3618                for chunk in buffer.text_for_range(selection.start..selection.end) {
 3619                    text.push_str(chunk);
 3620                    len += chunk.len();
 3621                }
 3622                clipboard_selections.push(ClipboardSelection {
 3623                    len,
 3624                    is_entire_line,
 3625                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 3626                });
 3627            }
 3628        }
 3629
 3630        self.transact(cx, |this, cx| {
 3631            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3632                s.select(selections);
 3633            });
 3634            this.insert("", cx);
 3635            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3636        });
 3637    }
 3638
 3639    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 3640        let selections = self.selections.all::<Point>(cx);
 3641        let buffer = self.buffer.read(cx).read(cx);
 3642        let mut text = String::new();
 3643
 3644        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3645        {
 3646            let max_point = buffer.max_point();
 3647            for selection in selections.iter() {
 3648                let mut start = selection.start;
 3649                let mut end = selection.end;
 3650                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 3651                if is_entire_line {
 3652                    start = Point::new(start.row, 0);
 3653                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 3654                }
 3655                let mut len = 0;
 3656                for chunk in buffer.text_for_range(start..end) {
 3657                    text.push_str(chunk);
 3658                    len += chunk.len();
 3659                }
 3660                clipboard_selections.push(ClipboardSelection {
 3661                    len,
 3662                    is_entire_line,
 3663                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 3664                });
 3665            }
 3666        }
 3667
 3668        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3669    }
 3670
 3671    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 3672        self.transact(cx, |this, cx| {
 3673            if let Some(item) = cx.as_mut().read_from_clipboard() {
 3674                let mut clipboard_text = Cow::Borrowed(item.text());
 3675                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 3676                    let old_selections = this.selections.all::<usize>(cx);
 3677                    let all_selections_were_entire_line =
 3678                        clipboard_selections.iter().all(|s| s.is_entire_line);
 3679                    let first_selection_indent_column =
 3680                        clipboard_selections.first().map(|s| s.first_line_indent);
 3681                    if clipboard_selections.len() != old_selections.len() {
 3682                        let mut newline_separated_text = String::new();
 3683                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
 3684                        let mut ix = 0;
 3685                        while let Some(clipboard_selection) = clipboard_selections.next() {
 3686                            newline_separated_text
 3687                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
 3688                            ix += clipboard_selection.len;
 3689                            if clipboard_selections.peek().is_some() {
 3690                                newline_separated_text.push('\n');
 3691                            }
 3692                        }
 3693                        clipboard_text = Cow::Owned(newline_separated_text);
 3694                    }
 3695
 3696                    this.buffer.update(cx, |buffer, cx| {
 3697                        let snapshot = buffer.read(cx);
 3698                        let mut start_offset = 0;
 3699                        let mut edits = Vec::new();
 3700                        let mut original_indent_columns = Vec::new();
 3701                        let line_mode = this.selections.line_mode;
 3702                        for (ix, selection) in old_selections.iter().enumerate() {
 3703                            let to_insert;
 3704                            let entire_line;
 3705                            let original_indent_column;
 3706                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 3707                                let end_offset = start_offset + clipboard_selection.len;
 3708                                to_insert = &clipboard_text[start_offset..end_offset];
 3709                                entire_line = clipboard_selection.is_entire_line;
 3710                                start_offset = end_offset;
 3711                                original_indent_column =
 3712                                    Some(clipboard_selection.first_line_indent);
 3713                            } else {
 3714                                to_insert = clipboard_text.as_str();
 3715                                entire_line = all_selections_were_entire_line;
 3716                                original_indent_column = first_selection_indent_column
 3717                            }
 3718
 3719                            // If the corresponding selection was empty when this slice of the
 3720                            // clipboard text was written, then the entire line containing the
 3721                            // selection was copied. If this selection is also currently empty,
 3722                            // then paste the line before the current line of the buffer.
 3723                            let range = if selection.is_empty() && !line_mode && entire_line {
 3724                                let column = selection.start.to_point(&snapshot).column as usize;
 3725                                let line_start = selection.start - column;
 3726                                line_start..line_start
 3727                            } else {
 3728                                selection.range()
 3729                            };
 3730
 3731                            edits.push((range, to_insert));
 3732                            original_indent_columns.extend(original_indent_column);
 3733                        }
 3734                        drop(snapshot);
 3735
 3736                        buffer.edit(
 3737                            edits,
 3738                            Some(AutoindentMode::Block {
 3739                                original_indent_columns,
 3740                            }),
 3741                            cx,
 3742                        );
 3743                    });
 3744
 3745                    let selections = this.selections.all::<usize>(cx);
 3746                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 3747                } else {
 3748                    this.insert(&clipboard_text, cx);
 3749                }
 3750            }
 3751        });
 3752    }
 3753
 3754    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 3755        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 3756            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 3757                self.change_selections(None, cx, |s| {
 3758                    s.select_anchors(selections.to_vec());
 3759                });
 3760            }
 3761            self.request_autoscroll(Autoscroll::Fit, cx);
 3762            self.unmark_text(cx);
 3763            cx.emit(Event::Edited);
 3764        }
 3765    }
 3766
 3767    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 3768        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 3769            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 3770            {
 3771                self.change_selections(None, cx, |s| {
 3772                    s.select_anchors(selections.to_vec());
 3773                });
 3774            }
 3775            self.request_autoscroll(Autoscroll::Fit, cx);
 3776            self.unmark_text(cx);
 3777            cx.emit(Event::Edited);
 3778        }
 3779    }
 3780
 3781    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 3782        self.buffer
 3783            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 3784    }
 3785
 3786    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 3787        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3788            let line_mode = s.line_mode;
 3789            s.move_with(|map, selection| {
 3790                let cursor = if selection.is_empty() && !line_mode {
 3791                    movement::left(map, selection.start)
 3792                } else {
 3793                    selection.start
 3794                };
 3795                selection.collapse_to(cursor, SelectionGoal::None);
 3796            });
 3797        })
 3798    }
 3799
 3800    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 3801        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3802            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 3803        })
 3804    }
 3805
 3806    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 3807        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3808            let line_mode = s.line_mode;
 3809            s.move_with(|map, selection| {
 3810                let cursor = if selection.is_empty() && !line_mode {
 3811                    movement::right(map, selection.end)
 3812                } else {
 3813                    selection.end
 3814                };
 3815                selection.collapse_to(cursor, SelectionGoal::None)
 3816            });
 3817        })
 3818    }
 3819
 3820    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 3821        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3822            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 3823        })
 3824    }
 3825
 3826    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 3827        if self.take_rename(true, cx).is_some() {
 3828            return;
 3829        }
 3830
 3831        if let Some(context_menu) = self.context_menu.as_mut() {
 3832            if context_menu.select_prev(cx) {
 3833                return;
 3834            }
 3835        }
 3836
 3837        if matches!(self.mode, EditorMode::SingleLine) {
 3838            cx.propagate_action();
 3839            return;
 3840        }
 3841
 3842        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3843            let line_mode = s.line_mode;
 3844            s.move_with(|map, selection| {
 3845                if !selection.is_empty() && !line_mode {
 3846                    selection.goal = SelectionGoal::None;
 3847                }
 3848                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
 3849                selection.collapse_to(cursor, goal);
 3850            });
 3851        })
 3852    }
 3853
 3854    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 3855        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3856            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
 3857        })
 3858    }
 3859
 3860    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 3861        self.take_rename(true, cx);
 3862
 3863        if let Some(context_menu) = self.context_menu.as_mut() {
 3864            if context_menu.select_next(cx) {
 3865                return;
 3866            }
 3867        }
 3868
 3869        if matches!(self.mode, EditorMode::SingleLine) {
 3870            cx.propagate_action();
 3871            return;
 3872        }
 3873
 3874        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3875            let line_mode = s.line_mode;
 3876            s.move_with(|map, selection| {
 3877                if !selection.is_empty() && !line_mode {
 3878                    selection.goal = SelectionGoal::None;
 3879                }
 3880                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
 3881                selection.collapse_to(cursor, goal);
 3882            });
 3883        });
 3884    }
 3885
 3886    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 3887        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3888            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
 3889        });
 3890    }
 3891
 3892    pub fn move_to_previous_word_start(
 3893        &mut self,
 3894        _: &MoveToPreviousWordStart,
 3895        cx: &mut ViewContext<Self>,
 3896    ) {
 3897        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3898            s.move_cursors_with(|map, head, _| {
 3899                (
 3900                    movement::previous_word_start(map, head),
 3901                    SelectionGoal::None,
 3902                )
 3903            });
 3904        })
 3905    }
 3906
 3907    pub fn move_to_previous_subword_start(
 3908        &mut self,
 3909        _: &MoveToPreviousSubwordStart,
 3910        cx: &mut ViewContext<Self>,
 3911    ) {
 3912        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3913            s.move_cursors_with(|map, head, _| {
 3914                (
 3915                    movement::previous_subword_start(map, head),
 3916                    SelectionGoal::None,
 3917                )
 3918            });
 3919        })
 3920    }
 3921
 3922    pub fn select_to_previous_word_start(
 3923        &mut self,
 3924        _: &SelectToPreviousWordStart,
 3925        cx: &mut ViewContext<Self>,
 3926    ) {
 3927        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3928            s.move_heads_with(|map, head, _| {
 3929                (
 3930                    movement::previous_word_start(map, head),
 3931                    SelectionGoal::None,
 3932                )
 3933            });
 3934        })
 3935    }
 3936
 3937    pub fn select_to_previous_subword_start(
 3938        &mut self,
 3939        _: &SelectToPreviousSubwordStart,
 3940        cx: &mut ViewContext<Self>,
 3941    ) {
 3942        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3943            s.move_heads_with(|map, head, _| {
 3944                (
 3945                    movement::previous_subword_start(map, head),
 3946                    SelectionGoal::None,
 3947                )
 3948            });
 3949        })
 3950    }
 3951
 3952    pub fn delete_to_previous_word_start(
 3953        &mut self,
 3954        _: &DeleteToPreviousWordStart,
 3955        cx: &mut ViewContext<Self>,
 3956    ) {
 3957        self.transact(cx, |this, cx| {
 3958            this.select_autoclose_pair(cx);
 3959            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3960                let line_mode = s.line_mode;
 3961                s.move_with(|map, selection| {
 3962                    if selection.is_empty() && !line_mode {
 3963                        let cursor = movement::previous_word_start(map, selection.head());
 3964                        selection.set_head(cursor, SelectionGoal::None);
 3965                    }
 3966                });
 3967            });
 3968            this.insert("", cx);
 3969        });
 3970    }
 3971
 3972    pub fn delete_to_previous_subword_start(
 3973        &mut self,
 3974        _: &DeleteToPreviousSubwordStart,
 3975        cx: &mut ViewContext<Self>,
 3976    ) {
 3977        self.transact(cx, |this, cx| {
 3978            this.select_autoclose_pair(cx);
 3979            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3980                let line_mode = s.line_mode;
 3981                s.move_with(|map, selection| {
 3982                    if selection.is_empty() && !line_mode {
 3983                        let cursor = movement::previous_subword_start(map, selection.head());
 3984                        selection.set_head(cursor, SelectionGoal::None);
 3985                    }
 3986                });
 3987            });
 3988            this.insert("", cx);
 3989        });
 3990    }
 3991
 3992    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 3993        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 3994            s.move_cursors_with(|map, head, _| {
 3995                (movement::next_word_end(map, head), SelectionGoal::None)
 3996            });
 3997        })
 3998    }
 3999
 4000    pub fn move_to_next_subword_end(
 4001        &mut self,
 4002        _: &MoveToNextSubwordEnd,
 4003        cx: &mut ViewContext<Self>,
 4004    ) {
 4005        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4006            s.move_cursors_with(|map, head, _| {
 4007                (movement::next_subword_end(map, head), SelectionGoal::None)
 4008            });
 4009        })
 4010    }
 4011
 4012    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 4013        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4014            s.move_heads_with(|map, head, _| {
 4015                (movement::next_word_end(map, head), SelectionGoal::None)
 4016            });
 4017        })
 4018    }
 4019
 4020    pub fn select_to_next_subword_end(
 4021        &mut self,
 4022        _: &SelectToNextSubwordEnd,
 4023        cx: &mut ViewContext<Self>,
 4024    ) {
 4025        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4026            s.move_heads_with(|map, head, _| {
 4027                (movement::next_subword_end(map, head), SelectionGoal::None)
 4028            });
 4029        })
 4030    }
 4031
 4032    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 4033        self.transact(cx, |this, cx| {
 4034            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4035                let line_mode = s.line_mode;
 4036                s.move_with(|map, selection| {
 4037                    if selection.is_empty() && !line_mode {
 4038                        let cursor = movement::next_word_end(map, selection.head());
 4039                        selection.set_head(cursor, SelectionGoal::None);
 4040                    }
 4041                });
 4042            });
 4043            this.insert("", cx);
 4044        });
 4045    }
 4046
 4047    pub fn delete_to_next_subword_end(
 4048        &mut self,
 4049        _: &DeleteToNextSubwordEnd,
 4050        cx: &mut ViewContext<Self>,
 4051    ) {
 4052        self.transact(cx, |this, cx| {
 4053            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4054                s.move_with(|map, selection| {
 4055                    if selection.is_empty() {
 4056                        let cursor = movement::next_subword_end(map, selection.head());
 4057                        selection.set_head(cursor, SelectionGoal::None);
 4058                    }
 4059                });
 4060            });
 4061            this.insert("", cx);
 4062        });
 4063    }
 4064
 4065    pub fn move_to_beginning_of_line(
 4066        &mut self,
 4067        _: &MoveToBeginningOfLine,
 4068        cx: &mut ViewContext<Self>,
 4069    ) {
 4070        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4071            s.move_cursors_with(|map, head, _| {
 4072                (
 4073                    movement::line_beginning(map, head, true),
 4074                    SelectionGoal::None,
 4075                )
 4076            });
 4077        })
 4078    }
 4079
 4080    pub fn select_to_beginning_of_line(
 4081        &mut self,
 4082        action: &SelectToBeginningOfLine,
 4083        cx: &mut ViewContext<Self>,
 4084    ) {
 4085        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4086            s.move_heads_with(|map, head, _| {
 4087                (
 4088                    movement::line_beginning(map, head, action.stop_at_soft_wraps),
 4089                    SelectionGoal::None,
 4090                )
 4091            });
 4092        });
 4093    }
 4094
 4095    pub fn delete_to_beginning_of_line(
 4096        &mut self,
 4097        _: &DeleteToBeginningOfLine,
 4098        cx: &mut ViewContext<Self>,
 4099    ) {
 4100        self.transact(cx, |this, cx| {
 4101            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4102                s.move_with(|_, selection| {
 4103                    selection.reversed = true;
 4104                });
 4105            });
 4106
 4107            this.select_to_beginning_of_line(
 4108                &SelectToBeginningOfLine {
 4109                    stop_at_soft_wraps: false,
 4110                },
 4111                cx,
 4112            );
 4113            this.backspace(&Backspace, cx);
 4114        });
 4115    }
 4116
 4117    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 4118        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4119            s.move_cursors_with(|map, head, _| {
 4120                (movement::line_end(map, head, true), SelectionGoal::None)
 4121            });
 4122        })
 4123    }
 4124
 4125    pub fn select_to_end_of_line(
 4126        &mut self,
 4127        action: &SelectToEndOfLine,
 4128        cx: &mut ViewContext<Self>,
 4129    ) {
 4130        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4131            s.move_heads_with(|map, head, _| {
 4132                (
 4133                    movement::line_end(map, head, action.stop_at_soft_wraps),
 4134                    SelectionGoal::None,
 4135                )
 4136            });
 4137        })
 4138    }
 4139
 4140    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 4141        self.transact(cx, |this, cx| {
 4142            this.select_to_end_of_line(
 4143                &SelectToEndOfLine {
 4144                    stop_at_soft_wraps: false,
 4145                },
 4146                cx,
 4147            );
 4148            this.delete(&Delete, cx);
 4149        });
 4150    }
 4151
 4152    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 4153        self.transact(cx, |this, cx| {
 4154            this.select_to_end_of_line(
 4155                &SelectToEndOfLine {
 4156                    stop_at_soft_wraps: false,
 4157                },
 4158                cx,
 4159            );
 4160            this.cut(&Cut, cx);
 4161        });
 4162    }
 4163
 4164    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 4165        if matches!(self.mode, EditorMode::SingleLine) {
 4166            cx.propagate_action();
 4167            return;
 4168        }
 4169
 4170        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4171            s.select_ranges(vec![0..0]);
 4172        });
 4173    }
 4174
 4175    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 4176        let mut selection = self.selections.last::<Point>(cx);
 4177        selection.set_head(Point::zero(), SelectionGoal::None);
 4178
 4179        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4180            s.select(vec![selection]);
 4181        });
 4182    }
 4183
 4184    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 4185        if matches!(self.mode, EditorMode::SingleLine) {
 4186            cx.propagate_action();
 4187            return;
 4188        }
 4189
 4190        let cursor = self.buffer.read(cx).read(cx).len();
 4191        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4192            s.select_ranges(vec![cursor..cursor])
 4193        });
 4194    }
 4195
 4196    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 4197        self.nav_history = nav_history;
 4198    }
 4199
 4200    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 4201        self.nav_history.as_ref()
 4202    }
 4203
 4204    fn push_to_nav_history(
 4205        &self,
 4206        position: Anchor,
 4207        new_position: Option<Point>,
 4208        cx: &mut ViewContext<Self>,
 4209    ) {
 4210        if let Some(nav_history) = &self.nav_history {
 4211            let buffer = self.buffer.read(cx).read(cx);
 4212            let point = position.to_point(&buffer);
 4213            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
 4214            drop(buffer);
 4215
 4216            if let Some(new_position) = new_position {
 4217                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 4218                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 4219                    return;
 4220                }
 4221            }
 4222
 4223            nav_history.push(
 4224                Some(NavigationData {
 4225                    cursor_anchor: position,
 4226                    cursor_position: point,
 4227                    scroll_position: self.scroll_position,
 4228                    scroll_top_anchor: self.scroll_top_anchor.clone(),
 4229                    scroll_top_row,
 4230                }),
 4231                cx,
 4232            );
 4233        }
 4234    }
 4235
 4236    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 4237        let buffer = self.buffer.read(cx).snapshot(cx);
 4238        let mut selection = self.selections.first::<usize>(cx);
 4239        selection.set_head(buffer.len(), SelectionGoal::None);
 4240        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4241            s.select(vec![selection]);
 4242        });
 4243    }
 4244
 4245    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 4246        let end = self.buffer.read(cx).read(cx).len();
 4247        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4248            s.select_ranges(vec![0..end]);
 4249        });
 4250    }
 4251
 4252    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 4253        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4254        let mut selections = self.selections.all::<Point>(cx);
 4255        let max_point = display_map.buffer_snapshot.max_point();
 4256        for selection in &mut selections {
 4257            let rows = selection.spanned_rows(true, &display_map);
 4258            selection.start = Point::new(rows.start, 0);
 4259            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 4260            selection.reversed = false;
 4261        }
 4262        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4263            s.select(selections);
 4264        });
 4265    }
 4266
 4267    pub fn split_selection_into_lines(
 4268        &mut self,
 4269        _: &SplitSelectionIntoLines,
 4270        cx: &mut ViewContext<Self>,
 4271    ) {
 4272        let mut to_unfold = Vec::new();
 4273        let mut new_selection_ranges = Vec::new();
 4274        {
 4275            let selections = self.selections.all::<Point>(cx);
 4276            let buffer = self.buffer.read(cx).read(cx);
 4277            for selection in selections {
 4278                for row in selection.start.row..selection.end.row {
 4279                    let cursor = Point::new(row, buffer.line_len(row));
 4280                    new_selection_ranges.push(cursor..cursor);
 4281                }
 4282                new_selection_ranges.push(selection.end..selection.end);
 4283                to_unfold.push(selection.start..selection.end);
 4284            }
 4285        }
 4286        self.unfold_ranges(to_unfold, true, cx);
 4287        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4288            s.select_ranges(new_selection_ranges);
 4289        });
 4290    }
 4291
 4292    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 4293        self.add_selection(true, cx);
 4294    }
 4295
 4296    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 4297        self.add_selection(false, cx);
 4298    }
 4299
 4300    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 4301        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4302        let mut selections = self.selections.all::<Point>(cx);
 4303        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4304            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4305            let range = oldest_selection.display_range(&display_map).sorted();
 4306            let columns = cmp::min(range.start.column(), range.end.column())
 4307                ..cmp::max(range.start.column(), range.end.column());
 4308
 4309            selections.clear();
 4310            let mut stack = Vec::new();
 4311            for row in range.start.row()..=range.end.row() {
 4312                if let Some(selection) = self.selections.build_columnar_selection(
 4313                    &display_map,
 4314                    row,
 4315                    &columns,
 4316                    oldest_selection.reversed,
 4317                ) {
 4318                    stack.push(selection.id);
 4319                    selections.push(selection);
 4320                }
 4321            }
 4322
 4323            if above {
 4324                stack.reverse();
 4325            }
 4326
 4327            AddSelectionsState { above, stack }
 4328        });
 4329
 4330        let last_added_selection = *state.stack.last().unwrap();
 4331        let mut new_selections = Vec::new();
 4332        if above == state.above {
 4333            let end_row = if above {
 4334                0
 4335            } else {
 4336                display_map.max_point().row()
 4337            };
 4338
 4339            'outer: for selection in selections {
 4340                if selection.id == last_added_selection {
 4341                    let range = selection.display_range(&display_map).sorted();
 4342                    debug_assert_eq!(range.start.row(), range.end.row());
 4343                    let mut row = range.start.row();
 4344                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4345                    {
 4346                        start..end
 4347                    } else {
 4348                        cmp::min(range.start.column(), range.end.column())
 4349                            ..cmp::max(range.start.column(), range.end.column())
 4350                    };
 4351
 4352                    while row != end_row {
 4353                        if above {
 4354                            row -= 1;
 4355                        } else {
 4356                            row += 1;
 4357                        }
 4358
 4359                        if let Some(new_selection) = self.selections.build_columnar_selection(
 4360                            &display_map,
 4361                            row,
 4362                            &columns,
 4363                            selection.reversed,
 4364                        ) {
 4365                            state.stack.push(new_selection.id);
 4366                            if above {
 4367                                new_selections.push(new_selection);
 4368                                new_selections.push(selection);
 4369                            } else {
 4370                                new_selections.push(selection);
 4371                                new_selections.push(new_selection);
 4372                            }
 4373
 4374                            continue 'outer;
 4375                        }
 4376                    }
 4377                }
 4378
 4379                new_selections.push(selection);
 4380            }
 4381        } else {
 4382            new_selections = selections;
 4383            new_selections.retain(|s| s.id != last_added_selection);
 4384            state.stack.pop();
 4385        }
 4386
 4387        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4388            s.select(new_selections);
 4389        });
 4390        if state.stack.len() > 1 {
 4391            self.add_selections_state = Some(state);
 4392        }
 4393    }
 4394
 4395    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4396        self.push_to_selection_history();
 4397        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4398        let buffer = &display_map.buffer_snapshot;
 4399        let mut selections = self.selections.all::<usize>(cx);
 4400        if let Some(mut select_next_state) = self.select_next_state.take() {
 4401            let query = &select_next_state.query;
 4402            if !select_next_state.done {
 4403                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4404                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4405                let mut next_selected_range = None;
 4406
 4407                let bytes_after_last_selection =
 4408                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4409                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4410                let query_matches = query
 4411                    .stream_find_iter(bytes_after_last_selection)
 4412                    .map(|result| (last_selection.end, result))
 4413                    .chain(
 4414                        query
 4415                            .stream_find_iter(bytes_before_first_selection)
 4416                            .map(|result| (0, result)),
 4417                    );
 4418                for (start_offset, query_match) in query_matches {
 4419                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4420                    let offset_range =
 4421                        start_offset + query_match.start()..start_offset + query_match.end();
 4422                    let display_range = offset_range.start.to_display_point(&display_map)
 4423                        ..offset_range.end.to_display_point(&display_map);
 4424
 4425                    if !select_next_state.wordwise
 4426                        || (!movement::is_inside_word(&display_map, display_range.start)
 4427                            && !movement::is_inside_word(&display_map, display_range.end))
 4428                    {
 4429                        next_selected_range = Some(offset_range);
 4430                        break;
 4431                    }
 4432                }
 4433
 4434                if let Some(next_selected_range) = next_selected_range {
 4435                    self.unfold_ranges([next_selected_range.clone()], false, cx);
 4436                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
 4437                        if action.replace_newest {
 4438                            s.delete(s.newest_anchor().id);
 4439                        }
 4440                        s.insert_range(next_selected_range);
 4441                    });
 4442                } else {
 4443                    select_next_state.done = true;
 4444                }
 4445            }
 4446
 4447            self.select_next_state = Some(select_next_state);
 4448        } else if selections.len() == 1 {
 4449            let selection = selections.last_mut().unwrap();
 4450            if selection.start == selection.end {
 4451                let word_range = movement::surrounding_word(
 4452                    &display_map,
 4453                    selection.start.to_display_point(&display_map),
 4454                );
 4455                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4456                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4457                selection.goal = SelectionGoal::None;
 4458                selection.reversed = false;
 4459
 4460                let query = buffer
 4461                    .text_for_range(selection.start..selection.end)
 4462                    .collect::<String>();
 4463                let select_state = SelectNextState {
 4464                    query: AhoCorasick::new_auto_configured(&[query]),
 4465                    wordwise: true,
 4466                    done: false,
 4467                };
 4468                self.unfold_ranges([selection.start..selection.end], false, cx);
 4469                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
 4470                    s.select(selections);
 4471                });
 4472                self.select_next_state = Some(select_state);
 4473            } else {
 4474                let query = buffer
 4475                    .text_for_range(selection.start..selection.end)
 4476                    .collect::<String>();
 4477                self.select_next_state = Some(SelectNextState {
 4478                    query: AhoCorasick::new_auto_configured(&[query]),
 4479                    wordwise: false,
 4480                    done: false,
 4481                });
 4482                self.select_next(action, cx);
 4483            }
 4484        }
 4485    }
 4486
 4487    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4488        self.transact(cx, |this, cx| {
 4489            let mut selections = this.selections.all::<Point>(cx);
 4490            let mut edits = Vec::new();
 4491            let mut selection_edit_ranges = Vec::new();
 4492            let mut last_toggled_row = None;
 4493            let snapshot = this.buffer.read(cx).read(cx);
 4494            let empty_str: Arc<str> = "".into();
 4495            let mut suffixes_inserted = Vec::new();
 4496
 4497            fn comment_prefix_range(
 4498                snapshot: &MultiBufferSnapshot,
 4499                row: u32,
 4500                comment_prefix: &str,
 4501                comment_prefix_whitespace: &str,
 4502            ) -> Range<Point> {
 4503                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 4504
 4505                let mut line_bytes = snapshot
 4506                    .bytes_in_range(start..snapshot.max_point())
 4507                    .flatten()
 4508                    .copied();
 4509
 4510                // If this line currently begins with the line comment prefix, then record
 4511                // the range containing the prefix.
 4512                if line_bytes
 4513                    .by_ref()
 4514                    .take(comment_prefix.len())
 4515                    .eq(comment_prefix.bytes())
 4516                {
 4517                    // Include any whitespace that matches the comment prefix.
 4518                    let matching_whitespace_len = line_bytes
 4519                        .zip(comment_prefix_whitespace.bytes())
 4520                        .take_while(|(a, b)| a == b)
 4521                        .count() as u32;
 4522                    let end = Point::new(
 4523                        start.row,
 4524                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 4525                    );
 4526                    start..end
 4527                } else {
 4528                    start..start
 4529                }
 4530            }
 4531
 4532            fn comment_suffix_range(
 4533                snapshot: &MultiBufferSnapshot,
 4534                row: u32,
 4535                comment_suffix: &str,
 4536                comment_suffix_has_leading_space: bool,
 4537            ) -> Range<Point> {
 4538                let end = Point::new(row, snapshot.line_len(row));
 4539                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 4540
 4541                let mut line_end_bytes = snapshot
 4542                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 4543                    .flatten()
 4544                    .copied();
 4545
 4546                let leading_space_len = if suffix_start_column > 0
 4547                    && line_end_bytes.next() == Some(b' ')
 4548                    && comment_suffix_has_leading_space
 4549                {
 4550                    1
 4551                } else {
 4552                    0
 4553                };
 4554
 4555                // If this line currently begins with the line comment prefix, then record
 4556                // the range containing the prefix.
 4557                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 4558                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 4559                    start..end
 4560                } else {
 4561                    end..end
 4562                }
 4563            }
 4564
 4565            // TODO: Handle selections that cross excerpts
 4566            for selection in &mut selections {
 4567                let language = if let Some(language) = snapshot.language_at(selection.start) {
 4568                    language
 4569                } else {
 4570                    continue;
 4571                };
 4572
 4573                selection_edit_ranges.clear();
 4574
 4575                // If multiple selections contain a given row, avoid processing that
 4576                // row more than once.
 4577                let mut start_row = selection.start.row;
 4578                if last_toggled_row == Some(start_row) {
 4579                    start_row += 1;
 4580                }
 4581                let end_row =
 4582                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 4583                        selection.end.row - 1
 4584                    } else {
 4585                        selection.end.row
 4586                    };
 4587                last_toggled_row = Some(end_row);
 4588
 4589                if start_row > end_row {
 4590                    continue;
 4591                }
 4592
 4593                // If the language has line comments, toggle those.
 4594                if let Some(full_comment_prefix) = language.line_comment_prefix() {
 4595                    // Split the comment prefix's trailing whitespace into a separate string,
 4596                    // as that portion won't be used for detecting if a line is a comment.
 4597                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4598                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4599                    let mut all_selection_lines_are_comments = true;
 4600
 4601                    for row in start_row..=end_row {
 4602                        if snapshot.is_line_blank(row) {
 4603                            continue;
 4604                        }
 4605
 4606                        let prefix_range = comment_prefix_range(
 4607                            snapshot.deref(),
 4608                            row,
 4609                            comment_prefix,
 4610                            comment_prefix_whitespace,
 4611                        );
 4612                        if prefix_range.is_empty() {
 4613                            all_selection_lines_are_comments = false;
 4614                        }
 4615                        selection_edit_ranges.push(prefix_range);
 4616                    }
 4617
 4618                    if all_selection_lines_are_comments {
 4619                        edits.extend(
 4620                            selection_edit_ranges
 4621                                .iter()
 4622                                .cloned()
 4623                                .map(|range| (range, empty_str.clone())),
 4624                        );
 4625                    } else {
 4626                        let min_column = selection_edit_ranges
 4627                            .iter()
 4628                            .map(|r| r.start.column)
 4629                            .min()
 4630                            .unwrap_or(0);
 4631                        edits.extend(selection_edit_ranges.iter().map(|range| {
 4632                            let position = Point::new(range.start.row, min_column);
 4633                            (position..position, full_comment_prefix.clone())
 4634                        }));
 4635                    }
 4636                } else if let Some((full_comment_prefix, comment_suffix)) =
 4637                    language.block_comment_delimiters()
 4638                {
 4639                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4640                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4641                    let prefix_range = comment_prefix_range(
 4642                        snapshot.deref(),
 4643                        start_row,
 4644                        comment_prefix,
 4645                        comment_prefix_whitespace,
 4646                    );
 4647                    let suffix_range = comment_suffix_range(
 4648                        snapshot.deref(),
 4649                        end_row,
 4650                        comment_suffix.trim_start_matches(' '),
 4651                        comment_suffix.starts_with(' '),
 4652                    );
 4653
 4654                    if prefix_range.is_empty() || suffix_range.is_empty() {
 4655                        edits.push((
 4656                            prefix_range.start..prefix_range.start,
 4657                            full_comment_prefix.clone(),
 4658                        ));
 4659                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 4660                        suffixes_inserted.push((end_row, comment_suffix.len()));
 4661                    } else {
 4662                        edits.push((prefix_range, empty_str.clone()));
 4663                        edits.push((suffix_range, empty_str.clone()));
 4664                    }
 4665                } else {
 4666                    continue;
 4667                }
 4668            }
 4669
 4670            drop(snapshot);
 4671            this.buffer.update(cx, |buffer, cx| {
 4672                buffer.edit(edits, None, cx);
 4673            });
 4674
 4675            // Adjust selections so that they end before any comment suffixes that
 4676            // were inserted.
 4677            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 4678            let mut selections = this.selections.all::<Point>(cx);
 4679            let snapshot = this.buffer.read(cx).read(cx);
 4680            for selection in &mut selections {
 4681                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 4682                    match row.cmp(&selection.end.row) {
 4683                        Ordering::Less => {
 4684                            suffixes_inserted.next();
 4685                            continue;
 4686                        }
 4687                        Ordering::Greater => break,
 4688                        Ordering::Equal => {
 4689                            if selection.end.column == snapshot.line_len(row) {
 4690                                if selection.is_empty() {
 4691                                    selection.start.column -= suffix_len as u32;
 4692                                }
 4693                                selection.end.column -= suffix_len as u32;
 4694                            }
 4695                            break;
 4696                        }
 4697                    }
 4698                }
 4699            }
 4700
 4701            drop(snapshot);
 4702            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
 4703        });
 4704    }
 4705
 4706    pub fn select_larger_syntax_node(
 4707        &mut self,
 4708        _: &SelectLargerSyntaxNode,
 4709        cx: &mut ViewContext<Self>,
 4710    ) {
 4711        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4712        let buffer = self.buffer.read(cx).snapshot(cx);
 4713        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 4714
 4715        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4716        let mut selected_larger_node = false;
 4717        let new_selections = old_selections
 4718            .iter()
 4719            .map(|selection| {
 4720                let old_range = selection.start..selection.end;
 4721                let mut new_range = old_range.clone();
 4722                while let Some(containing_range) =
 4723                    buffer.range_for_syntax_ancestor(new_range.clone())
 4724                {
 4725                    new_range = containing_range;
 4726                    if !display_map.intersects_fold(new_range.start)
 4727                        && !display_map.intersects_fold(new_range.end)
 4728                    {
 4729                        break;
 4730                    }
 4731                }
 4732
 4733                selected_larger_node |= new_range != old_range;
 4734                Selection {
 4735                    id: selection.id,
 4736                    start: new_range.start,
 4737                    end: new_range.end,
 4738                    goal: SelectionGoal::None,
 4739                    reversed: selection.reversed,
 4740                }
 4741            })
 4742            .collect::<Vec<_>>();
 4743
 4744        if selected_larger_node {
 4745            stack.push(old_selections);
 4746            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4747                s.select(new_selections);
 4748            });
 4749        }
 4750        self.select_larger_syntax_node_stack = stack;
 4751    }
 4752
 4753    pub fn select_smaller_syntax_node(
 4754        &mut self,
 4755        _: &SelectSmallerSyntaxNode,
 4756        cx: &mut ViewContext<Self>,
 4757    ) {
 4758        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4759        if let Some(selections) = stack.pop() {
 4760            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4761                s.select(selections.to_vec());
 4762            });
 4763        }
 4764        self.select_larger_syntax_node_stack = stack;
 4765    }
 4766
 4767    pub fn move_to_enclosing_bracket(
 4768        &mut self,
 4769        _: &MoveToEnclosingBracket,
 4770        cx: &mut ViewContext<Self>,
 4771    ) {
 4772        let buffer = self.buffer.read(cx).snapshot(cx);
 4773        let mut selections = self.selections.all::<usize>(cx);
 4774        for selection in &mut selections {
 4775            if let Some((open_range, close_range)) =
 4776                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4777            {
 4778                let close_range = close_range.to_inclusive();
 4779                let destination = if close_range.contains(&selection.start)
 4780                    && close_range.contains(&selection.end)
 4781                {
 4782                    open_range.end
 4783                } else {
 4784                    *close_range.start()
 4785                };
 4786                selection.start = destination;
 4787                selection.end = destination;
 4788            }
 4789        }
 4790
 4791        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
 4792            s.select(selections);
 4793        });
 4794    }
 4795
 4796    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4797        self.end_selection(cx);
 4798        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4799        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4800            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 4801            self.select_next_state = entry.select_next_state;
 4802            self.add_selections_state = entry.add_selections_state;
 4803            self.request_autoscroll(Autoscroll::Newest, cx);
 4804        }
 4805        self.selection_history.mode = SelectionHistoryMode::Normal;
 4806    }
 4807
 4808    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4809        self.end_selection(cx);
 4810        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4811        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4812            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 4813            self.select_next_state = entry.select_next_state;
 4814            self.add_selections_state = entry.add_selections_state;
 4815            self.request_autoscroll(Autoscroll::Newest, cx);
 4816        }
 4817        self.selection_history.mode = SelectionHistoryMode::Normal;
 4818    }
 4819
 4820    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 4821        self.go_to_diagnostic_impl(Direction::Next, cx)
 4822    }
 4823
 4824    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4825        self.go_to_diagnostic_impl(Direction::Prev, cx)
 4826    }
 4827
 4828    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4829        let buffer = self.buffer.read(cx).snapshot(cx);
 4830        let selection = self.selections.newest::<usize>(cx);
 4831
 4832        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
 4833        if direction == Direction::Next {
 4834            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 4835                let (group_id, jump_to) = popover.activation_info();
 4836                if self.activate_diagnostics(group_id, cx) {
 4837                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
 4838                        let mut new_selection = s.newest_anchor().clone();
 4839                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 4840                        s.select_anchors(vec![new_selection.clone()]);
 4841                    });
 4842                }
 4843                return;
 4844            }
 4845        }
 4846
 4847        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4848            active_diagnostics
 4849                .primary_range
 4850                .to_offset(&buffer)
 4851                .to_inclusive()
 4852        });
 4853        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4854            if active_primary_range.contains(&selection.head()) {
 4855                *active_primary_range.end()
 4856            } else {
 4857                selection.head()
 4858            }
 4859        } else {
 4860            selection.head()
 4861        };
 4862
 4863        loop {
 4864            let mut diagnostics = if direction == Direction::Prev {
 4865                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4866            } else {
 4867                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4868            };
 4869            let group = diagnostics.find_map(|entry| {
 4870                if entry.diagnostic.is_primary
 4871                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4872                    && !entry.range.is_empty()
 4873                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4874                {
 4875                    Some((entry.range, entry.diagnostic.group_id))
 4876                } else {
 4877                    None
 4878                }
 4879            });
 4880
 4881            if let Some((primary_range, group_id)) = group {
 4882                if self.activate_diagnostics(group_id, cx) {
 4883                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
 4884                        s.select(vec![Selection {
 4885                            id: selection.id,
 4886                            start: primary_range.start,
 4887                            end: primary_range.start,
 4888                            reversed: false,
 4889                            goal: SelectionGoal::None,
 4890                        }]);
 4891                    });
 4892                }
 4893                break;
 4894            } else {
 4895                // Cycle around to the start of the buffer, potentially moving back to the start of
 4896                // the currently active diagnostic.
 4897                active_primary_range.take();
 4898                if direction == Direction::Prev {
 4899                    if search_start == buffer.len() {
 4900                        break;
 4901                    } else {
 4902                        search_start = buffer.len();
 4903                    }
 4904                } else if search_start == 0 {
 4905                    break;
 4906                } else {
 4907                    search_start = 0;
 4908                }
 4909            }
 4910        }
 4911    }
 4912
 4913    pub fn go_to_definition(
 4914        workspace: &mut Workspace,
 4915        _: &GoToDefinition,
 4916        cx: &mut ViewContext<Workspace>,
 4917    ) {
 4918        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
 4919    }
 4920
 4921    pub fn go_to_type_definition(
 4922        workspace: &mut Workspace,
 4923        _: &GoToTypeDefinition,
 4924        cx: &mut ViewContext<Workspace>,
 4925    ) {
 4926        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
 4927    }
 4928
 4929    fn go_to_definition_of_kind(
 4930        kind: GotoDefinitionKind,
 4931        workspace: &mut Workspace,
 4932        cx: &mut ViewContext<Workspace>,
 4933    ) {
 4934        let active_item = workspace.active_item(cx);
 4935        let editor_handle = if let Some(editor) = active_item
 4936            .as_ref()
 4937            .and_then(|item| item.act_as::<Self>(cx))
 4938        {
 4939            editor
 4940        } else {
 4941            return;
 4942        };
 4943
 4944        let editor = editor_handle.read(cx);
 4945        let buffer = editor.buffer.read(cx);
 4946        let head = editor.selections.newest::<usize>(cx).head();
 4947        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 4948            text_anchor
 4949        } else {
 4950            return;
 4951        };
 4952
 4953        let project = workspace.project().clone();
 4954        let definitions = project.update(cx, |project, cx| match kind {
 4955            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 4956            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 4957        });
 4958
 4959        cx.spawn(|workspace, mut cx| async move {
 4960            let definitions = definitions.await?;
 4961            workspace.update(&mut cx, |workspace, cx| {
 4962                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
 4963            });
 4964
 4965            Ok::<(), anyhow::Error>(())
 4966        })
 4967        .detach_and_log_err(cx);
 4968    }
 4969
 4970    pub fn navigate_to_definitions(
 4971        workspace: &mut Workspace,
 4972        editor_handle: ViewHandle<Editor>,
 4973        definitions: Vec<LocationLink>,
 4974        cx: &mut ViewContext<Workspace>,
 4975    ) {
 4976        let pane = workspace.active_pane().clone();
 4977        for definition in definitions {
 4978            let range = definition
 4979                .target
 4980                .range
 4981                .to_offset(definition.target.buffer.read(cx));
 4982
 4983            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
 4984            target_editor_handle.update(cx, |target_editor, cx| {
 4985                // When selecting a definition in a different buffer, disable the nav history
 4986                // to avoid creating a history entry at the previous cursor location.
 4987                if editor_handle != target_editor_handle {
 4988                    pane.update(cx, |pane, _| pane.disable_history());
 4989                }
 4990                target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
 4991                    s.select_ranges([range]);
 4992                });
 4993
 4994                pane.update(cx, |pane, _| pane.enable_history());
 4995            });
 4996        }
 4997    }
 4998
 4999    pub fn find_all_references(
 5000        workspace: &mut Workspace,
 5001        _: &FindAllReferences,
 5002        cx: &mut ViewContext<Workspace>,
 5003    ) -> Option<Task<Result<()>>> {
 5004        let active_item = workspace.active_item(cx)?;
 5005        let editor_handle = active_item.act_as::<Self>(cx)?;
 5006
 5007        let editor = editor_handle.read(cx);
 5008        let buffer = editor.buffer.read(cx);
 5009        let head = editor.selections.newest::<usize>(cx).head();
 5010        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 5011        let replica_id = editor.replica_id(cx);
 5012
 5013        let project = workspace.project().clone();
 5014        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 5015        Some(cx.spawn(|workspace, mut cx| async move {
 5016            let mut locations = references.await?;
 5017            if locations.is_empty() {
 5018                return Ok(());
 5019            }
 5020
 5021            locations.sort_by_key(|location| location.buffer.id());
 5022            let mut locations = locations.into_iter().peekable();
 5023            let mut ranges_to_highlight = Vec::new();
 5024
 5025            let excerpt_buffer = cx.add_model(|cx| {
 5026                let mut symbol_name = None;
 5027                let mut multibuffer = MultiBuffer::new(replica_id);
 5028                while let Some(location) = locations.next() {
 5029                    let buffer = location.buffer.read(cx);
 5030                    let mut ranges_for_buffer = Vec::new();
 5031                    let range = location.range.to_offset(buffer);
 5032                    ranges_for_buffer.push(range.clone());
 5033                    if symbol_name.is_none() {
 5034                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 5035                    }
 5036
 5037                    while let Some(next_location) = locations.peek() {
 5038                        if next_location.buffer == location.buffer {
 5039                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 5040                            locations.next();
 5041                        } else {
 5042                            break;
 5043                        }
 5044                    }
 5045
 5046                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 5047                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 5048                        location.buffer.clone(),
 5049                        ranges_for_buffer,
 5050                        1,
 5051                        cx,
 5052                    ));
 5053                }
 5054                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 5055            });
 5056
 5057            workspace.update(&mut cx, |workspace, cx| {
 5058                let editor =
 5059                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 5060                editor.update(cx, |editor, cx| {
 5061                    editor.highlight_background::<Self>(
 5062                        ranges_to_highlight,
 5063                        |theme| theme.editor.highlighted_line_background,
 5064                        cx,
 5065                    );
 5066                });
 5067                workspace.add_item(Box::new(editor), cx);
 5068            });
 5069
 5070            Ok(())
 5071        }))
 5072    }
 5073
 5074    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 5075        use language::ToOffset as _;
 5076
 5077        let project = self.project.clone()?;
 5078        let selection = self.selections.newest_anchor().clone();
 5079        let (cursor_buffer, cursor_buffer_position) = self
 5080            .buffer
 5081            .read(cx)
 5082            .text_anchor_for_position(selection.head(), cx)?;
 5083        let (tail_buffer, _) = self
 5084            .buffer
 5085            .read(cx)
 5086            .text_anchor_for_position(selection.tail(), cx)?;
 5087        if tail_buffer != cursor_buffer {
 5088            return None;
 5089        }
 5090
 5091        let snapshot = cursor_buffer.read(cx).snapshot();
 5092        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 5093        let prepare_rename = project.update(cx, |project, cx| {
 5094            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 5095        });
 5096
 5097        Some(cx.spawn(|this, mut cx| async move {
 5098            let rename_range = if let Some(range) = prepare_rename.await? {
 5099                Some(range)
 5100            } else {
 5101                this.read_with(&cx, |this, cx| {
 5102                    let buffer = this.buffer.read(cx).snapshot(cx);
 5103                    let mut buffer_highlights = this
 5104                        .document_highlights_for_position(selection.head(), &buffer)
 5105                        .filter(|highlight| {
 5106                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 5107                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 5108                        });
 5109                    buffer_highlights
 5110                        .next()
 5111                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 5112                })
 5113            };
 5114            if let Some(rename_range) = rename_range {
 5115                let rename_buffer_range = rename_range.to_offset(&snapshot);
 5116                let cursor_offset_in_rename_range =
 5117                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 5118
 5119                this.update(&mut cx, |this, cx| {
 5120                    this.take_rename(false, cx);
 5121                    let style = this.style(cx);
 5122                    let buffer = this.buffer.read(cx).read(cx);
 5123                    let cursor_offset = selection.head().to_offset(&buffer);
 5124                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 5125                    let rename_end = rename_start + rename_buffer_range.len();
 5126                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 5127                    let mut old_highlight_id = None;
 5128                    let old_name: Arc<str> = buffer
 5129                        .chunks(rename_start..rename_end, true)
 5130                        .map(|chunk| {
 5131                            if old_highlight_id.is_none() {
 5132                                old_highlight_id = chunk.syntax_highlight_id;
 5133                            }
 5134                            chunk.text
 5135                        })
 5136                        .collect::<String>()
 5137                        .into();
 5138
 5139                    drop(buffer);
 5140
 5141                    // Position the selection in the rename editor so that it matches the current selection.
 5142                    this.show_local_selections = false;
 5143                    let rename_editor = cx.add_view(|cx| {
 5144                        let mut editor = Editor::single_line(None, cx);
 5145                        if let Some(old_highlight_id) = old_highlight_id {
 5146                            editor.override_text_style =
 5147                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 5148                        }
 5149                        editor.buffer.update(cx, |buffer, cx| {
 5150                            buffer.edit([(0..0, old_name.clone())], None, cx)
 5151                        });
 5152                        editor.select_all(&SelectAll, cx);
 5153                        editor
 5154                    });
 5155
 5156                    let ranges = this
 5157                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 5158                        .into_iter()
 5159                        .flat_map(|(_, ranges)| ranges)
 5160                        .chain(
 5161                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 5162                                .into_iter()
 5163                                .flat_map(|(_, ranges)| ranges),
 5164                        )
 5165                        .collect();
 5166
 5167                    this.highlight_text::<Rename>(
 5168                        ranges,
 5169                        HighlightStyle {
 5170                            fade_out: Some(style.rename_fade),
 5171                            ..Default::default()
 5172                        },
 5173                        cx,
 5174                    );
 5175                    cx.focus(&rename_editor);
 5176                    let block_id = this.insert_blocks(
 5177                        [BlockProperties {
 5178                            style: BlockStyle::Flex,
 5179                            position: range.start.clone(),
 5180                            height: 1,
 5181                            render: Arc::new({
 5182                                let editor = rename_editor.clone();
 5183                                move |cx: &mut BlockContext| {
 5184                                    ChildView::new(editor.clone())
 5185                                        .contained()
 5186                                        .with_padding_left(cx.anchor_x)
 5187                                        .boxed()
 5188                                }
 5189                            }),
 5190                            disposition: BlockDisposition::Below,
 5191                        }],
 5192                        cx,
 5193                    )[0];
 5194                    this.pending_rename = Some(RenameState {
 5195                        range,
 5196                        old_name,
 5197                        editor: rename_editor,
 5198                        block_id,
 5199                    });
 5200                });
 5201            }
 5202
 5203            Ok(())
 5204        }))
 5205    }
 5206
 5207    pub fn confirm_rename(
 5208        workspace: &mut Workspace,
 5209        _: &ConfirmRename,
 5210        cx: &mut ViewContext<Workspace>,
 5211    ) -> Option<Task<Result<()>>> {
 5212        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 5213
 5214        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 5215            let rename = editor.take_rename(false, cx)?;
 5216            let buffer = editor.buffer.read(cx);
 5217            let (start_buffer, start) =
 5218                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 5219            let (end_buffer, end) =
 5220                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 5221            if start_buffer == end_buffer {
 5222                let new_name = rename.editor.read(cx).text(cx);
 5223                Some((start_buffer, start..end, rename.old_name, new_name))
 5224            } else {
 5225                None
 5226            }
 5227        })?;
 5228
 5229        let rename = workspace.project().clone().update(cx, |project, cx| {
 5230            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 5231        });
 5232
 5233        Some(cx.spawn(|workspace, mut cx| async move {
 5234            let project_transaction = rename.await?;
 5235            Self::open_project_transaction(
 5236                editor.clone(),
 5237                workspace,
 5238                project_transaction,
 5239                format!("Rename: {}{}", old_name, new_name),
 5240                cx.clone(),
 5241            )
 5242            .await?;
 5243
 5244            editor.update(&mut cx, |editor, cx| {
 5245                editor.refresh_document_highlights(cx);
 5246            });
 5247            Ok(())
 5248        }))
 5249    }
 5250
 5251    fn take_rename(
 5252        &mut self,
 5253        moving_cursor: bool,
 5254        cx: &mut ViewContext<Self>,
 5255    ) -> Option<RenameState> {
 5256        let rename = self.pending_rename.take()?;
 5257        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 5258        self.clear_text_highlights::<Rename>(cx);
 5259        self.show_local_selections = true;
 5260
 5261        if moving_cursor {
 5262            let rename_editor = rename.editor.read(cx);
 5263            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 5264
 5265            // Update the selection to match the position of the selection inside
 5266            // the rename editor.
 5267            let snapshot = self.buffer.read(cx).read(cx);
 5268            let rename_range = rename.range.to_offset(&snapshot);
 5269            let cursor_in_editor = snapshot
 5270                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 5271                .min(rename_range.end);
 5272            drop(snapshot);
 5273
 5274            self.change_selections(None, cx, |s| {
 5275                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 5276            });
 5277        } else {
 5278            self.refresh_document_highlights(cx);
 5279        }
 5280
 5281        Some(rename)
 5282    }
 5283
 5284    #[cfg(any(test, feature = "test-support"))]
 5285    pub fn pending_rename(&self) -> Option<&RenameState> {
 5286        self.pending_rename.as_ref()
 5287    }
 5288
 5289    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
 5290        let project = match &self.project {
 5291            Some(project) => project.clone(),
 5292            None => return None,
 5293        };
 5294
 5295        Some(self.perform_format(project, cx))
 5296    }
 5297
 5298    fn perform_format(
 5299        &mut self,
 5300        project: ModelHandle<Project>,
 5301        cx: &mut ViewContext<'_, Self>,
 5302    ) -> Task<Result<()>> {
 5303        let buffer = self.buffer().clone();
 5304        let buffers = buffer.read(cx).all_buffers();
 5305
 5306        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
 5307        let format = project.update(cx, |project, cx| {
 5308            project.format(buffers, true, FormatTrigger::Manual, cx)
 5309        });
 5310
 5311        cx.spawn(|_, mut cx| async move {
 5312            let transaction = futures::select_biased! {
 5313                _ = timeout => {
 5314                    log::warn!("timed out waiting for formatting");
 5315                    None
 5316                }
 5317                transaction = format.log_err().fuse() => transaction,
 5318            };
 5319
 5320            buffer.update(&mut cx, |buffer, cx| {
 5321                if let Some(transaction) = transaction {
 5322                    if !buffer.is_singleton() {
 5323                        buffer.push_transaction(&transaction.0);
 5324                    }
 5325                }
 5326
 5327                cx.notify();
 5328            });
 5329
 5330            Ok(())
 5331        })
 5332    }
 5333
 5334    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 5335        if let Some(project) = self.project.clone() {
 5336            self.buffer.update(cx, |multi_buffer, cx| {
 5337                project.update(cx, |project, cx| {
 5338                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 5339                });
 5340            })
 5341        }
 5342    }
 5343
 5344    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 5345        cx.show_character_palette();
 5346    }
 5347
 5348    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 5349        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 5350            let buffer = self.buffer.read(cx).snapshot(cx);
 5351            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 5352            let is_valid = buffer
 5353                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 5354                .any(|entry| {
 5355                    entry.diagnostic.is_primary
 5356                        && !entry.range.is_empty()
 5357                        && entry.range.start == primary_range_start
 5358                        && entry.diagnostic.message == active_diagnostics.primary_message
 5359                });
 5360
 5361            if is_valid != active_diagnostics.is_valid {
 5362                active_diagnostics.is_valid = is_valid;
 5363                let mut new_styles = HashMap::default();
 5364                for (block_id, diagnostic) in &active_diagnostics.blocks {
 5365                    new_styles.insert(
 5366                        *block_id,
 5367                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 5368                    );
 5369                }
 5370                self.display_map
 5371                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 5372            }
 5373        }
 5374    }
 5375
 5376    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 5377        self.dismiss_diagnostics(cx);
 5378        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 5379            let buffer = self.buffer.read(cx).snapshot(cx);
 5380
 5381            let mut primary_range = None;
 5382            let mut primary_message = None;
 5383            let mut group_end = Point::zero();
 5384            let diagnostic_group = buffer
 5385                .diagnostic_group::<Point>(group_id)
 5386                .map(|entry| {
 5387                    if entry.range.end > group_end {
 5388                        group_end = entry.range.end;
 5389                    }
 5390                    if entry.diagnostic.is_primary {
 5391                        primary_range = Some(entry.range.clone());
 5392                        primary_message = Some(entry.diagnostic.message.clone());
 5393                    }
 5394                    entry
 5395                })
 5396                .collect::<Vec<_>>();
 5397            let primary_range = primary_range?;
 5398            let primary_message = primary_message?;
 5399            let primary_range =
 5400                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5401
 5402            let blocks = display_map
 5403                .insert_blocks(
 5404                    diagnostic_group.iter().map(|entry| {
 5405                        let diagnostic = entry.diagnostic.clone();
 5406                        let message_height = diagnostic.message.lines().count() as u8;
 5407                        BlockProperties {
 5408                            style: BlockStyle::Fixed,
 5409                            position: buffer.anchor_after(entry.range.start),
 5410                            height: message_height,
 5411                            render: diagnostic_block_renderer(diagnostic, true),
 5412                            disposition: BlockDisposition::Below,
 5413                        }
 5414                    }),
 5415                    cx,
 5416                )
 5417                .into_iter()
 5418                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5419                .collect();
 5420
 5421            Some(ActiveDiagnosticGroup {
 5422                primary_range,
 5423                primary_message,
 5424                blocks,
 5425                is_valid: true,
 5426            })
 5427        });
 5428        self.active_diagnostics.is_some()
 5429    }
 5430
 5431    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5432        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5433            self.display_map.update(cx, |display_map, cx| {
 5434                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5435            });
 5436            cx.notify();
 5437        }
 5438    }
 5439
 5440    pub fn set_selections_from_remote(
 5441        &mut self,
 5442        selections: Vec<Selection<Anchor>>,
 5443        cx: &mut ViewContext<Self>,
 5444    ) {
 5445        let old_cursor_position = self.selections.newest_anchor().head();
 5446        self.selections.change_with(cx, |s| {
 5447            s.select_anchors(selections);
 5448        });
 5449        self.selections_did_change(false, &old_cursor_position, cx);
 5450    }
 5451
 5452    fn push_to_selection_history(&mut self) {
 5453        self.selection_history.push(SelectionHistoryEntry {
 5454            selections: self.selections.disjoint_anchors(),
 5455            select_next_state: self.select_next_state.clone(),
 5456            add_selections_state: self.add_selections_state.clone(),
 5457        });
 5458    }
 5459
 5460    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5461        self.autoscroll_request = Some((autoscroll, true));
 5462        cx.notify();
 5463    }
 5464
 5465    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5466        self.autoscroll_request = Some((autoscroll, false));
 5467        cx.notify();
 5468    }
 5469
 5470    pub fn transact(
 5471        &mut self,
 5472        cx: &mut ViewContext<Self>,
 5473        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5474    ) -> Option<TransactionId> {
 5475        self.start_transaction_at(Instant::now(), cx);
 5476        update(self, cx);
 5477        self.end_transaction_at(Instant::now(), cx)
 5478    }
 5479
 5480    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5481        self.end_selection(cx);
 5482        if let Some(tx_id) = self
 5483            .buffer
 5484            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5485        {
 5486            self.selection_history
 5487                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 5488        }
 5489    }
 5490
 5491    fn end_transaction_at(
 5492        &mut self,
 5493        now: Instant,
 5494        cx: &mut ViewContext<Self>,
 5495    ) -> Option<TransactionId> {
 5496        if let Some(tx_id) = self
 5497            .buffer
 5498            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5499        {
 5500            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5501                *end_selections = Some(self.selections.disjoint_anchors());
 5502            } else {
 5503                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5504            }
 5505
 5506            cx.emit(Event::Edited);
 5507            Some(tx_id)
 5508        } else {
 5509            None
 5510        }
 5511    }
 5512
 5513    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5514        log::info!("Editor::page_up");
 5515    }
 5516
 5517    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5518        log::info!("Editor::page_down");
 5519    }
 5520
 5521    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5522        let mut fold_ranges = Vec::new();
 5523
 5524        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5525        let selections = self.selections.all::<Point>(cx);
 5526        for selection in selections {
 5527            let range = selection.display_range(&display_map).sorted();
 5528            let buffer_start_row = range.start.to_point(&display_map).row;
 5529
 5530            for row in (0..=range.end.row()).rev() {
 5531                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5532                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5533                    if fold_range.end.row >= buffer_start_row {
 5534                        fold_ranges.push(fold_range);
 5535                        if row <= range.start.row() {
 5536                            break;
 5537                        }
 5538                    }
 5539                }
 5540            }
 5541        }
 5542
 5543        self.fold_ranges(fold_ranges, cx);
 5544    }
 5545
 5546    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5547        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5548        let buffer = &display_map.buffer_snapshot;
 5549        let selections = self.selections.all::<Point>(cx);
 5550        let ranges = selections
 5551            .iter()
 5552            .map(|s| {
 5553                let range = s.display_range(&display_map).sorted();
 5554                let mut start = range.start.to_point(&display_map);
 5555                let mut end = range.end.to_point(&display_map);
 5556                start.column = 0;
 5557                end.column = buffer.line_len(end.row);
 5558                start..end
 5559            })
 5560            .collect::<Vec<_>>();
 5561        self.unfold_ranges(ranges, true, cx);
 5562    }
 5563
 5564    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5565        let max_point = display_map.max_point();
 5566        if display_row >= max_point.row() {
 5567            false
 5568        } else {
 5569            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5570            if is_blank {
 5571                false
 5572            } else {
 5573                for display_row in display_row + 1..=max_point.row() {
 5574                    let (indent, is_blank) = display_map.line_indent(display_row);
 5575                    if !is_blank {
 5576                        return indent > start_indent;
 5577                    }
 5578                }
 5579                false
 5580            }
 5581        }
 5582    }
 5583
 5584    fn foldable_range_for_line(
 5585        &self,
 5586        display_map: &DisplaySnapshot,
 5587        start_row: u32,
 5588    ) -> Range<Point> {
 5589        let max_point = display_map.max_point();
 5590
 5591        let (start_indent, _) = display_map.line_indent(start_row);
 5592        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5593        let mut end = None;
 5594        for row in start_row + 1..=max_point.row() {
 5595            let (indent, is_blank) = display_map.line_indent(row);
 5596            if !is_blank && indent <= start_indent {
 5597                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5598                break;
 5599            }
 5600        }
 5601
 5602        let end = end.unwrap_or(max_point);
 5603        start.to_point(display_map)..end.to_point(display_map)
 5604    }
 5605
 5606    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5607        let selections = self.selections.all::<Point>(cx);
 5608        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5609        self.fold_ranges(ranges, cx);
 5610    }
 5611
 5612    pub fn fold_ranges<T: ToOffset>(
 5613        &mut self,
 5614        ranges: impl IntoIterator<Item = Range<T>>,
 5615        cx: &mut ViewContext<Self>,
 5616    ) {
 5617        let mut ranges = ranges.into_iter().peekable();
 5618        if ranges.peek().is_some() {
 5619            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5620            self.request_autoscroll(Autoscroll::Fit, cx);
 5621            cx.notify();
 5622        }
 5623    }
 5624
 5625    pub fn unfold_ranges<T: ToOffset>(
 5626        &mut self,
 5627        ranges: impl IntoIterator<Item = Range<T>>,
 5628        inclusive: bool,
 5629        cx: &mut ViewContext<Self>,
 5630    ) {
 5631        let mut ranges = ranges.into_iter().peekable();
 5632        if ranges.peek().is_some() {
 5633            self.display_map
 5634                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5635            self.request_autoscroll(Autoscroll::Fit, cx);
 5636            cx.notify();
 5637        }
 5638    }
 5639
 5640    pub fn insert_blocks(
 5641        &mut self,
 5642        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5643        cx: &mut ViewContext<Self>,
 5644    ) -> Vec<BlockId> {
 5645        let blocks = self
 5646            .display_map
 5647            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5648        self.request_autoscroll(Autoscroll::Fit, cx);
 5649        blocks
 5650    }
 5651
 5652    pub fn replace_blocks(
 5653        &mut self,
 5654        blocks: HashMap<BlockId, RenderBlock>,
 5655        cx: &mut ViewContext<Self>,
 5656    ) {
 5657        self.display_map
 5658            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5659        self.request_autoscroll(Autoscroll::Fit, cx);
 5660    }
 5661
 5662    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5663        self.display_map.update(cx, |display_map, cx| {
 5664            display_map.remove_blocks(block_ids, cx)
 5665        });
 5666    }
 5667
 5668    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5669        self.display_map
 5670            .update(cx, |map, cx| map.snapshot(cx))
 5671            .longest_row()
 5672    }
 5673
 5674    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5675        self.display_map
 5676            .update(cx, |map, cx| map.snapshot(cx))
 5677            .max_point()
 5678    }
 5679
 5680    pub fn text(&self, cx: &AppContext) -> String {
 5681        self.buffer.read(cx).read(cx).text()
 5682    }
 5683
 5684    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5685        self.transact(cx, |this, cx| {
 5686            this.buffer
 5687                .read(cx)
 5688                .as_singleton()
 5689                .expect("you can only call set_text on editors for singleton buffers")
 5690                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5691        });
 5692    }
 5693
 5694    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5695        self.display_map
 5696            .update(cx, |map, cx| map.snapshot(cx))
 5697            .text()
 5698    }
 5699
 5700    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5701        let language_name = self
 5702            .buffer
 5703            .read(cx)
 5704            .as_singleton()
 5705            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5706            .map(|l| l.name());
 5707
 5708        let settings = cx.global::<Settings>();
 5709        let mode = self
 5710            .soft_wrap_mode_override
 5711            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5712        match mode {
 5713            settings::SoftWrap::None => SoftWrap::None,
 5714            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5715            settings::SoftWrap::PreferredLineLength => {
 5716                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5717            }
 5718        }
 5719    }
 5720
 5721    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5722        self.soft_wrap_mode_override = Some(mode);
 5723        cx.notify();
 5724    }
 5725
 5726    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5727        self.display_map
 5728            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5729    }
 5730
 5731    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5732        self.highlighted_rows = rows;
 5733    }
 5734
 5735    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5736        self.highlighted_rows.clone()
 5737    }
 5738
 5739    pub fn highlight_background<T: 'static>(
 5740        &mut self,
 5741        ranges: Vec<Range<Anchor>>,
 5742        color_fetcher: fn(&Theme) -> Color,
 5743        cx: &mut ViewContext<Self>,
 5744    ) {
 5745        self.background_highlights
 5746            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5747        cx.notify();
 5748    }
 5749
 5750    #[allow(clippy::type_complexity)]
 5751    pub fn clear_background_highlights<T: 'static>(
 5752        &mut self,
 5753        cx: &mut ViewContext<Self>,
 5754    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5755        cx.notify();
 5756        self.background_highlights.remove(&TypeId::of::<T>())
 5757    }
 5758
 5759    #[cfg(feature = "test-support")]
 5760    pub fn all_background_highlights(
 5761        &mut self,
 5762        cx: &mut ViewContext<Self>,
 5763    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5764        let snapshot = self.snapshot(cx);
 5765        let buffer = &snapshot.buffer_snapshot;
 5766        let start = buffer.anchor_before(0);
 5767        let end = buffer.anchor_after(buffer.len());
 5768        let theme = cx.global::<Settings>().theme.as_ref();
 5769        self.background_highlights_in_range(start..end, &snapshot, theme)
 5770    }
 5771
 5772    fn document_highlights_for_position<'a>(
 5773        &'a self,
 5774        position: Anchor,
 5775        buffer: &'a MultiBufferSnapshot,
 5776    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5777        let read_highlights = self
 5778            .background_highlights
 5779            .get(&TypeId::of::<DocumentHighlightRead>())
 5780            .map(|h| &h.1);
 5781        let write_highlights = self
 5782            .background_highlights
 5783            .get(&TypeId::of::<DocumentHighlightWrite>())
 5784            .map(|h| &h.1);
 5785        let left_position = position.bias_left(buffer);
 5786        let right_position = position.bias_right(buffer);
 5787        read_highlights
 5788            .into_iter()
 5789            .chain(write_highlights)
 5790            .flat_map(move |ranges| {
 5791                let start_ix = match ranges.binary_search_by(|probe| {
 5792                    let cmp = probe.end.cmp(&left_position, buffer);
 5793                    if cmp.is_ge() {
 5794                        Ordering::Greater
 5795                    } else {
 5796                        Ordering::Less
 5797                    }
 5798                }) {
 5799                    Ok(i) | Err(i) => i,
 5800                };
 5801
 5802                let right_position = right_position.clone();
 5803                ranges[start_ix..]
 5804                    .iter()
 5805                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 5806            })
 5807    }
 5808
 5809    pub fn background_highlights_in_range(
 5810        &self,
 5811        search_range: Range<Anchor>,
 5812        display_snapshot: &DisplaySnapshot,
 5813        theme: &Theme,
 5814    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5815        let mut results = Vec::new();
 5816        let buffer = &display_snapshot.buffer_snapshot;
 5817        for (color_fetcher, ranges) in self.background_highlights.values() {
 5818            let color = color_fetcher(theme);
 5819            let start_ix = match ranges.binary_search_by(|probe| {
 5820                let cmp = probe.end.cmp(&search_range.start, buffer);
 5821                if cmp.is_gt() {
 5822                    Ordering::Greater
 5823                } else {
 5824                    Ordering::Less
 5825                }
 5826            }) {
 5827                Ok(i) | Err(i) => i,
 5828            };
 5829            for range in &ranges[start_ix..] {
 5830                if range.start.cmp(&search_range.end, buffer).is_ge() {
 5831                    break;
 5832                }
 5833                let start = range
 5834                    .start
 5835                    .to_point(buffer)
 5836                    .to_display_point(display_snapshot);
 5837                let end = range
 5838                    .end
 5839                    .to_point(buffer)
 5840                    .to_display_point(display_snapshot);
 5841                results.push((start..end, color))
 5842            }
 5843        }
 5844        results
 5845    }
 5846
 5847    pub fn highlight_text<T: 'static>(
 5848        &mut self,
 5849        ranges: Vec<Range<Anchor>>,
 5850        style: HighlightStyle,
 5851        cx: &mut ViewContext<Self>,
 5852    ) {
 5853        self.display_map.update(cx, |map, _| {
 5854            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5855        });
 5856        cx.notify();
 5857    }
 5858
 5859    pub fn text_highlights<'a, T: 'static>(
 5860        &'a self,
 5861        cx: &'a AppContext,
 5862    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 5863        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 5864    }
 5865
 5866    pub fn clear_text_highlights<T: 'static>(
 5867        &mut self,
 5868        cx: &mut ViewContext<Self>,
 5869    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5870        cx.notify();
 5871        self.display_map
 5872            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5873    }
 5874
 5875    fn next_blink_epoch(&mut self) -> usize {
 5876        self.blink_epoch += 1;
 5877        self.blink_epoch
 5878    }
 5879
 5880    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5881        if !self.focused {
 5882            return;
 5883        }
 5884
 5885        self.show_local_cursors = true;
 5886        cx.notify();
 5887
 5888        let epoch = self.next_blink_epoch();
 5889        cx.spawn(|this, mut cx| {
 5890            let this = this.downgrade();
 5891            async move {
 5892                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5893                if let Some(this) = this.upgrade(&cx) {
 5894                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5895                }
 5896            }
 5897        })
 5898        .detach();
 5899    }
 5900
 5901    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5902        if epoch == self.blink_epoch {
 5903            self.blinking_paused = false;
 5904            self.blink_cursors(epoch, cx);
 5905        }
 5906    }
 5907
 5908    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5909        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5910            self.show_local_cursors = !self.show_local_cursors;
 5911            cx.notify();
 5912
 5913            let epoch = self.next_blink_epoch();
 5914            cx.spawn(|this, mut cx| {
 5915                let this = this.downgrade();
 5916                async move {
 5917                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5918                    if let Some(this) = this.upgrade(&cx) {
 5919                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5920                    }
 5921                }
 5922            })
 5923            .detach();
 5924        }
 5925    }
 5926
 5927    pub fn show_local_cursors(&self) -> bool {
 5928        self.show_local_cursors && self.focused
 5929    }
 5930
 5931    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5932        cx.notify();
 5933    }
 5934
 5935    fn on_buffer_event(
 5936        &mut self,
 5937        _: ModelHandle<MultiBuffer>,
 5938        event: &language::Event,
 5939        cx: &mut ViewContext<Self>,
 5940    ) {
 5941        match event {
 5942            language::Event::Edited => {
 5943                self.refresh_active_diagnostics(cx);
 5944                self.refresh_code_actions(cx);
 5945                cx.emit(Event::BufferEdited);
 5946            }
 5947            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5948            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 5949            language::Event::Saved => cx.emit(Event::Saved),
 5950            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5951            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5952            language::Event::Closed => cx.emit(Event::Closed),
 5953            language::Event::DiagnosticsUpdated => {
 5954                self.refresh_active_diagnostics(cx);
 5955            }
 5956            _ => {}
 5957        }
 5958    }
 5959
 5960    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5961        cx.notify();
 5962    }
 5963
 5964    pub fn set_searchable(&mut self, searchable: bool) {
 5965        self.searchable = searchable;
 5966    }
 5967
 5968    pub fn searchable(&self) -> bool {
 5969        self.searchable
 5970    }
 5971
 5972    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5973        let active_item = workspace.active_item(cx);
 5974        let editor_handle = if let Some(editor) = active_item
 5975            .as_ref()
 5976            .and_then(|item| item.act_as::<Self>(cx))
 5977        {
 5978            editor
 5979        } else {
 5980            cx.propagate_action();
 5981            return;
 5982        };
 5983
 5984        let editor = editor_handle.read(cx);
 5985        let buffer = editor.buffer.read(cx);
 5986        if buffer.is_singleton() {
 5987            cx.propagate_action();
 5988            return;
 5989        }
 5990
 5991        let mut new_selections_by_buffer = HashMap::default();
 5992        for selection in editor.selections.all::<usize>(cx) {
 5993            for (buffer, mut range) in
 5994                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5995            {
 5996                if selection.reversed {
 5997                    mem::swap(&mut range.start, &mut range.end);
 5998                }
 5999                new_selections_by_buffer
 6000                    .entry(buffer)
 6001                    .or_insert(Vec::new())
 6002                    .push(range)
 6003            }
 6004        }
 6005
 6006        editor_handle.update(cx, |editor, cx| {
 6007            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 6008        });
 6009        let pane = workspace.active_pane().clone();
 6010        pane.update(cx, |pane, _| pane.disable_history());
 6011
 6012        // We defer the pane interaction because we ourselves are a workspace item
 6013        // and activating a new item causes the pane to call a method on us reentrantly,
 6014        // which panics if we're on the stack.
 6015        cx.defer(move |workspace, cx| {
 6016            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 6017                let editor = workspace.open_project_item::<Self>(buffer, cx);
 6018                editor.update(cx, |editor, cx| {
 6019                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 6020                        s.select_ranges(ranges);
 6021                    });
 6022                });
 6023            }
 6024
 6025            pane.update(cx, |pane, _| pane.enable_history());
 6026        });
 6027    }
 6028
 6029    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 6030        let editor = workspace.open_path(action.path.clone(), true, cx);
 6031        let position = action.position;
 6032        let anchor = action.anchor;
 6033        cx.spawn_weak(|_, mut cx| async move {
 6034            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 6035            editor.update(&mut cx, |editor, cx| {
 6036                let buffer = editor.buffer().read(cx).as_singleton()?;
 6037                let buffer = buffer.read(cx);
 6038                let cursor = if buffer.can_resolve(&anchor) {
 6039                    language::ToPoint::to_point(&anchor, buffer)
 6040                } else {
 6041                    buffer.clip_point(position, Bias::Left)
 6042                };
 6043
 6044                let nav_history = editor.nav_history.take();
 6045                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 6046                    s.select_ranges([cursor..cursor]);
 6047                });
 6048                editor.nav_history = nav_history;
 6049
 6050                Some(())
 6051            })?;
 6052            Some(())
 6053        })
 6054        .detach()
 6055    }
 6056
 6057    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 6058        let snapshot = self.buffer.read(cx).read(cx);
 6059        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 6060        Some(
 6061            ranges
 6062                .iter()
 6063                .map(move |range| {
 6064                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 6065                })
 6066                .collect(),
 6067        )
 6068    }
 6069
 6070    fn selection_replacement_ranges(
 6071        &self,
 6072        range: Range<OffsetUtf16>,
 6073        cx: &AppContext,
 6074    ) -> Vec<Range<OffsetUtf16>> {
 6075        let selections = self.selections.all::<OffsetUtf16>(cx);
 6076        let newest_selection = selections
 6077            .iter()
 6078            .max_by_key(|selection| selection.id)
 6079            .unwrap();
 6080        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 6081        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 6082        let snapshot = self.buffer.read(cx).read(cx);
 6083        selections
 6084            .into_iter()
 6085            .map(|mut selection| {
 6086                selection.start.0 =
 6087                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 6088                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 6089                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 6090                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 6091            })
 6092            .collect()
 6093    }
 6094
 6095    fn report_event(&self, name: &str, cx: &AppContext) {
 6096        if let Some((project, file)) = self.project.as_ref().zip(
 6097            self.buffer
 6098                .read(cx)
 6099                .as_singleton()
 6100                .and_then(|b| b.read(cx).file()),
 6101        ) {
 6102            project.read(cx).client().report_event(
 6103                name,
 6104                json!({
 6105                    "file_extension": file
 6106                        .path()
 6107                        .extension()
 6108                        .and_then(|e| e.to_str())
 6109                }),
 6110            );
 6111        }
 6112    }
 6113}
 6114
 6115impl EditorSnapshot {
 6116    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 6117        self.display_snapshot.buffer_snapshot.language_at(position)
 6118    }
 6119
 6120    pub fn is_focused(&self) -> bool {
 6121        self.is_focused
 6122    }
 6123
 6124    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 6125        self.placeholder_text.as_ref()
 6126    }
 6127
 6128    pub fn scroll_position(&self) -> Vector2F {
 6129        compute_scroll_position(
 6130            &self.display_snapshot,
 6131            self.scroll_position,
 6132            &self.scroll_top_anchor,
 6133        )
 6134    }
 6135}
 6136
 6137impl Deref for EditorSnapshot {
 6138    type Target = DisplaySnapshot;
 6139
 6140    fn deref(&self) -> &Self::Target {
 6141        &self.display_snapshot
 6142    }
 6143}
 6144
 6145fn compute_scroll_position(
 6146    snapshot: &DisplaySnapshot,
 6147    mut scroll_position: Vector2F,
 6148    scroll_top_anchor: &Anchor,
 6149) -> Vector2F {
 6150    if *scroll_top_anchor != Anchor::min() {
 6151        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 6152        scroll_position.set_y(scroll_top + scroll_position.y());
 6153    } else {
 6154        scroll_position.set_y(0.);
 6155    }
 6156    scroll_position
 6157}
 6158
 6159#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 6160pub enum Event {
 6161    BufferEdited,
 6162    Edited,
 6163    Reparsed,
 6164    Blurred,
 6165    DirtyChanged,
 6166    Saved,
 6167    TitleChanged,
 6168    SelectionsChanged { local: bool },
 6169    ScrollPositionChanged { local: bool },
 6170    Closed,
 6171    IgnoredInput,
 6172}
 6173
 6174pub struct EditorFocused(pub ViewHandle<Editor>);
 6175pub struct EditorBlurred(pub ViewHandle<Editor>);
 6176pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6177
 6178impl Entity for Editor {
 6179    type Event = Event;
 6180
 6181    fn release(&mut self, cx: &mut MutableAppContext) {
 6182        cx.emit_global(EditorReleased(self.handle.clone()));
 6183    }
 6184}
 6185
 6186impl View for Editor {
 6187    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6188        let style = self.style(cx);
 6189        let font_changed = self.display_map.update(cx, |map, cx| {
 6190            map.set_font(style.text.font_id, style.text.font_size, cx)
 6191        });
 6192
 6193        if font_changed {
 6194            let handle = self.handle.clone();
 6195            cx.defer(move |cx| {
 6196                if let Some(editor) = handle.upgrade(cx) {
 6197                    editor.update(cx, |editor, cx| {
 6198                        hide_hover(editor, cx);
 6199                        hide_link_definition(editor, cx);
 6200                    })
 6201                }
 6202            });
 6203        }
 6204
 6205        Stack::new()
 6206            .with_child(
 6207                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
 6208            )
 6209            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
 6210            .boxed()
 6211    }
 6212
 6213    fn ui_name() -> &'static str {
 6214        "Editor"
 6215    }
 6216
 6217    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6218        let focused_event = EditorFocused(cx.handle());
 6219        cx.emit_global(focused_event);
 6220        if let Some(rename) = self.pending_rename.as_ref() {
 6221            cx.focus(&rename.editor);
 6222        } else {
 6223            self.focused = true;
 6224            self.blink_cursors(self.blink_epoch, cx);
 6225            self.buffer.update(cx, |buffer, cx| {
 6226                buffer.finalize_last_transaction(cx);
 6227                if self.leader_replica_id.is_none() {
 6228                    buffer.set_active_selections(
 6229                        &self.selections.disjoint_anchors(),
 6230                        self.selections.line_mode,
 6231                        cx,
 6232                    );
 6233                }
 6234            });
 6235        }
 6236    }
 6237
 6238    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 6239        let blurred_event = EditorBlurred(cx.handle());
 6240        cx.emit_global(blurred_event);
 6241        self.focused = false;
 6242        self.buffer
 6243            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6244        self.hide_context_menu(cx);
 6245        hide_hover(self, cx);
 6246        cx.emit(Event::Blurred);
 6247        cx.notify();
 6248    }
 6249
 6250    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6251        let mut context = Self::default_keymap_context();
 6252        let mode = match self.mode {
 6253            EditorMode::SingleLine => "single_line",
 6254            EditorMode::AutoHeight { .. } => "auto_height",
 6255            EditorMode::Full => "full",
 6256        };
 6257        context.map.insert("mode".into(), mode.into());
 6258        if self.pending_rename.is_some() {
 6259            context.set.insert("renaming".into());
 6260        }
 6261        match self.context_menu.as_ref() {
 6262            Some(ContextMenu::Completions(_)) => {
 6263                context.set.insert("showing_completions".into());
 6264            }
 6265            Some(ContextMenu::CodeActions(_)) => {
 6266                context.set.insert("showing_code_actions".into());
 6267            }
 6268            None => {}
 6269        }
 6270
 6271        for layer in self.keymap_context_layers.values() {
 6272            context.extend(layer);
 6273        }
 6274
 6275        context
 6276    }
 6277
 6278    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 6279        Some(
 6280            self.buffer
 6281                .read(cx)
 6282                .read(cx)
 6283                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 6284                .collect(),
 6285        )
 6286    }
 6287
 6288    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6289        // Prevent the IME menu from appearing when holding down an alphabetic key
 6290        // while input is disabled.
 6291        if !self.input_enabled {
 6292            return None;
 6293        }
 6294
 6295        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 6296        Some(range.start.0..range.end.0)
 6297    }
 6298
 6299    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 6300        let snapshot = self.buffer.read(cx).read(cx);
 6301        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 6302        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 6303    }
 6304
 6305    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 6306        self.clear_text_highlights::<InputComposition>(cx);
 6307        self.ime_transaction.take();
 6308    }
 6309
 6310    fn replace_text_in_range(
 6311        &mut self,
 6312        range_utf16: Option<Range<usize>>,
 6313        text: &str,
 6314        cx: &mut ViewContext<Self>,
 6315    ) {
 6316        if !self.input_enabled {
 6317            cx.emit(Event::IgnoredInput);
 6318            return;
 6319        }
 6320
 6321        self.transact(cx, |this, cx| {
 6322            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 6323                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6324                Some(this.selection_replacement_ranges(range_utf16, cx))
 6325            } else {
 6326                this.marked_text_ranges(cx)
 6327            };
 6328
 6329            if let Some(new_selected_ranges) = new_selected_ranges {
 6330                this.change_selections(None, cx, |selections| {
 6331                    selections.select_ranges(new_selected_ranges)
 6332                });
 6333            }
 6334            this.handle_input(text, cx);
 6335        });
 6336
 6337        if let Some(transaction) = self.ime_transaction {
 6338            self.buffer.update(cx, |buffer, cx| {
 6339                buffer.group_until_transaction(transaction, cx);
 6340            });
 6341        }
 6342
 6343        self.unmark_text(cx);
 6344    }
 6345
 6346    fn replace_and_mark_text_in_range(
 6347        &mut self,
 6348        range_utf16: Option<Range<usize>>,
 6349        text: &str,
 6350        new_selected_range_utf16: Option<Range<usize>>,
 6351        cx: &mut ViewContext<Self>,
 6352    ) {
 6353        if !self.input_enabled {
 6354            cx.emit(Event::IgnoredInput);
 6355            return;
 6356        }
 6357
 6358        let transaction = self.transact(cx, |this, cx| {
 6359            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 6360                let snapshot = this.buffer.read(cx).read(cx);
 6361                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 6362                    for marked_range in &mut marked_ranges {
 6363                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 6364                        marked_range.start.0 += relative_range_utf16.start;
 6365                        marked_range.start =
 6366                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 6367                        marked_range.end =
 6368                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 6369                    }
 6370                }
 6371                Some(marked_ranges)
 6372            } else if let Some(range_utf16) = range_utf16 {
 6373                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 6374                Some(this.selection_replacement_ranges(range_utf16, cx))
 6375            } else {
 6376                None
 6377            };
 6378
 6379            if let Some(ranges) = ranges_to_replace {
 6380                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 6381            }
 6382
 6383            let marked_ranges = {
 6384                let snapshot = this.buffer.read(cx).read(cx);
 6385                this.selections
 6386                    .disjoint_anchors()
 6387                    .iter()
 6388                    .map(|selection| {
 6389                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 6390                    })
 6391                    .collect::<Vec<_>>()
 6392            };
 6393
 6394            if text.is_empty() {
 6395                this.unmark_text(cx);
 6396            } else {
 6397                this.highlight_text::<InputComposition>(
 6398                    marked_ranges.clone(),
 6399                    this.style(cx).composition_mark,
 6400                    cx,
 6401                );
 6402            }
 6403
 6404            this.handle_input(text, cx);
 6405
 6406            if let Some(new_selected_range) = new_selected_range_utf16 {
 6407                let snapshot = this.buffer.read(cx).read(cx);
 6408                let new_selected_ranges = marked_ranges
 6409                    .into_iter()
 6410                    .map(|marked_range| {
 6411                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 6412                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 6413                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 6414                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 6415                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 6416                    })
 6417                    .collect::<Vec<_>>();
 6418
 6419                drop(snapshot);
 6420                this.change_selections(None, cx, |selections| {
 6421                    selections.select_ranges(new_selected_ranges)
 6422                });
 6423            }
 6424        });
 6425
 6426        self.ime_transaction = self.ime_transaction.or(transaction);
 6427        if let Some(transaction) = self.ime_transaction {
 6428            self.buffer.update(cx, |buffer, cx| {
 6429                buffer.group_until_transaction(transaction, cx);
 6430            });
 6431        }
 6432
 6433        if self.text_highlights::<InputComposition>(cx).is_none() {
 6434            self.ime_transaction.take();
 6435        }
 6436    }
 6437}
 6438
 6439fn build_style(
 6440    settings: &Settings,
 6441    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6442    override_text_style: Option<&OverrideTextStyle>,
 6443    cx: &AppContext,
 6444) -> EditorStyle {
 6445    let font_cache = cx.font_cache();
 6446
 6447    let mut theme = settings.theme.editor.clone();
 6448    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6449        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6450        theme.text_color = field_editor_theme.text.color;
 6451        theme.selection = field_editor_theme.selection;
 6452        theme.background = field_editor_theme
 6453            .container
 6454            .background_color
 6455            .unwrap_or_default();
 6456        EditorStyle {
 6457            text: field_editor_theme.text,
 6458            placeholder_text: field_editor_theme.placeholder_text,
 6459            theme,
 6460        }
 6461    } else {
 6462        let font_family_id = settings.buffer_font_family;
 6463        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6464        let font_properties = Default::default();
 6465        let font_id = font_cache
 6466            .select_font(font_family_id, &font_properties)
 6467            .unwrap();
 6468        let font_size = settings.buffer_font_size;
 6469        EditorStyle {
 6470            text: TextStyle {
 6471                color: settings.theme.editor.text_color,
 6472                font_family_name,
 6473                font_family_id,
 6474                font_id,
 6475                font_size,
 6476                font_properties,
 6477                underline: Default::default(),
 6478            },
 6479            placeholder_text: None,
 6480            theme,
 6481        }
 6482    };
 6483
 6484    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6485        if let Some(highlighted) = style
 6486            .text
 6487            .clone()
 6488            .highlight(highlight_style, font_cache)
 6489            .log_err()
 6490        {
 6491            style.text = highlighted;
 6492        }
 6493    }
 6494
 6495    style
 6496}
 6497
 6498trait SelectionExt {
 6499    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6500    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6501    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6502    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6503        -> Range<u32>;
 6504}
 6505
 6506impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6507    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6508        let start = self.start.to_point(buffer);
 6509        let end = self.end.to_point(buffer);
 6510        if self.reversed {
 6511            end..start
 6512        } else {
 6513            start..end
 6514        }
 6515    }
 6516
 6517    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6518        let start = self.start.to_offset(buffer);
 6519        let end = self.end.to_offset(buffer);
 6520        if self.reversed {
 6521            end..start
 6522        } else {
 6523            start..end
 6524        }
 6525    }
 6526
 6527    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6528        let start = self
 6529            .start
 6530            .to_point(&map.buffer_snapshot)
 6531            .to_display_point(map);
 6532        let end = self
 6533            .end
 6534            .to_point(&map.buffer_snapshot)
 6535            .to_display_point(map);
 6536        if self.reversed {
 6537            end..start
 6538        } else {
 6539            start..end
 6540        }
 6541    }
 6542
 6543    fn spanned_rows(
 6544        &self,
 6545        include_end_if_at_line_start: bool,
 6546        map: &DisplaySnapshot,
 6547    ) -> Range<u32> {
 6548        let start = self.start.to_point(&map.buffer_snapshot);
 6549        let mut end = self.end.to_point(&map.buffer_snapshot);
 6550        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6551            end.row -= 1;
 6552        }
 6553
 6554        let buffer_start = map.prev_line_boundary(start).0;
 6555        let buffer_end = map.next_line_boundary(end).0;
 6556        buffer_start.row..buffer_end.row + 1
 6557    }
 6558}
 6559
 6560impl<T: InvalidationRegion> InvalidationStack<T> {
 6561    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6562    where
 6563        S: Clone + ToOffset,
 6564    {
 6565        while let Some(region) = self.last() {
 6566            let all_selections_inside_invalidation_ranges =
 6567                if selections.len() == region.ranges().len() {
 6568                    selections
 6569                        .iter()
 6570                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 6571                        .all(|(selection, invalidation_range)| {
 6572                            let head = selection.head().to_offset(buffer);
 6573                            invalidation_range.start <= head && invalidation_range.end >= head
 6574                        })
 6575                } else {
 6576                    false
 6577                };
 6578
 6579            if all_selections_inside_invalidation_ranges {
 6580                break;
 6581            } else {
 6582                self.pop();
 6583            }
 6584        }
 6585    }
 6586}
 6587
 6588impl<T> Default for InvalidationStack<T> {
 6589    fn default() -> Self {
 6590        Self(Default::default())
 6591    }
 6592}
 6593
 6594impl<T> Deref for InvalidationStack<T> {
 6595    type Target = Vec<T>;
 6596
 6597    fn deref(&self) -> &Self::Target {
 6598        &self.0
 6599    }
 6600}
 6601
 6602impl<T> DerefMut for InvalidationStack<T> {
 6603    fn deref_mut(&mut self) -> &mut Self::Target {
 6604        &mut self.0
 6605    }
 6606}
 6607
 6608impl InvalidationRegion for SnippetState {
 6609    fn ranges(&self) -> &[Range<Anchor>] {
 6610        &self.ranges[self.active_index]
 6611    }
 6612}
 6613
 6614impl Deref for EditorStyle {
 6615    type Target = theme::Editor;
 6616
 6617    fn deref(&self) -> &Self::Target {
 6618        &self.theme
 6619    }
 6620}
 6621
 6622pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6623    let mut highlighted_lines = Vec::new();
 6624    for line in diagnostic.message.lines() {
 6625        highlighted_lines.push(highlight_diagnostic_message(line));
 6626    }
 6627
 6628    Arc::new(move |cx: &mut BlockContext| {
 6629        let settings = cx.global::<Settings>();
 6630        let theme = &settings.theme.editor;
 6631        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6632        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6633        Flex::column()
 6634            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6635                Label::new(
 6636                    line.clone(),
 6637                    style.message.clone().with_font_size(font_size),
 6638                )
 6639                .with_highlights(highlights.clone())
 6640                .contained()
 6641                .with_margin_left(cx.anchor_x)
 6642                .boxed()
 6643            }))
 6644            .aligned()
 6645            .left()
 6646            .boxed()
 6647    })
 6648}
 6649
 6650pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6651    let mut message_without_backticks = String::new();
 6652    let mut prev_offset = 0;
 6653    let mut inside_block = false;
 6654    let mut highlights = Vec::new();
 6655    for (match_ix, (offset, _)) in message
 6656        .match_indices('`')
 6657        .chain([(message.len(), "")])
 6658        .enumerate()
 6659    {
 6660        message_without_backticks.push_str(&message[prev_offset..offset]);
 6661        if inside_block {
 6662            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6663        }
 6664
 6665        inside_block = !inside_block;
 6666        prev_offset = offset + 1;
 6667    }
 6668
 6669    (message_without_backticks, highlights)
 6670}
 6671
 6672pub fn diagnostic_style(
 6673    severity: DiagnosticSeverity,
 6674    valid: bool,
 6675    theme: &theme::Editor,
 6676) -> DiagnosticStyle {
 6677    match (severity, valid) {
 6678        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6679        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6680        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6681        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6682        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6683        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6684        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6685        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6686        _ => theme.invalid_hint_diagnostic.clone(),
 6687    }
 6688}
 6689
 6690pub fn combine_syntax_and_fuzzy_match_highlights(
 6691    text: &str,
 6692    default_style: HighlightStyle,
 6693    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6694    match_indices: &[usize],
 6695) -> Vec<(Range<usize>, HighlightStyle)> {
 6696    let mut result = Vec::new();
 6697    let mut match_indices = match_indices.iter().copied().peekable();
 6698
 6699    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6700    {
 6701        syntax_highlight.weight = None;
 6702
 6703        // Add highlights for any fuzzy match characters before the next
 6704        // syntax highlight range.
 6705        while let Some(&match_index) = match_indices.peek() {
 6706            if match_index >= range.start {
 6707                break;
 6708            }
 6709            match_indices.next();
 6710            let end_index = char_ix_after(match_index, text);
 6711            let mut match_style = default_style;
 6712            match_style.weight = Some(fonts::Weight::BOLD);
 6713            result.push((match_index..end_index, match_style));
 6714        }
 6715
 6716        if range.start == usize::MAX {
 6717            break;
 6718        }
 6719
 6720        // Add highlights for any fuzzy match characters within the
 6721        // syntax highlight range.
 6722        let mut offset = range.start;
 6723        while let Some(&match_index) = match_indices.peek() {
 6724            if match_index >= range.end {
 6725                break;
 6726            }
 6727
 6728            match_indices.next();
 6729            if match_index > offset {
 6730                result.push((offset..match_index, syntax_highlight));
 6731            }
 6732
 6733            let mut end_index = char_ix_after(match_index, text);
 6734            while let Some(&next_match_index) = match_indices.peek() {
 6735                if next_match_index == end_index && next_match_index < range.end {
 6736                    end_index = char_ix_after(next_match_index, text);
 6737                    match_indices.next();
 6738                } else {
 6739                    break;
 6740                }
 6741            }
 6742
 6743            let mut match_style = syntax_highlight;
 6744            match_style.weight = Some(fonts::Weight::BOLD);
 6745            result.push((match_index..end_index, match_style));
 6746            offset = end_index;
 6747        }
 6748
 6749        if offset < range.end {
 6750            result.push((offset..range.end, syntax_highlight));
 6751        }
 6752    }
 6753
 6754    fn char_ix_after(ix: usize, text: &str) -> usize {
 6755        ix + text[ix..].chars().next().unwrap().len_utf8()
 6756    }
 6757
 6758    result
 6759}
 6760
 6761pub fn styled_runs_for_code_label<'a>(
 6762    label: &'a CodeLabel,
 6763    syntax_theme: &'a theme::SyntaxTheme,
 6764) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6765    let fade_out = HighlightStyle {
 6766        fade_out: Some(0.35),
 6767        ..Default::default()
 6768    };
 6769
 6770    let mut prev_end = label.filter_range.end;
 6771    label
 6772        .runs
 6773        .iter()
 6774        .enumerate()
 6775        .flat_map(move |(ix, (range, highlight_id))| {
 6776            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6777                style
 6778            } else {
 6779                return Default::default();
 6780            };
 6781            let mut muted_style = style;
 6782            muted_style.highlight(fade_out);
 6783
 6784            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6785            if range.start >= label.filter_range.end {
 6786                if range.start > prev_end {
 6787                    runs.push((prev_end..range.start, fade_out));
 6788                }
 6789                runs.push((range.clone(), muted_style));
 6790            } else if range.end <= label.filter_range.end {
 6791                runs.push((range.clone(), style));
 6792            } else {
 6793                runs.push((range.start..label.filter_range.end, style));
 6794                runs.push((label.filter_range.end..range.end, muted_style));
 6795            }
 6796            prev_end = cmp::max(prev_end, range.end);
 6797
 6798            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6799                runs.push((prev_end..label.text.len(), fade_out));
 6800            }
 6801
 6802            runs
 6803        })
 6804}
 6805
 6806#[cfg(test)]
 6807mod tests {
 6808    use crate::test::{
 6809        assert_text_with_selections, build_editor, select_ranges, EditorLspTestContext,
 6810        EditorTestContext,
 6811    };
 6812
 6813    use super::*;
 6814    use futures::StreamExt;
 6815    use gpui::{
 6816        geometry::rect::RectF,
 6817        platform::{WindowBounds, WindowOptions},
 6818    };
 6819    use indoc::indoc;
 6820    use language::{FakeLspAdapter, LanguageConfig, LanguageRegistry};
 6821    use project::FakeFs;
 6822    use settings::EditorSettings;
 6823    use std::{cell::RefCell, rc::Rc, time::Instant};
 6824    use text::Point;
 6825    use unindent::Unindent;
 6826    use util::{
 6827        assert_set_eq,
 6828        test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
 6829    };
 6830    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6831
 6832    #[gpui::test]
 6833    fn test_edit_events(cx: &mut MutableAppContext) {
 6834        cx.set_global(Settings::test(cx));
 6835        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6836
 6837        let events = Rc::new(RefCell::new(Vec::new()));
 6838        let (_, editor1) = cx.add_window(Default::default(), {
 6839            let events = events.clone();
 6840            |cx| {
 6841                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6842                    if matches!(
 6843                        event,
 6844                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6845                    ) {
 6846                        events.borrow_mut().push(("editor1", *event));
 6847                    }
 6848                })
 6849                .detach();
 6850                Editor::for_buffer(buffer.clone(), None, cx)
 6851            }
 6852        });
 6853        let (_, editor2) = cx.add_window(Default::default(), {
 6854            let events = events.clone();
 6855            |cx| {
 6856                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6857                    if matches!(
 6858                        event,
 6859                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6860                    ) {
 6861                        events.borrow_mut().push(("editor2", *event));
 6862                    }
 6863                })
 6864                .detach();
 6865                Editor::for_buffer(buffer.clone(), None, cx)
 6866            }
 6867        });
 6868        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6869
 6870        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6871        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6872        assert_eq!(
 6873            mem::take(&mut *events.borrow_mut()),
 6874            [
 6875                ("editor1", Event::Edited),
 6876                ("editor1", Event::BufferEdited),
 6877                ("editor2", Event::BufferEdited),
 6878                ("editor1", Event::DirtyChanged),
 6879                ("editor2", Event::DirtyChanged)
 6880            ]
 6881        );
 6882
 6883        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6884        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6885        assert_eq!(
 6886            mem::take(&mut *events.borrow_mut()),
 6887            [
 6888                ("editor2", Event::Edited),
 6889                ("editor1", Event::BufferEdited),
 6890                ("editor2", Event::BufferEdited),
 6891            ]
 6892        );
 6893
 6894        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6895        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6896        assert_eq!(
 6897            mem::take(&mut *events.borrow_mut()),
 6898            [
 6899                ("editor1", Event::Edited),
 6900                ("editor1", Event::BufferEdited),
 6901                ("editor2", Event::BufferEdited),
 6902                ("editor1", Event::DirtyChanged),
 6903                ("editor2", Event::DirtyChanged),
 6904            ]
 6905        );
 6906
 6907        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6908        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6909        assert_eq!(
 6910            mem::take(&mut *events.borrow_mut()),
 6911            [
 6912                ("editor1", Event::Edited),
 6913                ("editor1", Event::BufferEdited),
 6914                ("editor2", Event::BufferEdited),
 6915                ("editor1", Event::DirtyChanged),
 6916                ("editor2", Event::DirtyChanged),
 6917            ]
 6918        );
 6919
 6920        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6921        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6922        assert_eq!(
 6923            mem::take(&mut *events.borrow_mut()),
 6924            [
 6925                ("editor2", Event::Edited),
 6926                ("editor1", Event::BufferEdited),
 6927                ("editor2", Event::BufferEdited),
 6928                ("editor1", Event::DirtyChanged),
 6929                ("editor2", Event::DirtyChanged),
 6930            ]
 6931        );
 6932
 6933        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6934        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6935        assert_eq!(
 6936            mem::take(&mut *events.borrow_mut()),
 6937            [
 6938                ("editor2", Event::Edited),
 6939                ("editor1", Event::BufferEdited),
 6940                ("editor2", Event::BufferEdited),
 6941                ("editor1", Event::DirtyChanged),
 6942                ("editor2", Event::DirtyChanged),
 6943            ]
 6944        );
 6945
 6946        // No event is emitted when the mutation is a no-op.
 6947        editor2.update(cx, |editor, cx| {
 6948            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6949
 6950            editor.backspace(&Backspace, cx);
 6951        });
 6952        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6953    }
 6954
 6955    #[gpui::test]
 6956    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6957        cx.set_global(Settings::test(cx));
 6958        let mut now = Instant::now();
 6959        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6960        let group_interval = buffer.read(cx).transaction_group_interval();
 6961        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6962        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6963
 6964        editor.update(cx, |editor, cx| {
 6965            editor.start_transaction_at(now, cx);
 6966            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6967
 6968            editor.insert("cd", cx);
 6969            editor.end_transaction_at(now, cx);
 6970            assert_eq!(editor.text(cx), "12cd56");
 6971            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6972
 6973            editor.start_transaction_at(now, cx);
 6974            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6975            editor.insert("e", cx);
 6976            editor.end_transaction_at(now, cx);
 6977            assert_eq!(editor.text(cx), "12cde6");
 6978            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6979
 6980            now += group_interval + Duration::from_millis(1);
 6981            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6982
 6983            // Simulate an edit in another editor
 6984            buffer.update(cx, |buffer, cx| {
 6985                buffer.start_transaction_at(now, cx);
 6986                buffer.edit([(0..1, "a")], None, cx);
 6987                buffer.edit([(1..1, "b")], None, cx);
 6988                buffer.end_transaction_at(now, cx);
 6989            });
 6990
 6991            assert_eq!(editor.text(cx), "ab2cde6");
 6992            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6993
 6994            // Last transaction happened past the group interval in a different editor.
 6995            // Undo it individually and don't restore selections.
 6996            editor.undo(&Undo, cx);
 6997            assert_eq!(editor.text(cx), "12cde6");
 6998            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6999
 7000            // First two transactions happened within the group interval in this editor.
 7001            // Undo them together and restore selections.
 7002            editor.undo(&Undo, cx);
 7003            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 7004            assert_eq!(editor.text(cx), "123456");
 7005            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 7006
 7007            // Redo the first two transactions together.
 7008            editor.redo(&Redo, cx);
 7009            assert_eq!(editor.text(cx), "12cde6");
 7010            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 7011
 7012            // Redo the last transaction on its own.
 7013            editor.redo(&Redo, cx);
 7014            assert_eq!(editor.text(cx), "ab2cde6");
 7015            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 7016
 7017            // Test empty transactions.
 7018            editor.start_transaction_at(now, cx);
 7019            editor.end_transaction_at(now, cx);
 7020            editor.undo(&Undo, cx);
 7021            assert_eq!(editor.text(cx), "12cde6");
 7022        });
 7023    }
 7024
 7025    #[gpui::test]
 7026    fn test_ime_composition(cx: &mut MutableAppContext) {
 7027        cx.set_global(Settings::test(cx));
 7028        let buffer = cx.add_model(|cx| {
 7029            let mut buffer = language::Buffer::new(0, "abcde", cx);
 7030            // Ensure automatic grouping doesn't occur.
 7031            buffer.set_group_interval(Duration::ZERO);
 7032            buffer
 7033        });
 7034
 7035        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 7036        cx.add_window(Default::default(), |cx| {
 7037            let mut editor = build_editor(buffer.clone(), cx);
 7038
 7039            // Start a new IME composition.
 7040            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 7041            editor.replace_and_mark_text_in_range(Some(0..1), "á", None, cx);
 7042            editor.replace_and_mark_text_in_range(Some(0..1), "ä", None, cx);
 7043            assert_eq!(editor.text(cx), "äbcde");
 7044            assert_eq!(
 7045                editor.marked_text_ranges(cx),
 7046                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 7047            );
 7048
 7049            // Finalize IME composition.
 7050            editor.replace_text_in_range(None, "ā", cx);
 7051            assert_eq!(editor.text(cx), "ābcde");
 7052            assert_eq!(editor.marked_text_ranges(cx), None);
 7053
 7054            // IME composition edits are grouped and are undone/redone at once.
 7055            editor.undo(&Default::default(), cx);
 7056            assert_eq!(editor.text(cx), "abcde");
 7057            assert_eq!(editor.marked_text_ranges(cx), None);
 7058            editor.redo(&Default::default(), cx);
 7059            assert_eq!(editor.text(cx), "ābcde");
 7060            assert_eq!(editor.marked_text_ranges(cx), None);
 7061
 7062            // Start a new IME composition.
 7063            editor.replace_and_mark_text_in_range(Some(0..1), "à", None, cx);
 7064            assert_eq!(
 7065                editor.marked_text_ranges(cx),
 7066                Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
 7067            );
 7068
 7069            // Undoing during an IME composition cancels it.
 7070            editor.undo(&Default::default(), cx);
 7071            assert_eq!(editor.text(cx), "ābcde");
 7072            assert_eq!(editor.marked_text_ranges(cx), None);
 7073
 7074            // Start a new IME composition with an invalid marked range, ensuring it gets clipped.
 7075            editor.replace_and_mark_text_in_range(Some(4..999), "è", None, cx);
 7076            assert_eq!(editor.text(cx), "ābcdè");
 7077            assert_eq!(
 7078                editor.marked_text_ranges(cx),
 7079                Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
 7080            );
 7081
 7082            // Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
 7083            editor.replace_text_in_range(Some(4..999), "ę", cx);
 7084            assert_eq!(editor.text(cx), "ābcdę");
 7085            assert_eq!(editor.marked_text_ranges(cx), None);
 7086
 7087            // Start a new IME composition with multiple cursors.
 7088            editor.change_selections(None, cx, |s| {
 7089                s.select_ranges([
 7090                    OffsetUtf16(1)..OffsetUtf16(1),
 7091                    OffsetUtf16(3)..OffsetUtf16(3),
 7092                    OffsetUtf16(5)..OffsetUtf16(5),
 7093                ])
 7094            });
 7095            editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, cx);
 7096            assert_eq!(editor.text(cx), "XYZbXYZdXYZ");
 7097            assert_eq!(
 7098                editor.marked_text_ranges(cx),
 7099                Some(vec![
 7100                    OffsetUtf16(0)..OffsetUtf16(3),
 7101                    OffsetUtf16(4)..OffsetUtf16(7),
 7102                    OffsetUtf16(8)..OffsetUtf16(11)
 7103                ])
 7104            );
 7105
 7106            // Ensure the newly-marked range gets treated as relative to the previously-marked ranges.
 7107            editor.replace_and_mark_text_in_range(Some(1..2), "1", None, cx);
 7108            assert_eq!(editor.text(cx), "X1ZbX1ZdX1Z");
 7109            assert_eq!(
 7110                editor.marked_text_ranges(cx),
 7111                Some(vec![
 7112                    OffsetUtf16(1)..OffsetUtf16(2),
 7113                    OffsetUtf16(5)..OffsetUtf16(6),
 7114                    OffsetUtf16(9)..OffsetUtf16(10)
 7115                ])
 7116            );
 7117
 7118            // Finalize IME composition with multiple cursors.
 7119            editor.replace_text_in_range(Some(9..10), "2", cx);
 7120            assert_eq!(editor.text(cx), "X2ZbX2ZdX2Z");
 7121            assert_eq!(editor.marked_text_ranges(cx), None);
 7122
 7123            editor
 7124        });
 7125    }
 7126
 7127    #[gpui::test]
 7128    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 7129        cx.set_global(Settings::test(cx));
 7130
 7131        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 7132        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7133        editor.update(cx, |view, cx| {
 7134            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7135        });
 7136        assert_eq!(
 7137            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7138            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7139        );
 7140
 7141        editor.update(cx, |view, cx| {
 7142            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7143        });
 7144
 7145        assert_eq!(
 7146            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7147            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7148        );
 7149
 7150        editor.update(cx, |view, cx| {
 7151            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7152        });
 7153
 7154        assert_eq!(
 7155            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7156            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 7157        );
 7158
 7159        editor.update(cx, |view, cx| {
 7160            view.end_selection(cx);
 7161            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7162        });
 7163
 7164        assert_eq!(
 7165            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7166            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 7167        );
 7168
 7169        editor.update(cx, |view, cx| {
 7170            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 7171            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 7172        });
 7173
 7174        assert_eq!(
 7175            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7176            [
 7177                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 7178                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 7179            ]
 7180        );
 7181
 7182        editor.update(cx, |view, cx| {
 7183            view.end_selection(cx);
 7184        });
 7185
 7186        assert_eq!(
 7187            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 7188            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 7189        );
 7190    }
 7191
 7192    #[gpui::test]
 7193    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 7194        cx.set_global(Settings::test(cx));
 7195        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7196        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7197
 7198        view.update(cx, |view, cx| {
 7199            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 7200            assert_eq!(
 7201                view.selections.display_ranges(cx),
 7202                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 7203            );
 7204        });
 7205
 7206        view.update(cx, |view, cx| {
 7207            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 7208            assert_eq!(
 7209                view.selections.display_ranges(cx),
 7210                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7211            );
 7212        });
 7213
 7214        view.update(cx, |view, cx| {
 7215            view.cancel(&Cancel, cx);
 7216            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7217            assert_eq!(
 7218                view.selections.display_ranges(cx),
 7219                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 7220            );
 7221        });
 7222    }
 7223
 7224    #[gpui::test]
 7225    fn test_clone(cx: &mut gpui::MutableAppContext) {
 7226        let (text, selection_ranges) = marked_text_ranges(
 7227            indoc! {"
 7228                one
 7229                two
 7230                threeˇ
 7231                four
 7232                fiveˇ
 7233            "},
 7234            true,
 7235        );
 7236        cx.set_global(Settings::test(cx));
 7237        let buffer = MultiBuffer::build_simple(&text, cx);
 7238
 7239        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7240
 7241        editor.update(cx, |editor, cx| {
 7242            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 7243            editor.fold_ranges(
 7244                [
 7245                    Point::new(1, 0)..Point::new(2, 0),
 7246                    Point::new(3, 0)..Point::new(4, 0),
 7247                ],
 7248                cx,
 7249            );
 7250        });
 7251
 7252        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 7253            cx.add_window(Default::default(), |cx| editor.clone(cx))
 7254        });
 7255
 7256        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 7257        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 7258
 7259        assert_eq!(
 7260            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 7261            editor.update(cx, |e, cx| e.display_text(cx))
 7262        );
 7263        assert_eq!(
 7264            cloned_snapshot
 7265                .folds_in_range(0..text.len())
 7266                .collect::<Vec<_>>(),
 7267            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 7268        );
 7269        assert_set_eq!(
 7270            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 7271            editor.read(cx).selections.ranges(cx)
 7272        );
 7273        assert_set_eq!(
 7274            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 7275            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 7276        );
 7277    }
 7278
 7279    #[gpui::test]
 7280    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 7281        cx.set_global(Settings::test(cx));
 7282        use workspace::Item;
 7283        let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(None, cx));
 7284        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 7285
 7286        cx.add_view(&pane, |cx| {
 7287            let mut editor = build_editor(buffer.clone(), cx);
 7288            let handle = cx.handle();
 7289            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 7290
 7291            fn pop_history(
 7292                editor: &mut Editor,
 7293                cx: &mut MutableAppContext,
 7294            ) -> Option<NavigationEntry> {
 7295                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 7296            }
 7297
 7298            // Move the cursor a small distance.
 7299            // Nothing is added to the navigation history.
 7300            editor.change_selections(None, cx, |s| {
 7301                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 7302            });
 7303            editor.change_selections(None, cx, |s| {
 7304                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 7305            });
 7306            assert!(pop_history(&mut editor, cx).is_none());
 7307
 7308            // Move the cursor a large distance.
 7309            // The history can jump back to the previous position.
 7310            editor.change_selections(None, cx, |s| {
 7311                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 7312            });
 7313            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7314            editor.navigate(nav_entry.data.unwrap(), cx);
 7315            assert_eq!(nav_entry.item.id(), cx.view_id());
 7316            assert_eq!(
 7317                editor.selections.display_ranges(cx),
 7318                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 7319            );
 7320            assert!(pop_history(&mut editor, cx).is_none());
 7321
 7322            // Move the cursor a small distance via the mouse.
 7323            // Nothing is added to the navigation history.
 7324            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 7325            editor.end_selection(cx);
 7326            assert_eq!(
 7327                editor.selections.display_ranges(cx),
 7328                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7329            );
 7330            assert!(pop_history(&mut editor, cx).is_none());
 7331
 7332            // Move the cursor a large distance via the mouse.
 7333            // The history can jump back to the previous position.
 7334            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 7335            editor.end_selection(cx);
 7336            assert_eq!(
 7337                editor.selections.display_ranges(cx),
 7338                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 7339            );
 7340            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7341            editor.navigate(nav_entry.data.unwrap(), cx);
 7342            assert_eq!(nav_entry.item.id(), cx.view_id());
 7343            assert_eq!(
 7344                editor.selections.display_ranges(cx),
 7345                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 7346            );
 7347            assert!(pop_history(&mut editor, cx).is_none());
 7348
 7349            // Set scroll position to check later
 7350            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 7351            let original_scroll_position = editor.scroll_position;
 7352            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 7353
 7354            // Jump to the end of the document and adjust scroll
 7355            editor.move_to_end(&MoveToEnd, cx);
 7356            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 7357            assert_ne!(editor.scroll_position, original_scroll_position);
 7358            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7359
 7360            let nav_entry = pop_history(&mut editor, cx).unwrap();
 7361            editor.navigate(nav_entry.data.unwrap(), cx);
 7362            assert_eq!(editor.scroll_position, original_scroll_position);
 7363            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 7364
 7365            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 7366            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 7367            invalid_anchor.text_anchor.buffer_id = Some(999);
 7368            let invalid_point = Point::new(9999, 0);
 7369            editor.navigate(
 7370                Box::new(NavigationData {
 7371                    cursor_anchor: invalid_anchor.clone(),
 7372                    cursor_position: invalid_point,
 7373                    scroll_top_anchor: invalid_anchor,
 7374                    scroll_top_row: invalid_point.row,
 7375                    scroll_position: Default::default(),
 7376                }),
 7377                cx,
 7378            );
 7379            assert_eq!(
 7380                editor.selections.display_ranges(cx),
 7381                &[editor.max_point(cx)..editor.max_point(cx)]
 7382            );
 7383            assert_eq!(
 7384                editor.scroll_position(cx),
 7385                vec2f(0., editor.max_point(cx).row() as f32)
 7386            );
 7387
 7388            editor
 7389        });
 7390    }
 7391
 7392    #[gpui::test]
 7393    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 7394        cx.set_global(Settings::test(cx));
 7395        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 7396        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7397
 7398        view.update(cx, |view, cx| {
 7399            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 7400            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 7401            view.end_selection(cx);
 7402
 7403            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 7404            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 7405            view.end_selection(cx);
 7406            assert_eq!(
 7407                view.selections.display_ranges(cx),
 7408                [
 7409                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 7410                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 7411                ]
 7412            );
 7413        });
 7414
 7415        view.update(cx, |view, cx| {
 7416            view.cancel(&Cancel, cx);
 7417            assert_eq!(
 7418                view.selections.display_ranges(cx),
 7419                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 7420            );
 7421        });
 7422
 7423        view.update(cx, |view, cx| {
 7424            view.cancel(&Cancel, cx);
 7425            assert_eq!(
 7426                view.selections.display_ranges(cx),
 7427                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 7428            );
 7429        });
 7430    }
 7431
 7432    #[gpui::test]
 7433    fn test_fold(cx: &mut gpui::MutableAppContext) {
 7434        cx.set_global(Settings::test(cx));
 7435        let buffer = MultiBuffer::build_simple(
 7436            &"
 7437                impl Foo {
 7438                    // Hello!
 7439
 7440                    fn a() {
 7441                        1
 7442                    }
 7443
 7444                    fn b() {
 7445                        2
 7446                    }
 7447
 7448                    fn c() {
 7449                        3
 7450                    }
 7451                }
 7452            "
 7453            .unindent(),
 7454            cx,
 7455        );
 7456        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7457
 7458        view.update(cx, |view, cx| {
 7459            view.change_selections(None, cx, |s| {
 7460                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 7461            });
 7462            view.fold(&Fold, cx);
 7463            assert_eq!(
 7464                view.display_text(cx),
 7465                "
 7466                    impl Foo {
 7467                        // Hello!
 7468
 7469                        fn a() {
 7470                            1
 7471                        }
 7472
 7473                        fn b() {…
 7474                        }
 7475
 7476                        fn c() {…
 7477                        }
 7478                    }
 7479                "
 7480                .unindent(),
 7481            );
 7482
 7483            view.fold(&Fold, cx);
 7484            assert_eq!(
 7485                view.display_text(cx),
 7486                "
 7487                    impl Foo {…
 7488                    }
 7489                "
 7490                .unindent(),
 7491            );
 7492
 7493            view.unfold_lines(&UnfoldLines, cx);
 7494            assert_eq!(
 7495                view.display_text(cx),
 7496                "
 7497                    impl Foo {
 7498                        // Hello!
 7499
 7500                        fn a() {
 7501                            1
 7502                        }
 7503
 7504                        fn b() {…
 7505                        }
 7506
 7507                        fn c() {…
 7508                        }
 7509                    }
 7510                "
 7511                .unindent(),
 7512            );
 7513
 7514            view.unfold_lines(&UnfoldLines, cx);
 7515            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7516        });
 7517    }
 7518
 7519    #[gpui::test]
 7520    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7521        cx.set_global(Settings::test(cx));
 7522        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7523        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7524
 7525        buffer.update(cx, |buffer, cx| {
 7526            buffer.edit(
 7527                vec![
 7528                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7529                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7530                ],
 7531                None,
 7532                cx,
 7533            );
 7534        });
 7535
 7536        view.update(cx, |view, cx| {
 7537            assert_eq!(
 7538                view.selections.display_ranges(cx),
 7539                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7540            );
 7541
 7542            view.move_down(&MoveDown, cx);
 7543            assert_eq!(
 7544                view.selections.display_ranges(cx),
 7545                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7546            );
 7547
 7548            view.move_right(&MoveRight, cx);
 7549            assert_eq!(
 7550                view.selections.display_ranges(cx),
 7551                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7552            );
 7553
 7554            view.move_left(&MoveLeft, cx);
 7555            assert_eq!(
 7556                view.selections.display_ranges(cx),
 7557                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7558            );
 7559
 7560            view.move_up(&MoveUp, cx);
 7561            assert_eq!(
 7562                view.selections.display_ranges(cx),
 7563                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7564            );
 7565
 7566            view.move_to_end(&MoveToEnd, cx);
 7567            assert_eq!(
 7568                view.selections.display_ranges(cx),
 7569                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7570            );
 7571
 7572            view.move_to_beginning(&MoveToBeginning, cx);
 7573            assert_eq!(
 7574                view.selections.display_ranges(cx),
 7575                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7576            );
 7577
 7578            view.change_selections(None, cx, |s| {
 7579                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 7580            });
 7581            view.select_to_beginning(&SelectToBeginning, cx);
 7582            assert_eq!(
 7583                view.selections.display_ranges(cx),
 7584                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7585            );
 7586
 7587            view.select_to_end(&SelectToEnd, cx);
 7588            assert_eq!(
 7589                view.selections.display_ranges(cx),
 7590                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7591            );
 7592        });
 7593    }
 7594
 7595    #[gpui::test]
 7596    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7597        cx.set_global(Settings::test(cx));
 7598        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7599        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7600
 7601        assert_eq!('ⓐ'.len_utf8(), 3);
 7602        assert_eq!('α'.len_utf8(), 2);
 7603
 7604        view.update(cx, |view, cx| {
 7605            view.fold_ranges(
 7606                vec![
 7607                    Point::new(0, 6)..Point::new(0, 12),
 7608                    Point::new(1, 2)..Point::new(1, 4),
 7609                    Point::new(2, 4)..Point::new(2, 8),
 7610                ],
 7611                cx,
 7612            );
 7613            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7614
 7615            view.move_right(&MoveRight, cx);
 7616            assert_eq!(
 7617                view.selections.display_ranges(cx),
 7618                &[empty_range(0, "".len())]
 7619            );
 7620            view.move_right(&MoveRight, cx);
 7621            assert_eq!(
 7622                view.selections.display_ranges(cx),
 7623                &[empty_range(0, "ⓐⓑ".len())]
 7624            );
 7625            view.move_right(&MoveRight, cx);
 7626            assert_eq!(
 7627                view.selections.display_ranges(cx),
 7628                &[empty_range(0, "ⓐⓑ…".len())]
 7629            );
 7630
 7631            view.move_down(&MoveDown, cx);
 7632            assert_eq!(
 7633                view.selections.display_ranges(cx),
 7634                &[empty_range(1, "ab…".len())]
 7635            );
 7636            view.move_left(&MoveLeft, cx);
 7637            assert_eq!(
 7638                view.selections.display_ranges(cx),
 7639                &[empty_range(1, "ab".len())]
 7640            );
 7641            view.move_left(&MoveLeft, cx);
 7642            assert_eq!(
 7643                view.selections.display_ranges(cx),
 7644                &[empty_range(1, "a".len())]
 7645            );
 7646
 7647            view.move_down(&MoveDown, cx);
 7648            assert_eq!(
 7649                view.selections.display_ranges(cx),
 7650                &[empty_range(2, "α".len())]
 7651            );
 7652            view.move_right(&MoveRight, cx);
 7653            assert_eq!(
 7654                view.selections.display_ranges(cx),
 7655                &[empty_range(2, "αβ".len())]
 7656            );
 7657            view.move_right(&MoveRight, cx);
 7658            assert_eq!(
 7659                view.selections.display_ranges(cx),
 7660                &[empty_range(2, "αβ…".len())]
 7661            );
 7662            view.move_right(&MoveRight, cx);
 7663            assert_eq!(
 7664                view.selections.display_ranges(cx),
 7665                &[empty_range(2, "αβ…ε".len())]
 7666            );
 7667
 7668            view.move_up(&MoveUp, cx);
 7669            assert_eq!(
 7670                view.selections.display_ranges(cx),
 7671                &[empty_range(1, "ab…e".len())]
 7672            );
 7673            view.move_up(&MoveUp, cx);
 7674            assert_eq!(
 7675                view.selections.display_ranges(cx),
 7676                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7677            );
 7678            view.move_left(&MoveLeft, cx);
 7679            assert_eq!(
 7680                view.selections.display_ranges(cx),
 7681                &[empty_range(0, "ⓐⓑ…".len())]
 7682            );
 7683            view.move_left(&MoveLeft, cx);
 7684            assert_eq!(
 7685                view.selections.display_ranges(cx),
 7686                &[empty_range(0, "ⓐⓑ".len())]
 7687            );
 7688            view.move_left(&MoveLeft, cx);
 7689            assert_eq!(
 7690                view.selections.display_ranges(cx),
 7691                &[empty_range(0, "".len())]
 7692            );
 7693        });
 7694    }
 7695
 7696    #[gpui::test]
 7697    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7698        cx.set_global(Settings::test(cx));
 7699        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7700        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7701        view.update(cx, |view, cx| {
 7702            view.change_selections(None, cx, |s| {
 7703                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7704            });
 7705            view.move_down(&MoveDown, cx);
 7706            assert_eq!(
 7707                view.selections.display_ranges(cx),
 7708                &[empty_range(1, "abcd".len())]
 7709            );
 7710
 7711            view.move_down(&MoveDown, cx);
 7712            assert_eq!(
 7713                view.selections.display_ranges(cx),
 7714                &[empty_range(2, "αβγ".len())]
 7715            );
 7716
 7717            view.move_down(&MoveDown, cx);
 7718            assert_eq!(
 7719                view.selections.display_ranges(cx),
 7720                &[empty_range(3, "abcd".len())]
 7721            );
 7722
 7723            view.move_down(&MoveDown, cx);
 7724            assert_eq!(
 7725                view.selections.display_ranges(cx),
 7726                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7727            );
 7728
 7729            view.move_up(&MoveUp, cx);
 7730            assert_eq!(
 7731                view.selections.display_ranges(cx),
 7732                &[empty_range(3, "abcd".len())]
 7733            );
 7734
 7735            view.move_up(&MoveUp, cx);
 7736            assert_eq!(
 7737                view.selections.display_ranges(cx),
 7738                &[empty_range(2, "αβγ".len())]
 7739            );
 7740        });
 7741    }
 7742
 7743    #[gpui::test]
 7744    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7745        cx.set_global(Settings::test(cx));
 7746        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7747        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7748        view.update(cx, |view, cx| {
 7749            view.change_selections(None, cx, |s| {
 7750                s.select_display_ranges([
 7751                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7752                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7753                ]);
 7754            });
 7755        });
 7756
 7757        view.update(cx, |view, cx| {
 7758            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7759            assert_eq!(
 7760                view.selections.display_ranges(cx),
 7761                &[
 7762                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7763                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7764                ]
 7765            );
 7766        });
 7767
 7768        view.update(cx, |view, cx| {
 7769            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7770            assert_eq!(
 7771                view.selections.display_ranges(cx),
 7772                &[
 7773                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7774                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7775                ]
 7776            );
 7777        });
 7778
 7779        view.update(cx, |view, cx| {
 7780            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7781            assert_eq!(
 7782                view.selections.display_ranges(cx),
 7783                &[
 7784                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7785                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7786                ]
 7787            );
 7788        });
 7789
 7790        view.update(cx, |view, cx| {
 7791            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7792            assert_eq!(
 7793                view.selections.display_ranges(cx),
 7794                &[
 7795                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7796                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7797                ]
 7798            );
 7799        });
 7800
 7801        // Moving to the end of line again is a no-op.
 7802        view.update(cx, |view, cx| {
 7803            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7804            assert_eq!(
 7805                view.selections.display_ranges(cx),
 7806                &[
 7807                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7808                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7809                ]
 7810            );
 7811        });
 7812
 7813        view.update(cx, |view, cx| {
 7814            view.move_left(&MoveLeft, cx);
 7815            view.select_to_beginning_of_line(
 7816                &SelectToBeginningOfLine {
 7817                    stop_at_soft_wraps: true,
 7818                },
 7819                cx,
 7820            );
 7821            assert_eq!(
 7822                view.selections.display_ranges(cx),
 7823                &[
 7824                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7825                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7826                ]
 7827            );
 7828        });
 7829
 7830        view.update(cx, |view, cx| {
 7831            view.select_to_beginning_of_line(
 7832                &SelectToBeginningOfLine {
 7833                    stop_at_soft_wraps: true,
 7834                },
 7835                cx,
 7836            );
 7837            assert_eq!(
 7838                view.selections.display_ranges(cx),
 7839                &[
 7840                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7841                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7842                ]
 7843            );
 7844        });
 7845
 7846        view.update(cx, |view, cx| {
 7847            view.select_to_beginning_of_line(
 7848                &SelectToBeginningOfLine {
 7849                    stop_at_soft_wraps: true,
 7850                },
 7851                cx,
 7852            );
 7853            assert_eq!(
 7854                view.selections.display_ranges(cx),
 7855                &[
 7856                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7857                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7858                ]
 7859            );
 7860        });
 7861
 7862        view.update(cx, |view, cx| {
 7863            view.select_to_end_of_line(
 7864                &SelectToEndOfLine {
 7865                    stop_at_soft_wraps: true,
 7866                },
 7867                cx,
 7868            );
 7869            assert_eq!(
 7870                view.selections.display_ranges(cx),
 7871                &[
 7872                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7873                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7874                ]
 7875            );
 7876        });
 7877
 7878        view.update(cx, |view, cx| {
 7879            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7880            assert_eq!(view.display_text(cx), "ab\n  de");
 7881            assert_eq!(
 7882                view.selections.display_ranges(cx),
 7883                &[
 7884                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7885                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7886                ]
 7887            );
 7888        });
 7889
 7890        view.update(cx, |view, cx| {
 7891            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7892            assert_eq!(view.display_text(cx), "\n");
 7893            assert_eq!(
 7894                view.selections.display_ranges(cx),
 7895                &[
 7896                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7897                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7898                ]
 7899            );
 7900        });
 7901    }
 7902
 7903    #[gpui::test]
 7904    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7905        cx.set_global(Settings::test(cx));
 7906        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7907        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7908        view.update(cx, |view, cx| {
 7909            view.change_selections(None, cx, |s| {
 7910                s.select_display_ranges([
 7911                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7912                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7913                ])
 7914            });
 7915
 7916            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7917            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7918
 7919            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7920            assert_selection_ranges("use stdˇ::str::{foo, bar}\n\n  ˇ{baz.qux()}", view, cx);
 7921
 7922            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7923            assert_selection_ranges("use ˇstd::str::{foo, bar}\n\nˇ  {baz.qux()}", view, cx);
 7924
 7925            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7926            assert_selection_ranges("ˇuse std::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7927
 7928            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7929            assert_selection_ranges("ˇuse std::str::{foo, barˇ}\n\n  {baz.qux()}", view, cx);
 7930
 7931            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7932            assert_selection_ranges("useˇ std::str::{foo, bar}ˇ\n\n  {baz.qux()}", view, cx);
 7933
 7934            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7935            assert_selection_ranges("use stdˇ::str::{foo, bar}\nˇ\n  {baz.qux()}", view, cx);
 7936
 7937            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7938            assert_selection_ranges("use std::ˇstr::{foo, bar}\n\n  {ˇbaz.qux()}", view, cx);
 7939
 7940            view.move_right(&MoveRight, cx);
 7941            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7942            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7943
 7944            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7945            assert_selection_ranges("use std«ˇ::s»tr::{foo, bar}\n\n  «ˇ{b»az.qux()}", view, cx);
 7946
 7947            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7948            assert_selection_ranges("use std::«ˇs»tr::{foo, bar}\n\n  {«ˇb»az.qux()}", view, cx);
 7949        });
 7950    }
 7951
 7952    #[gpui::test]
 7953    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7954        cx.set_global(Settings::test(cx));
 7955        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7956        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7957
 7958        view.update(cx, |view, cx| {
 7959            view.set_wrap_width(Some(140.), cx);
 7960            assert_eq!(
 7961                view.display_text(cx),
 7962                "use one::{\n    two::three::\n    four::five\n};"
 7963            );
 7964
 7965            view.change_selections(None, cx, |s| {
 7966                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7967            });
 7968
 7969            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7970            assert_eq!(
 7971                view.selections.display_ranges(cx),
 7972                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7973            );
 7974
 7975            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7976            assert_eq!(
 7977                view.selections.display_ranges(cx),
 7978                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7979            );
 7980
 7981            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7982            assert_eq!(
 7983                view.selections.display_ranges(cx),
 7984                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7985            );
 7986
 7987            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7988            assert_eq!(
 7989                view.selections.display_ranges(cx),
 7990                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7991            );
 7992
 7993            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7994            assert_eq!(
 7995                view.selections.display_ranges(cx),
 7996                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7997            );
 7998
 7999            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 8000            assert_eq!(
 8001                view.selections.display_ranges(cx),
 8002                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 8003            );
 8004        });
 8005    }
 8006
 8007    #[gpui::test]
 8008    async fn test_delete_to_beginning_of_line(cx: &mut gpui::TestAppContext) {
 8009        let mut cx = EditorTestContext::new(cx);
 8010        cx.set_state("one «two threeˇ» four");
 8011        cx.update_editor(|editor, cx| {
 8012            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 8013            assert_eq!(editor.text(cx), " four");
 8014        });
 8015    }
 8016
 8017    #[gpui::test]
 8018    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 8019        cx.set_global(Settings::test(cx));
 8020        let buffer = MultiBuffer::build_simple("one two three four", cx);
 8021        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 8022
 8023        view.update(cx, |view, cx| {
 8024            view.change_selections(None, cx, |s| {
 8025                s.select_display_ranges([
 8026                    // an empty selection - the preceding word fragment is deleted
 8027                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8028                    // characters selected - they are deleted
 8029                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 8030                ])
 8031            });
 8032            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 8033        });
 8034
 8035        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 8036
 8037        view.update(cx, |view, cx| {
 8038            view.change_selections(None, cx, |s| {
 8039                s.select_display_ranges([
 8040                    // an empty selection - the following word fragment is deleted
 8041                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8042                    // characters selected - they are deleted
 8043                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 8044                ])
 8045            });
 8046            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 8047        });
 8048
 8049        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 8050    }
 8051
 8052    #[gpui::test]
 8053    fn test_newline(cx: &mut gpui::MutableAppContext) {
 8054        cx.set_global(Settings::test(cx));
 8055        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 8056        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 8057
 8058        view.update(cx, |view, cx| {
 8059            view.change_selections(None, cx, |s| {
 8060                s.select_display_ranges([
 8061                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8062                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8063                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 8064                ])
 8065            });
 8066
 8067            view.newline(&Newline, cx);
 8068            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 8069        });
 8070    }
 8071
 8072    #[gpui::test]
 8073    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 8074        cx.set_global(Settings::test(cx));
 8075        let buffer = MultiBuffer::build_simple(
 8076            "
 8077                a
 8078                b(
 8079                    X
 8080                )
 8081                c(
 8082                    X
 8083                )
 8084            "
 8085            .unindent()
 8086            .as_str(),
 8087            cx,
 8088        );
 8089
 8090        let (_, editor) = cx.add_window(Default::default(), |cx| {
 8091            let mut editor = build_editor(buffer.clone(), cx);
 8092            editor.change_selections(None, cx, |s| {
 8093                s.select_ranges([
 8094                    Point::new(2, 4)..Point::new(2, 5),
 8095                    Point::new(5, 4)..Point::new(5, 5),
 8096                ])
 8097            });
 8098            editor
 8099        });
 8100
 8101        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 8102        buffer.update(cx, |buffer, cx| {
 8103            buffer.edit(
 8104                [
 8105                    (Point::new(1, 2)..Point::new(3, 0), ""),
 8106                    (Point::new(4, 2)..Point::new(6, 0), ""),
 8107                ],
 8108                None,
 8109                cx,
 8110            );
 8111            assert_eq!(
 8112                buffer.read(cx).text(),
 8113                "
 8114                    a
 8115                    b()
 8116                    c()
 8117                "
 8118                .unindent()
 8119            );
 8120        });
 8121
 8122        editor.update(cx, |editor, cx| {
 8123            assert_eq!(
 8124                editor.selections.ranges(cx),
 8125                &[
 8126                    Point::new(1, 2)..Point::new(1, 2),
 8127                    Point::new(2, 2)..Point::new(2, 2),
 8128                ],
 8129            );
 8130
 8131            editor.newline(&Newline, cx);
 8132            assert_eq!(
 8133                editor.text(cx),
 8134                "
 8135                    a
 8136                    b(
 8137                    )
 8138                    c(
 8139                    )
 8140                "
 8141                .unindent()
 8142            );
 8143
 8144            // The selections are moved after the inserted newlines
 8145            assert_eq!(
 8146                editor.selections.ranges(cx),
 8147                &[
 8148                    Point::new(2, 0)..Point::new(2, 0),
 8149                    Point::new(4, 0)..Point::new(4, 0),
 8150                ],
 8151            );
 8152        });
 8153    }
 8154
 8155    #[gpui::test]
 8156    async fn test_newline_below(cx: &mut gpui::TestAppContext) {
 8157        let mut cx = EditorTestContext::new(cx);
 8158        cx.update(|cx| {
 8159            cx.update_global::<Settings, _, _>(|settings, _| {
 8160                settings.editor_overrides.tab_size = Some(NonZeroU32::new(4).unwrap());
 8161            });
 8162        });
 8163
 8164        let language = Arc::new(
 8165            Language::new(
 8166                LanguageConfig::default(),
 8167                Some(tree_sitter_rust::language()),
 8168            )
 8169            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8170            .unwrap(),
 8171        );
 8172        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8173
 8174        cx.set_state(indoc! {"
 8175            const a: ˇA = (
 8176 8177                    «const_functionˇ»(ˇ),
 8178                    so«mˇ»et«hˇ»ing_ˇelse,ˇ
 8179 8180            ˇ);ˇ
 8181        "});
 8182        cx.update_editor(|e, cx| e.newline_below(&NewlineBelow, cx));
 8183        cx.assert_editor_state(indoc! {"
 8184            const a: A = (
 8185                ˇ
 8186                (
 8187                    ˇ
 8188                    const_function(),
 8189                    ˇ
 8190                    ˇ
 8191                    something_else,
 8192                    ˇ
 8193                    ˇ
 8194                    ˇ
 8195                    ˇ
 8196                )
 8197                ˇ
 8198            );
 8199            ˇ
 8200            ˇ
 8201        "});
 8202    }
 8203
 8204    #[gpui::test]
 8205    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 8206        cx.set_global(Settings::test(cx));
 8207        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 8208        let (_, editor) = cx.add_window(Default::default(), |cx| {
 8209            let mut editor = build_editor(buffer.clone(), cx);
 8210            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 8211            editor
 8212        });
 8213
 8214        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 8215        buffer.update(cx, |buffer, cx| {
 8216            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
 8217            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 8218        });
 8219
 8220        editor.update(cx, |editor, cx| {
 8221            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 8222
 8223            editor.insert("Z", cx);
 8224            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 8225
 8226            // The selections are moved after the inserted characters
 8227            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 8228        });
 8229    }
 8230
 8231    #[gpui::test]
 8232    async fn test_tab(cx: &mut gpui::TestAppContext) {
 8233        let mut cx = EditorTestContext::new(cx);
 8234        cx.update(|cx| {
 8235            cx.update_global::<Settings, _, _>(|settings, _| {
 8236                settings.editor_overrides.tab_size = Some(NonZeroU32::new(3).unwrap());
 8237            });
 8238        });
 8239        cx.set_state(indoc! {"
 8240            ˇabˇc
 8241            ˇ🏀ˇ🏀ˇefg
 8242 8243        "});
 8244        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8245        cx.assert_editor_state(indoc! {"
 8246              ˇab ˇc
 8247              ˇ🏀  ˇ🏀  ˇefg
 8248           d  ˇ
 8249        "});
 8250
 8251        cx.set_state(indoc! {"
 8252            a
 8253            «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8254        "});
 8255        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8256        cx.assert_editor_state(indoc! {"
 8257            a
 8258               «🏀ˇ»🏀«🏀ˇ»🏀«🏀ˇ»
 8259        "});
 8260    }
 8261
 8262    #[gpui::test]
 8263    async fn test_tab_on_blank_line_auto_indents(cx: &mut gpui::TestAppContext) {
 8264        let mut cx = EditorTestContext::new(cx);
 8265        let language = Arc::new(
 8266            Language::new(
 8267                LanguageConfig::default(),
 8268                Some(tree_sitter_rust::language()),
 8269            )
 8270            .with_indents_query(r#"(_ "(" ")" @end) @indent"#)
 8271            .unwrap(),
 8272        );
 8273        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 8274
 8275        // cursors that are already at the suggested indent level insert
 8276        // a soft tab. cursors that are to the left of the suggested indent
 8277        // auto-indent their line.
 8278        cx.set_state(indoc! {"
 8279            ˇ
 8280            const a: B = (
 8281                c(
 8282                    d(
 8283            ˇ
 8284                    )
 8285            ˇ
 8286            ˇ    )
 8287            );
 8288        "});
 8289        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8290        cx.assert_editor_state(indoc! {"
 8291                ˇ
 8292            const a: B = (
 8293                c(
 8294                    d(
 8295                        ˇ
 8296                    )
 8297                    ˇ
 8298                ˇ)
 8299            );
 8300        "});
 8301
 8302        // handle auto-indent when there are multiple cursors on the same line
 8303        cx.set_state(indoc! {"
 8304            const a: B = (
 8305                c(
 8306            ˇ    ˇ    
 8307            ˇ    )
 8308            );
 8309        "});
 8310        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8311        cx.assert_editor_state(indoc! {"
 8312            const a: B = (
 8313                c(
 8314                    ˇ
 8315                ˇ)
 8316            );
 8317        "});
 8318    }
 8319
 8320    #[gpui::test]
 8321    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 8322        let mut cx = EditorTestContext::new(cx);
 8323
 8324        cx.set_state(indoc! {"
 8325              «oneˇ» «twoˇ»
 8326            three
 8327             four
 8328        "});
 8329        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8330        cx.assert_editor_state(indoc! {"
 8331                «oneˇ» «twoˇ»
 8332            three
 8333             four
 8334        "});
 8335
 8336        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8337        cx.assert_editor_state(indoc! {"
 8338            «oneˇ» «twoˇ»
 8339            three
 8340             four
 8341        "});
 8342
 8343        // select across line ending
 8344        cx.set_state(indoc! {"
 8345            one two
 8346            t«hree
 8347            ˇ» four
 8348        "});
 8349        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8350        cx.assert_editor_state(indoc! {"
 8351            one two
 8352                t«hree
 8353            ˇ» four
 8354        "});
 8355
 8356        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8357        cx.assert_editor_state(indoc! {"
 8358            one two
 8359            t«hree
 8360            ˇ» four
 8361        "});
 8362
 8363        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8364        cx.set_state(indoc! {"
 8365            one two
 8366            ˇthree
 8367                four
 8368        "});
 8369        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8370        cx.assert_editor_state(indoc! {"
 8371            one two
 8372                ˇthree
 8373                four
 8374        "});
 8375
 8376        cx.set_state(indoc! {"
 8377            one two
 8378            ˇ    three
 8379             four
 8380        "});
 8381        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8382        cx.assert_editor_state(indoc! {"
 8383            one two
 8384            ˇthree
 8385             four
 8386        "});
 8387    }
 8388
 8389    #[gpui::test]
 8390    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 8391        let mut cx = EditorTestContext::new(cx);
 8392        cx.update(|cx| {
 8393            cx.update_global::<Settings, _, _>(|settings, _| {
 8394                settings.editor_overrides.hard_tabs = Some(true);
 8395            });
 8396        });
 8397
 8398        // select two ranges on one line
 8399        cx.set_state(indoc! {"
 8400            «oneˇ» «twoˇ»
 8401            three
 8402            four
 8403        "});
 8404        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8405        cx.assert_editor_state(indoc! {"
 8406            \t«oneˇ» «twoˇ»
 8407            three
 8408            four
 8409        "});
 8410        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8411        cx.assert_editor_state(indoc! {"
 8412            \t\t«oneˇ» «twoˇ»
 8413            three
 8414            four
 8415        "});
 8416        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8417        cx.assert_editor_state(indoc! {"
 8418            \t«oneˇ» «twoˇ»
 8419            three
 8420            four
 8421        "});
 8422        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8423        cx.assert_editor_state(indoc! {"
 8424            «oneˇ» «twoˇ»
 8425            three
 8426            four
 8427        "});
 8428
 8429        // select across a line ending
 8430        cx.set_state(indoc! {"
 8431            one two
 8432            t«hree
 8433            ˇ»four
 8434        "});
 8435        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8436        cx.assert_editor_state(indoc! {"
 8437            one two
 8438            \tt«hree
 8439            ˇ»four
 8440        "});
 8441        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8442        cx.assert_editor_state(indoc! {"
 8443            one two
 8444            \t\tt«hree
 8445            ˇ»four
 8446        "});
 8447        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8448        cx.assert_editor_state(indoc! {"
 8449            one two
 8450            \tt«hree
 8451            ˇ»four
 8452        "});
 8453        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8454        cx.assert_editor_state(indoc! {"
 8455            one two
 8456            t«hree
 8457            ˇ»four
 8458        "});
 8459
 8460        // Ensure that indenting/outdenting works when the cursor is at column 0.
 8461        cx.set_state(indoc! {"
 8462            one two
 8463            ˇthree
 8464            four
 8465        "});
 8466        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8467        cx.assert_editor_state(indoc! {"
 8468            one two
 8469            ˇthree
 8470            four
 8471        "});
 8472        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 8473        cx.assert_editor_state(indoc! {"
 8474            one two
 8475            \tˇthree
 8476            four
 8477        "});
 8478        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 8479        cx.assert_editor_state(indoc! {"
 8480            one two
 8481            ˇthree
 8482            four
 8483        "});
 8484    }
 8485
 8486    #[gpui::test]
 8487    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 8488        cx.set_global(
 8489            Settings::test(cx)
 8490                .with_language_defaults(
 8491                    "TOML",
 8492                    EditorSettings {
 8493                        tab_size: Some(2.try_into().unwrap()),
 8494                        ..Default::default()
 8495                    },
 8496                )
 8497                .with_language_defaults(
 8498                    "Rust",
 8499                    EditorSettings {
 8500                        tab_size: Some(4.try_into().unwrap()),
 8501                        ..Default::default()
 8502                    },
 8503                ),
 8504        );
 8505        let toml_language = Arc::new(Language::new(
 8506            LanguageConfig {
 8507                name: "TOML".into(),
 8508                ..Default::default()
 8509            },
 8510            None,
 8511        ));
 8512        let rust_language = Arc::new(Language::new(
 8513            LanguageConfig {
 8514                name: "Rust".into(),
 8515                ..Default::default()
 8516            },
 8517            None,
 8518        ));
 8519
 8520        let toml_buffer = cx
 8521            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 8522        let rust_buffer = cx.add_model(|cx| {
 8523            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 8524        });
 8525        let multibuffer = cx.add_model(|cx| {
 8526            let mut multibuffer = MultiBuffer::new(0);
 8527            multibuffer.push_excerpts(
 8528                toml_buffer.clone(),
 8529                [ExcerptRange {
 8530                    context: Point::new(0, 0)..Point::new(2, 0),
 8531                    primary: None,
 8532                }],
 8533                cx,
 8534            );
 8535            multibuffer.push_excerpts(
 8536                rust_buffer.clone(),
 8537                [ExcerptRange {
 8538                    context: Point::new(0, 0)..Point::new(1, 0),
 8539                    primary: None,
 8540                }],
 8541                cx,
 8542            );
 8543            multibuffer
 8544        });
 8545
 8546        cx.add_window(Default::default(), |cx| {
 8547            let mut editor = build_editor(multibuffer, cx);
 8548
 8549            assert_eq!(
 8550                editor.text(cx),
 8551                indoc! {"
 8552                    a = 1
 8553                    b = 2
 8554
 8555                    const c: usize = 3;
 8556                "}
 8557            );
 8558
 8559            select_ranges(
 8560                &mut editor,
 8561                indoc! {"
 8562                    «aˇ» = 1
 8563                    b = 2
 8564
 8565                    «const c:ˇ» usize = 3;
 8566                "},
 8567                cx,
 8568            );
 8569
 8570            editor.tab(&Tab, cx);
 8571            assert_text_with_selections(
 8572                &mut editor,
 8573                indoc! {"
 8574                      «aˇ» = 1
 8575                    b = 2
 8576
 8577                        «const c:ˇ» usize = 3;
 8578                "},
 8579                cx,
 8580            );
 8581            editor.tab_prev(&TabPrev, cx);
 8582            assert_text_with_selections(
 8583                &mut editor,
 8584                indoc! {"
 8585                    «aˇ» = 1
 8586                    b = 2
 8587
 8588                    «const c:ˇ» usize = 3;
 8589                "},
 8590                cx,
 8591            );
 8592
 8593            editor
 8594        });
 8595    }
 8596
 8597    #[gpui::test]
 8598    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 8599        let mut cx = EditorTestContext::new(cx);
 8600
 8601        // Basic backspace
 8602        cx.set_state(indoc! {"
 8603            onˇe two three
 8604            fou«rˇ» five six
 8605            seven «ˇeight nine
 8606            »ten
 8607        "});
 8608        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8609        cx.assert_editor_state(indoc! {"
 8610            oˇe two three
 8611            fouˇ five six
 8612            seven ˇten
 8613        "});
 8614
 8615        // Test backspace inside and around indents
 8616        cx.set_state(indoc! {"
 8617            zero
 8618                ˇone
 8619                    ˇtwo
 8620                ˇ ˇ ˇ  three
 8621            ˇ  ˇ  four
 8622        "});
 8623        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8624        cx.assert_editor_state(indoc! {"
 8625            zero
 8626            ˇone
 8627                ˇtwo
 8628            ˇ  threeˇ  four
 8629        "});
 8630
 8631        // Test backspace with line_mode set to true
 8632        cx.update_editor(|e, _| e.selections.line_mode = true);
 8633        cx.set_state(indoc! {"
 8634            The ˇquick ˇbrown
 8635            fox jumps over
 8636            the lazy dog
 8637            ˇThe qu«ick bˇ»rown"});
 8638        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8639        cx.assert_editor_state(indoc! {"
 8640            ˇfox jumps over
 8641            the lazy dogˇ"});
 8642    }
 8643
 8644    #[gpui::test]
 8645    async fn test_delete(cx: &mut gpui::TestAppContext) {
 8646        let mut cx = EditorTestContext::new(cx);
 8647
 8648        cx.set_state(indoc! {"
 8649            onˇe two three
 8650            fou«rˇ» five six
 8651            seven «ˇeight nine
 8652            »ten
 8653        "});
 8654        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 8655        cx.assert_editor_state(indoc! {"
 8656            onˇ two three
 8657            fouˇ five six
 8658            seven ˇten
 8659        "});
 8660
 8661        // Test backspace with line_mode set to true
 8662        cx.update_editor(|e, _| e.selections.line_mode = true);
 8663        cx.set_state(indoc! {"
 8664            The ˇquick ˇbrown
 8665            fox «ˇjum»ps over
 8666            the lazy dog
 8667            ˇThe qu«ick bˇ»rown"});
 8668        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 8669        cx.assert_editor_state("ˇthe lazy dogˇ");
 8670    }
 8671
 8672    #[gpui::test]
 8673    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8674        cx.set_global(Settings::test(cx));
 8675        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8676        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8677        view.update(cx, |view, cx| {
 8678            view.change_selections(None, cx, |s| {
 8679                s.select_display_ranges([
 8680                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8681                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8682                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8683                ])
 8684            });
 8685            view.delete_line(&DeleteLine, cx);
 8686            assert_eq!(view.display_text(cx), "ghi");
 8687            assert_eq!(
 8688                view.selections.display_ranges(cx),
 8689                vec![
 8690                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8691                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8692                ]
 8693            );
 8694        });
 8695
 8696        cx.set_global(Settings::test(cx));
 8697        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8698        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8699        view.update(cx, |view, cx| {
 8700            view.change_selections(None, cx, |s| {
 8701                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 8702            });
 8703            view.delete_line(&DeleteLine, cx);
 8704            assert_eq!(view.display_text(cx), "ghi\n");
 8705            assert_eq!(
 8706                view.selections.display_ranges(cx),
 8707                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8708            );
 8709        });
 8710    }
 8711
 8712    #[gpui::test]
 8713    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8714        cx.set_global(Settings::test(cx));
 8715        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8716        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8717        view.update(cx, |view, cx| {
 8718            view.change_selections(None, cx, |s| {
 8719                s.select_display_ranges([
 8720                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8721                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8722                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8723                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8724                ])
 8725            });
 8726            view.duplicate_line(&DuplicateLine, cx);
 8727            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8728            assert_eq!(
 8729                view.selections.display_ranges(cx),
 8730                vec![
 8731                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8732                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8733                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8734                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8735                ]
 8736            );
 8737        });
 8738
 8739        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8740        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8741        view.update(cx, |view, cx| {
 8742            view.change_selections(None, cx, |s| {
 8743                s.select_display_ranges([
 8744                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8745                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8746                ])
 8747            });
 8748            view.duplicate_line(&DuplicateLine, cx);
 8749            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8750            assert_eq!(
 8751                view.selections.display_ranges(cx),
 8752                vec![
 8753                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8754                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8755                ]
 8756            );
 8757        });
 8758    }
 8759
 8760    #[gpui::test]
 8761    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8762        cx.set_global(Settings::test(cx));
 8763        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8764        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8765        view.update(cx, |view, cx| {
 8766            view.fold_ranges(
 8767                vec![
 8768                    Point::new(0, 2)..Point::new(1, 2),
 8769                    Point::new(2, 3)..Point::new(4, 1),
 8770                    Point::new(7, 0)..Point::new(8, 4),
 8771                ],
 8772                cx,
 8773            );
 8774            view.change_selections(None, cx, |s| {
 8775                s.select_display_ranges([
 8776                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8777                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8778                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8779                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8780                ])
 8781            });
 8782            assert_eq!(
 8783                view.display_text(cx),
 8784                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8785            );
 8786
 8787            view.move_line_up(&MoveLineUp, cx);
 8788            assert_eq!(
 8789                view.display_text(cx),
 8790                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8791            );
 8792            assert_eq!(
 8793                view.selections.display_ranges(cx),
 8794                vec![
 8795                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8796                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8797                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8798                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8799                ]
 8800            );
 8801        });
 8802
 8803        view.update(cx, |view, cx| {
 8804            view.move_line_down(&MoveLineDown, cx);
 8805            assert_eq!(
 8806                view.display_text(cx),
 8807                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8808            );
 8809            assert_eq!(
 8810                view.selections.display_ranges(cx),
 8811                vec![
 8812                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8813                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8814                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8815                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8816                ]
 8817            );
 8818        });
 8819
 8820        view.update(cx, |view, cx| {
 8821            view.move_line_down(&MoveLineDown, cx);
 8822            assert_eq!(
 8823                view.display_text(cx),
 8824                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8825            );
 8826            assert_eq!(
 8827                view.selections.display_ranges(cx),
 8828                vec![
 8829                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8830                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8831                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8832                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8833                ]
 8834            );
 8835        });
 8836
 8837        view.update(cx, |view, cx| {
 8838            view.move_line_up(&MoveLineUp, cx);
 8839            assert_eq!(
 8840                view.display_text(cx),
 8841                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8842            );
 8843            assert_eq!(
 8844                view.selections.display_ranges(cx),
 8845                vec![
 8846                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8847                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8848                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8849                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8850                ]
 8851            );
 8852        });
 8853    }
 8854
 8855    #[gpui::test]
 8856    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8857        cx.set_global(Settings::test(cx));
 8858        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8859        let snapshot = buffer.read(cx).snapshot(cx);
 8860        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8861        editor.update(cx, |editor, cx| {
 8862            editor.insert_blocks(
 8863                [BlockProperties {
 8864                    style: BlockStyle::Fixed,
 8865                    position: snapshot.anchor_after(Point::new(2, 0)),
 8866                    disposition: BlockDisposition::Below,
 8867                    height: 1,
 8868                    render: Arc::new(|_| Empty::new().boxed()),
 8869                }],
 8870                cx,
 8871            );
 8872            editor.change_selections(None, cx, |s| {
 8873                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8874            });
 8875            editor.move_line_down(&MoveLineDown, cx);
 8876        });
 8877    }
 8878
 8879    #[gpui::test]
 8880    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8881        cx.set_global(Settings::test(cx));
 8882
 8883        _ = cx
 8884            .add_window(Default::default(), |cx| {
 8885                let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8886
 8887                editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8888                editor.transpose(&Default::default(), cx);
 8889                assert_eq!(editor.text(cx), "bac");
 8890                assert_eq!(editor.selections.ranges(cx), [2..2]);
 8891
 8892                editor.transpose(&Default::default(), cx);
 8893                assert_eq!(editor.text(cx), "bca");
 8894                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8895
 8896                editor.transpose(&Default::default(), cx);
 8897                assert_eq!(editor.text(cx), "bac");
 8898                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8899
 8900                editor
 8901            })
 8902            .1;
 8903
 8904        _ = cx
 8905            .add_window(Default::default(), |cx| {
 8906                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8907
 8908                editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8909                editor.transpose(&Default::default(), cx);
 8910                assert_eq!(editor.text(cx), "acb\nde");
 8911                assert_eq!(editor.selections.ranges(cx), [3..3]);
 8912
 8913                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8914                editor.transpose(&Default::default(), cx);
 8915                assert_eq!(editor.text(cx), "acbd\ne");
 8916                assert_eq!(editor.selections.ranges(cx), [5..5]);
 8917
 8918                editor.transpose(&Default::default(), cx);
 8919                assert_eq!(editor.text(cx), "acbde\n");
 8920                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8921
 8922                editor.transpose(&Default::default(), cx);
 8923                assert_eq!(editor.text(cx), "acbd\ne");
 8924                assert_eq!(editor.selections.ranges(cx), [6..6]);
 8925
 8926                editor
 8927            })
 8928            .1;
 8929
 8930        _ = cx
 8931            .add_window(Default::default(), |cx| {
 8932                let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8933
 8934                editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8935                editor.transpose(&Default::default(), cx);
 8936                assert_eq!(editor.text(cx), "bacd\ne");
 8937                assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8938
 8939                editor.transpose(&Default::default(), cx);
 8940                assert_eq!(editor.text(cx), "bcade\n");
 8941                assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8942
 8943                editor.transpose(&Default::default(), cx);
 8944                assert_eq!(editor.text(cx), "bcda\ne");
 8945                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8946
 8947                editor.transpose(&Default::default(), cx);
 8948                assert_eq!(editor.text(cx), "bcade\n");
 8949                assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8950
 8951                editor.transpose(&Default::default(), cx);
 8952                assert_eq!(editor.text(cx), "bcaed\n");
 8953                assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8954
 8955                editor
 8956            })
 8957            .1;
 8958
 8959        _ = cx
 8960            .add_window(Default::default(), |cx| {
 8961                let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8962
 8963                editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8964                editor.transpose(&Default::default(), cx);
 8965                assert_eq!(editor.text(cx), "🏀🍐✋");
 8966                assert_eq!(editor.selections.ranges(cx), [8..8]);
 8967
 8968                editor.transpose(&Default::default(), cx);
 8969                assert_eq!(editor.text(cx), "🏀✋🍐");
 8970                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8971
 8972                editor.transpose(&Default::default(), cx);
 8973                assert_eq!(editor.text(cx), "🏀🍐✋");
 8974                assert_eq!(editor.selections.ranges(cx), [11..11]);
 8975
 8976                editor
 8977            })
 8978            .1;
 8979    }
 8980
 8981    #[gpui::test]
 8982    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8983        let mut cx = EditorTestContext::new(cx);
 8984
 8985        cx.set_state("«one✅ ˇ»two «three ˇ»four «five ˇ»six ");
 8986        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8987        cx.assert_editor_state("ˇtwo ˇfour ˇsix ");
 8988
 8989        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8990        cx.set_state("two ˇfour ˇsix ˇ");
 8991        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8992        cx.assert_editor_state("two one✅ ˇfour three ˇsix five ˇ");
 8993
 8994        // Paste again but with only two cursors. Since the number of cursors doesn't
 8995        // match the number of slices in the clipboard, the entire clipboard text
 8996        // is pasted at each cursor.
 8997        cx.set_state("ˇtwo one✅ four three six five ˇ");
 8998        cx.update_editor(|e, cx| {
 8999            e.handle_input("( ", cx);
 9000            e.paste(&Paste, cx);
 9001            e.handle_input(") ", cx);
 9002        });
 9003        cx.assert_editor_state(indoc! {"
 9004            ( one✅ 
 9005            three 
 9006            five ) ˇtwo one✅ four three six five ( one✅ 
 9007            three 
 9008            five ) ˇ"});
 9009
 9010        // Cut with three selections, one of which is full-line.
 9011        cx.set_state(indoc! {"
 9012            1«2ˇ»3
 9013            4ˇ567
 9014            «8ˇ»9"});
 9015        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 9016        cx.assert_editor_state(indoc! {"
 9017            1ˇ3
 9018            ˇ9"});
 9019
 9020        // Paste with three selections, noticing how the copied selection that was full-line
 9021        // gets inserted before the second cursor.
 9022        cx.set_state(indoc! {"
 9023            1ˇ3
 9024 9025            «oˇ»ne"});
 9026        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9027        cx.assert_editor_state(indoc! {"
 9028            12ˇ3
 9029            4567
 9030 9031            8ˇne"});
 9032
 9033        // Copy with a single cursor only, which writes the whole line into the clipboard.
 9034        cx.set_state(indoc! {"
 9035            The quick brown
 9036            fox juˇmps over
 9037            the lazy dog"});
 9038        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 9039        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 9040
 9041        // Paste with three selections, noticing how the copied full-line selection is inserted
 9042        // before the empty selections but replaces the selection that is non-empty.
 9043        cx.set_state(indoc! {"
 9044            Tˇhe quick brown
 9045            «foˇ»x jumps over
 9046            tˇhe lazy dog"});
 9047        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9048        cx.assert_editor_state(indoc! {"
 9049            fox jumps over
 9050            Tˇhe quick brown
 9051            fox jumps over
 9052            ˇx jumps over
 9053            fox jumps over
 9054            tˇhe lazy dog"});
 9055    }
 9056
 9057    #[gpui::test]
 9058    async fn test_paste_multiline(cx: &mut gpui::TestAppContext) {
 9059        let mut cx = EditorTestContext::new(cx);
 9060        let language = Arc::new(Language::new(
 9061            LanguageConfig::default(),
 9062            Some(tree_sitter_rust::language()),
 9063        ));
 9064        cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx));
 9065
 9066        // Cut an indented block, without the leading whitespace.
 9067        cx.set_state(indoc! {"
 9068            const a: B = (
 9069                c(),
 9070                «d(
 9071                    e,
 9072                    f
 9073                )ˇ»
 9074            );
 9075        "});
 9076        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 9077        cx.assert_editor_state(indoc! {"
 9078            const a: B = (
 9079                c(),
 9080                ˇ
 9081            );
 9082        "});
 9083
 9084        // Paste it at the same position.
 9085        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9086        cx.assert_editor_state(indoc! {"
 9087            const a: B = (
 9088                c(),
 9089                d(
 9090                    e,
 9091                    f
 9092 9093            );
 9094        "});
 9095
 9096        // Paste it at a line with a lower indent level.
 9097        cx.set_state(indoc! {"
 9098            ˇ
 9099            const a: B = (
 9100                c(),
 9101            );
 9102        "});
 9103        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9104        cx.assert_editor_state(indoc! {"
 9105            d(
 9106                e,
 9107                f
 9108 9109            const a: B = (
 9110                c(),
 9111            );
 9112        "});
 9113
 9114        // Cut an indented block, with the leading whitespace.
 9115        cx.set_state(indoc! {"
 9116            const a: B = (
 9117                c(),
 9118            «    d(
 9119                    e,
 9120                    f
 9121                )
 9122            ˇ»);
 9123        "});
 9124        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 9125        cx.assert_editor_state(indoc! {"
 9126            const a: B = (
 9127                c(),
 9128            ˇ);
 9129        "});
 9130
 9131        // Paste it at the same position.
 9132        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9133        cx.assert_editor_state(indoc! {"
 9134            const a: B = (
 9135                c(),
 9136                d(
 9137                    e,
 9138                    f
 9139                )
 9140            ˇ);
 9141        "});
 9142
 9143        // Paste it at a line with a higher indent level.
 9144        cx.set_state(indoc! {"
 9145            const a: B = (
 9146                c(),
 9147                d(
 9148                    e,
 9149 9150                )
 9151            );
 9152        "});
 9153        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 9154        cx.assert_editor_state(indoc! {"
 9155            const a: B = (
 9156                c(),
 9157                d(
 9158                    e,
 9159                    f    d(
 9160                        e,
 9161                        f
 9162                    )
 9163            ˇ
 9164                )
 9165            );
 9166        "});
 9167    }
 9168
 9169    #[gpui::test]
 9170    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 9171        cx.set_global(Settings::test(cx));
 9172        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 9173        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9174        view.update(cx, |view, cx| {
 9175            view.select_all(&SelectAll, cx);
 9176            assert_eq!(
 9177                view.selections.display_ranges(cx),
 9178                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 9179            );
 9180        });
 9181    }
 9182
 9183    #[gpui::test]
 9184    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 9185        cx.set_global(Settings::test(cx));
 9186        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 9187        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9188        view.update(cx, |view, cx| {
 9189            view.change_selections(None, cx, |s| {
 9190                s.select_display_ranges([
 9191                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9192                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9193                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9194                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 9195                ])
 9196            });
 9197            view.select_line(&SelectLine, cx);
 9198            assert_eq!(
 9199                view.selections.display_ranges(cx),
 9200                vec![
 9201                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 9202                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 9203                ]
 9204            );
 9205        });
 9206
 9207        view.update(cx, |view, cx| {
 9208            view.select_line(&SelectLine, cx);
 9209            assert_eq!(
 9210                view.selections.display_ranges(cx),
 9211                vec![
 9212                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 9213                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 9214                ]
 9215            );
 9216        });
 9217
 9218        view.update(cx, |view, cx| {
 9219            view.select_line(&SelectLine, cx);
 9220            assert_eq!(
 9221                view.selections.display_ranges(cx),
 9222                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 9223            );
 9224        });
 9225    }
 9226
 9227    #[gpui::test]
 9228    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 9229        cx.set_global(Settings::test(cx));
 9230        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 9231        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9232        view.update(cx, |view, cx| {
 9233            view.fold_ranges(
 9234                vec![
 9235                    Point::new(0, 2)..Point::new(1, 2),
 9236                    Point::new(2, 3)..Point::new(4, 1),
 9237                    Point::new(7, 0)..Point::new(8, 4),
 9238                ],
 9239                cx,
 9240            );
 9241            view.change_selections(None, cx, |s| {
 9242                s.select_display_ranges([
 9243                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9244                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9245                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9246                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9247                ])
 9248            });
 9249            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 9250        });
 9251
 9252        view.update(cx, |view, cx| {
 9253            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9254            assert_eq!(
 9255                view.display_text(cx),
 9256                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 9257            );
 9258            assert_eq!(
 9259                view.selections.display_ranges(cx),
 9260                [
 9261                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 9262                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 9263                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 9264                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 9265                ]
 9266            );
 9267        });
 9268
 9269        view.update(cx, |view, cx| {
 9270            view.change_selections(None, cx, |s| {
 9271                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 9272            });
 9273            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 9274            assert_eq!(
 9275                view.display_text(cx),
 9276                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 9277            );
 9278            assert_eq!(
 9279                view.selections.display_ranges(cx),
 9280                [
 9281                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 9282                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 9283                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9284                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 9285                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 9286                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 9287                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 9288                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 9289                ]
 9290            );
 9291        });
 9292    }
 9293
 9294    #[gpui::test]
 9295    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 9296        cx.set_global(Settings::test(cx));
 9297        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 9298        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 9299
 9300        view.update(cx, |view, cx| {
 9301            view.change_selections(None, cx, |s| {
 9302                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 9303            });
 9304        });
 9305        view.update(cx, |view, cx| {
 9306            view.add_selection_above(&AddSelectionAbove, cx);
 9307            assert_eq!(
 9308                view.selections.display_ranges(cx),
 9309                vec![
 9310                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9311                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9312                ]
 9313            );
 9314        });
 9315
 9316        view.update(cx, |view, cx| {
 9317            view.add_selection_above(&AddSelectionAbove, cx);
 9318            assert_eq!(
 9319                view.selections.display_ranges(cx),
 9320                vec![
 9321                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9322                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9323                ]
 9324            );
 9325        });
 9326
 9327        view.update(cx, |view, cx| {
 9328            view.add_selection_below(&AddSelectionBelow, cx);
 9329            assert_eq!(
 9330                view.selections.display_ranges(cx),
 9331                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9332            );
 9333
 9334            view.undo_selection(&UndoSelection, cx);
 9335            assert_eq!(
 9336                view.selections.display_ranges(cx),
 9337                vec![
 9338                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 9339                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 9340                ]
 9341            );
 9342
 9343            view.redo_selection(&RedoSelection, cx);
 9344            assert_eq!(
 9345                view.selections.display_ranges(cx),
 9346                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 9347            );
 9348        });
 9349
 9350        view.update(cx, |view, cx| {
 9351            view.add_selection_below(&AddSelectionBelow, cx);
 9352            assert_eq!(
 9353                view.selections.display_ranges(cx),
 9354                vec![
 9355                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9356                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9357                ]
 9358            );
 9359        });
 9360
 9361        view.update(cx, |view, cx| {
 9362            view.add_selection_below(&AddSelectionBelow, cx);
 9363            assert_eq!(
 9364                view.selections.display_ranges(cx),
 9365                vec![
 9366                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 9367                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 9368                ]
 9369            );
 9370        });
 9371
 9372        view.update(cx, |view, cx| {
 9373            view.change_selections(None, cx, |s| {
 9374                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 9375            });
 9376        });
 9377        view.update(cx, |view, cx| {
 9378            view.add_selection_below(&AddSelectionBelow, cx);
 9379            assert_eq!(
 9380                view.selections.display_ranges(cx),
 9381                vec![
 9382                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9383                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9384                ]
 9385            );
 9386        });
 9387
 9388        view.update(cx, |view, cx| {
 9389            view.add_selection_below(&AddSelectionBelow, cx);
 9390            assert_eq!(
 9391                view.selections.display_ranges(cx),
 9392                vec![
 9393                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 9394                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 9395                ]
 9396            );
 9397        });
 9398
 9399        view.update(cx, |view, cx| {
 9400            view.add_selection_above(&AddSelectionAbove, cx);
 9401            assert_eq!(
 9402                view.selections.display_ranges(cx),
 9403                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9404            );
 9405        });
 9406
 9407        view.update(cx, |view, cx| {
 9408            view.add_selection_above(&AddSelectionAbove, cx);
 9409            assert_eq!(
 9410                view.selections.display_ranges(cx),
 9411                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 9412            );
 9413        });
 9414
 9415        view.update(cx, |view, cx| {
 9416            view.change_selections(None, cx, |s| {
 9417                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 9418            });
 9419            view.add_selection_below(&AddSelectionBelow, cx);
 9420            assert_eq!(
 9421                view.selections.display_ranges(cx),
 9422                vec![
 9423                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9424                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9425                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9426                ]
 9427            );
 9428        });
 9429
 9430        view.update(cx, |view, cx| {
 9431            view.add_selection_below(&AddSelectionBelow, cx);
 9432            assert_eq!(
 9433                view.selections.display_ranges(cx),
 9434                vec![
 9435                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9436                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9437                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9438                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 9439                ]
 9440            );
 9441        });
 9442
 9443        view.update(cx, |view, cx| {
 9444            view.add_selection_above(&AddSelectionAbove, cx);
 9445            assert_eq!(
 9446                view.selections.display_ranges(cx),
 9447                vec![
 9448                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 9449                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 9450                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 9451                ]
 9452            );
 9453        });
 9454
 9455        view.update(cx, |view, cx| {
 9456            view.change_selections(None, cx, |s| {
 9457                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 9458            });
 9459        });
 9460        view.update(cx, |view, cx| {
 9461            view.add_selection_above(&AddSelectionAbove, cx);
 9462            assert_eq!(
 9463                view.selections.display_ranges(cx),
 9464                vec![
 9465                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 9466                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9467                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9468                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9469                ]
 9470            );
 9471        });
 9472
 9473        view.update(cx, |view, cx| {
 9474            view.add_selection_below(&AddSelectionBelow, cx);
 9475            assert_eq!(
 9476                view.selections.display_ranges(cx),
 9477                vec![
 9478                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 9479                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 9480                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 9481                ]
 9482            );
 9483        });
 9484    }
 9485
 9486    #[gpui::test]
 9487    async fn test_select_next(cx: &mut gpui::TestAppContext) {
 9488        let mut cx = EditorTestContext::new(cx);
 9489        cx.set_state("abc\nˇabc abc\ndefabc\nabc");
 9490
 9491        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9492        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9493
 9494        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9495        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9496
 9497        cx.update_editor(|view, cx| view.undo_selection(&UndoSelection, cx));
 9498        cx.assert_editor_state("abc\n«abcˇ» abc\ndefabc\nabc");
 9499
 9500        cx.update_editor(|view, cx| view.redo_selection(&RedoSelection, cx));
 9501        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\nabc");
 9502
 9503        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9504        cx.assert_editor_state("abc\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9505
 9506        cx.update_editor(|e, cx| e.select_next(&SelectNext::default(), cx));
 9507        cx.assert_editor_state("«abcˇ»\n«abcˇ» «abcˇ»\ndefabc\n«abcˇ»");
 9508    }
 9509
 9510    #[gpui::test]
 9511    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 9512        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9513        let language = Arc::new(Language::new(
 9514            LanguageConfig::default(),
 9515            Some(tree_sitter_rust::language()),
 9516        ));
 9517
 9518        let text = r#"
 9519            use mod1::mod2::{mod3, mod4};
 9520
 9521            fn fn_1(param1: bool, param2: &str) {
 9522                let var1 = "text";
 9523            }
 9524        "#
 9525        .unindent();
 9526
 9527        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9528        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9529        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9530        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9531            .await;
 9532
 9533        view.update(cx, |view, cx| {
 9534            view.change_selections(None, cx, |s| {
 9535                s.select_display_ranges([
 9536                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9537                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9538                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9539                ]);
 9540            });
 9541            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9542        });
 9543        assert_eq!(
 9544            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 9545            &[
 9546                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9547                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9548                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9549            ]
 9550        );
 9551
 9552        view.update(cx, |view, cx| {
 9553            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9554        });
 9555        assert_eq!(
 9556            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9557            &[
 9558                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9559                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9560            ]
 9561        );
 9562
 9563        view.update(cx, |view, cx| {
 9564            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9565        });
 9566        assert_eq!(
 9567            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9568            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9569        );
 9570
 9571        // Trying to expand the selected syntax node one more time has no effect.
 9572        view.update(cx, |view, cx| {
 9573            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9574        });
 9575        assert_eq!(
 9576            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9577            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 9578        );
 9579
 9580        view.update(cx, |view, cx| {
 9581            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9582        });
 9583        assert_eq!(
 9584            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9585            &[
 9586                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9587                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 9588            ]
 9589        );
 9590
 9591        view.update(cx, |view, cx| {
 9592            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9593        });
 9594        assert_eq!(
 9595            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9596            &[
 9597                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 9598                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9599                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 9600            ]
 9601        );
 9602
 9603        view.update(cx, |view, cx| {
 9604            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9605        });
 9606        assert_eq!(
 9607            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9608            &[
 9609                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9610                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9611                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9612            ]
 9613        );
 9614
 9615        // Trying to shrink the selected syntax node one more time has no effect.
 9616        view.update(cx, |view, cx| {
 9617            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 9618        });
 9619        assert_eq!(
 9620            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9621            &[
 9622                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 9623                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 9624                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 9625            ]
 9626        );
 9627
 9628        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9629        // a fold.
 9630        view.update(cx, |view, cx| {
 9631            view.fold_ranges(
 9632                vec![
 9633                    Point::new(0, 21)..Point::new(0, 24),
 9634                    Point::new(3, 20)..Point::new(3, 22),
 9635                ],
 9636                cx,
 9637            );
 9638            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9639        });
 9640        assert_eq!(
 9641            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 9642            &[
 9643                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9644                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9645                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9646            ]
 9647        );
 9648    }
 9649
 9650    #[gpui::test]
 9651    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9652        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9653        let language = Arc::new(
 9654            Language::new(
 9655                LanguageConfig {
 9656                    brackets: vec![
 9657                        BracketPair {
 9658                            start: "{".to_string(),
 9659                            end: "}".to_string(),
 9660                            close: false,
 9661                            newline: true,
 9662                        },
 9663                        BracketPair {
 9664                            start: "(".to_string(),
 9665                            end: ")".to_string(),
 9666                            close: false,
 9667                            newline: true,
 9668                        },
 9669                    ],
 9670                    ..Default::default()
 9671                },
 9672                Some(tree_sitter_rust::language()),
 9673            )
 9674            .with_indents_query(
 9675                r#"
 9676                (_ "(" ")" @end) @indent
 9677                (_ "{" "}" @end) @indent
 9678                "#,
 9679            )
 9680            .unwrap(),
 9681        );
 9682
 9683        let text = "fn a() {}";
 9684
 9685        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9686        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9687        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9688        editor
 9689            .condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9690            .await;
 9691
 9692        editor.update(cx, |editor, cx| {
 9693            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 9694            editor.newline(&Newline, cx);
 9695            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9696            assert_eq!(
 9697                editor.selections.ranges(cx),
 9698                &[
 9699                    Point::new(1, 4)..Point::new(1, 4),
 9700                    Point::new(3, 4)..Point::new(3, 4),
 9701                    Point::new(5, 0)..Point::new(5, 0)
 9702                ]
 9703            );
 9704        });
 9705    }
 9706
 9707    #[gpui::test]
 9708    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9709        let mut cx = EditorTestContext::new(cx);
 9710
 9711        let language = Arc::new(Language::new(
 9712            LanguageConfig {
 9713                brackets: vec![
 9714                    BracketPair {
 9715                        start: "{".to_string(),
 9716                        end: "}".to_string(),
 9717                        close: true,
 9718                        newline: true,
 9719                    },
 9720                    BracketPair {
 9721                        start: "/*".to_string(),
 9722                        end: " */".to_string(),
 9723                        close: true,
 9724                        newline: true,
 9725                    },
 9726                    BracketPair {
 9727                        start: "[".to_string(),
 9728                        end: "]".to_string(),
 9729                        close: false,
 9730                        newline: true,
 9731                    },
 9732                ],
 9733                autoclose_before: "})]".to_string(),
 9734                ..Default::default()
 9735            },
 9736            Some(tree_sitter_rust::language()),
 9737        ));
 9738
 9739        let registry = Arc::new(LanguageRegistry::test());
 9740        registry.add(language.clone());
 9741        cx.update_buffer(|buffer, cx| {
 9742            buffer.set_language_registry(registry);
 9743            buffer.set_language(Some(language), cx);
 9744        });
 9745
 9746        cx.set_state(
 9747            &r#"
 9748                🏀ˇ
 9749                εˇ
 9750                ❤️ˇ
 9751            "#
 9752            .unindent(),
 9753        );
 9754
 9755        // autoclose multiple nested brackets at multiple cursors
 9756        cx.update_editor(|view, cx| {
 9757            view.handle_input("{", cx);
 9758            view.handle_input("{", cx);
 9759            view.handle_input("{", cx);
 9760        });
 9761        cx.assert_editor_state(
 9762            &"
 9763                🏀{{{ˇ}}}
 9764                ε{{{ˇ}}}
 9765                ❤️{{{ˇ}}}
 9766            "
 9767            .unindent(),
 9768        );
 9769
 9770        // skip over the auto-closed brackets when typing a closing bracket
 9771        cx.update_editor(|view, cx| {
 9772            view.move_right(&MoveRight, cx);
 9773            view.handle_input("}", cx);
 9774            view.handle_input("}", cx);
 9775            view.handle_input("}", cx);
 9776        });
 9777        cx.assert_editor_state(
 9778            &"
 9779                🏀{{{}}}}ˇ
 9780                ε{{{}}}}ˇ
 9781                ❤️{{{}}}}ˇ
 9782            "
 9783            .unindent(),
 9784        );
 9785
 9786        // autoclose multi-character pairs
 9787        cx.set_state(
 9788            &"
 9789                ˇ
 9790                ˇ
 9791            "
 9792            .unindent(),
 9793        );
 9794        cx.update_editor(|view, cx| {
 9795            view.handle_input("/", cx);
 9796            view.handle_input("*", cx);
 9797        });
 9798        cx.assert_editor_state(
 9799            &"
 9800                /*ˇ */
 9801                /*ˇ */
 9802            "
 9803            .unindent(),
 9804        );
 9805
 9806        // one cursor autocloses a multi-character pair, one cursor
 9807        // does not autoclose.
 9808        cx.set_state(
 9809            &"
 9810 9811                ˇ
 9812            "
 9813            .unindent(),
 9814        );
 9815        cx.update_editor(|view, cx| view.handle_input("*", cx));
 9816        cx.assert_editor_state(
 9817            &"
 9818                /*ˇ */
 9819 9820            "
 9821            .unindent(),
 9822        );
 9823
 9824        // Don't autoclose if the next character isn't whitespace and isn't
 9825        // listed in the language's "autoclose_before" section.
 9826        cx.set_state("ˇa b");
 9827        cx.update_editor(|view, cx| view.handle_input("{", cx));
 9828        cx.assert_editor_state("{ˇa b");
 9829
 9830        // Surround with brackets if text is selected
 9831        cx.set_state("«aˇ» b");
 9832        cx.update_editor(|view, cx| view.handle_input("{", cx));
 9833        cx.assert_editor_state("{«aˇ»} b");
 9834    }
 9835
 9836    #[gpui::test]
 9837    async fn test_autoclose_with_embedded_language(cx: &mut gpui::TestAppContext) {
 9838        let mut cx = EditorTestContext::new(cx);
 9839
 9840        let html_language = Arc::new(
 9841            Language::new(
 9842                LanguageConfig {
 9843                    name: "HTML".into(),
 9844                    brackets: vec![
 9845                        BracketPair {
 9846                            start: "<".into(),
 9847                            end: ">".into(),
 9848                            ..Default::default()
 9849                        },
 9850                        BracketPair {
 9851                            start: "{".into(),
 9852                            end: "}".into(),
 9853                            ..Default::default()
 9854                        },
 9855                        BracketPair {
 9856                            start: "(".into(),
 9857                            end: ")".into(),
 9858                            ..Default::default()
 9859                        },
 9860                    ],
 9861                    autoclose_before: "})]>".into(),
 9862                    ..Default::default()
 9863                },
 9864                Some(tree_sitter_html::language()),
 9865            )
 9866            .with_injection_query(
 9867                r#"
 9868                (script_element
 9869                    (raw_text) @content
 9870                    (#set! "language" "javascript"))
 9871                "#,
 9872            )
 9873            .unwrap(),
 9874        );
 9875
 9876        let javascript_language = Arc::new(Language::new(
 9877            LanguageConfig {
 9878                name: "JavaScript".into(),
 9879                brackets: vec![
 9880                    BracketPair {
 9881                        start: "/*".into(),
 9882                        end: " */".into(),
 9883                        ..Default::default()
 9884                    },
 9885                    BracketPair {
 9886                        start: "{".into(),
 9887                        end: "}".into(),
 9888                        ..Default::default()
 9889                    },
 9890                    BracketPair {
 9891                        start: "(".into(),
 9892                        end: ")".into(),
 9893                        ..Default::default()
 9894                    },
 9895                ],
 9896                autoclose_before: "})]>".into(),
 9897                ..Default::default()
 9898            },
 9899            Some(tree_sitter_javascript::language()),
 9900        ));
 9901
 9902        let registry = Arc::new(LanguageRegistry::test());
 9903        registry.add(html_language.clone());
 9904        registry.add(javascript_language.clone());
 9905
 9906        cx.update_buffer(|buffer, cx| {
 9907            buffer.set_language_registry(registry);
 9908            buffer.set_language(Some(html_language), cx);
 9909        });
 9910
 9911        cx.set_state(
 9912            &r#"
 9913                <body>ˇ
 9914                    <script>
 9915                        var x = 1;ˇ
 9916                    </script>
 9917                </body>ˇ
 9918            "#
 9919            .unindent(),
 9920        );
 9921
 9922        // Precondition: different languages are active at different locations.
 9923        cx.update_editor(|editor, cx| {
 9924            let snapshot = editor.snapshot(cx);
 9925            let cursors = editor.selections.ranges::<usize>(cx);
 9926            let languages = cursors
 9927                .iter()
 9928                .map(|c| snapshot.language_at(c.start).unwrap().name())
 9929                .collect::<Vec<_>>();
 9930            assert_eq!(
 9931                languages,
 9932                &["HTML".into(), "JavaScript".into(), "HTML".into()]
 9933            );
 9934        });
 9935
 9936        // Angle brackets autoclose in HTML, but not JavaScript.
 9937        cx.update_editor(|editor, cx| {
 9938            editor.handle_input("<", cx);
 9939            editor.handle_input("a", cx);
 9940        });
 9941        cx.assert_editor_state(
 9942            &r#"
 9943                <body><aˇ>
 9944                    <script>
 9945                        var x = 1;<aˇ
 9946                    </script>
 9947                </body><aˇ>
 9948            "#
 9949            .unindent(),
 9950        );
 9951
 9952        // Curly braces and parens autoclose in both HTML and JavaScript.
 9953        cx.update_editor(|editor, cx| {
 9954            editor.handle_input(" b=", cx);
 9955            editor.handle_input("{", cx);
 9956            editor.handle_input("c", cx);
 9957            editor.handle_input("(", cx);
 9958        });
 9959        cx.assert_editor_state(
 9960            &r#"
 9961                <body><a b={c(ˇ)}>
 9962                    <script>
 9963                        var x = 1;<a b={c(ˇ)}
 9964                    </script>
 9965                </body><a b={c(ˇ)}>
 9966            "#
 9967            .unindent(),
 9968        );
 9969
 9970        // Brackets that were already autoclosed are skipped.
 9971        cx.update_editor(|editor, cx| {
 9972            editor.handle_input(")", cx);
 9973            editor.handle_input("d", cx);
 9974            editor.handle_input("}", cx);
 9975        });
 9976        cx.assert_editor_state(
 9977            &r#"
 9978                <body><a b={c()d}ˇ>
 9979                    <script>
 9980                        var x = 1;<a b={c()d}ˇ
 9981                    </script>
 9982                </body><a b={c()d}ˇ>
 9983            "#
 9984            .unindent(),
 9985        );
 9986        cx.update_editor(|editor, cx| {
 9987            editor.handle_input(">", cx);
 9988        });
 9989        cx.assert_editor_state(
 9990            &r#"
 9991                <body><a b={c()d}>ˇ
 9992                    <script>
 9993                        var x = 1;<a b={c()d}>ˇ
 9994                    </script>
 9995                </body><a b={c()d}>ˇ
 9996            "#
 9997            .unindent(),
 9998        );
 9999
10000        // Reset
10001        cx.set_state(
10002            &r#"
10003                <body>ˇ
10004                    <script>
10005                        var x = 1;ˇ
10006                    </script>
10007                </body>ˇ
10008            "#
10009            .unindent(),
10010        );
10011
10012        cx.update_editor(|editor, cx| {
10013            editor.handle_input("<", cx);
10014        });
10015        cx.assert_editor_state(
10016            &r#"
10017                <body><ˇ>
10018                    <script>
10019                        var x = 1;<ˇ
10020                    </script>
10021                </body><ˇ>
10022            "#
10023            .unindent(),
10024        );
10025
10026        // When backspacing, the closing angle brackets are removed.
10027        cx.update_editor(|editor, cx| {
10028            editor.backspace(&Backspace, cx);
10029        });
10030        cx.assert_editor_state(
10031            &r#"
10032                <body>ˇ
10033                    <script>
10034                        var x = 1;ˇ
10035                    </script>
10036                </body>ˇ
10037            "#
10038            .unindent(),
10039        );
10040
10041        // Block comments autoclose in JavaScript, but not HTML.
10042        cx.update_editor(|editor, cx| {
10043            editor.handle_input("/", cx);
10044            editor.handle_input("*", cx);
10045        });
10046        cx.assert_editor_state(
10047            &r#"
10048                <body>/*ˇ
10049                    <script>
10050                        var x = 1;/*ˇ */
10051                    </script>
10052                </body>/*ˇ
10053            "#
10054            .unindent(),
10055        );
10056    }
10057
10058    #[gpui::test]
10059    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
10060        cx.update(|cx| cx.set_global(Settings::test(cx)));
10061        let language = Arc::new(Language::new(
10062            LanguageConfig {
10063                brackets: vec![BracketPair {
10064                    start: "{".to_string(),
10065                    end: "}".to_string(),
10066                    close: true,
10067                    newline: true,
10068                }],
10069                ..Default::default()
10070            },
10071            Some(tree_sitter_rust::language()),
10072        ));
10073
10074        let text = r#"
10075            a
10076            b
10077            c
10078        "#
10079        .unindent();
10080
10081        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10082        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10083        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10084        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10085            .await;
10086
10087        view.update(cx, |view, cx| {
10088            view.change_selections(None, cx, |s| {
10089                s.select_display_ranges([
10090                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
10091                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
10092                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
10093                ])
10094            });
10095
10096            view.handle_input("{", cx);
10097            view.handle_input("{", cx);
10098            view.handle_input("{", cx);
10099            assert_eq!(
10100                view.text(cx),
10101                "
10102                {{{a}}}
10103                {{{b}}}
10104                {{{c}}}
10105                "
10106                .unindent()
10107            );
10108            assert_eq!(
10109                view.selections.display_ranges(cx),
10110                [
10111                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
10112                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
10113                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
10114                ]
10115            );
10116
10117            view.undo(&Undo, cx);
10118            assert_eq!(
10119                view.text(cx),
10120                "
10121                a
10122                b
10123                c
10124                "
10125                .unindent()
10126            );
10127            assert_eq!(
10128                view.selections.display_ranges(cx),
10129                [
10130                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
10131                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
10132                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
10133                ]
10134            );
10135        });
10136    }
10137
10138    #[gpui::test]
10139    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
10140        cx.update(|cx| cx.set_global(Settings::test(cx)));
10141        let language = Arc::new(Language::new(
10142            LanguageConfig {
10143                brackets: vec![BracketPair {
10144                    start: "{".to_string(),
10145                    end: "}".to_string(),
10146                    close: true,
10147                    newline: true,
10148                }],
10149                autoclose_before: "}".to_string(),
10150                ..Default::default()
10151            },
10152            Some(tree_sitter_rust::language()),
10153        ));
10154
10155        let text = r#"
10156            a
10157            b
10158            c
10159        "#
10160        .unindent();
10161
10162        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10163        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10164        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10165        editor
10166            .condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10167            .await;
10168
10169        editor.update(cx, |editor, cx| {
10170            editor.change_selections(None, cx, |s| {
10171                s.select_ranges([
10172                    Point::new(0, 1)..Point::new(0, 1),
10173                    Point::new(1, 1)..Point::new(1, 1),
10174                    Point::new(2, 1)..Point::new(2, 1),
10175                ])
10176            });
10177
10178            editor.handle_input("{", cx);
10179            editor.handle_input("{", cx);
10180            editor.handle_input("_", cx);
10181            assert_eq!(
10182                editor.text(cx),
10183                "
10184                a{{_}}
10185                b{{_}}
10186                c{{_}}
10187                "
10188                .unindent()
10189            );
10190            assert_eq!(
10191                editor.selections.ranges::<Point>(cx),
10192                [
10193                    Point::new(0, 4)..Point::new(0, 4),
10194                    Point::new(1, 4)..Point::new(1, 4),
10195                    Point::new(2, 4)..Point::new(2, 4)
10196                ]
10197            );
10198
10199            editor.backspace(&Default::default(), cx);
10200            editor.backspace(&Default::default(), cx);
10201            assert_eq!(
10202                editor.text(cx),
10203                "
10204                a{}
10205                b{}
10206                c{}
10207                "
10208                .unindent()
10209            );
10210            assert_eq!(
10211                editor.selections.ranges::<Point>(cx),
10212                [
10213                    Point::new(0, 2)..Point::new(0, 2),
10214                    Point::new(1, 2)..Point::new(1, 2),
10215                    Point::new(2, 2)..Point::new(2, 2)
10216                ]
10217            );
10218
10219            editor.delete_to_previous_word_start(&Default::default(), cx);
10220            assert_eq!(
10221                editor.text(cx),
10222                "
10223                a
10224                b
10225                c
10226                "
10227                .unindent()
10228            );
10229            assert_eq!(
10230                editor.selections.ranges::<Point>(cx),
10231                [
10232                    Point::new(0, 1)..Point::new(0, 1),
10233                    Point::new(1, 1)..Point::new(1, 1),
10234                    Point::new(2, 1)..Point::new(2, 1)
10235                ]
10236            );
10237        });
10238    }
10239
10240    #[gpui::test]
10241    async fn test_snippets(cx: &mut gpui::TestAppContext) {
10242        cx.update(|cx| cx.set_global(Settings::test(cx)));
10243
10244        let (text, insertion_ranges) = marked_text_ranges(
10245            indoc! {"
10246                a.ˇ b
10247                a.ˇ b
10248                a.ˇ b
10249            "},
10250            false,
10251        );
10252
10253        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
10254        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10255
10256        editor.update(cx, |editor, cx| {
10257            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
10258
10259            editor
10260                .insert_snippet(&insertion_ranges, snippet, cx)
10261                .unwrap();
10262
10263            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text: &str) {
10264                let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
10265                assert_eq!(editor.text(cx), expected_text);
10266                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
10267            }
10268
10269            assert(
10270                editor,
10271                cx,
10272                indoc! {"
10273                    a.f(«one», two, «three») b
10274                    a.f(«one», two, «three») b
10275                    a.f(«one», two, «three») b
10276                "},
10277            );
10278
10279            // Can't move earlier than the first tab stop
10280            assert!(!editor.move_to_prev_snippet_tabstop(cx));
10281            assert(
10282                editor,
10283                cx,
10284                indoc! {"
10285                    a.f(«one», two, «three») b
10286                    a.f(«one», two, «three») b
10287                    a.f(«one», two, «three») b
10288                "},
10289            );
10290
10291            assert!(editor.move_to_next_snippet_tabstop(cx));
10292            assert(
10293                editor,
10294                cx,
10295                indoc! {"
10296                    a.f(one, «two», three) b
10297                    a.f(one, «two», three) b
10298                    a.f(one, «two», three) b
10299                "},
10300            );
10301
10302            editor.move_to_prev_snippet_tabstop(cx);
10303            assert(
10304                editor,
10305                cx,
10306                indoc! {"
10307                    a.f(«one», two, «three») b
10308                    a.f(«one», two, «three») b
10309                    a.f(«one», two, «three») b
10310                "},
10311            );
10312
10313            assert!(editor.move_to_next_snippet_tabstop(cx));
10314            assert(
10315                editor,
10316                cx,
10317                indoc! {"
10318                    a.f(one, «two», three) b
10319                    a.f(one, «two», three) b
10320                    a.f(one, «two», three) b
10321                "},
10322            );
10323            assert!(editor.move_to_next_snippet_tabstop(cx));
10324            assert(
10325                editor,
10326                cx,
10327                indoc! {"
10328                    a.f(one, two, three)ˇ b
10329                    a.f(one, two, three)ˇ b
10330                    a.f(one, two, three)ˇ b
10331                "},
10332            );
10333
10334            // As soon as the last tab stop is reached, snippet state is gone
10335            editor.move_to_prev_snippet_tabstop(cx);
10336            assert(
10337                editor,
10338                cx,
10339                indoc! {"
10340                    a.f(one, two, three)ˇ b
10341                    a.f(one, two, three)ˇ b
10342                    a.f(one, two, three)ˇ b
10343                "},
10344            );
10345        });
10346    }
10347
10348    #[gpui::test]
10349    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
10350        cx.foreground().forbid_parking();
10351
10352        let mut language = Language::new(
10353            LanguageConfig {
10354                name: "Rust".into(),
10355                path_suffixes: vec!["rs".to_string()],
10356                ..Default::default()
10357            },
10358            Some(tree_sitter_rust::language()),
10359        );
10360        let mut fake_servers = language
10361            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10362                capabilities: lsp::ServerCapabilities {
10363                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10364                    ..Default::default()
10365                },
10366                ..Default::default()
10367            }))
10368            .await;
10369
10370        let fs = FakeFs::new(cx.background());
10371        fs.insert_file("/file.rs", Default::default()).await;
10372
10373        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10374        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10375        let buffer = project
10376            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10377            .await
10378            .unwrap();
10379
10380        cx.foreground().start_waiting();
10381        let fake_server = fake_servers.next().await.unwrap();
10382
10383        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10384        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10385        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10386        assert!(cx.read(|cx| editor.is_dirty(cx)));
10387
10388        let save = cx.update(|cx| editor.save(project.clone(), cx));
10389        fake_server
10390            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10391                assert_eq!(
10392                    params.text_document.uri,
10393                    lsp::Url::from_file_path("/file.rs").unwrap()
10394                );
10395                assert_eq!(params.options.tab_size, 4);
10396                Ok(Some(vec![lsp::TextEdit::new(
10397                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10398                    ", ".to_string(),
10399                )]))
10400            })
10401            .next()
10402            .await;
10403        cx.foreground().start_waiting();
10404        save.await.unwrap();
10405        assert_eq!(
10406            editor.read_with(cx, |editor, cx| editor.text(cx)),
10407            "one, two\nthree\n"
10408        );
10409        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10410
10411        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10412        assert!(cx.read(|cx| editor.is_dirty(cx)));
10413
10414        // Ensure we can still save even if formatting hangs.
10415        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10416            assert_eq!(
10417                params.text_document.uri,
10418                lsp::Url::from_file_path("/file.rs").unwrap()
10419            );
10420            futures::future::pending::<()>().await;
10421            unreachable!()
10422        });
10423        let save = cx.update(|cx| editor.save(project.clone(), cx));
10424        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10425        cx.foreground().start_waiting();
10426        save.await.unwrap();
10427        assert_eq!(
10428            editor.read_with(cx, |editor, cx| editor.text(cx)),
10429            "one\ntwo\nthree\n"
10430        );
10431        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10432
10433        // Set rust language override and assert overriden tabsize is sent to language server
10434        cx.update(|cx| {
10435            cx.update_global::<Settings, _, _>(|settings, _| {
10436                settings.language_overrides.insert(
10437                    "Rust".into(),
10438                    EditorSettings {
10439                        tab_size: Some(8.try_into().unwrap()),
10440                        ..Default::default()
10441                    },
10442                );
10443            })
10444        });
10445
10446        let save = cx.update(|cx| editor.save(project.clone(), cx));
10447        fake_server
10448            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10449                assert_eq!(
10450                    params.text_document.uri,
10451                    lsp::Url::from_file_path("/file.rs").unwrap()
10452                );
10453                assert_eq!(params.options.tab_size, 8);
10454                Ok(Some(vec![]))
10455            })
10456            .next()
10457            .await;
10458        cx.foreground().start_waiting();
10459        save.await.unwrap();
10460    }
10461
10462    #[gpui::test]
10463    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
10464        cx.foreground().forbid_parking();
10465
10466        let mut language = Language::new(
10467            LanguageConfig {
10468                name: "Rust".into(),
10469                path_suffixes: vec!["rs".to_string()],
10470                ..Default::default()
10471            },
10472            Some(tree_sitter_rust::language()),
10473        );
10474        let mut fake_servers = language
10475            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10476                capabilities: lsp::ServerCapabilities {
10477                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
10478                    ..Default::default()
10479                },
10480                ..Default::default()
10481            }))
10482            .await;
10483
10484        let fs = FakeFs::new(cx.background());
10485        fs.insert_file("/file.rs", Default::default()).await;
10486
10487        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10488        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10489        let buffer = project
10490            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10491            .await
10492            .unwrap();
10493
10494        cx.foreground().start_waiting();
10495        let fake_server = fake_servers.next().await.unwrap();
10496
10497        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10498        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10499        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10500        assert!(cx.read(|cx| editor.is_dirty(cx)));
10501
10502        let save = cx.update(|cx| editor.save(project.clone(), cx));
10503        fake_server
10504            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10505                assert_eq!(
10506                    params.text_document.uri,
10507                    lsp::Url::from_file_path("/file.rs").unwrap()
10508                );
10509                assert_eq!(params.options.tab_size, 4);
10510                Ok(Some(vec![lsp::TextEdit::new(
10511                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10512                    ", ".to_string(),
10513                )]))
10514            })
10515            .next()
10516            .await;
10517        cx.foreground().start_waiting();
10518        save.await.unwrap();
10519        assert_eq!(
10520            editor.read_with(cx, |editor, cx| editor.text(cx)),
10521            "one, two\nthree\n"
10522        );
10523        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10524
10525        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10526        assert!(cx.read(|cx| editor.is_dirty(cx)));
10527
10528        // Ensure we can still save even if formatting hangs.
10529        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
10530            move |params, _| async move {
10531                assert_eq!(
10532                    params.text_document.uri,
10533                    lsp::Url::from_file_path("/file.rs").unwrap()
10534                );
10535                futures::future::pending::<()>().await;
10536                unreachable!()
10537            },
10538        );
10539        let save = cx.update(|cx| editor.save(project.clone(), cx));
10540        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10541        cx.foreground().start_waiting();
10542        save.await.unwrap();
10543        assert_eq!(
10544            editor.read_with(cx, |editor, cx| editor.text(cx)),
10545            "one\ntwo\nthree\n"
10546        );
10547        assert!(!cx.read(|cx| editor.is_dirty(cx)));
10548
10549        // Set rust language override and assert overriden tabsize is sent to language server
10550        cx.update(|cx| {
10551            cx.update_global::<Settings, _, _>(|settings, _| {
10552                settings.language_overrides.insert(
10553                    "Rust".into(),
10554                    EditorSettings {
10555                        tab_size: Some(8.try_into().unwrap()),
10556                        ..Default::default()
10557                    },
10558                );
10559            })
10560        });
10561
10562        let save = cx.update(|cx| editor.save(project.clone(), cx));
10563        fake_server
10564            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
10565                assert_eq!(
10566                    params.text_document.uri,
10567                    lsp::Url::from_file_path("/file.rs").unwrap()
10568                );
10569                assert_eq!(params.options.tab_size, 8);
10570                Ok(Some(vec![]))
10571            })
10572            .next()
10573            .await;
10574        cx.foreground().start_waiting();
10575        save.await.unwrap();
10576    }
10577
10578    #[gpui::test]
10579    async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
10580        cx.foreground().forbid_parking();
10581
10582        let mut language = Language::new(
10583            LanguageConfig {
10584                name: "Rust".into(),
10585                path_suffixes: vec!["rs".to_string()],
10586                ..Default::default()
10587            },
10588            Some(tree_sitter_rust::language()),
10589        );
10590        let mut fake_servers = language
10591            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
10592                capabilities: lsp::ServerCapabilities {
10593                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
10594                    ..Default::default()
10595                },
10596                ..Default::default()
10597            }))
10598            .await;
10599
10600        let fs = FakeFs::new(cx.background());
10601        fs.insert_file("/file.rs", Default::default()).await;
10602
10603        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
10604        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
10605        let buffer = project
10606            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
10607            .await
10608            .unwrap();
10609
10610        cx.foreground().start_waiting();
10611        let fake_server = fake_servers.next().await.unwrap();
10612
10613        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10614        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
10615        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10616
10617        let format = editor.update(cx, |editor, cx| editor.perform_format(project.clone(), cx));
10618        fake_server
10619            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10620                assert_eq!(
10621                    params.text_document.uri,
10622                    lsp::Url::from_file_path("/file.rs").unwrap()
10623                );
10624                assert_eq!(params.options.tab_size, 4);
10625                Ok(Some(vec![lsp::TextEdit::new(
10626                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
10627                    ", ".to_string(),
10628                )]))
10629            })
10630            .next()
10631            .await;
10632        cx.foreground().start_waiting();
10633        format.await.unwrap();
10634        assert_eq!(
10635            editor.read_with(cx, |editor, cx| editor.text(cx)),
10636            "one, two\nthree\n"
10637        );
10638
10639        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
10640        // Ensure we don't lock if formatting hangs.
10641        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
10642            assert_eq!(
10643                params.text_document.uri,
10644                lsp::Url::from_file_path("/file.rs").unwrap()
10645            );
10646            futures::future::pending::<()>().await;
10647            unreachable!()
10648        });
10649        let format = editor.update(cx, |editor, cx| editor.perform_format(project, cx));
10650        cx.foreground().advance_clock(super::FORMAT_TIMEOUT);
10651        cx.foreground().start_waiting();
10652        format.await.unwrap();
10653        assert_eq!(
10654            editor.read_with(cx, |editor, cx| editor.text(cx)),
10655            "one\ntwo\nthree\n"
10656        );
10657    }
10658
10659    #[gpui::test]
10660    async fn test_completion(cx: &mut gpui::TestAppContext) {
10661        let mut cx = EditorLspTestContext::new_rust(
10662            lsp::ServerCapabilities {
10663                completion_provider: Some(lsp::CompletionOptions {
10664                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
10665                    ..Default::default()
10666                }),
10667                ..Default::default()
10668            },
10669            cx,
10670        )
10671        .await;
10672
10673        cx.set_state(indoc! {"
10674            oneˇ
10675            two
10676            three
10677        "});
10678        cx.simulate_keystroke(".");
10679        handle_completion_request(
10680            &mut cx,
10681            indoc! {"
10682                one.|<>
10683                two
10684                three
10685            "},
10686            vec!["first_completion", "second_completion"],
10687        )
10688        .await;
10689        cx.condition(|editor, _| editor.context_menu_visible())
10690            .await;
10691        let apply_additional_edits = cx.update_editor(|editor, cx| {
10692            editor.move_down(&MoveDown, cx);
10693            editor
10694                .confirm_completion(&ConfirmCompletion::default(), cx)
10695                .unwrap()
10696        });
10697        cx.assert_editor_state(indoc! {"
10698            one.second_completionˇ
10699            two
10700            three
10701        "});
10702
10703        handle_resolve_completion_request(
10704            &mut cx,
10705            Some((
10706                indoc! {"
10707                    one.second_completion
10708                    two
10709                    threeˇ
10710                "},
10711                "\nadditional edit",
10712            )),
10713        )
10714        .await;
10715        apply_additional_edits.await.unwrap();
10716        cx.assert_editor_state(indoc! {"
10717            one.second_completionˇ
10718            two
10719            three
10720            additional edit
10721        "});
10722
10723        cx.set_state(indoc! {"
10724            one.second_completion
10725            twoˇ
10726            threeˇ
10727            additional edit
10728        "});
10729        cx.simulate_keystroke(" ");
10730        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10731        cx.simulate_keystroke("s");
10732        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10733
10734        cx.assert_editor_state(indoc! {"
10735            one.second_completion
10736            two sˇ
10737            three sˇ
10738            additional edit
10739        "});
10740        //
10741        handle_completion_request(
10742            &mut cx,
10743            indoc! {"
10744                one.second_completion
10745                two s
10746                three <s|>
10747                additional edit
10748            "},
10749            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10750        )
10751        .await;
10752        cx.condition(|editor, _| editor.context_menu_visible())
10753            .await;
10754
10755        cx.simulate_keystroke("i");
10756
10757        handle_completion_request(
10758            &mut cx,
10759            indoc! {"
10760                one.second_completion
10761                two si
10762                three <si|>
10763                additional edit
10764            "},
10765            vec!["fourth_completion", "fifth_completion", "sixth_completion"],
10766        )
10767        .await;
10768        cx.condition(|editor, _| editor.context_menu_visible())
10769            .await;
10770
10771        let apply_additional_edits = cx.update_editor(|editor, cx| {
10772            editor
10773                .confirm_completion(&ConfirmCompletion::default(), cx)
10774                .unwrap()
10775        });
10776        cx.assert_editor_state(indoc! {"
10777            one.second_completion
10778            two sixth_completionˇ
10779            three sixth_completionˇ
10780            additional edit
10781        "});
10782
10783        handle_resolve_completion_request(&mut cx, None).await;
10784        apply_additional_edits.await.unwrap();
10785
10786        cx.update(|cx| {
10787            cx.update_global::<Settings, _, _>(|settings, _| {
10788                settings.show_completions_on_input = false;
10789            })
10790        });
10791        cx.set_state("editorˇ");
10792        cx.simulate_keystroke(".");
10793        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10794        cx.simulate_keystroke("c");
10795        cx.simulate_keystroke("l");
10796        cx.simulate_keystroke("o");
10797        cx.assert_editor_state("editor.cloˇ");
10798        assert!(cx.editor(|e, _| e.context_menu.is_none()));
10799        cx.update_editor(|editor, cx| {
10800            editor.show_completions(&ShowCompletions, cx);
10801        });
10802        handle_completion_request(&mut cx, "editor.<clo|>", vec!["close", "clobber"]).await;
10803        cx.condition(|editor, _| editor.context_menu_visible())
10804            .await;
10805        let apply_additional_edits = cx.update_editor(|editor, cx| {
10806            editor
10807                .confirm_completion(&ConfirmCompletion::default(), cx)
10808                .unwrap()
10809        });
10810        cx.assert_editor_state("editor.closeˇ");
10811        handle_resolve_completion_request(&mut cx, None).await;
10812        apply_additional_edits.await.unwrap();
10813
10814        // Handle completion request passing a marked string specifying where the completion
10815        // should be triggered from using '|' character, what range should be replaced, and what completions
10816        // should be returned using '<' and '>' to delimit the range
10817        async fn handle_completion_request<'a>(
10818            cx: &mut EditorLspTestContext<'a>,
10819            marked_string: &str,
10820            completions: Vec<&'static str>,
10821        ) {
10822            let complete_from_marker: TextRangeMarker = '|'.into();
10823            let replace_range_marker: TextRangeMarker = ('<', '>').into();
10824            let (_, mut marked_ranges) = marked_text_ranges_by(
10825                marked_string,
10826                vec![complete_from_marker.clone(), replace_range_marker.clone()],
10827            );
10828
10829            let complete_from_position =
10830                cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
10831            let replace_range =
10832                cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
10833
10834            cx.handle_request::<lsp::request::Completion, _, _>(move |url, params, _| {
10835                let completions = completions.clone();
10836                async move {
10837                    assert_eq!(params.text_document_position.text_document.uri, url.clone());
10838                    assert_eq!(
10839                        params.text_document_position.position,
10840                        complete_from_position
10841                    );
10842                    Ok(Some(lsp::CompletionResponse::Array(
10843                        completions
10844                            .iter()
10845                            .map(|completion_text| lsp::CompletionItem {
10846                                label: completion_text.to_string(),
10847                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
10848                                    range: replace_range,
10849                                    new_text: completion_text.to_string(),
10850                                })),
10851                                ..Default::default()
10852                            })
10853                            .collect(),
10854                    )))
10855                }
10856            })
10857            .next()
10858            .await;
10859        }
10860
10861        async fn handle_resolve_completion_request<'a>(
10862            cx: &mut EditorLspTestContext<'a>,
10863            edit: Option<(&'static str, &'static str)>,
10864        ) {
10865            let edit = edit.map(|(marked_string, new_text)| {
10866                let (_, marked_ranges) = marked_text_ranges(marked_string, false);
10867                let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
10868                vec![lsp::TextEdit::new(replace_range, new_text.to_string())]
10869            });
10870
10871            cx.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _, _| {
10872                let edit = edit.clone();
10873                async move {
10874                    Ok(lsp::CompletionItem {
10875                        additional_text_edits: edit,
10876                        ..Default::default()
10877                    })
10878                }
10879            })
10880            .next()
10881            .await;
10882        }
10883    }
10884
10885    #[gpui::test]
10886    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
10887        cx.update(|cx| cx.set_global(Settings::test(cx)));
10888        let language = Arc::new(Language::new(
10889            LanguageConfig {
10890                line_comment: Some("// ".into()),
10891                ..Default::default()
10892            },
10893            Some(tree_sitter_rust::language()),
10894        ));
10895
10896        let text = "
10897            fn a() {
10898                //b();
10899                // c();
10900                //  d();
10901            }
10902        "
10903        .unindent();
10904
10905        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10906        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10907        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10908
10909        view.update(cx, |editor, cx| {
10910            // If multiple selections intersect a line, the line is only
10911            // toggled once.
10912            editor.change_selections(None, cx, |s| {
10913                s.select_display_ranges([
10914                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
10915                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
10916                ])
10917            });
10918            editor.toggle_comments(&ToggleComments, cx);
10919            assert_eq!(
10920                editor.text(cx),
10921                "
10922                    fn a() {
10923                        b();
10924                        c();
10925                         d();
10926                    }
10927                "
10928                .unindent()
10929            );
10930
10931            // The comment prefix is inserted at the same column for every line
10932            // in a selection.
10933            editor.change_selections(None, cx, |s| {
10934                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
10935            });
10936            editor.toggle_comments(&ToggleComments, cx);
10937            assert_eq!(
10938                editor.text(cx),
10939                "
10940                    fn a() {
10941                        // b();
10942                        // c();
10943                        //  d();
10944                    }
10945                "
10946                .unindent()
10947            );
10948
10949            // If a selection ends at the beginning of a line, that line is not toggled.
10950            editor.change_selections(None, cx, |s| {
10951                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
10952            });
10953            editor.toggle_comments(&ToggleComments, cx);
10954            assert_eq!(
10955                editor.text(cx),
10956                "
10957                        fn a() {
10958                            // b();
10959                            c();
10960                            //  d();
10961                        }
10962                    "
10963                .unindent()
10964            );
10965        });
10966    }
10967
10968    #[gpui::test]
10969    async fn test_toggle_block_comment(cx: &mut gpui::TestAppContext) {
10970        let mut cx = EditorTestContext::new(cx);
10971
10972        let html_language = Arc::new(
10973            Language::new(
10974                LanguageConfig {
10975                    name: "HTML".into(),
10976                    block_comment: Some(("<!-- ".into(), " -->".into())),
10977                    ..Default::default()
10978                },
10979                Some(tree_sitter_html::language()),
10980            )
10981            .with_injection_query(
10982                r#"
10983                (script_element
10984                    (raw_text) @content
10985                    (#set! "language" "javascript"))
10986                "#,
10987            )
10988            .unwrap(),
10989        );
10990
10991        let javascript_language = Arc::new(Language::new(
10992            LanguageConfig {
10993                name: "JavaScript".into(),
10994                line_comment: Some("// ".into()),
10995                ..Default::default()
10996            },
10997            Some(tree_sitter_javascript::language()),
10998        ));
10999
11000        let registry = Arc::new(LanguageRegistry::test());
11001        registry.add(html_language.clone());
11002        registry.add(javascript_language.clone());
11003
11004        cx.update_buffer(|buffer, cx| {
11005            buffer.set_language_registry(registry);
11006            buffer.set_language(Some(html_language), cx);
11007        });
11008
11009        // Toggle comments for empty selections
11010        cx.set_state(
11011            &r#"
11012                <p>A</p>ˇ
11013                <p>B</p>ˇ
11014                <p>C</p>ˇ
11015            "#
11016            .unindent(),
11017        );
11018        cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments, cx));
11019        cx.assert_editor_state(
11020            &r#"
11021                <!-- <p>A</p>ˇ -->
11022                <!-- <p>B</p>ˇ -->
11023                <!-- <p>C</p>ˇ -->
11024            "#
11025            .unindent(),
11026        );
11027        cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments, cx));
11028        cx.assert_editor_state(
11029            &r#"
11030                <p>A</p>ˇ
11031                <p>B</p>ˇ
11032                <p>C</p>ˇ
11033            "#
11034            .unindent(),
11035        );
11036
11037        // Toggle comments for mixture of empty and non-empty selections, where
11038        // multiple selections occupy a given line.
11039        cx.set_state(
11040            &r#"
11041                <p>A«</p>
11042                <p>ˇ»B</p>ˇ
11043                <p>C«</p>
11044                <p>ˇ»D</p>ˇ
11045            "#
11046            .unindent(),
11047        );
11048
11049        cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments, cx));
11050        cx.assert_editor_state(
11051            &r#"
11052                <!-- <p>A«</p>
11053                <p>ˇ»B</p>ˇ -->
11054                <!-- <p>C«</p>
11055                <p>ˇ»D</p>ˇ -->
11056            "#
11057            .unindent(),
11058        );
11059        cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments, cx));
11060        cx.assert_editor_state(
11061            &r#"
11062                <p>A«</p>
11063                <p>ˇ»B</p>ˇ
11064                <p>C«</p>
11065                <p>ˇ»D</p>ˇ
11066            "#
11067            .unindent(),
11068        );
11069
11070        // Toggle comments when different languages are active for different
11071        // selections.
11072        cx.set_state(
11073            &r#"
11074                ˇ<script>
11075                    ˇvar x = new Y();
11076                ˇ</script>
11077            "#
11078            .unindent(),
11079        );
11080        cx.foreground().run_until_parked();
11081        cx.update_editor(|editor, cx| editor.toggle_comments(&ToggleComments, cx));
11082        cx.assert_editor_state(
11083            &r#"
11084                <!-- ˇ<script> -->
11085                    // ˇvar x = new Y();
11086                <!-- ˇ</script> -->
11087            "#
11088            .unindent(),
11089        );
11090    }
11091
11092    #[gpui::test]
11093    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
11094        cx.set_global(Settings::test(cx));
11095        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
11096        let multibuffer = cx.add_model(|cx| {
11097            let mut multibuffer = MultiBuffer::new(0);
11098            multibuffer.push_excerpts(
11099                buffer.clone(),
11100                [
11101                    ExcerptRange {
11102                        context: Point::new(0, 0)..Point::new(0, 4),
11103                        primary: None,
11104                    },
11105                    ExcerptRange {
11106                        context: Point::new(1, 0)..Point::new(1, 4),
11107                        primary: None,
11108                    },
11109                ],
11110                cx,
11111            );
11112            multibuffer
11113        });
11114
11115        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
11116
11117        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
11118        view.update(cx, |view, cx| {
11119            assert_eq!(view.text(cx), "aaaa\nbbbb");
11120            view.change_selections(None, cx, |s| {
11121                s.select_ranges([
11122                    Point::new(0, 0)..Point::new(0, 0),
11123                    Point::new(1, 0)..Point::new(1, 0),
11124                ])
11125            });
11126
11127            view.handle_input("X", cx);
11128            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
11129            assert_eq!(
11130                view.selections.ranges(cx),
11131                [
11132                    Point::new(0, 1)..Point::new(0, 1),
11133                    Point::new(1, 1)..Point::new(1, 1),
11134                ]
11135            )
11136        });
11137    }
11138
11139    #[gpui::test]
11140    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
11141        cx.set_global(Settings::test(cx));
11142        let markers = vec![('[', ']').into(), ('(', ')').into()];
11143        let (initial_text, mut excerpt_ranges) = marked_text_ranges_by(
11144            indoc! {"
11145                [aaaa
11146                (bbbb]
11147                cccc)",
11148            },
11149            markers.clone(),
11150        );
11151        let excerpt_ranges = markers.into_iter().map(|marker| {
11152            let context = excerpt_ranges.remove(&marker).unwrap()[0].clone();
11153            ExcerptRange {
11154                context,
11155                primary: None,
11156            }
11157        });
11158        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
11159        let multibuffer = cx.add_model(|cx| {
11160            let mut multibuffer = MultiBuffer::new(0);
11161            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
11162            multibuffer
11163        });
11164
11165        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
11166        view.update(cx, |view, cx| {
11167            let (expected_text, selection_ranges) = marked_text_ranges(
11168                indoc! {"
11169                    aaaa
11170                    bˇbbb
11171                    bˇbbˇb
11172                    cccc"
11173                },
11174                true,
11175            );
11176            assert_eq!(view.text(cx), expected_text);
11177            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
11178
11179            view.handle_input("X", cx);
11180
11181            let (expected_text, expected_selections) = marked_text_ranges(
11182                indoc! {"
11183                    aaaa
11184                    bXˇbbXb
11185                    bXˇbbXˇb
11186                    cccc"
11187                },
11188                false,
11189            );
11190            assert_eq!(view.text(cx), expected_text);
11191            assert_eq!(view.selections.ranges(cx), expected_selections);
11192
11193            view.newline(&Newline, cx);
11194            let (expected_text, expected_selections) = marked_text_ranges(
11195                indoc! {"
11196                    aaaa
11197                    bX
11198                    ˇbbX
11199                    b
11200                    bX
11201                    ˇbbX
11202                    ˇb
11203                    cccc"
11204                },
11205                false,
11206            );
11207            assert_eq!(view.text(cx), expected_text);
11208            assert_eq!(view.selections.ranges(cx), expected_selections);
11209        });
11210    }
11211
11212    #[gpui::test]
11213    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
11214        cx.set_global(Settings::test(cx));
11215        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
11216        let mut excerpt1_id = None;
11217        let multibuffer = cx.add_model(|cx| {
11218            let mut multibuffer = MultiBuffer::new(0);
11219            excerpt1_id = multibuffer
11220                .push_excerpts(
11221                    buffer.clone(),
11222                    [
11223                        ExcerptRange {
11224                            context: Point::new(0, 0)..Point::new(1, 4),
11225                            primary: None,
11226                        },
11227                        ExcerptRange {
11228                            context: Point::new(1, 0)..Point::new(2, 4),
11229                            primary: None,
11230                        },
11231                    ],
11232                    cx,
11233                )
11234                .into_iter()
11235                .next();
11236            multibuffer
11237        });
11238        assert_eq!(
11239            multibuffer.read(cx).read(cx).text(),
11240            "aaaa\nbbbb\nbbbb\ncccc"
11241        );
11242        let (_, editor) = cx.add_window(Default::default(), |cx| {
11243            let mut editor = build_editor(multibuffer.clone(), cx);
11244            let snapshot = editor.snapshot(cx);
11245            editor.change_selections(None, cx, |s| {
11246                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
11247            });
11248            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
11249            assert_eq!(
11250                editor.selections.ranges(cx),
11251                [
11252                    Point::new(1, 3)..Point::new(1, 3),
11253                    Point::new(2, 1)..Point::new(2, 1),
11254                ]
11255            );
11256            editor
11257        });
11258
11259        // Refreshing selections is a no-op when excerpts haven't changed.
11260        editor.update(cx, |editor, cx| {
11261            editor.change_selections(None, cx, |s| {
11262                s.refresh();
11263            });
11264            assert_eq!(
11265                editor.selections.ranges(cx),
11266                [
11267                    Point::new(1, 3)..Point::new(1, 3),
11268                    Point::new(2, 1)..Point::new(2, 1),
11269                ]
11270            );
11271        });
11272
11273        multibuffer.update(cx, |multibuffer, cx| {
11274            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
11275        });
11276        editor.update(cx, |editor, cx| {
11277            // Removing an excerpt causes the first selection to become degenerate.
11278            assert_eq!(
11279                editor.selections.ranges(cx),
11280                [
11281                    Point::new(0, 0)..Point::new(0, 0),
11282                    Point::new(0, 1)..Point::new(0, 1)
11283                ]
11284            );
11285
11286            // Refreshing selections will relocate the first selection to the original buffer
11287            // location.
11288            editor.change_selections(None, cx, |s| {
11289                s.refresh();
11290            });
11291            assert_eq!(
11292                editor.selections.ranges(cx),
11293                [
11294                    Point::new(0, 1)..Point::new(0, 1),
11295                    Point::new(0, 3)..Point::new(0, 3)
11296                ]
11297            );
11298            assert!(editor.selections.pending_anchor().is_some());
11299        });
11300    }
11301
11302    #[gpui::test]
11303    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
11304        cx.set_global(Settings::test(cx));
11305        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
11306        let mut excerpt1_id = None;
11307        let multibuffer = cx.add_model(|cx| {
11308            let mut multibuffer = MultiBuffer::new(0);
11309            excerpt1_id = multibuffer
11310                .push_excerpts(
11311                    buffer.clone(),
11312                    [
11313                        ExcerptRange {
11314                            context: Point::new(0, 0)..Point::new(1, 4),
11315                            primary: None,
11316                        },
11317                        ExcerptRange {
11318                            context: Point::new(1, 0)..Point::new(2, 4),
11319                            primary: None,
11320                        },
11321                    ],
11322                    cx,
11323                )
11324                .into_iter()
11325                .next();
11326            multibuffer
11327        });
11328        assert_eq!(
11329            multibuffer.read(cx).read(cx).text(),
11330            "aaaa\nbbbb\nbbbb\ncccc"
11331        );
11332        let (_, editor) = cx.add_window(Default::default(), |cx| {
11333            let mut editor = build_editor(multibuffer.clone(), cx);
11334            let snapshot = editor.snapshot(cx);
11335            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
11336            assert_eq!(
11337                editor.selections.ranges(cx),
11338                [Point::new(1, 3)..Point::new(1, 3)]
11339            );
11340            editor
11341        });
11342
11343        multibuffer.update(cx, |multibuffer, cx| {
11344            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
11345        });
11346        editor.update(cx, |editor, cx| {
11347            assert_eq!(
11348                editor.selections.ranges(cx),
11349                [Point::new(0, 0)..Point::new(0, 0)]
11350            );
11351
11352            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
11353            editor.change_selections(None, cx, |s| {
11354                s.refresh();
11355            });
11356            assert_eq!(
11357                editor.selections.ranges(cx),
11358                [Point::new(0, 3)..Point::new(0, 3)]
11359            );
11360            assert!(editor.selections.pending_anchor().is_some());
11361        });
11362    }
11363
11364    #[gpui::test]
11365    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
11366        cx.update(|cx| cx.set_global(Settings::test(cx)));
11367        let language = Arc::new(
11368            Language::new(
11369                LanguageConfig {
11370                    brackets: vec![
11371                        BracketPair {
11372                            start: "{".to_string(),
11373                            end: "}".to_string(),
11374                            close: true,
11375                            newline: true,
11376                        },
11377                        BracketPair {
11378                            start: "/* ".to_string(),
11379                            end: " */".to_string(),
11380                            close: true,
11381                            newline: true,
11382                        },
11383                    ],
11384                    ..Default::default()
11385                },
11386                Some(tree_sitter_rust::language()),
11387            )
11388            .with_indents_query("")
11389            .unwrap(),
11390        );
11391
11392        let text = concat!(
11393            "{   }\n",     // Suppress rustfmt
11394            "  x\n",       //
11395            "  /*   */\n", //
11396            "x\n",         //
11397            "{{} }\n",     //
11398        );
11399
11400        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
11401        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
11402        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
11403        view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
11404            .await;
11405
11406        view.update(cx, |view, cx| {
11407            view.change_selections(None, cx, |s| {
11408                s.select_display_ranges([
11409                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
11410                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
11411                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
11412                ])
11413            });
11414            view.newline(&Newline, cx);
11415
11416            assert_eq!(
11417                view.buffer().read(cx).read(cx).text(),
11418                concat!(
11419                    "{ \n",    // Suppress rustfmt
11420                    "\n",      //
11421                    "}\n",     //
11422                    "  x\n",   //
11423                    "  /* \n", //
11424                    "  \n",    //
11425                    "  */\n",  //
11426                    "x\n",     //
11427                    "{{} \n",  //
11428                    "}\n",     //
11429                )
11430            );
11431        });
11432    }
11433
11434    #[gpui::test]
11435    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
11436        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
11437
11438        cx.set_global(Settings::test(cx));
11439        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
11440
11441        editor.update(cx, |editor, cx| {
11442            struct Type1;
11443            struct Type2;
11444
11445            let buffer = buffer.read(cx).snapshot(cx);
11446
11447            let anchor_range = |range: Range<Point>| {
11448                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
11449            };
11450
11451            editor.highlight_background::<Type1>(
11452                vec![
11453                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
11454                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
11455                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
11456                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
11457                ],
11458                |_| Color::red(),
11459                cx,
11460            );
11461            editor.highlight_background::<Type2>(
11462                vec![
11463                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
11464                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
11465                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
11466                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
11467                ],
11468                |_| Color::green(),
11469                cx,
11470            );
11471
11472            let snapshot = editor.snapshot(cx);
11473            let mut highlighted_ranges = editor.background_highlights_in_range(
11474                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
11475                &snapshot,
11476                cx.global::<Settings>().theme.as_ref(),
11477            );
11478            // Enforce a consistent ordering based on color without relying on the ordering of the
11479            // highlight's `TypeId` which is non-deterministic.
11480            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
11481            assert_eq!(
11482                highlighted_ranges,
11483                &[
11484                    (
11485                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
11486                        Color::green(),
11487                    ),
11488                    (
11489                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
11490                        Color::green(),
11491                    ),
11492                    (
11493                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
11494                        Color::red(),
11495                    ),
11496                    (
11497                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11498                        Color::red(),
11499                    ),
11500                ]
11501            );
11502            assert_eq!(
11503                editor.background_highlights_in_range(
11504                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
11505                    &snapshot,
11506                    cx.global::<Settings>().theme.as_ref(),
11507                ),
11508                &[(
11509                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
11510                    Color::red(),
11511                )]
11512            );
11513        });
11514    }
11515
11516    #[gpui::test]
11517    fn test_following(cx: &mut gpui::MutableAppContext) {
11518        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
11519
11520        cx.set_global(Settings::test(cx));
11521
11522        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
11523        let (_, follower) = cx.add_window(
11524            WindowOptions {
11525                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
11526                ..Default::default()
11527            },
11528            |cx| build_editor(buffer.clone(), cx),
11529        );
11530
11531        let pending_update = Rc::new(RefCell::new(None));
11532        follower.update(cx, {
11533            let update = pending_update.clone();
11534            |_, cx| {
11535                cx.subscribe(&leader, move |_, leader, event, cx| {
11536                    leader
11537                        .read(cx)
11538                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
11539                })
11540                .detach();
11541            }
11542        });
11543
11544        // Update the selections only
11545        leader.update(cx, |leader, cx| {
11546            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11547        });
11548        follower.update(cx, |follower, cx| {
11549            follower
11550                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11551                .unwrap();
11552        });
11553        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
11554
11555        // Update the scroll position only
11556        leader.update(cx, |leader, cx| {
11557            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11558        });
11559        follower.update(cx, |follower, cx| {
11560            follower
11561                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11562                .unwrap();
11563        });
11564        assert_eq!(
11565            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
11566            vec2f(1.5, 3.5)
11567        );
11568
11569        // Update the selections and scroll position
11570        leader.update(cx, |leader, cx| {
11571            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
11572            leader.request_autoscroll(Autoscroll::Newest, cx);
11573            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
11574        });
11575        follower.update(cx, |follower, cx| {
11576            let initial_scroll_position = follower.scroll_position(cx);
11577            follower
11578                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11579                .unwrap();
11580            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
11581            assert!(follower.autoscroll_request.is_some());
11582        });
11583        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
11584
11585        // Creating a pending selection that precedes another selection
11586        leader.update(cx, |leader, cx| {
11587            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
11588            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
11589        });
11590        follower.update(cx, |follower, cx| {
11591            follower
11592                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11593                .unwrap();
11594        });
11595        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
11596
11597        // Extend the pending selection so that it surrounds another selection
11598        leader.update(cx, |leader, cx| {
11599            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
11600        });
11601        follower.update(cx, |follower, cx| {
11602            follower
11603                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
11604                .unwrap();
11605        });
11606        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
11607    }
11608
11609    #[test]
11610    fn test_combine_syntax_and_fuzzy_match_highlights() {
11611        let string = "abcdefghijklmnop";
11612        let syntax_ranges = [
11613            (
11614                0..3,
11615                HighlightStyle {
11616                    color: Some(Color::red()),
11617                    ..Default::default()
11618                },
11619            ),
11620            (
11621                4..8,
11622                HighlightStyle {
11623                    color: Some(Color::green()),
11624                    ..Default::default()
11625                },
11626            ),
11627        ];
11628        let match_indices = [4, 6, 7, 8];
11629        assert_eq!(
11630            combine_syntax_and_fuzzy_match_highlights(
11631                string,
11632                Default::default(),
11633                syntax_ranges.into_iter(),
11634                &match_indices,
11635            ),
11636            &[
11637                (
11638                    0..3,
11639                    HighlightStyle {
11640                        color: Some(Color::red()),
11641                        ..Default::default()
11642                    },
11643                ),
11644                (
11645                    4..5,
11646                    HighlightStyle {
11647                        color: Some(Color::green()),
11648                        weight: Some(fonts::Weight::BOLD),
11649                        ..Default::default()
11650                    },
11651                ),
11652                (
11653                    5..6,
11654                    HighlightStyle {
11655                        color: Some(Color::green()),
11656                        ..Default::default()
11657                    },
11658                ),
11659                (
11660                    6..8,
11661                    HighlightStyle {
11662                        color: Some(Color::green()),
11663                        weight: Some(fonts::Weight::BOLD),
11664                        ..Default::default()
11665                    },
11666                ),
11667                (
11668                    8..9,
11669                    HighlightStyle {
11670                        weight: Some(fonts::Weight::BOLD),
11671                        ..Default::default()
11672                    },
11673                ),
11674            ]
11675        );
11676    }
11677
11678    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
11679        let point = DisplayPoint::new(row as u32, column as u32);
11680        point..point
11681    }
11682
11683    fn assert_selection_ranges(marked_text: &str, view: &mut Editor, cx: &mut ViewContext<Editor>) {
11684        let (text, ranges) = marked_text_ranges(marked_text, true);
11685        assert_eq!(view.text(cx), text);
11686        assert_eq!(
11687            view.selections.ranges(cx),
11688            ranges,
11689            "Assert selections are {}",
11690            marked_text
11691        );
11692    }
11693}
11694
11695trait RangeExt<T> {
11696    fn sorted(&self) -> Range<T>;
11697    fn to_inclusive(&self) -> RangeInclusive<T>;
11698}
11699
11700impl<T: Ord + Clone> RangeExt<T> for Range<T> {
11701    fn sorted(&self) -> Self {
11702        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
11703    }
11704
11705    fn to_inclusive(&self) -> RangeInclusive<T> {
11706        self.start.clone()..=self.end.clone()
11707    }
11708}
11709
11710trait RangeToAnchorExt {
11711    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
11712}
11713
11714impl<T: ToOffset> RangeToAnchorExt for Range<T> {
11715    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
11716        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
11717    }
11718}