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