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, Theme};
   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, (fn(&Theme) -> 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                editor.highlight_background::<Self>(
 2557                    ranges_to_highlight,
 2558                    |theme| theme.editor.highlighted_line_background,
 2559                    cx,
 2560                );
 2561            });
 2562        });
 2563
 2564        Ok(())
 2565    }
 2566
 2567    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2568        let project = self.project.as_ref()?;
 2569        let buffer = self.buffer.read(cx);
 2570        let newest_selection = self.newest_anchor_selection().clone();
 2571        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 2572        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 2573        if start_buffer != end_buffer {
 2574            return None;
 2575        }
 2576
 2577        let actions = project.update(cx, |project, cx| {
 2578            project.code_actions(&start_buffer, start..end, cx)
 2579        });
 2580        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2581            let actions = actions.await;
 2582            if let Some(this) = this.upgrade(&cx) {
 2583                this.update(&mut cx, |this, cx| {
 2584                    this.available_code_actions = actions.log_err().and_then(|actions| {
 2585                        if actions.is_empty() {
 2586                            None
 2587                        } else {
 2588                            Some((start_buffer, actions.into()))
 2589                        }
 2590                    });
 2591                    cx.notify();
 2592                })
 2593            }
 2594        }));
 2595        None
 2596    }
 2597
 2598    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2599        if self.pending_rename.is_some() {
 2600            return None;
 2601        }
 2602
 2603        let project = self.project.as_ref()?;
 2604        let buffer = self.buffer.read(cx);
 2605        let newest_selection = self.newest_anchor_selection().clone();
 2606        let cursor_position = newest_selection.head();
 2607        let (cursor_buffer, cursor_buffer_position) =
 2608            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 2609        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 2610        if cursor_buffer != tail_buffer {
 2611            return None;
 2612        }
 2613
 2614        let highlights = project.update(cx, |project, cx| {
 2615            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 2616        });
 2617
 2618        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2619            let highlights = highlights.log_err().await;
 2620            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
 2621                this.update(&mut cx, |this, cx| {
 2622                    if this.pending_rename.is_some() {
 2623                        return;
 2624                    }
 2625
 2626                    let buffer_id = cursor_position.buffer_id;
 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                        |theme| theme.editor.document_highlight_read_background,
 2674                        cx,
 2675                    );
 2676                    this.highlight_background::<DocumentHighlightWrite>(
 2677                        write_ranges,
 2678                        |theme| theme.editor.document_highlight_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                    editor.highlight_background::<Self>(
 4595                        ranges_to_highlight,
 4596                        |theme| theme.editor.highlighted_line_background,
 4597                        cx,
 4598                    );
 4599                });
 4600                workspace.add_item(Box::new(editor), cx);
 4601            });
 4602
 4603            Ok(())
 4604        }))
 4605    }
 4606
 4607    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4608        use language::ToOffset as _;
 4609
 4610        let project = self.project.clone()?;
 4611        let selection = self.newest_anchor_selection().clone();
 4612        let (cursor_buffer, cursor_buffer_position) = self
 4613            .buffer
 4614            .read(cx)
 4615            .text_anchor_for_position(selection.head(), cx)?;
 4616        let (tail_buffer, _) = self
 4617            .buffer
 4618            .read(cx)
 4619            .text_anchor_for_position(selection.tail(), cx)?;
 4620        if tail_buffer != cursor_buffer {
 4621            return None;
 4622        }
 4623
 4624        let snapshot = cursor_buffer.read(cx).snapshot();
 4625        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4626        let prepare_rename = project.update(cx, |project, cx| {
 4627            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4628        });
 4629
 4630        Some(cx.spawn(|this, mut cx| async move {
 4631            if let Some(rename_range) = prepare_rename.await? {
 4632                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4633                let cursor_offset_in_rename_range =
 4634                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4635
 4636                this.update(&mut cx, |this, cx| {
 4637                    this.take_rename(false, cx);
 4638                    let style = this.style(cx);
 4639                    let buffer = this.buffer.read(cx).read(cx);
 4640                    let cursor_offset = selection.head().to_offset(&buffer);
 4641                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4642                    let rename_end = rename_start + rename_buffer_range.len();
 4643                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4644                    let mut old_highlight_id = None;
 4645                    let old_name = buffer
 4646                        .chunks(rename_start..rename_end, true)
 4647                        .map(|chunk| {
 4648                            if old_highlight_id.is_none() {
 4649                                old_highlight_id = chunk.syntax_highlight_id;
 4650                            }
 4651                            chunk.text
 4652                        })
 4653                        .collect();
 4654
 4655                    drop(buffer);
 4656
 4657                    // Position the selection in the rename editor so that it matches the current selection.
 4658                    this.show_local_selections = false;
 4659                    let rename_editor = cx.add_view(|cx| {
 4660                        let mut editor = Editor::single_line(None, cx);
 4661                        if let Some(old_highlight_id) = old_highlight_id {
 4662                            editor.override_text_style =
 4663                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4664                        }
 4665                        editor
 4666                            .buffer
 4667                            .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
 4668                        editor.select_all(&SelectAll, cx);
 4669                        editor
 4670                    });
 4671
 4672                    let ranges = this
 4673                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4674                        .into_iter()
 4675                        .flat_map(|(_, ranges)| ranges)
 4676                        .chain(
 4677                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4678                                .into_iter()
 4679                                .flat_map(|(_, ranges)| ranges),
 4680                        )
 4681                        .collect();
 4682
 4683                    this.highlight_text::<Rename>(
 4684                        ranges,
 4685                        HighlightStyle {
 4686                            fade_out: Some(style.rename_fade),
 4687                            ..Default::default()
 4688                        },
 4689                        cx,
 4690                    );
 4691                    cx.focus(&rename_editor);
 4692                    let block_id = this.insert_blocks(
 4693                        [BlockProperties {
 4694                            position: range.start.clone(),
 4695                            height: 1,
 4696                            render: Arc::new({
 4697                                let editor = rename_editor.clone();
 4698                                move |cx: &BlockContext| {
 4699                                    ChildView::new(editor.clone())
 4700                                        .contained()
 4701                                        .with_padding_left(cx.anchor_x)
 4702                                        .boxed()
 4703                                }
 4704                            }),
 4705                            disposition: BlockDisposition::Below,
 4706                        }],
 4707                        cx,
 4708                    )[0];
 4709                    this.pending_rename = Some(RenameState {
 4710                        range,
 4711                        old_name,
 4712                        editor: rename_editor,
 4713                        block_id,
 4714                    });
 4715                });
 4716            }
 4717
 4718            Ok(())
 4719        }))
 4720    }
 4721
 4722    pub fn confirm_rename(
 4723        workspace: &mut Workspace,
 4724        _: &ConfirmRename,
 4725        cx: &mut ViewContext<Workspace>,
 4726    ) -> Option<Task<Result<()>>> {
 4727        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4728
 4729        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4730            let rename = editor.take_rename(false, cx)?;
 4731            let buffer = editor.buffer.read(cx);
 4732            let (start_buffer, start) =
 4733                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4734            let (end_buffer, end) =
 4735                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4736            if start_buffer == end_buffer {
 4737                let new_name = rename.editor.read(cx).text(cx);
 4738                Some((start_buffer, start..end, rename.old_name, new_name))
 4739            } else {
 4740                None
 4741            }
 4742        })?;
 4743
 4744        let rename = workspace.project().clone().update(cx, |project, cx| {
 4745            project.perform_rename(
 4746                buffer.clone(),
 4747                range.start.clone(),
 4748                new_name.clone(),
 4749                true,
 4750                cx,
 4751            )
 4752        });
 4753
 4754        Some(cx.spawn(|workspace, mut cx| async move {
 4755            let project_transaction = rename.await?;
 4756            Self::open_project_transaction(
 4757                editor.clone(),
 4758                workspace,
 4759                project_transaction,
 4760                format!("Rename: {}{}", old_name, new_name),
 4761                cx.clone(),
 4762            )
 4763            .await?;
 4764
 4765            editor.update(&mut cx, |editor, cx| {
 4766                editor.refresh_document_highlights(cx);
 4767            });
 4768            Ok(())
 4769        }))
 4770    }
 4771
 4772    fn take_rename(
 4773        &mut self,
 4774        moving_cursor: bool,
 4775        cx: &mut ViewContext<Self>,
 4776    ) -> Option<RenameState> {
 4777        let rename = self.pending_rename.take()?;
 4778        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4779        self.clear_text_highlights::<Rename>(cx);
 4780        self.show_local_selections = true;
 4781
 4782        if moving_cursor {
 4783            let cursor_in_rename_editor =
 4784                rename.editor.read(cx).newest_selection::<usize>(cx).head();
 4785
 4786            // Update the selection to match the position of the selection inside
 4787            // the rename editor.
 4788            let snapshot = self.buffer.read(cx).read(cx);
 4789            let rename_range = rename.range.to_offset(&snapshot);
 4790            let cursor_in_editor = snapshot
 4791                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4792                .min(rename_range.end);
 4793            drop(snapshot);
 4794
 4795            self.update_selections(
 4796                vec![Selection {
 4797                    id: self.newest_anchor_selection().id,
 4798                    start: cursor_in_editor,
 4799                    end: cursor_in_editor,
 4800                    reversed: false,
 4801                    goal: SelectionGoal::None,
 4802                }],
 4803                None,
 4804                cx,
 4805            );
 4806        }
 4807
 4808        Some(rename)
 4809    }
 4810
 4811    fn invalidate_rename_range(
 4812        &mut self,
 4813        buffer: &MultiBufferSnapshot,
 4814        cx: &mut ViewContext<Self>,
 4815    ) {
 4816        if let Some(rename) = self.pending_rename.as_ref() {
 4817            if self.selections.len() == 1 {
 4818                let head = self.selections[0].head().to_offset(buffer);
 4819                let range = rename.range.to_offset(buffer).to_inclusive();
 4820                if range.contains(&head) {
 4821                    return;
 4822                }
 4823            }
 4824            let rename = self.pending_rename.take().unwrap();
 4825            self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4826            self.clear_background_highlights::<Rename>(cx);
 4827        }
 4828    }
 4829
 4830    #[cfg(any(test, feature = "test-support"))]
 4831    pub fn pending_rename(&self) -> Option<&RenameState> {
 4832        self.pending_rename.as_ref()
 4833    }
 4834
 4835    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4836        if let Some(project) = self.project.clone() {
 4837            self.buffer.update(cx, |multi_buffer, cx| {
 4838                project.update(cx, |project, cx| {
 4839                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4840                });
 4841            })
 4842        }
 4843    }
 4844
 4845    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4846        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4847            let buffer = self.buffer.read(cx).snapshot(cx);
 4848            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4849            let is_valid = buffer
 4850                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4851                .any(|entry| {
 4852                    entry.diagnostic.is_primary
 4853                        && !entry.range.is_empty()
 4854                        && entry.range.start == primary_range_start
 4855                        && entry.diagnostic.message == active_diagnostics.primary_message
 4856                });
 4857
 4858            if is_valid != active_diagnostics.is_valid {
 4859                active_diagnostics.is_valid = is_valid;
 4860                let mut new_styles = HashMap::default();
 4861                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4862                    new_styles.insert(
 4863                        *block_id,
 4864                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4865                    );
 4866                }
 4867                self.display_map
 4868                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4869            }
 4870        }
 4871    }
 4872
 4873    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4874        self.dismiss_diagnostics(cx);
 4875        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4876            let buffer = self.buffer.read(cx).snapshot(cx);
 4877
 4878            let mut primary_range = None;
 4879            let mut primary_message = None;
 4880            let mut group_end = Point::zero();
 4881            let diagnostic_group = buffer
 4882                .diagnostic_group::<Point>(group_id)
 4883                .map(|entry| {
 4884                    if entry.range.end > group_end {
 4885                        group_end = entry.range.end;
 4886                    }
 4887                    if entry.diagnostic.is_primary {
 4888                        primary_range = Some(entry.range.clone());
 4889                        primary_message = Some(entry.diagnostic.message.clone());
 4890                    }
 4891                    entry
 4892                })
 4893                .collect::<Vec<_>>();
 4894            let primary_range = primary_range.unwrap();
 4895            let primary_message = primary_message.unwrap();
 4896            let primary_range =
 4897                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 4898
 4899            let blocks = display_map
 4900                .insert_blocks(
 4901                    diagnostic_group.iter().map(|entry| {
 4902                        let diagnostic = entry.diagnostic.clone();
 4903                        let message_height = diagnostic.message.lines().count() as u8;
 4904                        BlockProperties {
 4905                            position: buffer.anchor_after(entry.range.start),
 4906                            height: message_height,
 4907                            render: diagnostic_block_renderer(diagnostic, true),
 4908                            disposition: BlockDisposition::Below,
 4909                        }
 4910                    }),
 4911                    cx,
 4912                )
 4913                .into_iter()
 4914                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 4915                .collect();
 4916
 4917            Some(ActiveDiagnosticGroup {
 4918                primary_range,
 4919                primary_message,
 4920                blocks,
 4921                is_valid: true,
 4922            })
 4923        });
 4924    }
 4925
 4926    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 4927        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 4928            self.display_map.update(cx, |display_map, cx| {
 4929                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 4930            });
 4931            cx.notify();
 4932        }
 4933    }
 4934
 4935    fn build_columnar_selection(
 4936        &mut self,
 4937        display_map: &DisplaySnapshot,
 4938        row: u32,
 4939        columns: &Range<u32>,
 4940        reversed: bool,
 4941    ) -> Option<Selection<Point>> {
 4942        let is_empty = columns.start == columns.end;
 4943        let line_len = display_map.line_len(row);
 4944        if columns.start < line_len || (is_empty && columns.start == line_len) {
 4945            let start = DisplayPoint::new(row, columns.start);
 4946            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
 4947            Some(Selection {
 4948                id: post_inc(&mut self.next_selection_id),
 4949                start: start.to_point(display_map),
 4950                end: end.to_point(display_map),
 4951                reversed,
 4952                goal: SelectionGoal::ColumnRange {
 4953                    start: columns.start,
 4954                    end: columns.end,
 4955                },
 4956            })
 4957        } else {
 4958            None
 4959        }
 4960    }
 4961
 4962    pub fn local_selections_in_range(
 4963        &self,
 4964        range: Range<Anchor>,
 4965        display_map: &DisplaySnapshot,
 4966    ) -> Vec<Selection<Point>> {
 4967        let buffer = &display_map.buffer_snapshot;
 4968
 4969        let start_ix = match self
 4970            .selections
 4971            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
 4972        {
 4973            Ok(ix) | Err(ix) => ix,
 4974        };
 4975        let end_ix = match self
 4976            .selections
 4977            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
 4978        {
 4979            Ok(ix) => ix + 1,
 4980            Err(ix) => ix,
 4981        };
 4982
 4983        fn point_selection(
 4984            selection: &Selection<Anchor>,
 4985            buffer: &MultiBufferSnapshot,
 4986        ) -> Selection<Point> {
 4987            let start = selection.start.to_point(&buffer);
 4988            let end = selection.end.to_point(&buffer);
 4989            Selection {
 4990                id: selection.id,
 4991                start,
 4992                end,
 4993                reversed: selection.reversed,
 4994                goal: selection.goal,
 4995            }
 4996        }
 4997
 4998        self.selections[start_ix..end_ix]
 4999            .iter()
 5000            .chain(
 5001                self.pending_selection
 5002                    .as_ref()
 5003                    .map(|pending| &pending.selection),
 5004            )
 5005            .map(|s| point_selection(s, &buffer))
 5006            .collect()
 5007    }
 5008
 5009    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
 5010    where
 5011        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
 5012    {
 5013        let buffer = self.buffer.read(cx).snapshot(cx);
 5014        let mut selections = self
 5015            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
 5016            .peekable();
 5017
 5018        let mut pending_selection = self.pending_selection::<D>(&buffer);
 5019
 5020        iter::from_fn(move || {
 5021            if let Some(pending) = pending_selection.as_mut() {
 5022                while let Some(next_selection) = selections.peek() {
 5023                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 5024                        let next_selection = selections.next().unwrap();
 5025                        if next_selection.start < pending.start {
 5026                            pending.start = next_selection.start;
 5027                        }
 5028                        if next_selection.end > pending.end {
 5029                            pending.end = next_selection.end;
 5030                        }
 5031                    } else if next_selection.end < pending.start {
 5032                        return selections.next();
 5033                    } else {
 5034                        break;
 5035                    }
 5036                }
 5037
 5038                pending_selection.take()
 5039            } else {
 5040                selections.next()
 5041            }
 5042        })
 5043        .collect()
 5044    }
 5045
 5046    fn resolve_selections<'a, D, I>(
 5047        &self,
 5048        selections: I,
 5049        snapshot: &MultiBufferSnapshot,
 5050    ) -> impl 'a + Iterator<Item = Selection<D>>
 5051    where
 5052        D: TextDimension + Ord + Sub<D, Output = D>,
 5053        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 5054    {
 5055        let (to_summarize, selections) = selections.into_iter().tee();
 5056        let mut summaries = snapshot
 5057            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
 5058            .into_iter();
 5059        selections.map(move |s| Selection {
 5060            id: s.id,
 5061            start: summaries.next().unwrap(),
 5062            end: summaries.next().unwrap(),
 5063            reversed: s.reversed,
 5064            goal: s.goal,
 5065        })
 5066    }
 5067
 5068    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5069        &self,
 5070        snapshot: &MultiBufferSnapshot,
 5071    ) -> Option<Selection<D>> {
 5072        self.pending_selection
 5073            .as_ref()
 5074            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
 5075    }
 5076
 5077    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5078        &self,
 5079        selection: &Selection<Anchor>,
 5080        buffer: &MultiBufferSnapshot,
 5081    ) -> Selection<D> {
 5082        Selection {
 5083            id: selection.id,
 5084            start: selection.start.summary::<D>(&buffer),
 5085            end: selection.end.summary::<D>(&buffer),
 5086            reversed: selection.reversed,
 5087            goal: selection.goal,
 5088        }
 5089    }
 5090
 5091    fn selection_count<'a>(&self) -> usize {
 5092        let mut count = self.selections.len();
 5093        if self.pending_selection.is_some() {
 5094            count += 1;
 5095        }
 5096        count
 5097    }
 5098
 5099    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5100        &self,
 5101        cx: &AppContext,
 5102    ) -> Selection<D> {
 5103        let snapshot = self.buffer.read(cx).read(cx);
 5104        self.selections
 5105            .iter()
 5106            .min_by_key(|s| s.id)
 5107            .map(|selection| self.resolve_selection(selection, &snapshot))
 5108            .or_else(|| self.pending_selection(&snapshot))
 5109            .unwrap()
 5110    }
 5111
 5112    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5113        &self,
 5114        cx: &AppContext,
 5115    ) -> Selection<D> {
 5116        self.resolve_selection(
 5117            self.newest_anchor_selection(),
 5118            &self.buffer.read(cx).read(cx),
 5119        )
 5120    }
 5121
 5122    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
 5123        &self,
 5124        snapshot: &MultiBufferSnapshot,
 5125    ) -> Selection<D> {
 5126        self.resolve_selection(self.newest_anchor_selection(), snapshot)
 5127    }
 5128
 5129    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
 5130        self.pending_selection
 5131            .as_ref()
 5132            .map(|s| &s.selection)
 5133            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
 5134            .unwrap()
 5135    }
 5136
 5137    pub fn update_selections<T>(
 5138        &mut self,
 5139        mut selections: Vec<Selection<T>>,
 5140        autoscroll: Option<Autoscroll>,
 5141        cx: &mut ViewContext<Self>,
 5142    ) where
 5143        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
 5144    {
 5145        let buffer = self.buffer.read(cx).snapshot(cx);
 5146        selections.sort_unstable_by_key(|s| s.start);
 5147
 5148        // Merge overlapping selections.
 5149        let mut i = 1;
 5150        while i < selections.len() {
 5151            if selections[i - 1].end >= selections[i].start {
 5152                let removed = selections.remove(i);
 5153                if removed.start < selections[i - 1].start {
 5154                    selections[i - 1].start = removed.start;
 5155                }
 5156                if removed.end > selections[i - 1].end {
 5157                    selections[i - 1].end = removed.end;
 5158                }
 5159            } else {
 5160                i += 1;
 5161            }
 5162        }
 5163
 5164        if let Some(autoscroll) = autoscroll {
 5165            self.request_autoscroll(autoscroll, cx);
 5166        }
 5167
 5168        self.set_selections(
 5169            Arc::from_iter(selections.into_iter().map(|selection| {
 5170                let end_bias = if selection.end > selection.start {
 5171                    Bias::Left
 5172                } else {
 5173                    Bias::Right
 5174                };
 5175                Selection {
 5176                    id: selection.id,
 5177                    start: buffer.anchor_after(selection.start),
 5178                    end: buffer.anchor_at(selection.end, end_bias),
 5179                    reversed: selection.reversed,
 5180                    goal: selection.goal,
 5181                }
 5182            })),
 5183            None,
 5184            true,
 5185            cx,
 5186        );
 5187    }
 5188
 5189    pub fn set_selections_from_remote(
 5190        &mut self,
 5191        mut selections: Vec<Selection<Anchor>>,
 5192        cx: &mut ViewContext<Self>,
 5193    ) {
 5194        let buffer = self.buffer.read(cx);
 5195        let buffer = buffer.read(cx);
 5196        selections.sort_by(|a, b| {
 5197            a.start
 5198                .cmp(&b.start, &*buffer)
 5199                .then_with(|| b.end.cmp(&a.end, &*buffer))
 5200        });
 5201
 5202        // Merge overlapping selections
 5203        let mut i = 1;
 5204        while i < selections.len() {
 5205            if selections[i - 1]
 5206                .end
 5207                .cmp(&selections[i].start, &*buffer)
 5208                .is_ge()
 5209            {
 5210                let removed = selections.remove(i);
 5211                if removed
 5212                    .start
 5213                    .cmp(&selections[i - 1].start, &*buffer)
 5214                    .is_lt()
 5215                {
 5216                    selections[i - 1].start = removed.start;
 5217                }
 5218                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
 5219                    selections[i - 1].end = removed.end;
 5220                }
 5221            } else {
 5222                i += 1;
 5223            }
 5224        }
 5225
 5226        drop(buffer);
 5227        self.set_selections(selections.into(), None, false, cx);
 5228    }
 5229
 5230    /// Compute new ranges for any selections that were located in excerpts that have
 5231    /// since been removed.
 5232    ///
 5233    /// Returns a `HashMap` indicating which selections whose former head position
 5234    /// was no longer present. The keys of the map are selection ids. The values are
 5235    /// the id of the new excerpt where the head of the selection has been moved.
 5236    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
 5237        let snapshot = self.buffer.read(cx).read(cx);
 5238        let mut selections_with_lost_position = HashMap::default();
 5239
 5240        let mut pending_selection = self.pending_selection.take();
 5241        if let Some(pending) = pending_selection.as_mut() {
 5242            let anchors =
 5243                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
 5244            let (_, start, kept_start) = anchors[0].clone();
 5245            let (_, end, kept_end) = anchors[1].clone();
 5246            let kept_head = if pending.selection.reversed {
 5247                kept_start
 5248            } else {
 5249                kept_end
 5250            };
 5251            if !kept_head {
 5252                selections_with_lost_position.insert(
 5253                    pending.selection.id,
 5254                    pending.selection.head().excerpt_id.clone(),
 5255                );
 5256            }
 5257
 5258            pending.selection.start = start;
 5259            pending.selection.end = end;
 5260        }
 5261
 5262        let anchors_with_status = snapshot.refresh_anchors(
 5263            self.selections
 5264                .iter()
 5265                .flat_map(|selection| [&selection.start, &selection.end]),
 5266        );
 5267        self.selections = anchors_with_status
 5268            .chunks(2)
 5269            .map(|selection_anchors| {
 5270                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
 5271                let (_, end, kept_end) = selection_anchors[1].clone();
 5272                let selection = &self.selections[anchor_ix / 2];
 5273                let kept_head = if selection.reversed {
 5274                    kept_start
 5275                } else {
 5276                    kept_end
 5277                };
 5278                if !kept_head {
 5279                    selections_with_lost_position
 5280                        .insert(selection.id, selection.head().excerpt_id.clone());
 5281                }
 5282
 5283                Selection {
 5284                    id: selection.id,
 5285                    start,
 5286                    end,
 5287                    reversed: selection.reversed,
 5288                    goal: selection.goal,
 5289                }
 5290            })
 5291            .collect();
 5292        drop(snapshot);
 5293
 5294        let new_selections = self.local_selections::<usize>(cx);
 5295        if !new_selections.is_empty() {
 5296            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 5297        }
 5298        self.pending_selection = pending_selection;
 5299
 5300        selections_with_lost_position
 5301    }
 5302
 5303    fn set_selections(
 5304        &mut self,
 5305        selections: Arc<[Selection<Anchor>]>,
 5306        pending_selection: Option<PendingSelection>,
 5307        local: bool,
 5308        cx: &mut ViewContext<Self>,
 5309    ) {
 5310        assert!(
 5311            !selections.is_empty() || pending_selection.is_some(),
 5312            "must have at least one selection"
 5313        );
 5314
 5315        let old_cursor_position = self.newest_anchor_selection().head();
 5316
 5317        self.push_to_selection_history();
 5318        self.selections = selections;
 5319        self.pending_selection = pending_selection;
 5320        if self.focused && self.leader_replica_id.is_none() {
 5321            self.buffer.update(cx, |buffer, cx| {
 5322                buffer.set_active_selections(&self.selections, cx)
 5323            });
 5324        }
 5325
 5326        let display_map = self
 5327            .display_map
 5328            .update(cx, |display_map, cx| display_map.snapshot(cx));
 5329        let buffer = &display_map.buffer_snapshot;
 5330        self.add_selections_state = None;
 5331        self.select_next_state = None;
 5332        self.select_larger_syntax_node_stack.clear();
 5333        self.autoclose_stack.invalidate(&self.selections, &buffer);
 5334        self.snippet_stack.invalidate(&self.selections, &buffer);
 5335        self.invalidate_rename_range(&buffer, cx);
 5336
 5337        let new_cursor_position = self.newest_anchor_selection().head();
 5338
 5339        self.push_to_nav_history(
 5340            old_cursor_position.clone(),
 5341            Some(new_cursor_position.to_point(&buffer)),
 5342            cx,
 5343        );
 5344
 5345        if local {
 5346            let completion_menu = match self.context_menu.as_mut() {
 5347                Some(ContextMenu::Completions(menu)) => Some(menu),
 5348                _ => {
 5349                    self.context_menu.take();
 5350                    None
 5351                }
 5352            };
 5353
 5354            if let Some(completion_menu) = completion_menu {
 5355                let cursor_position = new_cursor_position.to_offset(&buffer);
 5356                let (word_range, kind) =
 5357                    buffer.surrounding_word(completion_menu.initial_position.clone());
 5358                if kind == Some(CharKind::Word)
 5359                    && word_range.to_inclusive().contains(&cursor_position)
 5360                {
 5361                    let query = Self::completion_query(&buffer, cursor_position);
 5362                    cx.background()
 5363                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 5364                    self.show_completions(&ShowCompletions, cx);
 5365                } else {
 5366                    self.hide_context_menu(cx);
 5367                }
 5368            }
 5369
 5370            if old_cursor_position.to_display_point(&display_map).row()
 5371                != new_cursor_position.to_display_point(&display_map).row()
 5372            {
 5373                self.available_code_actions.take();
 5374            }
 5375            self.refresh_code_actions(cx);
 5376            self.refresh_document_highlights(cx);
 5377        }
 5378
 5379        self.pause_cursor_blinking(cx);
 5380        cx.emit(Event::SelectionsChanged { local });
 5381    }
 5382
 5383    fn push_to_selection_history(&mut self) {
 5384        self.selection_history.push(SelectionHistoryEntry {
 5385            selections: self.selections.clone(),
 5386            select_next_state: self.select_next_state.clone(),
 5387            add_selections_state: self.add_selections_state.clone(),
 5388        });
 5389    }
 5390
 5391    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5392        self.autoscroll_request = Some((autoscroll, true));
 5393        cx.notify();
 5394    }
 5395
 5396    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5397        self.autoscroll_request = Some((autoscroll, false));
 5398        cx.notify();
 5399    }
 5400
 5401    pub fn transact(
 5402        &mut self,
 5403        cx: &mut ViewContext<Self>,
 5404        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5405    ) {
 5406        self.start_transaction_at(Instant::now(), cx);
 5407        update(self, cx);
 5408        self.end_transaction_at(Instant::now(), cx);
 5409    }
 5410
 5411    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5412        self.end_selection(cx);
 5413        if let Some(tx_id) = self
 5414            .buffer
 5415            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5416        {
 5417            self.selection_history
 5418                .insert_transaction(tx_id, self.selections.clone());
 5419        }
 5420    }
 5421
 5422    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5423        if let Some(tx_id) = self
 5424            .buffer
 5425            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5426        {
 5427            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5428                *end_selections = Some(self.selections.clone());
 5429            } else {
 5430                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5431            }
 5432
 5433            cx.emit(Event::Edited);
 5434        }
 5435    }
 5436
 5437    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5438        log::info!("Editor::page_up");
 5439    }
 5440
 5441    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5442        log::info!("Editor::page_down");
 5443    }
 5444
 5445    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5446        let mut fold_ranges = Vec::new();
 5447
 5448        let selections = self.local_selections::<Point>(cx);
 5449        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5450        for selection in selections {
 5451            let range = selection.display_range(&display_map).sorted();
 5452            let buffer_start_row = range.start.to_point(&display_map).row;
 5453
 5454            for row in (0..=range.end.row()).rev() {
 5455                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5456                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5457                    if fold_range.end.row >= buffer_start_row {
 5458                        fold_ranges.push(fold_range);
 5459                        if row <= range.start.row() {
 5460                            break;
 5461                        }
 5462                    }
 5463                }
 5464            }
 5465        }
 5466
 5467        self.fold_ranges(fold_ranges, cx);
 5468    }
 5469
 5470    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5471        let selections = self.local_selections::<Point>(cx);
 5472        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5473        let buffer = &display_map.buffer_snapshot;
 5474        let ranges = selections
 5475            .iter()
 5476            .map(|s| {
 5477                let range = s.display_range(&display_map).sorted();
 5478                let mut start = range.start.to_point(&display_map);
 5479                let mut end = range.end.to_point(&display_map);
 5480                start.column = 0;
 5481                end.column = buffer.line_len(end.row);
 5482                start..end
 5483            })
 5484            .collect::<Vec<_>>();
 5485        self.unfold_ranges(ranges, true, cx);
 5486    }
 5487
 5488    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5489        let max_point = display_map.max_point();
 5490        if display_row >= max_point.row() {
 5491            false
 5492        } else {
 5493            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5494            if is_blank {
 5495                false
 5496            } else {
 5497                for display_row in display_row + 1..=max_point.row() {
 5498                    let (indent, is_blank) = display_map.line_indent(display_row);
 5499                    if !is_blank {
 5500                        return indent > start_indent;
 5501                    }
 5502                }
 5503                false
 5504            }
 5505        }
 5506    }
 5507
 5508    fn foldable_range_for_line(
 5509        &self,
 5510        display_map: &DisplaySnapshot,
 5511        start_row: u32,
 5512    ) -> Range<Point> {
 5513        let max_point = display_map.max_point();
 5514
 5515        let (start_indent, _) = display_map.line_indent(start_row);
 5516        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5517        let mut end = None;
 5518        for row in start_row + 1..=max_point.row() {
 5519            let (indent, is_blank) = display_map.line_indent(row);
 5520            if !is_blank && indent <= start_indent {
 5521                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5522                break;
 5523            }
 5524        }
 5525
 5526        let end = end.unwrap_or(max_point);
 5527        return start.to_point(display_map)..end.to_point(display_map);
 5528    }
 5529
 5530    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5531        let selections = self.local_selections::<Point>(cx);
 5532        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5533        self.fold_ranges(ranges, cx);
 5534    }
 5535
 5536    pub fn fold_ranges<T: ToOffset>(
 5537        &mut self,
 5538        ranges: impl IntoIterator<Item = Range<T>>,
 5539        cx: &mut ViewContext<Self>,
 5540    ) {
 5541        let mut ranges = ranges.into_iter().peekable();
 5542        if ranges.peek().is_some() {
 5543            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5544            self.request_autoscroll(Autoscroll::Fit, cx);
 5545            cx.notify();
 5546        }
 5547    }
 5548
 5549    pub fn unfold_ranges<T: ToOffset>(
 5550        &mut self,
 5551        ranges: impl IntoIterator<Item = Range<T>>,
 5552        inclusive: bool,
 5553        cx: &mut ViewContext<Self>,
 5554    ) {
 5555        let mut ranges = ranges.into_iter().peekable();
 5556        if ranges.peek().is_some() {
 5557            self.display_map
 5558                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5559            self.request_autoscroll(Autoscroll::Fit, cx);
 5560            cx.notify();
 5561        }
 5562    }
 5563
 5564    pub fn insert_blocks(
 5565        &mut self,
 5566        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5567        cx: &mut ViewContext<Self>,
 5568    ) -> Vec<BlockId> {
 5569        let blocks = self
 5570            .display_map
 5571            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5572        self.request_autoscroll(Autoscroll::Fit, cx);
 5573        blocks
 5574    }
 5575
 5576    pub fn replace_blocks(
 5577        &mut self,
 5578        blocks: HashMap<BlockId, RenderBlock>,
 5579        cx: &mut ViewContext<Self>,
 5580    ) {
 5581        self.display_map
 5582            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5583        self.request_autoscroll(Autoscroll::Fit, cx);
 5584    }
 5585
 5586    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5587        self.display_map.update(cx, |display_map, cx| {
 5588            display_map.remove_blocks(block_ids, cx)
 5589        });
 5590    }
 5591
 5592    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5593        self.display_map
 5594            .update(cx, |map, cx| map.snapshot(cx))
 5595            .longest_row()
 5596    }
 5597
 5598    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5599        self.display_map
 5600            .update(cx, |map, cx| map.snapshot(cx))
 5601            .max_point()
 5602    }
 5603
 5604    pub fn text(&self, cx: &AppContext) -> String {
 5605        self.buffer.read(cx).read(cx).text()
 5606    }
 5607
 5608    pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
 5609        self.transact(cx, |this, cx| {
 5610            this.buffer
 5611                .read(cx)
 5612                .as_singleton()
 5613                .expect("you can only call set_text on editors for singleton buffers")
 5614                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5615        });
 5616    }
 5617
 5618    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5619        self.display_map
 5620            .update(cx, |map, cx| map.snapshot(cx))
 5621            .text()
 5622    }
 5623
 5624    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5625        let language_name = self
 5626            .buffer
 5627            .read(cx)
 5628            .as_singleton()
 5629            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5630            .map(|l| l.name());
 5631
 5632        let settings = cx.global::<Settings>();
 5633        let mode = self
 5634            .soft_wrap_mode_override
 5635            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5636        match mode {
 5637            settings::SoftWrap::None => SoftWrap::None,
 5638            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5639            settings::SoftWrap::PreferredLineLength => {
 5640                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5641            }
 5642        }
 5643    }
 5644
 5645    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5646        self.soft_wrap_mode_override = Some(mode);
 5647        cx.notify();
 5648    }
 5649
 5650    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5651        self.display_map
 5652            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5653    }
 5654
 5655    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5656        self.highlighted_rows = rows;
 5657    }
 5658
 5659    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5660        self.highlighted_rows.clone()
 5661    }
 5662
 5663    pub fn highlight_background<T: 'static>(
 5664        &mut self,
 5665        ranges: Vec<Range<Anchor>>,
 5666        color_fetcher: fn(&Theme) -> Color,
 5667        cx: &mut ViewContext<Self>,
 5668    ) {
 5669        self.background_highlights
 5670            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5671        cx.notify();
 5672    }
 5673
 5674    pub fn clear_background_highlights<T: 'static>(
 5675        &mut self,
 5676        cx: &mut ViewContext<Self>,
 5677    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5678        cx.notify();
 5679        self.background_highlights.remove(&TypeId::of::<T>())
 5680    }
 5681
 5682    #[cfg(feature = "test-support")]
 5683    pub fn all_background_highlights(
 5684        &mut self,
 5685        cx: &mut ViewContext<Self>,
 5686    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5687        let snapshot = self.snapshot(cx);
 5688        let buffer = &snapshot.buffer_snapshot;
 5689        let start = buffer.anchor_before(0);
 5690        let end = buffer.anchor_after(buffer.len());
 5691        let theme = cx.global::<Settings>().theme.as_ref();
 5692        self.background_highlights_in_range(start..end, &snapshot, theme)
 5693    }
 5694
 5695    pub fn background_highlights_in_range(
 5696        &self,
 5697        search_range: Range<Anchor>,
 5698        display_snapshot: &DisplaySnapshot,
 5699        theme: &Theme,
 5700    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5701        let mut results = Vec::new();
 5702        let buffer = &display_snapshot.buffer_snapshot;
 5703        for (color_fetcher, ranges) in self.background_highlights.values() {
 5704            let color = color_fetcher(theme);
 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                cx.global::<Settings>().theme.as_ref(),
 9843            );
 9844            // Enforce a consistent ordering based on color without relying on the ordering of the
 9845            // highlight's `TypeId` which is non-deterministic.
 9846            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9847            assert_eq!(
 9848                highlighted_ranges,
 9849                &[
 9850                    (
 9851                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9852                        Color::green(),
 9853                    ),
 9854                    (
 9855                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9856                        Color::green(),
 9857                    ),
 9858                    (
 9859                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9860                        Color::red(),
 9861                    ),
 9862                    (
 9863                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9864                        Color::red(),
 9865                    ),
 9866                ]
 9867            );
 9868            assert_eq!(
 9869                editor.background_highlights_in_range(
 9870                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9871                    &snapshot,
 9872                    cx.global::<Settings>().theme.as_ref(),
 9873                ),
 9874                &[(
 9875                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9876                    Color::red(),
 9877                )]
 9878            );
 9879        });
 9880    }
 9881
 9882    #[gpui::test]
 9883    fn test_following(cx: &mut gpui::MutableAppContext) {
 9884        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9885
 9886        cx.set_global(Settings::test(cx));
 9887
 9888        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9889        let (_, follower) = cx.add_window(
 9890            WindowOptions {
 9891                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
 9892                ..Default::default()
 9893            },
 9894            |cx| build_editor(buffer.clone(), cx),
 9895        );
 9896
 9897        let pending_update = Rc::new(RefCell::new(None));
 9898        follower.update(cx, {
 9899            let update = pending_update.clone();
 9900            |_, cx| {
 9901                cx.subscribe(&leader, move |_, leader, event, cx| {
 9902                    leader
 9903                        .read(cx)
 9904                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
 9905                })
 9906                .detach();
 9907            }
 9908        });
 9909
 9910        // Update the selections only
 9911        leader.update(cx, |leader, cx| {
 9912            leader.select_ranges([1..1], None, cx);
 9913        });
 9914        follower.update(cx, |follower, cx| {
 9915            follower
 9916                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9917                .unwrap();
 9918        });
 9919        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
 9920
 9921        // Update the scroll position only
 9922        leader.update(cx, |leader, cx| {
 9923            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9924        });
 9925        follower.update(cx, |follower, cx| {
 9926            follower
 9927                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9928                .unwrap();
 9929        });
 9930        assert_eq!(
 9931            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
 9932            vec2f(1.5, 3.5)
 9933        );
 9934
 9935        // Update the selections and scroll position
 9936        leader.update(cx, |leader, cx| {
 9937            leader.select_ranges([0..0], None, cx);
 9938            leader.request_autoscroll(Autoscroll::Newest, cx);
 9939            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9940        });
 9941        follower.update(cx, |follower, cx| {
 9942            let initial_scroll_position = follower.scroll_position(cx);
 9943            follower
 9944                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9945                .unwrap();
 9946            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
 9947            assert!(follower.autoscroll_request.is_some());
 9948        });
 9949        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
 9950
 9951        // Creating a pending selection that precedes another selection
 9952        leader.update(cx, |leader, cx| {
 9953            leader.select_ranges([1..1], None, cx);
 9954            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
 9955        });
 9956        follower.update(cx, |follower, cx| {
 9957            follower
 9958                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9959                .unwrap();
 9960        });
 9961        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
 9962
 9963        // Extend the pending selection so that it surrounds another selection
 9964        leader.update(cx, |leader, cx| {
 9965            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
 9966        });
 9967        follower.update(cx, |follower, cx| {
 9968            follower
 9969                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9970                .unwrap();
 9971        });
 9972        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
 9973    }
 9974
 9975    #[test]
 9976    fn test_combine_syntax_and_fuzzy_match_highlights() {
 9977        let string = "abcdefghijklmnop";
 9978        let syntax_ranges = [
 9979            (
 9980                0..3,
 9981                HighlightStyle {
 9982                    color: Some(Color::red()),
 9983                    ..Default::default()
 9984                },
 9985            ),
 9986            (
 9987                4..8,
 9988                HighlightStyle {
 9989                    color: Some(Color::green()),
 9990                    ..Default::default()
 9991                },
 9992            ),
 9993        ];
 9994        let match_indices = [4, 6, 7, 8];
 9995        assert_eq!(
 9996            combine_syntax_and_fuzzy_match_highlights(
 9997                &string,
 9998                Default::default(),
 9999                syntax_ranges.into_iter(),
10000                &match_indices,
10001            ),
10002            &[
10003                (
10004                    0..3,
10005                    HighlightStyle {
10006                        color: Some(Color::red()),
10007                        ..Default::default()
10008                    },
10009                ),
10010                (
10011                    4..5,
10012                    HighlightStyle {
10013                        color: Some(Color::green()),
10014                        weight: Some(fonts::Weight::BOLD),
10015                        ..Default::default()
10016                    },
10017                ),
10018                (
10019                    5..6,
10020                    HighlightStyle {
10021                        color: Some(Color::green()),
10022                        ..Default::default()
10023                    },
10024                ),
10025                (
10026                    6..8,
10027                    HighlightStyle {
10028                        color: Some(Color::green()),
10029                        weight: Some(fonts::Weight::BOLD),
10030                        ..Default::default()
10031                    },
10032                ),
10033                (
10034                    8..9,
10035                    HighlightStyle {
10036                        weight: Some(fonts::Weight::BOLD),
10037                        ..Default::default()
10038                    },
10039                ),
10040            ]
10041        );
10042    }
10043
10044    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10045        let point = DisplayPoint::new(row as u32, column as u32);
10046        point..point
10047    }
10048
10049    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10050        Editor::new(EditorMode::Full, buffer, None, None, cx)
10051    }
10052
10053    fn assert_selection_ranges(
10054        marked_text: &str,
10055        selection_marker_pairs: Vec<(char, char)>,
10056        view: &mut Editor,
10057        cx: &mut ViewContext<Editor>,
10058    ) {
10059        let snapshot = view.snapshot(cx).display_snapshot;
10060        let mut marker_chars = Vec::new();
10061        for (start, end) in selection_marker_pairs.iter() {
10062            marker_chars.push(*start);
10063            marker_chars.push(*end);
10064        }
10065        let (_, markers) = marked_text_by(marked_text, marker_chars);
10066        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10067            .iter()
10068            .map(|(start, end)| {
10069                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10070                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10071                start..end
10072            })
10073            .collect();
10074        assert_eq!(
10075            view.selected_display_ranges(cx),
10076            &asserted_ranges[..],
10077            "Assert selections are {}",
10078            marked_text
10079        );
10080    }
10081}
10082
10083trait RangeExt<T> {
10084    fn sorted(&self) -> Range<T>;
10085    fn to_inclusive(&self) -> RangeInclusive<T>;
10086}
10087
10088impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10089    fn sorted(&self) -> Self {
10090        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10091    }
10092
10093    fn to_inclusive(&self) -> RangeInclusive<T> {
10094        self.start.clone()..=self.end.clone()
10095    }
10096}