editor.rs

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