editor.rs

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