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.move_selections(cx, |_, selection| {
 3795                selection.reversed = true;
 3796            });
 3797
 3798            this.select_to_beginning_of_line(
 3799                &SelectToBeginningOfLine {
 3800                    stop_at_soft_wraps: false,
 3801                },
 3802                cx,
 3803            );
 3804            this.backspace(&Backspace, cx);
 3805        });
 3806    }
 3807
 3808    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 3809        self.move_cursors(cx, |map, head, _| {
 3810            (movement::line_end(map, head, true), SelectionGoal::None)
 3811        });
 3812    }
 3813
 3814    pub fn select_to_end_of_line(
 3815        &mut self,
 3816        action: &SelectToEndOfLine,
 3817        cx: &mut ViewContext<Self>,
 3818    ) {
 3819        self.move_selection_heads(cx, |map, head, _| {
 3820            (
 3821                movement::line_end(map, head, action.stop_at_soft_wraps),
 3822                SelectionGoal::None,
 3823            )
 3824        });
 3825    }
 3826
 3827    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 3828        self.transact(cx, |this, cx| {
 3829            this.select_to_end_of_line(
 3830                &SelectToEndOfLine {
 3831                    stop_at_soft_wraps: false,
 3832                },
 3833                cx,
 3834            );
 3835            this.delete(&Delete, cx);
 3836        });
 3837    }
 3838
 3839    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 3840        self.transact(cx, |this, cx| {
 3841            this.select_to_end_of_line(
 3842                &SelectToEndOfLine {
 3843                    stop_at_soft_wraps: false,
 3844                },
 3845                cx,
 3846            );
 3847            this.cut(&Cut, cx);
 3848        });
 3849    }
 3850
 3851    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 3852        if matches!(self.mode, EditorMode::SingleLine) {
 3853            cx.propagate_action();
 3854            return;
 3855        }
 3856
 3857        let selection = Selection {
 3858            id: post_inc(&mut self.next_selection_id),
 3859            start: 0,
 3860            end: 0,
 3861            reversed: false,
 3862            goal: SelectionGoal::None,
 3863        };
 3864        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3865    }
 3866
 3867    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 3868        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
 3869        selection.set_head(Point::zero(), SelectionGoal::None);
 3870        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3871    }
 3872
 3873    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 3874        if matches!(self.mode, EditorMode::SingleLine) {
 3875            cx.propagate_action();
 3876            return;
 3877        }
 3878
 3879        let cursor = self.buffer.read(cx).read(cx).len();
 3880        let selection = Selection {
 3881            id: post_inc(&mut self.next_selection_id),
 3882            start: cursor,
 3883            end: cursor,
 3884            reversed: false,
 3885            goal: SelectionGoal::None,
 3886        };
 3887        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3888    }
 3889
 3890    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 3891        self.nav_history = nav_history;
 3892    }
 3893
 3894    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 3895        self.nav_history.as_ref()
 3896    }
 3897
 3898    fn push_to_nav_history(
 3899        &self,
 3900        position: Anchor,
 3901        new_position: Option<Point>,
 3902        cx: &mut ViewContext<Self>,
 3903    ) {
 3904        if let Some(nav_history) = &self.nav_history {
 3905            let buffer = self.buffer.read(cx).read(cx);
 3906            let offset = position.to_offset(&buffer);
 3907            let point = position.to_point(&buffer);
 3908            let scroll_top_offset = self.scroll_top_anchor.to_offset(&buffer);
 3909            drop(buffer);
 3910
 3911            if let Some(new_position) = new_position {
 3912                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 3913                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 3914                    return;
 3915                }
 3916            }
 3917
 3918            nav_history.push(Some(NavigationData {
 3919                cursor_anchor: position,
 3920                cursor_offset: offset,
 3921                scroll_position: self.scroll_position,
 3922                scroll_top_anchor: self.scroll_top_anchor.clone(),
 3923                scroll_top_offset,
 3924            }));
 3925        }
 3926    }
 3927
 3928    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 3929        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
 3930        selection.set_head(self.buffer.read(cx).read(cx).len(), SelectionGoal::None);
 3931        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3932    }
 3933
 3934    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 3935        let selection = Selection {
 3936            id: post_inc(&mut self.next_selection_id),
 3937            start: 0,
 3938            end: self.buffer.read(cx).read(cx).len(),
 3939            reversed: false,
 3940            goal: SelectionGoal::None,
 3941        };
 3942        self.update_selections(vec![selection], None, cx);
 3943    }
 3944
 3945    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 3946        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3947        let mut selections = self.local_selections::<Point>(cx);
 3948        let max_point = display_map.buffer_snapshot.max_point();
 3949        for selection in &mut selections {
 3950            let rows = selection.spanned_rows(true, &display_map);
 3951            selection.start = Point::new(rows.start, 0);
 3952            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 3953            selection.reversed = false;
 3954        }
 3955        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 3956    }
 3957
 3958    pub fn split_selection_into_lines(
 3959        &mut self,
 3960        _: &SplitSelectionIntoLines,
 3961        cx: &mut ViewContext<Self>,
 3962    ) {
 3963        let mut to_unfold = Vec::new();
 3964        let mut new_selections = Vec::new();
 3965        {
 3966            let selections = self.local_selections::<Point>(cx);
 3967            let buffer = self.buffer.read(cx).read(cx);
 3968            for selection in selections {
 3969                for row in selection.start.row..selection.end.row {
 3970                    let cursor = Point::new(row, buffer.line_len(row));
 3971                    new_selections.push(Selection {
 3972                        id: post_inc(&mut self.next_selection_id),
 3973                        start: cursor,
 3974                        end: cursor,
 3975                        reversed: false,
 3976                        goal: SelectionGoal::None,
 3977                    });
 3978                }
 3979                new_selections.push(Selection {
 3980                    id: selection.id,
 3981                    start: selection.end,
 3982                    end: selection.end,
 3983                    reversed: false,
 3984                    goal: SelectionGoal::None,
 3985                });
 3986                to_unfold.push(selection.start..selection.end);
 3987            }
 3988        }
 3989        self.unfold_ranges(to_unfold, true, cx);
 3990        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 3991    }
 3992
 3993    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 3994        self.add_selection(true, cx);
 3995    }
 3996
 3997    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 3998        self.add_selection(false, cx);
 3999    }
 4000
 4001    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 4002        self.push_to_selection_history();
 4003        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4004        let mut selections = self.local_selections::<Point>(cx);
 4005        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4006            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4007            let range = oldest_selection.display_range(&display_map).sorted();
 4008            let columns = cmp::min(range.start.column(), range.end.column())
 4009                ..cmp::max(range.start.column(), range.end.column());
 4010
 4011            selections.clear();
 4012            let mut stack = Vec::new();
 4013            for row in range.start.row()..=range.end.row() {
 4014                if let Some(selection) = self.build_columnar_selection(
 4015                    &display_map,
 4016                    row,
 4017                    &columns,
 4018                    oldest_selection.reversed,
 4019                ) {
 4020                    stack.push(selection.id);
 4021                    selections.push(selection);
 4022                }
 4023            }
 4024
 4025            if above {
 4026                stack.reverse();
 4027            }
 4028
 4029            AddSelectionsState { above, stack }
 4030        });
 4031
 4032        let last_added_selection = *state.stack.last().unwrap();
 4033        let mut new_selections = Vec::new();
 4034        if above == state.above {
 4035            let end_row = if above {
 4036                0
 4037            } else {
 4038                display_map.max_point().row()
 4039            };
 4040
 4041            'outer: for selection in selections {
 4042                if selection.id == last_added_selection {
 4043                    let range = selection.display_range(&display_map).sorted();
 4044                    debug_assert_eq!(range.start.row(), range.end.row());
 4045                    let mut row = range.start.row();
 4046                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4047                    {
 4048                        start..end
 4049                    } else {
 4050                        cmp::min(range.start.column(), range.end.column())
 4051                            ..cmp::max(range.start.column(), range.end.column())
 4052                    };
 4053
 4054                    while row != end_row {
 4055                        if above {
 4056                            row -= 1;
 4057                        } else {
 4058                            row += 1;
 4059                        }
 4060
 4061                        if let Some(new_selection) = self.build_columnar_selection(
 4062                            &display_map,
 4063                            row,
 4064                            &columns,
 4065                            selection.reversed,
 4066                        ) {
 4067                            state.stack.push(new_selection.id);
 4068                            if above {
 4069                                new_selections.push(new_selection);
 4070                                new_selections.push(selection);
 4071                            } else {
 4072                                new_selections.push(selection);
 4073                                new_selections.push(new_selection);
 4074                            }
 4075
 4076                            continue 'outer;
 4077                        }
 4078                    }
 4079                }
 4080
 4081                new_selections.push(selection);
 4082            }
 4083        } else {
 4084            new_selections = selections;
 4085            new_selections.retain(|s| s.id != last_added_selection);
 4086            state.stack.pop();
 4087        }
 4088
 4089        self.update_selections(new_selections, Some(Autoscroll::Newest), cx);
 4090        if state.stack.len() > 1 {
 4091            self.add_selections_state = Some(state);
 4092        }
 4093    }
 4094
 4095    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4096        self.push_to_selection_history();
 4097        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4098        let buffer = &display_map.buffer_snapshot;
 4099        let mut selections = self.local_selections::<usize>(cx);
 4100        if let Some(mut select_next_state) = self.select_next_state.take() {
 4101            let query = &select_next_state.query;
 4102            if !select_next_state.done {
 4103                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4104                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4105                let mut next_selected_range = None;
 4106
 4107                let bytes_after_last_selection =
 4108                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4109                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4110                let query_matches = query
 4111                    .stream_find_iter(bytes_after_last_selection)
 4112                    .map(|result| (last_selection.end, result))
 4113                    .chain(
 4114                        query
 4115                            .stream_find_iter(bytes_before_first_selection)
 4116                            .map(|result| (0, result)),
 4117                    );
 4118                for (start_offset, query_match) in query_matches {
 4119                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4120                    let offset_range =
 4121                        start_offset + query_match.start()..start_offset + query_match.end();
 4122                    let display_range = offset_range.start.to_display_point(&display_map)
 4123                        ..offset_range.end.to_display_point(&display_map);
 4124
 4125                    if !select_next_state.wordwise
 4126                        || (!movement::is_inside_word(&display_map, display_range.start)
 4127                            && !movement::is_inside_word(&display_map, display_range.end))
 4128                    {
 4129                        next_selected_range = Some(offset_range);
 4130                        break;
 4131                    }
 4132                }
 4133
 4134                if let Some(next_selected_range) = next_selected_range {
 4135                    if action.replace_newest {
 4136                        if let Some(newest_id) =
 4137                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
 4138                        {
 4139                            selections.retain(|s| s.id != newest_id);
 4140                        }
 4141                    }
 4142                    selections.push(Selection {
 4143                        id: post_inc(&mut self.next_selection_id),
 4144                        start: next_selected_range.start,
 4145                        end: next_selected_range.end,
 4146                        reversed: false,
 4147                        goal: SelectionGoal::None,
 4148                    });
 4149                    self.unfold_ranges([next_selected_range], false, cx);
 4150                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4151                } else {
 4152                    select_next_state.done = true;
 4153                }
 4154            }
 4155
 4156            self.select_next_state = Some(select_next_state);
 4157        } else if selections.len() == 1 {
 4158            let selection = selections.last_mut().unwrap();
 4159            if selection.start == selection.end {
 4160                let word_range = movement::surrounding_word(
 4161                    &display_map,
 4162                    selection.start.to_display_point(&display_map),
 4163                );
 4164                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4165                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4166                selection.goal = SelectionGoal::None;
 4167                selection.reversed = false;
 4168
 4169                let query = buffer
 4170                    .text_for_range(selection.start..selection.end)
 4171                    .collect::<String>();
 4172                let select_state = SelectNextState {
 4173                    query: AhoCorasick::new_auto_configured(&[query]),
 4174                    wordwise: true,
 4175                    done: false,
 4176                };
 4177                self.unfold_ranges([selection.start..selection.end], false, cx);
 4178                self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4179                self.select_next_state = Some(select_state);
 4180            } else {
 4181                let query = buffer
 4182                    .text_for_range(selection.start..selection.end)
 4183                    .collect::<String>();
 4184                self.select_next_state = Some(SelectNextState {
 4185                    query: AhoCorasick::new_auto_configured(&[query]),
 4186                    wordwise: false,
 4187                    done: false,
 4188                });
 4189                self.select_next(action, cx);
 4190            }
 4191        }
 4192    }
 4193
 4194    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4195        self.transact(cx, |this, cx| {
 4196            let mut selections = this.local_selections::<Point>(cx);
 4197            let mut all_selection_lines_are_comments = true;
 4198            let mut edit_ranges = Vec::new();
 4199            let mut last_toggled_row = None;
 4200            this.buffer.update(cx, |buffer, cx| {
 4201                // TODO: Handle selections that cross excerpts
 4202                for selection in &mut selections {
 4203                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
 4204                    // as that portion won't be used for detecting if a line is a comment.
 4205                    let full_comment_prefix = if let Some(prefix) = buffer
 4206                        .language_at(selection.start, cx)
 4207                        .and_then(|l| l.line_comment_prefix())
 4208                    {
 4209                        prefix.to_string()
 4210                    } else {
 4211                        return;
 4212                    };
 4213                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4214                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4215                    edit_ranges.clear();
 4216                    let snapshot = buffer.snapshot(cx);
 4217
 4218                    let end_row =
 4219                        if selection.end.row > selection.start.row && selection.end.column == 0 {
 4220                            selection.end.row
 4221                        } else {
 4222                            selection.end.row + 1
 4223                        };
 4224
 4225                    for row in selection.start.row..end_row {
 4226                        // If multiple selections contain a given row, avoid processing that
 4227                        // row more than once.
 4228                        if last_toggled_row == Some(row) {
 4229                            continue;
 4230                        } else {
 4231                            last_toggled_row = Some(row);
 4232                        }
 4233
 4234                        if snapshot.is_line_blank(row) {
 4235                            continue;
 4236                        }
 4237
 4238                        let start = Point::new(row, snapshot.indent_column_for_line(row));
 4239                        let mut line_bytes = snapshot
 4240                            .bytes_in_range(start..snapshot.max_point())
 4241                            .flatten()
 4242                            .copied();
 4243
 4244                        // If this line currently begins with the line comment prefix, then record
 4245                        // the range containing the prefix.
 4246                        if all_selection_lines_are_comments
 4247                            && line_bytes
 4248                                .by_ref()
 4249                                .take(comment_prefix.len())
 4250                                .eq(comment_prefix.bytes())
 4251                        {
 4252                            // Include any whitespace that matches the comment prefix.
 4253                            let matching_whitespace_len = line_bytes
 4254                                .zip(comment_prefix_whitespace.bytes())
 4255                                .take_while(|(a, b)| a == b)
 4256                                .count()
 4257                                as u32;
 4258                            let end = Point::new(
 4259                                row,
 4260                                start.column
 4261                                    + comment_prefix.len() as u32
 4262                                    + matching_whitespace_len,
 4263                            );
 4264                            edit_ranges.push(start..end);
 4265                        }
 4266                        // If this line does not begin with the line comment prefix, then record
 4267                        // the position where the prefix should be inserted.
 4268                        else {
 4269                            all_selection_lines_are_comments = false;
 4270                            edit_ranges.push(start..start);
 4271                        }
 4272                    }
 4273
 4274                    if !edit_ranges.is_empty() {
 4275                        if all_selection_lines_are_comments {
 4276                            buffer.edit(edit_ranges.iter().cloned(), "", cx);
 4277                        } else {
 4278                            let min_column =
 4279                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
 4280                            let edit_ranges = edit_ranges.iter().map(|range| {
 4281                                let position = Point::new(range.start.row, min_column);
 4282                                position..position
 4283                            });
 4284                            buffer.edit(edit_ranges, &full_comment_prefix, cx);
 4285                        }
 4286                    }
 4287                }
 4288            });
 4289
 4290            this.update_selections(
 4291                this.local_selections::<usize>(cx),
 4292                Some(Autoscroll::Fit),
 4293                cx,
 4294            );
 4295        });
 4296    }
 4297
 4298    pub fn select_larger_syntax_node(
 4299        &mut self,
 4300        _: &SelectLargerSyntaxNode,
 4301        cx: &mut ViewContext<Self>,
 4302    ) {
 4303        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
 4304        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4305        let buffer = self.buffer.read(cx).snapshot(cx);
 4306
 4307        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4308        let mut selected_larger_node = false;
 4309        let new_selections = old_selections
 4310            .iter()
 4311            .map(|selection| {
 4312                let old_range = selection.start..selection.end;
 4313                let mut new_range = old_range.clone();
 4314                while let Some(containing_range) =
 4315                    buffer.range_for_syntax_ancestor(new_range.clone())
 4316                {
 4317                    new_range = containing_range;
 4318                    if !display_map.intersects_fold(new_range.start)
 4319                        && !display_map.intersects_fold(new_range.end)
 4320                    {
 4321                        break;
 4322                    }
 4323                }
 4324
 4325                selected_larger_node |= new_range != old_range;
 4326                Selection {
 4327                    id: selection.id,
 4328                    start: new_range.start,
 4329                    end: new_range.end,
 4330                    goal: SelectionGoal::None,
 4331                    reversed: selection.reversed,
 4332                }
 4333            })
 4334            .collect::<Vec<_>>();
 4335
 4336        if selected_larger_node {
 4337            stack.push(old_selections);
 4338            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4339        }
 4340        self.select_larger_syntax_node_stack = stack;
 4341    }
 4342
 4343    pub fn select_smaller_syntax_node(
 4344        &mut self,
 4345        _: &SelectSmallerSyntaxNode,
 4346        cx: &mut ViewContext<Self>,
 4347    ) {
 4348        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4349        if let Some(selections) = stack.pop() {
 4350            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
 4351        }
 4352        self.select_larger_syntax_node_stack = stack;
 4353    }
 4354
 4355    pub fn move_to_enclosing_bracket(
 4356        &mut self,
 4357        _: &MoveToEnclosingBracket,
 4358        cx: &mut ViewContext<Self>,
 4359    ) {
 4360        let mut selections = self.local_selections::<usize>(cx);
 4361        let buffer = self.buffer.read(cx).snapshot(cx);
 4362        for selection in &mut selections {
 4363            if let Some((open_range, close_range)) =
 4364                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4365            {
 4366                let close_range = close_range.to_inclusive();
 4367                let destination = if close_range.contains(&selection.start)
 4368                    && close_range.contains(&selection.end)
 4369                {
 4370                    open_range.end
 4371                } else {
 4372                    *close_range.start()
 4373                };
 4374                selection.start = destination;
 4375                selection.end = destination;
 4376            }
 4377        }
 4378
 4379        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4380    }
 4381
 4382    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4383        self.end_selection(cx);
 4384        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4385        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4386            self.set_selections(entry.selections, None, true, cx);
 4387            self.select_next_state = entry.select_next_state;
 4388            self.add_selections_state = entry.add_selections_state;
 4389            self.request_autoscroll(Autoscroll::Newest, cx);
 4390        }
 4391        self.selection_history.mode = SelectionHistoryMode::Normal;
 4392    }
 4393
 4394    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4395        self.end_selection(cx);
 4396        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4397        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4398            self.set_selections(entry.selections, None, true, cx);
 4399            self.select_next_state = entry.select_next_state;
 4400            self.add_selections_state = entry.add_selections_state;
 4401            self.request_autoscroll(Autoscroll::Newest, cx);
 4402        }
 4403        self.selection_history.mode = SelectionHistoryMode::Normal;
 4404    }
 4405
 4406    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
 4407        self.go_to_diagnostic(Direction::Next, cx)
 4408    }
 4409
 4410    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4411        self.go_to_diagnostic(Direction::Prev, cx)
 4412    }
 4413
 4414    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4415        let buffer = self.buffer.read(cx).snapshot(cx);
 4416        let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
 4417        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4418            active_diagnostics
 4419                .primary_range
 4420                .to_offset(&buffer)
 4421                .to_inclusive()
 4422        });
 4423        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4424            if active_primary_range.contains(&selection.head()) {
 4425                *active_primary_range.end()
 4426            } else {
 4427                selection.head()
 4428            }
 4429        } else {
 4430            selection.head()
 4431        };
 4432
 4433        loop {
 4434            let mut diagnostics = if direction == Direction::Prev {
 4435                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4436            } else {
 4437                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4438            };
 4439            let group = diagnostics.find_map(|entry| {
 4440                if entry.diagnostic.is_primary
 4441                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4442                    && !entry.range.is_empty()
 4443                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4444                {
 4445                    Some((entry.range, entry.diagnostic.group_id))
 4446                } else {
 4447                    None
 4448                }
 4449            });
 4450
 4451            if let Some((primary_range, group_id)) = group {
 4452                self.activate_diagnostics(group_id, cx);
 4453                self.update_selections(
 4454                    vec![Selection {
 4455                        id: selection.id,
 4456                        start: primary_range.start,
 4457                        end: primary_range.start,
 4458                        reversed: false,
 4459                        goal: SelectionGoal::None,
 4460                    }],
 4461                    Some(Autoscroll::Center),
 4462                    cx,
 4463                );
 4464                break;
 4465            } else {
 4466                // Cycle around to the start of the buffer, potentially moving back to the start of
 4467                // the currently active diagnostic.
 4468                active_primary_range.take();
 4469                if direction == Direction::Prev {
 4470                    if search_start == buffer.len() {
 4471                        break;
 4472                    } else {
 4473                        search_start = buffer.len();
 4474                    }
 4475                } else {
 4476                    if search_start == 0 {
 4477                        break;
 4478                    } else {
 4479                        search_start = 0;
 4480                    }
 4481                }
 4482            }
 4483        }
 4484    }
 4485
 4486    pub fn go_to_definition(
 4487        workspace: &mut Workspace,
 4488        _: &GoToDefinition,
 4489        cx: &mut ViewContext<Workspace>,
 4490    ) {
 4491        let active_item = workspace.active_item(cx);
 4492        let editor_handle = if let Some(editor) = active_item
 4493            .as_ref()
 4494            .and_then(|item| item.act_as::<Self>(cx))
 4495        {
 4496            editor
 4497        } else {
 4498            return;
 4499        };
 4500
 4501        let editor = editor_handle.read(cx);
 4502        let head = editor.newest_selection::<usize>(cx).head();
 4503        let (buffer, head) =
 4504            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
 4505                text_anchor
 4506            } else {
 4507                return;
 4508            };
 4509
 4510        let project = workspace.project().clone();
 4511        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
 4512        cx.spawn(|workspace, mut cx| async move {
 4513            let definitions = definitions.await?;
 4514            workspace.update(&mut cx, |workspace, cx| {
 4515                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 4516                for definition in definitions {
 4517                    let range = definition.range.to_offset(definition.buffer.read(cx));
 4518
 4519                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
 4520                    target_editor_handle.update(cx, |target_editor, cx| {
 4521                        // When selecting a definition in a different buffer, disable the nav history
 4522                        // to avoid creating a history entry at the previous cursor location.
 4523                        if editor_handle != target_editor_handle {
 4524                            nav_history.borrow_mut().disable();
 4525                        }
 4526                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
 4527                        nav_history.borrow_mut().enable();
 4528                    });
 4529                }
 4530            });
 4531
 4532            Ok::<(), anyhow::Error>(())
 4533        })
 4534        .detach_and_log_err(cx);
 4535    }
 4536
 4537    pub fn find_all_references(
 4538        workspace: &mut Workspace,
 4539        _: &FindAllReferences,
 4540        cx: &mut ViewContext<Workspace>,
 4541    ) -> Option<Task<Result<()>>> {
 4542        let active_item = workspace.active_item(cx)?;
 4543        let editor_handle = active_item.act_as::<Self>(cx)?;
 4544
 4545        let editor = editor_handle.read(cx);
 4546        let head = editor.newest_selection::<usize>(cx).head();
 4547        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
 4548        let replica_id = editor.replica_id(cx);
 4549
 4550        let project = workspace.project().clone();
 4551        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4552        Some(cx.spawn(|workspace, mut cx| async move {
 4553            let mut locations = references.await?;
 4554            if locations.is_empty() {
 4555                return Ok(());
 4556            }
 4557
 4558            locations.sort_by_key(|location| location.buffer.id());
 4559            let mut locations = locations.into_iter().peekable();
 4560            let mut ranges_to_highlight = Vec::new();
 4561
 4562            let excerpt_buffer = cx.add_model(|cx| {
 4563                let mut symbol_name = None;
 4564                let mut multibuffer = MultiBuffer::new(replica_id);
 4565                while let Some(location) = locations.next() {
 4566                    let buffer = location.buffer.read(cx);
 4567                    let mut ranges_for_buffer = Vec::new();
 4568                    let range = location.range.to_offset(buffer);
 4569                    ranges_for_buffer.push(range.clone());
 4570                    if symbol_name.is_none() {
 4571                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4572                    }
 4573
 4574                    while let Some(next_location) = locations.peek() {
 4575                        if next_location.buffer == location.buffer {
 4576                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4577                            locations.next();
 4578                        } else {
 4579                            break;
 4580                        }
 4581                    }
 4582
 4583                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4584                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4585                        location.buffer.clone(),
 4586                        ranges_for_buffer,
 4587                        1,
 4588                        cx,
 4589                    ));
 4590                }
 4591                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4592            });
 4593
 4594            workspace.update(&mut cx, |workspace, cx| {
 4595                let editor =
 4596                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4597                editor.update(cx, |editor, cx| {
 4598                    editor.highlight_background::<Self>(
 4599                        ranges_to_highlight,
 4600                        |theme| theme.editor.highlighted_line_background,
 4601                        cx,
 4602                    );
 4603                });
 4604                workspace.add_item(Box::new(editor), cx);
 4605            });
 4606
 4607            Ok(())
 4608        }))
 4609    }
 4610
 4611    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4612        use language::ToOffset as _;
 4613
 4614        let project = self.project.clone()?;
 4615        let selection = self.newest_anchor_selection().clone();
 4616        let (cursor_buffer, cursor_buffer_position) = self
 4617            .buffer
 4618            .read(cx)
 4619            .text_anchor_for_position(selection.head(), cx)?;
 4620        let (tail_buffer, _) = self
 4621            .buffer
 4622            .read(cx)
 4623            .text_anchor_for_position(selection.tail(), cx)?;
 4624        if tail_buffer != cursor_buffer {
 4625            return None;
 4626        }
 4627
 4628        let snapshot = cursor_buffer.read(cx).snapshot();
 4629        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4630        let prepare_rename = project.update(cx, |project, cx| {
 4631            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4632        });
 4633
 4634        Some(cx.spawn(|this, mut cx| async move {
 4635            let rename_range = if let Some(range) = prepare_rename.await? {
 4636                Some(range)
 4637            } else {
 4638                this.read_with(&cx, |this, cx| {
 4639                    let buffer = this.buffer.read(cx).snapshot(cx);
 4640                    let mut buffer_highlights = this
 4641                        .document_highlights_for_position(selection.head(), &buffer)
 4642                        .filter(|highlight| {
 4643                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4644                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4645                        });
 4646                    buffer_highlights
 4647                        .next()
 4648                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4649                })
 4650            };
 4651            if let Some(rename_range) = rename_range {
 4652                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4653                let cursor_offset_in_rename_range =
 4654                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4655
 4656                this.update(&mut cx, |this, cx| {
 4657                    this.take_rename(false, cx);
 4658                    let style = this.style(cx);
 4659                    let buffer = this.buffer.read(cx).read(cx);
 4660                    let cursor_offset = selection.head().to_offset(&buffer);
 4661                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4662                    let rename_end = rename_start + rename_buffer_range.len();
 4663                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4664                    let mut old_highlight_id = None;
 4665                    let old_name = buffer
 4666                        .chunks(rename_start..rename_end, true)
 4667                        .map(|chunk| {
 4668                            if old_highlight_id.is_none() {
 4669                                old_highlight_id = chunk.syntax_highlight_id;
 4670                            }
 4671                            chunk.text
 4672                        })
 4673                        .collect();
 4674
 4675                    drop(buffer);
 4676
 4677                    // Position the selection in the rename editor so that it matches the current selection.
 4678                    this.show_local_selections = false;
 4679                    let rename_editor = cx.add_view(|cx| {
 4680                        let mut editor = Editor::single_line(None, cx);
 4681                        if let Some(old_highlight_id) = old_highlight_id {
 4682                            editor.override_text_style =
 4683                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4684                        }
 4685                        editor
 4686                            .buffer
 4687                            .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
 4688                        editor.select_all(&SelectAll, cx);
 4689                        editor
 4690                    });
 4691
 4692                    let ranges = this
 4693                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4694                        .into_iter()
 4695                        .flat_map(|(_, ranges)| ranges)
 4696                        .chain(
 4697                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4698                                .into_iter()
 4699                                .flat_map(|(_, ranges)| ranges),
 4700                        )
 4701                        .collect();
 4702
 4703                    this.highlight_text::<Rename>(
 4704                        ranges,
 4705                        HighlightStyle {
 4706                            fade_out: Some(style.rename_fade),
 4707                            ..Default::default()
 4708                        },
 4709                        cx,
 4710                    );
 4711                    cx.focus(&rename_editor);
 4712                    let block_id = this.insert_blocks(
 4713                        [BlockProperties {
 4714                            position: range.start.clone(),
 4715                            height: 1,
 4716                            render: Arc::new({
 4717                                let editor = rename_editor.clone();
 4718                                move |cx: &BlockContext| {
 4719                                    ChildView::new(editor.clone())
 4720                                        .contained()
 4721                                        .with_padding_left(cx.anchor_x)
 4722                                        .boxed()
 4723                                }
 4724                            }),
 4725                            disposition: BlockDisposition::Below,
 4726                        }],
 4727                        cx,
 4728                    )[0];
 4729                    this.pending_rename = Some(RenameState {
 4730                        range,
 4731                        old_name,
 4732                        editor: rename_editor,
 4733                        block_id,
 4734                    });
 4735                });
 4736            }
 4737
 4738            Ok(())
 4739        }))
 4740    }
 4741
 4742    pub fn confirm_rename(
 4743        workspace: &mut Workspace,
 4744        _: &ConfirmRename,
 4745        cx: &mut ViewContext<Workspace>,
 4746    ) -> Option<Task<Result<()>>> {
 4747        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4748
 4749        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4750            let rename = editor.take_rename(false, cx)?;
 4751            let buffer = editor.buffer.read(cx);
 4752            let (start_buffer, start) =
 4753                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4754            let (end_buffer, end) =
 4755                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4756            if start_buffer == end_buffer {
 4757                let new_name = rename.editor.read(cx).text(cx);
 4758                Some((start_buffer, start..end, rename.old_name, new_name))
 4759            } else {
 4760                None
 4761            }
 4762        })?;
 4763
 4764        let rename = workspace.project().clone().update(cx, |project, cx| {
 4765            project.perform_rename(
 4766                buffer.clone(),
 4767                range.start.clone(),
 4768                new_name.clone(),
 4769                true,
 4770                cx,
 4771            )
 4772        });
 4773
 4774        Some(cx.spawn(|workspace, mut cx| async move {
 4775            let project_transaction = rename.await?;
 4776            Self::open_project_transaction(
 4777                editor.clone(),
 4778                workspace,
 4779                project_transaction,
 4780                format!("Rename: {}{}", old_name, new_name),
 4781                cx.clone(),
 4782            )
 4783            .await?;
 4784
 4785            editor.update(&mut cx, |editor, cx| {
 4786                editor.refresh_document_highlights(cx);
 4787            });
 4788            Ok(())
 4789        }))
 4790    }
 4791
 4792    fn take_rename(
 4793        &mut self,
 4794        moving_cursor: bool,
 4795        cx: &mut ViewContext<Self>,
 4796    ) -> Option<RenameState> {
 4797        let rename = self.pending_rename.take()?;
 4798        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4799        self.clear_text_highlights::<Rename>(cx);
 4800        self.show_local_selections = true;
 4801
 4802        if moving_cursor {
 4803            let cursor_in_rename_editor =
 4804                rename.editor.read(cx).newest_selection::<usize>(cx).head();
 4805
 4806            // Update the selection to match the position of the selection inside
 4807            // the rename editor.
 4808            let snapshot = self.buffer.read(cx).read(cx);
 4809            let rename_range = rename.range.to_offset(&snapshot);
 4810            let cursor_in_editor = snapshot
 4811                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4812                .min(rename_range.end);
 4813            drop(snapshot);
 4814
 4815            self.update_selections(
 4816                vec![Selection {
 4817                    id: self.newest_anchor_selection().id,
 4818                    start: cursor_in_editor,
 4819                    end: cursor_in_editor,
 4820                    reversed: false,
 4821                    goal: SelectionGoal::None,
 4822                }],
 4823                None,
 4824                cx,
 4825            );
 4826        }
 4827
 4828        Some(rename)
 4829    }
 4830
 4831    #[cfg(any(test, feature = "test-support"))]
 4832    pub fn pending_rename(&self) -> Option<&RenameState> {
 4833        self.pending_rename.as_ref()
 4834    }
 4835
 4836    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4837        if let Some(project) = self.project.clone() {
 4838            self.buffer.update(cx, |multi_buffer, cx| {
 4839                project.update(cx, |project, cx| {
 4840                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4841                });
 4842            })
 4843        }
 4844    }
 4845
 4846    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4847        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4848            let buffer = self.buffer.read(cx).snapshot(cx);
 4849            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4850            let is_valid = buffer
 4851                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4852                .any(|entry| {
 4853                    entry.diagnostic.is_primary
 4854                        && !entry.range.is_empty()
 4855                        && entry.range.start == primary_range_start
 4856                        && entry.diagnostic.message == active_diagnostics.primary_message
 4857                });
 4858
 4859            if is_valid != active_diagnostics.is_valid {
 4860                active_diagnostics.is_valid = is_valid;
 4861                let mut new_styles = HashMap::default();
 4862                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4863                    new_styles.insert(
 4864                        *block_id,
 4865                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4866                    );
 4867                }
 4868                self.display_map
 4869                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4870            }
 4871        }
 4872    }
 4873
 4874    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4875        self.dismiss_diagnostics(cx);
 4876        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4877            let buffer = self.buffer.read(cx).snapshot(cx);
 4878
 4879            let mut primary_range = None;
 4880            let mut primary_message = None;
 4881            let mut group_end = Point::zero();
 4882            let diagnostic_group = buffer
 4883                .diagnostic_group::<Point>(group_id)
 4884                .map(|entry| {
 4885                    if entry.range.end > group_end {
 4886                        group_end = entry.range.end;
 4887                    }
 4888                    if entry.diagnostic.is_primary {
 4889                        primary_range = Some(entry.range.clone());
 4890                        primary_message = Some(entry.diagnostic.message.clone());
 4891                    }
 4892                    entry
 4893                })
 4894                .collect::<Vec<_>>();
 4895            let primary_range = primary_range.unwrap();
 4896            let primary_message = primary_message.unwrap();
 4897            let primary_range =
 4898                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 4899
 4900            let blocks = display_map
 4901                .insert_blocks(
 4902                    diagnostic_group.iter().map(|entry| {
 4903                        let diagnostic = entry.diagnostic.clone();
 4904                        let message_height = diagnostic.message.lines().count() as u8;
 4905                        BlockProperties {
 4906                            position: buffer.anchor_after(entry.range.start),
 4907                            height: message_height,
 4908                            render: diagnostic_block_renderer(diagnostic, true),
 4909                            disposition: BlockDisposition::Below,
 4910                        }
 4911                    }),
 4912                    cx,
 4913                )
 4914                .into_iter()
 4915                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 4916                .collect();
 4917
 4918            Some(ActiveDiagnosticGroup {
 4919                primary_range,
 4920                primary_message,
 4921                blocks,
 4922                is_valid: true,
 4923            })
 4924        });
 4925    }
 4926
 4927    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 4928        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 4929            self.display_map.update(cx, |display_map, cx| {
 4930                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 4931            });
 4932            cx.notify();
 4933        }
 4934    }
 4935
 4936    fn build_columnar_selection(
 4937        &mut self,
 4938        display_map: &DisplaySnapshot,
 4939        row: u32,
 4940        columns: &Range<u32>,
 4941        reversed: bool,
 4942    ) -> Option<Selection<Point>> {
 4943        let is_empty = columns.start == columns.end;
 4944        let line_len = display_map.line_len(row);
 4945        if columns.start < line_len || (is_empty && columns.start == line_len) {
 4946            let start = DisplayPoint::new(row, columns.start);
 4947            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
 4948            Some(Selection {
 4949                id: post_inc(&mut self.next_selection_id),
 4950                start: start.to_point(display_map),
 4951                end: end.to_point(display_map),
 4952                reversed,
 4953                goal: SelectionGoal::ColumnRange {
 4954                    start: columns.start,
 4955                    end: columns.end,
 4956                },
 4957            })
 4958        } else {
 4959            None
 4960        }
 4961    }
 4962
 4963    pub fn local_selections_in_range(
 4964        &self,
 4965        range: Range<Anchor>,
 4966        display_map: &DisplaySnapshot,
 4967    ) -> Vec<Selection<Point>> {
 4968        let buffer = &display_map.buffer_snapshot;
 4969
 4970        let start_ix = match self
 4971            .selections
 4972            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
 4973        {
 4974            Ok(ix) | Err(ix) => ix,
 4975        };
 4976        let end_ix = match self
 4977            .selections
 4978            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
 4979        {
 4980            Ok(ix) => ix + 1,
 4981            Err(ix) => ix,
 4982        };
 4983
 4984        fn point_selection(
 4985            selection: &Selection<Anchor>,
 4986            buffer: &MultiBufferSnapshot,
 4987        ) -> Selection<Point> {
 4988            let start = selection.start.to_point(&buffer);
 4989            let end = selection.end.to_point(&buffer);
 4990            Selection {
 4991                id: selection.id,
 4992                start,
 4993                end,
 4994                reversed: selection.reversed,
 4995                goal: selection.goal,
 4996            }
 4997        }
 4998
 4999        self.selections[start_ix..end_ix]
 5000            .iter()
 5001            .chain(
 5002                self.pending_selection
 5003                    .as_ref()
 5004                    .map(|pending| &pending.selection),
 5005            )
 5006            .map(|s| point_selection(s, &buffer))
 5007            .collect()
 5008    }
 5009
 5010    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
 5011    where
 5012        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
 5013    {
 5014        let buffer = self.buffer.read(cx).snapshot(cx);
 5015        let mut selections = self
 5016            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
 5017            .peekable();
 5018
 5019        let mut pending_selection = self.pending_selection::<D>(&buffer);
 5020
 5021        iter::from_fn(move || {
 5022            if let Some(pending) = pending_selection.as_mut() {
 5023                while let Some(next_selection) = selections.peek() {
 5024                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 5025                        let next_selection = selections.next().unwrap();
 5026                        if next_selection.start < pending.start {
 5027                            pending.start = next_selection.start;
 5028                        }
 5029                        if next_selection.end > pending.end {
 5030                            pending.end = next_selection.end;
 5031                        }
 5032                    } else if next_selection.end < pending.start {
 5033                        return selections.next();
 5034                    } else {
 5035                        break;
 5036                    }
 5037                }
 5038
 5039                pending_selection.take()
 5040            } else {
 5041                selections.next()
 5042            }
 5043        })
 5044        .collect()
 5045    }
 5046
 5047    fn resolve_selections<'a, D, I>(
 5048        &self,
 5049        selections: I,
 5050        snapshot: &MultiBufferSnapshot,
 5051    ) -> impl 'a + Iterator<Item = Selection<D>>
 5052    where
 5053        D: TextDimension + Ord + Sub<D, Output = D>,
 5054        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 5055    {
 5056        let (to_summarize, selections) = selections.into_iter().tee();
 5057        let mut summaries = snapshot
 5058            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
 5059            .into_iter();
 5060        selections.map(move |s| Selection {
 5061            id: s.id,
 5062            start: summaries.next().unwrap(),
 5063            end: summaries.next().unwrap(),
 5064            reversed: s.reversed,
 5065            goal: s.goal,
 5066        })
 5067    }
 5068
 5069    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5070        &self,
 5071        snapshot: &MultiBufferSnapshot,
 5072    ) -> Option<Selection<D>> {
 5073        self.pending_selection
 5074            .as_ref()
 5075            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
 5076    }
 5077
 5078    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5079        &self,
 5080        selection: &Selection<Anchor>,
 5081        buffer: &MultiBufferSnapshot,
 5082    ) -> Selection<D> {
 5083        Selection {
 5084            id: selection.id,
 5085            start: selection.start.summary::<D>(&buffer),
 5086            end: selection.end.summary::<D>(&buffer),
 5087            reversed: selection.reversed,
 5088            goal: selection.goal,
 5089        }
 5090    }
 5091
 5092    fn selection_count<'a>(&self) -> usize {
 5093        let mut count = self.selections.len();
 5094        if self.pending_selection.is_some() {
 5095            count += 1;
 5096        }
 5097        count
 5098    }
 5099
 5100    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5101        &self,
 5102        cx: &AppContext,
 5103    ) -> Selection<D> {
 5104        let snapshot = self.buffer.read(cx).read(cx);
 5105        self.selections
 5106            .iter()
 5107            .min_by_key(|s| s.id)
 5108            .map(|selection| self.resolve_selection(selection, &snapshot))
 5109            .or_else(|| self.pending_selection(&snapshot))
 5110            .unwrap()
 5111    }
 5112
 5113    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5114        &self,
 5115        cx: &AppContext,
 5116    ) -> Selection<D> {
 5117        self.resolve_selection(
 5118            self.newest_anchor_selection(),
 5119            &self.buffer.read(cx).read(cx),
 5120        )
 5121    }
 5122
 5123    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
 5124        &self,
 5125        snapshot: &MultiBufferSnapshot,
 5126    ) -> Selection<D> {
 5127        self.resolve_selection(self.newest_anchor_selection(), snapshot)
 5128    }
 5129
 5130    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
 5131        self.pending_selection
 5132            .as_ref()
 5133            .map(|s| &s.selection)
 5134            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
 5135            .unwrap()
 5136    }
 5137
 5138    pub fn update_selections<T>(
 5139        &mut self,
 5140        mut selections: Vec<Selection<T>>,
 5141        autoscroll: Option<Autoscroll>,
 5142        cx: &mut ViewContext<Self>,
 5143    ) where
 5144        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
 5145    {
 5146        let buffer = self.buffer.read(cx).snapshot(cx);
 5147        selections.sort_unstable_by_key(|s| s.start);
 5148
 5149        // Merge overlapping selections.
 5150        let mut i = 1;
 5151        while i < selections.len() {
 5152            if selections[i - 1].end >= selections[i].start {
 5153                let removed = selections.remove(i);
 5154                if removed.start < selections[i - 1].start {
 5155                    selections[i - 1].start = removed.start;
 5156                }
 5157                if removed.end > selections[i - 1].end {
 5158                    selections[i - 1].end = removed.end;
 5159                }
 5160            } else {
 5161                i += 1;
 5162            }
 5163        }
 5164
 5165        if let Some(autoscroll) = autoscroll {
 5166            self.request_autoscroll(autoscroll, cx);
 5167        }
 5168
 5169        self.set_selections(
 5170            Arc::from_iter(selections.into_iter().map(|selection| {
 5171                let end_bias = if selection.end > selection.start {
 5172                    Bias::Left
 5173                } else {
 5174                    Bias::Right
 5175                };
 5176                Selection {
 5177                    id: selection.id,
 5178                    start: buffer.anchor_after(selection.start),
 5179                    end: buffer.anchor_at(selection.end, end_bias),
 5180                    reversed: selection.reversed,
 5181                    goal: selection.goal,
 5182                }
 5183            })),
 5184            None,
 5185            true,
 5186            cx,
 5187        );
 5188    }
 5189
 5190    pub fn set_selections_from_remote(
 5191        &mut self,
 5192        mut selections: Vec<Selection<Anchor>>,
 5193        cx: &mut ViewContext<Self>,
 5194    ) {
 5195        let buffer = self.buffer.read(cx);
 5196        let buffer = buffer.read(cx);
 5197        selections.sort_by(|a, b| {
 5198            a.start
 5199                .cmp(&b.start, &*buffer)
 5200                .then_with(|| b.end.cmp(&a.end, &*buffer))
 5201        });
 5202
 5203        // Merge overlapping selections
 5204        let mut i = 1;
 5205        while i < selections.len() {
 5206            if selections[i - 1]
 5207                .end
 5208                .cmp(&selections[i].start, &*buffer)
 5209                .is_ge()
 5210            {
 5211                let removed = selections.remove(i);
 5212                if removed
 5213                    .start
 5214                    .cmp(&selections[i - 1].start, &*buffer)
 5215                    .is_lt()
 5216                {
 5217                    selections[i - 1].start = removed.start;
 5218                }
 5219                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
 5220                    selections[i - 1].end = removed.end;
 5221                }
 5222            } else {
 5223                i += 1;
 5224            }
 5225        }
 5226
 5227        drop(buffer);
 5228        self.set_selections(selections.into(), None, false, cx);
 5229    }
 5230
 5231    /// Compute new ranges for any selections that were located in excerpts that have
 5232    /// since been removed.
 5233    ///
 5234    /// Returns a `HashMap` indicating which selections whose former head position
 5235    /// was no longer present. The keys of the map are selection ids. The values are
 5236    /// the id of the new excerpt where the head of the selection has been moved.
 5237    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
 5238        let snapshot = self.buffer.read(cx).read(cx);
 5239        let mut selections_with_lost_position = HashMap::default();
 5240
 5241        let mut pending_selection = self.pending_selection.take();
 5242        if let Some(pending) = pending_selection.as_mut() {
 5243            let anchors =
 5244                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
 5245            let (_, start, kept_start) = anchors[0].clone();
 5246            let (_, end, kept_end) = anchors[1].clone();
 5247            let kept_head = if pending.selection.reversed {
 5248                kept_start
 5249            } else {
 5250                kept_end
 5251            };
 5252            if !kept_head {
 5253                selections_with_lost_position.insert(
 5254                    pending.selection.id,
 5255                    pending.selection.head().excerpt_id.clone(),
 5256                );
 5257            }
 5258
 5259            pending.selection.start = start;
 5260            pending.selection.end = end;
 5261        }
 5262
 5263        let anchors_with_status = snapshot.refresh_anchors(
 5264            self.selections
 5265                .iter()
 5266                .flat_map(|selection| [&selection.start, &selection.end]),
 5267        );
 5268        self.selections = anchors_with_status
 5269            .chunks(2)
 5270            .map(|selection_anchors| {
 5271                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
 5272                let (_, end, kept_end) = selection_anchors[1].clone();
 5273                let selection = &self.selections[anchor_ix / 2];
 5274                let kept_head = if selection.reversed {
 5275                    kept_start
 5276                } else {
 5277                    kept_end
 5278                };
 5279                if !kept_head {
 5280                    selections_with_lost_position
 5281                        .insert(selection.id, selection.head().excerpt_id.clone());
 5282                }
 5283
 5284                Selection {
 5285                    id: selection.id,
 5286                    start,
 5287                    end,
 5288                    reversed: selection.reversed,
 5289                    goal: selection.goal,
 5290                }
 5291            })
 5292            .collect();
 5293        drop(snapshot);
 5294
 5295        let new_selections = self.local_selections::<usize>(cx);
 5296        if !new_selections.is_empty() {
 5297            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 5298        }
 5299        self.pending_selection = pending_selection;
 5300
 5301        selections_with_lost_position
 5302    }
 5303
 5304    fn set_selections(
 5305        &mut self,
 5306        selections: Arc<[Selection<Anchor>]>,
 5307        pending_selection: Option<PendingSelection>,
 5308        local: bool,
 5309        cx: &mut ViewContext<Self>,
 5310    ) {
 5311        assert!(
 5312            !selections.is_empty() || pending_selection.is_some(),
 5313            "must have at least one selection"
 5314        );
 5315
 5316        let old_cursor_position = self.newest_anchor_selection().head();
 5317
 5318        self.push_to_selection_history();
 5319        self.selections = selections;
 5320        self.pending_selection = pending_selection;
 5321        if self.focused && self.leader_replica_id.is_none() {
 5322            self.buffer.update(cx, |buffer, cx| {
 5323                buffer.set_active_selections(&self.selections, cx)
 5324            });
 5325        }
 5326
 5327        let display_map = self
 5328            .display_map
 5329            .update(cx, |display_map, cx| display_map.snapshot(cx));
 5330        let buffer = &display_map.buffer_snapshot;
 5331        self.add_selections_state = None;
 5332        self.select_next_state = None;
 5333        self.select_larger_syntax_node_stack.clear();
 5334        self.autoclose_stack.invalidate(&self.selections, &buffer);
 5335        self.snippet_stack.invalidate(&self.selections, &buffer);
 5336        self.take_rename(false, cx);
 5337
 5338        let new_cursor_position = self.newest_anchor_selection().head();
 5339
 5340        self.push_to_nav_history(
 5341            old_cursor_position.clone(),
 5342            Some(new_cursor_position.to_point(&buffer)),
 5343            cx,
 5344        );
 5345
 5346        if local {
 5347            let completion_menu = match self.context_menu.as_mut() {
 5348                Some(ContextMenu::Completions(menu)) => Some(menu),
 5349                _ => {
 5350                    self.context_menu.take();
 5351                    None
 5352                }
 5353            };
 5354
 5355            if let Some(completion_menu) = completion_menu {
 5356                let cursor_position = new_cursor_position.to_offset(&buffer);
 5357                let (word_range, kind) =
 5358                    buffer.surrounding_word(completion_menu.initial_position.clone());
 5359                if kind == Some(CharKind::Word)
 5360                    && word_range.to_inclusive().contains(&cursor_position)
 5361                {
 5362                    let query = Self::completion_query(&buffer, cursor_position);
 5363                    cx.background()
 5364                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 5365                    self.show_completions(&ShowCompletions, cx);
 5366                } else {
 5367                    self.hide_context_menu(cx);
 5368                }
 5369            }
 5370
 5371            if old_cursor_position.to_display_point(&display_map).row()
 5372                != new_cursor_position.to_display_point(&display_map).row()
 5373            {
 5374                self.available_code_actions.take();
 5375            }
 5376            self.refresh_code_actions(cx);
 5377            self.refresh_document_highlights(cx);
 5378        }
 5379
 5380        self.pause_cursor_blinking(cx);
 5381        cx.emit(Event::SelectionsChanged { local });
 5382    }
 5383
 5384    fn push_to_selection_history(&mut self) {
 5385        self.selection_history.push(SelectionHistoryEntry {
 5386            selections: self.selections.clone(),
 5387            select_next_state: self.select_next_state.clone(),
 5388            add_selections_state: self.add_selections_state.clone(),
 5389        });
 5390    }
 5391
 5392    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5393        self.autoscroll_request = Some((autoscroll, true));
 5394        cx.notify();
 5395    }
 5396
 5397    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5398        self.autoscroll_request = Some((autoscroll, false));
 5399        cx.notify();
 5400    }
 5401
 5402    pub fn transact(
 5403        &mut self,
 5404        cx: &mut ViewContext<Self>,
 5405        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5406    ) {
 5407        self.start_transaction_at(Instant::now(), cx);
 5408        update(self, cx);
 5409        self.end_transaction_at(Instant::now(), cx);
 5410    }
 5411
 5412    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5413        self.end_selection(cx);
 5414        if let Some(tx_id) = self
 5415            .buffer
 5416            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5417        {
 5418            self.selection_history
 5419                .insert_transaction(tx_id, self.selections.clone());
 5420        }
 5421    }
 5422
 5423    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5424        if let Some(tx_id) = self
 5425            .buffer
 5426            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5427        {
 5428            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5429                *end_selections = Some(self.selections.clone());
 5430            } else {
 5431                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5432            }
 5433
 5434            cx.emit(Event::Edited);
 5435        }
 5436    }
 5437
 5438    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5439        log::info!("Editor::page_up");
 5440    }
 5441
 5442    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5443        log::info!("Editor::page_down");
 5444    }
 5445
 5446    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5447        let mut fold_ranges = Vec::new();
 5448
 5449        let selections = self.local_selections::<Point>(cx);
 5450        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5451        for selection in selections {
 5452            let range = selection.display_range(&display_map).sorted();
 5453            let buffer_start_row = range.start.to_point(&display_map).row;
 5454
 5455            for row in (0..=range.end.row()).rev() {
 5456                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5457                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5458                    if fold_range.end.row >= buffer_start_row {
 5459                        fold_ranges.push(fold_range);
 5460                        if row <= range.start.row() {
 5461                            break;
 5462                        }
 5463                    }
 5464                }
 5465            }
 5466        }
 5467
 5468        self.fold_ranges(fold_ranges, cx);
 5469    }
 5470
 5471    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5472        let selections = self.local_selections::<Point>(cx);
 5473        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5474        let buffer = &display_map.buffer_snapshot;
 5475        let ranges = selections
 5476            .iter()
 5477            .map(|s| {
 5478                let range = s.display_range(&display_map).sorted();
 5479                let mut start = range.start.to_point(&display_map);
 5480                let mut end = range.end.to_point(&display_map);
 5481                start.column = 0;
 5482                end.column = buffer.line_len(end.row);
 5483                start..end
 5484            })
 5485            .collect::<Vec<_>>();
 5486        self.unfold_ranges(ranges, true, cx);
 5487    }
 5488
 5489    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5490        let max_point = display_map.max_point();
 5491        if display_row >= max_point.row() {
 5492            false
 5493        } else {
 5494            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5495            if is_blank {
 5496                false
 5497            } else {
 5498                for display_row in display_row + 1..=max_point.row() {
 5499                    let (indent, is_blank) = display_map.line_indent(display_row);
 5500                    if !is_blank {
 5501                        return indent > start_indent;
 5502                    }
 5503                }
 5504                false
 5505            }
 5506        }
 5507    }
 5508
 5509    fn foldable_range_for_line(
 5510        &self,
 5511        display_map: &DisplaySnapshot,
 5512        start_row: u32,
 5513    ) -> Range<Point> {
 5514        let max_point = display_map.max_point();
 5515
 5516        let (start_indent, _) = display_map.line_indent(start_row);
 5517        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5518        let mut end = None;
 5519        for row in start_row + 1..=max_point.row() {
 5520            let (indent, is_blank) = display_map.line_indent(row);
 5521            if !is_blank && indent <= start_indent {
 5522                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5523                break;
 5524            }
 5525        }
 5526
 5527        let end = end.unwrap_or(max_point);
 5528        return start.to_point(display_map)..end.to_point(display_map);
 5529    }
 5530
 5531    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5532        let selections = self.local_selections::<Point>(cx);
 5533        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5534        self.fold_ranges(ranges, cx);
 5535    }
 5536
 5537    pub fn fold_ranges<T: ToOffset>(
 5538        &mut self,
 5539        ranges: impl IntoIterator<Item = Range<T>>,
 5540        cx: &mut ViewContext<Self>,
 5541    ) {
 5542        let mut ranges = ranges.into_iter().peekable();
 5543        if ranges.peek().is_some() {
 5544            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5545            self.request_autoscroll(Autoscroll::Fit, cx);
 5546            cx.notify();
 5547        }
 5548    }
 5549
 5550    pub fn unfold_ranges<T: ToOffset>(
 5551        &mut self,
 5552        ranges: impl IntoIterator<Item = Range<T>>,
 5553        inclusive: bool,
 5554        cx: &mut ViewContext<Self>,
 5555    ) {
 5556        let mut ranges = ranges.into_iter().peekable();
 5557        if ranges.peek().is_some() {
 5558            self.display_map
 5559                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5560            self.request_autoscroll(Autoscroll::Fit, cx);
 5561            cx.notify();
 5562        }
 5563    }
 5564
 5565    pub fn insert_blocks(
 5566        &mut self,
 5567        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5568        cx: &mut ViewContext<Self>,
 5569    ) -> Vec<BlockId> {
 5570        let blocks = self
 5571            .display_map
 5572            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5573        self.request_autoscroll(Autoscroll::Fit, cx);
 5574        blocks
 5575    }
 5576
 5577    pub fn replace_blocks(
 5578        &mut self,
 5579        blocks: HashMap<BlockId, RenderBlock>,
 5580        cx: &mut ViewContext<Self>,
 5581    ) {
 5582        self.display_map
 5583            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5584        self.request_autoscroll(Autoscroll::Fit, cx);
 5585    }
 5586
 5587    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5588        self.display_map.update(cx, |display_map, cx| {
 5589            display_map.remove_blocks(block_ids, cx)
 5590        });
 5591    }
 5592
 5593    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5594        self.display_map
 5595            .update(cx, |map, cx| map.snapshot(cx))
 5596            .longest_row()
 5597    }
 5598
 5599    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5600        self.display_map
 5601            .update(cx, |map, cx| map.snapshot(cx))
 5602            .max_point()
 5603    }
 5604
 5605    pub fn text(&self, cx: &AppContext) -> String {
 5606        self.buffer.read(cx).read(cx).text()
 5607    }
 5608
 5609    pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
 5610        self.transact(cx, |this, cx| {
 5611            this.buffer
 5612                .read(cx)
 5613                .as_singleton()
 5614                .expect("you can only call set_text on editors for singleton buffers")
 5615                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5616        });
 5617    }
 5618
 5619    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5620        self.display_map
 5621            .update(cx, |map, cx| map.snapshot(cx))
 5622            .text()
 5623    }
 5624
 5625    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5626        let language_name = self
 5627            .buffer
 5628            .read(cx)
 5629            .as_singleton()
 5630            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5631            .map(|l| l.name());
 5632
 5633        let settings = cx.global::<Settings>();
 5634        let mode = self
 5635            .soft_wrap_mode_override
 5636            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5637        match mode {
 5638            settings::SoftWrap::None => SoftWrap::None,
 5639            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5640            settings::SoftWrap::PreferredLineLength => {
 5641                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5642            }
 5643        }
 5644    }
 5645
 5646    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5647        self.soft_wrap_mode_override = Some(mode);
 5648        cx.notify();
 5649    }
 5650
 5651    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5652        self.display_map
 5653            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5654    }
 5655
 5656    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5657        self.highlighted_rows = rows;
 5658    }
 5659
 5660    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5661        self.highlighted_rows.clone()
 5662    }
 5663
 5664    pub fn highlight_background<T: 'static>(
 5665        &mut self,
 5666        ranges: Vec<Range<Anchor>>,
 5667        color_fetcher: fn(&Theme) -> Color,
 5668        cx: &mut ViewContext<Self>,
 5669    ) {
 5670        self.background_highlights
 5671            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5672        cx.notify();
 5673    }
 5674
 5675    pub fn clear_background_highlights<T: 'static>(
 5676        &mut self,
 5677        cx: &mut ViewContext<Self>,
 5678    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5679        cx.notify();
 5680        self.background_highlights.remove(&TypeId::of::<T>())
 5681    }
 5682
 5683    #[cfg(feature = "test-support")]
 5684    pub fn all_background_highlights(
 5685        &mut self,
 5686        cx: &mut ViewContext<Self>,
 5687    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5688        let snapshot = self.snapshot(cx);
 5689        let buffer = &snapshot.buffer_snapshot;
 5690        let start = buffer.anchor_before(0);
 5691        let end = buffer.anchor_after(buffer.len());
 5692        let theme = cx.global::<Settings>().theme.as_ref();
 5693        self.background_highlights_in_range(start..end, &snapshot, theme)
 5694    }
 5695
 5696    fn document_highlights_for_position<'a>(
 5697        &'a self,
 5698        position: Anchor,
 5699        buffer: &'a MultiBufferSnapshot,
 5700    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5701        let read_highlights = self
 5702            .background_highlights
 5703            .get(&TypeId::of::<DocumentHighlightRead>())
 5704            .map(|h| &h.1);
 5705        let write_highlights = self
 5706            .background_highlights
 5707            .get(&TypeId::of::<DocumentHighlightRead>())
 5708            .map(|h| &h.1);
 5709        let left_position = position.bias_left(buffer);
 5710        let right_position = position.bias_right(buffer);
 5711        read_highlights
 5712            .into_iter()
 5713            .chain(write_highlights)
 5714            .flat_map(move |ranges| {
 5715                let start_ix = match ranges.binary_search_by(|probe| {
 5716                    let cmp = probe.end.cmp(&left_position, &buffer);
 5717                    if cmp.is_ge() {
 5718                        Ordering::Greater
 5719                    } else {
 5720                        Ordering::Less
 5721                    }
 5722                }) {
 5723                    Ok(i) | Err(i) => i,
 5724                };
 5725
 5726                let right_position = right_position.clone();
 5727                ranges[start_ix..]
 5728                    .iter()
 5729                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5730            })
 5731    }
 5732
 5733    pub fn background_highlights_in_range(
 5734        &self,
 5735        search_range: Range<Anchor>,
 5736        display_snapshot: &DisplaySnapshot,
 5737        theme: &Theme,
 5738    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5739        let mut results = Vec::new();
 5740        let buffer = &display_snapshot.buffer_snapshot;
 5741        for (color_fetcher, ranges) in self.background_highlights.values() {
 5742            let color = color_fetcher(theme);
 5743            let start_ix = match ranges.binary_search_by(|probe| {
 5744                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5745                if cmp.is_gt() {
 5746                    Ordering::Greater
 5747                } else {
 5748                    Ordering::Less
 5749                }
 5750            }) {
 5751                Ok(i) | Err(i) => i,
 5752            };
 5753            for range in &ranges[start_ix..] {
 5754                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5755                    break;
 5756                }
 5757                let start = range
 5758                    .start
 5759                    .to_point(buffer)
 5760                    .to_display_point(display_snapshot);
 5761                let end = range
 5762                    .end
 5763                    .to_point(buffer)
 5764                    .to_display_point(display_snapshot);
 5765                results.push((start..end, color))
 5766            }
 5767        }
 5768        results
 5769    }
 5770
 5771    pub fn highlight_text<T: 'static>(
 5772        &mut self,
 5773        ranges: Vec<Range<Anchor>>,
 5774        style: HighlightStyle,
 5775        cx: &mut ViewContext<Self>,
 5776    ) {
 5777        self.display_map.update(cx, |map, _| {
 5778            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5779        });
 5780        cx.notify();
 5781    }
 5782
 5783    pub fn clear_text_highlights<T: 'static>(
 5784        &mut self,
 5785        cx: &mut ViewContext<Self>,
 5786    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5787        cx.notify();
 5788        self.display_map
 5789            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5790    }
 5791
 5792    fn next_blink_epoch(&mut self) -> usize {
 5793        self.blink_epoch += 1;
 5794        self.blink_epoch
 5795    }
 5796
 5797    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5798        if !self.focused {
 5799            return;
 5800        }
 5801
 5802        self.show_local_cursors = true;
 5803        cx.notify();
 5804
 5805        let epoch = self.next_blink_epoch();
 5806        cx.spawn(|this, mut cx| {
 5807            let this = this.downgrade();
 5808            async move {
 5809                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5810                if let Some(this) = this.upgrade(&cx) {
 5811                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5812                }
 5813            }
 5814        })
 5815        .detach();
 5816    }
 5817
 5818    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5819        if epoch == self.blink_epoch {
 5820            self.blinking_paused = false;
 5821            self.blink_cursors(epoch, cx);
 5822        }
 5823    }
 5824
 5825    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5826        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5827            self.show_local_cursors = !self.show_local_cursors;
 5828            cx.notify();
 5829
 5830            let epoch = self.next_blink_epoch();
 5831            cx.spawn(|this, mut cx| {
 5832                let this = this.downgrade();
 5833                async move {
 5834                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5835                    if let Some(this) = this.upgrade(&cx) {
 5836                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5837                    }
 5838                }
 5839            })
 5840            .detach();
 5841        }
 5842    }
 5843
 5844    pub fn show_local_cursors(&self) -> bool {
 5845        self.show_local_cursors && self.focused
 5846    }
 5847
 5848    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5849        cx.notify();
 5850    }
 5851
 5852    fn on_buffer_event(
 5853        &mut self,
 5854        _: ModelHandle<MultiBuffer>,
 5855        event: &language::Event,
 5856        cx: &mut ViewContext<Self>,
 5857    ) {
 5858        match event {
 5859            language::Event::Edited => {
 5860                self.refresh_active_diagnostics(cx);
 5861                self.refresh_code_actions(cx);
 5862                cx.emit(Event::BufferEdited);
 5863            }
 5864            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5865            language::Event::Dirtied => cx.emit(Event::Dirtied),
 5866            language::Event::Saved => cx.emit(Event::Saved),
 5867            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5868            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5869            language::Event::Closed => cx.emit(Event::Closed),
 5870            language::Event::DiagnosticsUpdated => {
 5871                self.refresh_active_diagnostics(cx);
 5872            }
 5873            _ => {}
 5874        }
 5875    }
 5876
 5877    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5878        cx.notify();
 5879    }
 5880
 5881    pub fn set_searchable(&mut self, searchable: bool) {
 5882        self.searchable = searchable;
 5883    }
 5884
 5885    pub fn searchable(&self) -> bool {
 5886        self.searchable
 5887    }
 5888
 5889    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5890        let active_item = workspace.active_item(cx);
 5891        let editor_handle = if let Some(editor) = active_item
 5892            .as_ref()
 5893            .and_then(|item| item.act_as::<Self>(cx))
 5894        {
 5895            editor
 5896        } else {
 5897            cx.propagate_action();
 5898            return;
 5899        };
 5900
 5901        let editor = editor_handle.read(cx);
 5902        let buffer = editor.buffer.read(cx);
 5903        if buffer.is_singleton() {
 5904            cx.propagate_action();
 5905            return;
 5906        }
 5907
 5908        let mut new_selections_by_buffer = HashMap::default();
 5909        for selection in editor.local_selections::<usize>(cx) {
 5910            for (buffer, mut range) in
 5911                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5912            {
 5913                if selection.reversed {
 5914                    mem::swap(&mut range.start, &mut range.end);
 5915                }
 5916                new_selections_by_buffer
 5917                    .entry(buffer)
 5918                    .or_insert(Vec::new())
 5919                    .push(range)
 5920            }
 5921        }
 5922
 5923        editor_handle.update(cx, |editor, cx| {
 5924            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
 5925        });
 5926        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 5927        nav_history.borrow_mut().disable();
 5928
 5929        // We defer the pane interaction because we ourselves are a workspace item
 5930        // and activating a new item causes the pane to call a method on us reentrantly,
 5931        // which panics if we're on the stack.
 5932        cx.defer(move |workspace, cx| {
 5933            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5934                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5935                editor.update(cx, |editor, cx| {
 5936                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
 5937                });
 5938            }
 5939
 5940            nav_history.borrow_mut().enable();
 5941        });
 5942    }
 5943}
 5944
 5945impl EditorSnapshot {
 5946    pub fn is_focused(&self) -> bool {
 5947        self.is_focused
 5948    }
 5949
 5950    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5951        self.placeholder_text.as_ref()
 5952    }
 5953
 5954    pub fn scroll_position(&self) -> Vector2F {
 5955        compute_scroll_position(
 5956            &self.display_snapshot,
 5957            self.scroll_position,
 5958            &self.scroll_top_anchor,
 5959        )
 5960    }
 5961}
 5962
 5963impl Deref for EditorSnapshot {
 5964    type Target = DisplaySnapshot;
 5965
 5966    fn deref(&self) -> &Self::Target {
 5967        &self.display_snapshot
 5968    }
 5969}
 5970
 5971fn compute_scroll_position(
 5972    snapshot: &DisplaySnapshot,
 5973    mut scroll_position: Vector2F,
 5974    scroll_top_anchor: &Anchor,
 5975) -> Vector2F {
 5976    if *scroll_top_anchor != Anchor::min() {
 5977        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5978        scroll_position.set_y(scroll_top + scroll_position.y());
 5979    } else {
 5980        scroll_position.set_y(0.);
 5981    }
 5982    scroll_position
 5983}
 5984
 5985#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5986pub enum Event {
 5987    Activate,
 5988    BufferEdited,
 5989    Edited,
 5990    Reparsed,
 5991    Blurred,
 5992    Dirtied,
 5993    Saved,
 5994    TitleChanged,
 5995    SelectionsChanged { local: bool },
 5996    ScrollPositionChanged { local: bool },
 5997    Closed,
 5998}
 5999
 6000pub struct EditorFocused(pub ViewHandle<Editor>);
 6001pub struct EditorBlurred(pub ViewHandle<Editor>);
 6002pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6003
 6004impl Entity for Editor {
 6005    type Event = Event;
 6006
 6007    fn release(&mut self, cx: &mut MutableAppContext) {
 6008        cx.emit_global(EditorReleased(self.handle.clone()));
 6009    }
 6010}
 6011
 6012impl View for Editor {
 6013    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6014        let style = self.style(cx);
 6015        self.display_map.update(cx, |map, cx| {
 6016            map.set_font(style.text.font_id, style.text.font_size, cx)
 6017        });
 6018        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 6019    }
 6020
 6021    fn ui_name() -> &'static str {
 6022        "Editor"
 6023    }
 6024
 6025    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 6026        let focused_event = EditorFocused(cx.handle());
 6027        cx.emit_global(focused_event);
 6028        if let Some(rename) = self.pending_rename.as_ref() {
 6029            cx.focus(&rename.editor);
 6030        } else {
 6031            self.focused = true;
 6032            self.blink_cursors(self.blink_epoch, cx);
 6033            self.buffer.update(cx, |buffer, cx| {
 6034                buffer.finalize_last_transaction(cx);
 6035                if self.leader_replica_id.is_none() {
 6036                    buffer.set_active_selections(&self.selections, cx);
 6037                }
 6038            });
 6039        }
 6040    }
 6041
 6042    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6043        let blurred_event = EditorBlurred(cx.handle());
 6044        cx.emit_global(blurred_event);
 6045        self.focused = false;
 6046        self.buffer
 6047            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6048        self.hide_context_menu(cx);
 6049        cx.emit(Event::Blurred);
 6050        cx.notify();
 6051    }
 6052
 6053    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6054        let mut context = Self::default_keymap_context();
 6055        let mode = match self.mode {
 6056            EditorMode::SingleLine => "single_line",
 6057            EditorMode::AutoHeight { .. } => "auto_height",
 6058            EditorMode::Full => "full",
 6059        };
 6060        context.map.insert("mode".into(), mode.into());
 6061        if self.pending_rename.is_some() {
 6062            context.set.insert("renaming".into());
 6063        }
 6064        match self.context_menu.as_ref() {
 6065            Some(ContextMenu::Completions(_)) => {
 6066                context.set.insert("showing_completions".into());
 6067            }
 6068            Some(ContextMenu::CodeActions(_)) => {
 6069                context.set.insert("showing_code_actions".into());
 6070            }
 6071            None => {}
 6072        }
 6073
 6074        for layer in self.keymap_context_layers.values() {
 6075            context.extend(layer);
 6076        }
 6077
 6078        context
 6079    }
 6080}
 6081
 6082fn build_style(
 6083    settings: &Settings,
 6084    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6085    override_text_style: Option<&OverrideTextStyle>,
 6086    cx: &AppContext,
 6087) -> EditorStyle {
 6088    let font_cache = cx.font_cache();
 6089
 6090    let mut theme = settings.theme.editor.clone();
 6091    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6092        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6093        theme.text_color = field_editor_theme.text.color;
 6094        theme.selection = field_editor_theme.selection;
 6095        theme.background = field_editor_theme
 6096            .container
 6097            .background_color
 6098            .unwrap_or_default();
 6099        EditorStyle {
 6100            text: field_editor_theme.text,
 6101            placeholder_text: field_editor_theme.placeholder_text,
 6102            theme,
 6103        }
 6104    } else {
 6105        let font_family_id = settings.buffer_font_family;
 6106        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6107        let font_properties = Default::default();
 6108        let font_id = font_cache
 6109            .select_font(font_family_id, &font_properties)
 6110            .unwrap();
 6111        let font_size = settings.buffer_font_size;
 6112        EditorStyle {
 6113            text: TextStyle {
 6114                color: settings.theme.editor.text_color,
 6115                font_family_name,
 6116                font_family_id,
 6117                font_id,
 6118                font_size,
 6119                font_properties,
 6120                underline: Default::default(),
 6121            },
 6122            placeholder_text: None,
 6123            theme,
 6124        }
 6125    };
 6126
 6127    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6128        if let Some(highlighted) = style
 6129            .text
 6130            .clone()
 6131            .highlight(highlight_style, font_cache)
 6132            .log_err()
 6133        {
 6134            style.text = highlighted;
 6135        }
 6136    }
 6137
 6138    style
 6139}
 6140
 6141trait SelectionExt {
 6142    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6143    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6144    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6145    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6146        -> Range<u32>;
 6147}
 6148
 6149impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6150    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6151        let start = self.start.to_point(buffer);
 6152        let end = self.end.to_point(buffer);
 6153        if self.reversed {
 6154            end..start
 6155        } else {
 6156            start..end
 6157        }
 6158    }
 6159
 6160    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6161        let start = self.start.to_offset(buffer);
 6162        let end = self.end.to_offset(buffer);
 6163        if self.reversed {
 6164            end..start
 6165        } else {
 6166            start..end
 6167        }
 6168    }
 6169
 6170    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6171        let start = self
 6172            .start
 6173            .to_point(&map.buffer_snapshot)
 6174            .to_display_point(map);
 6175        let end = self
 6176            .end
 6177            .to_point(&map.buffer_snapshot)
 6178            .to_display_point(map);
 6179        if self.reversed {
 6180            end..start
 6181        } else {
 6182            start..end
 6183        }
 6184    }
 6185
 6186    fn spanned_rows(
 6187        &self,
 6188        include_end_if_at_line_start: bool,
 6189        map: &DisplaySnapshot,
 6190    ) -> Range<u32> {
 6191        let start = self.start.to_point(&map.buffer_snapshot);
 6192        let mut end = self.end.to_point(&map.buffer_snapshot);
 6193        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6194            end.row -= 1;
 6195        }
 6196
 6197        let buffer_start = map.prev_line_boundary(start).0;
 6198        let buffer_end = map.next_line_boundary(end).0;
 6199        buffer_start.row..buffer_end.row + 1
 6200    }
 6201}
 6202
 6203impl<T: InvalidationRegion> InvalidationStack<T> {
 6204    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6205    where
 6206        S: Clone + ToOffset,
 6207    {
 6208        while let Some(region) = self.last() {
 6209            let all_selections_inside_invalidation_ranges =
 6210                if selections.len() == region.ranges().len() {
 6211                    selections
 6212                        .iter()
 6213                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6214                        .all(|(selection, invalidation_range)| {
 6215                            let head = selection.head().to_offset(&buffer);
 6216                            invalidation_range.start <= head && invalidation_range.end >= head
 6217                        })
 6218                } else {
 6219                    false
 6220                };
 6221
 6222            if all_selections_inside_invalidation_ranges {
 6223                break;
 6224            } else {
 6225                self.pop();
 6226            }
 6227        }
 6228    }
 6229}
 6230
 6231impl<T> Default for InvalidationStack<T> {
 6232    fn default() -> Self {
 6233        Self(Default::default())
 6234    }
 6235}
 6236
 6237impl<T> Deref for InvalidationStack<T> {
 6238    type Target = Vec<T>;
 6239
 6240    fn deref(&self) -> &Self::Target {
 6241        &self.0
 6242    }
 6243}
 6244
 6245impl<T> DerefMut for InvalidationStack<T> {
 6246    fn deref_mut(&mut self) -> &mut Self::Target {
 6247        &mut self.0
 6248    }
 6249}
 6250
 6251impl InvalidationRegion for BracketPairState {
 6252    fn ranges(&self) -> &[Range<Anchor>] {
 6253        &self.ranges
 6254    }
 6255}
 6256
 6257impl InvalidationRegion for SnippetState {
 6258    fn ranges(&self) -> &[Range<Anchor>] {
 6259        &self.ranges[self.active_index]
 6260    }
 6261}
 6262
 6263impl Deref for EditorStyle {
 6264    type Target = theme::Editor;
 6265
 6266    fn deref(&self) -> &Self::Target {
 6267        &self.theme
 6268    }
 6269}
 6270
 6271pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6272    let mut highlighted_lines = Vec::new();
 6273    for line in diagnostic.message.lines() {
 6274        highlighted_lines.push(highlight_diagnostic_message(line));
 6275    }
 6276
 6277    Arc::new(move |cx: &BlockContext| {
 6278        let settings = cx.global::<Settings>();
 6279        let theme = &settings.theme.editor;
 6280        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6281        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6282        Flex::column()
 6283            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6284                Label::new(
 6285                    line.clone(),
 6286                    style.message.clone().with_font_size(font_size),
 6287                )
 6288                .with_highlights(highlights.clone())
 6289                .contained()
 6290                .with_margin_left(cx.anchor_x)
 6291                .boxed()
 6292            }))
 6293            .aligned()
 6294            .left()
 6295            .boxed()
 6296    })
 6297}
 6298
 6299pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6300    let mut message_without_backticks = String::new();
 6301    let mut prev_offset = 0;
 6302    let mut inside_block = false;
 6303    let mut highlights = Vec::new();
 6304    for (match_ix, (offset, _)) in message
 6305        .match_indices('`')
 6306        .chain([(message.len(), "")])
 6307        .enumerate()
 6308    {
 6309        message_without_backticks.push_str(&message[prev_offset..offset]);
 6310        if inside_block {
 6311            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6312        }
 6313
 6314        inside_block = !inside_block;
 6315        prev_offset = offset + 1;
 6316    }
 6317
 6318    (message_without_backticks, highlights)
 6319}
 6320
 6321pub fn diagnostic_style(
 6322    severity: DiagnosticSeverity,
 6323    valid: bool,
 6324    theme: &theme::Editor,
 6325) -> DiagnosticStyle {
 6326    match (severity, valid) {
 6327        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6328        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6329        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6330        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6331        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6332        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6333        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6334        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6335        _ => theme.invalid_hint_diagnostic.clone(),
 6336    }
 6337}
 6338
 6339pub fn combine_syntax_and_fuzzy_match_highlights(
 6340    text: &str,
 6341    default_style: HighlightStyle,
 6342    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6343    match_indices: &[usize],
 6344) -> Vec<(Range<usize>, HighlightStyle)> {
 6345    let mut result = Vec::new();
 6346    let mut match_indices = match_indices.iter().copied().peekable();
 6347
 6348    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6349    {
 6350        syntax_highlight.weight = None;
 6351
 6352        // Add highlights for any fuzzy match characters before the next
 6353        // syntax highlight range.
 6354        while let Some(&match_index) = match_indices.peek() {
 6355            if match_index >= range.start {
 6356                break;
 6357            }
 6358            match_indices.next();
 6359            let end_index = char_ix_after(match_index, text);
 6360            let mut match_style = default_style;
 6361            match_style.weight = Some(fonts::Weight::BOLD);
 6362            result.push((match_index..end_index, match_style));
 6363        }
 6364
 6365        if range.start == usize::MAX {
 6366            break;
 6367        }
 6368
 6369        // Add highlights for any fuzzy match characters within the
 6370        // syntax highlight range.
 6371        let mut offset = range.start;
 6372        while let Some(&match_index) = match_indices.peek() {
 6373            if match_index >= range.end {
 6374                break;
 6375            }
 6376
 6377            match_indices.next();
 6378            if match_index > offset {
 6379                result.push((offset..match_index, syntax_highlight));
 6380            }
 6381
 6382            let mut end_index = char_ix_after(match_index, text);
 6383            while let Some(&next_match_index) = match_indices.peek() {
 6384                if next_match_index == end_index && next_match_index < range.end {
 6385                    end_index = char_ix_after(next_match_index, text);
 6386                    match_indices.next();
 6387                } else {
 6388                    break;
 6389                }
 6390            }
 6391
 6392            let mut match_style = syntax_highlight;
 6393            match_style.weight = Some(fonts::Weight::BOLD);
 6394            result.push((match_index..end_index, match_style));
 6395            offset = end_index;
 6396        }
 6397
 6398        if offset < range.end {
 6399            result.push((offset..range.end, syntax_highlight));
 6400        }
 6401    }
 6402
 6403    fn char_ix_after(ix: usize, text: &str) -> usize {
 6404        ix + text[ix..].chars().next().unwrap().len_utf8()
 6405    }
 6406
 6407    result
 6408}
 6409
 6410pub fn styled_runs_for_code_label<'a>(
 6411    label: &'a CodeLabel,
 6412    syntax_theme: &'a theme::SyntaxTheme,
 6413) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6414    let fade_out = HighlightStyle {
 6415        fade_out: Some(0.35),
 6416        ..Default::default()
 6417    };
 6418
 6419    let mut prev_end = label.filter_range.end;
 6420    label
 6421        .runs
 6422        .iter()
 6423        .enumerate()
 6424        .flat_map(move |(ix, (range, highlight_id))| {
 6425            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6426                style
 6427            } else {
 6428                return Default::default();
 6429            };
 6430            let mut muted_style = style.clone();
 6431            muted_style.highlight(fade_out);
 6432
 6433            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6434            if range.start >= label.filter_range.end {
 6435                if range.start > prev_end {
 6436                    runs.push((prev_end..range.start, fade_out));
 6437                }
 6438                runs.push((range.clone(), muted_style));
 6439            } else if range.end <= label.filter_range.end {
 6440                runs.push((range.clone(), style));
 6441            } else {
 6442                runs.push((range.start..label.filter_range.end, style));
 6443                runs.push((label.filter_range.end..range.end, muted_style));
 6444            }
 6445            prev_end = cmp::max(prev_end, range.end);
 6446
 6447            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6448                runs.push((prev_end..label.text.len(), fade_out));
 6449            }
 6450
 6451            runs
 6452        })
 6453}
 6454
 6455#[cfg(test)]
 6456mod tests {
 6457    use crate::test::{assert_text_with_selections, select_ranges};
 6458
 6459    use super::*;
 6460    use gpui::{
 6461        geometry::rect::RectF,
 6462        platform::{WindowBounds, WindowOptions},
 6463    };
 6464    use indoc::indoc;
 6465    use language::{FakeLspAdapter, LanguageConfig};
 6466    use lsp::FakeLanguageServer;
 6467    use project::FakeFs;
 6468    use settings::LanguageOverride;
 6469    use smol::stream::StreamExt;
 6470    use std::{cell::RefCell, rc::Rc, time::Instant};
 6471    use text::Point;
 6472    use unindent::Unindent;
 6473    use util::test::{marked_text_by, marked_text_ranges, sample_text};
 6474    use workspace::{FollowableItem, ItemHandle};
 6475
 6476    #[gpui::test]
 6477    fn test_edit_events(cx: &mut MutableAppContext) {
 6478        cx.set_global(Settings::test(cx));
 6479        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6480
 6481        let events = Rc::new(RefCell::new(Vec::new()));
 6482        let (_, editor1) = cx.add_window(Default::default(), {
 6483            let events = events.clone();
 6484            |cx| {
 6485                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6486                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6487                        events.borrow_mut().push(("editor1", *event));
 6488                    }
 6489                })
 6490                .detach();
 6491                Editor::for_buffer(buffer.clone(), None, cx)
 6492            }
 6493        });
 6494        let (_, editor2) = cx.add_window(Default::default(), {
 6495            let events = events.clone();
 6496            |cx| {
 6497                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6498                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6499                        events.borrow_mut().push(("editor2", *event));
 6500                    }
 6501                })
 6502                .detach();
 6503                Editor::for_buffer(buffer.clone(), None, cx)
 6504            }
 6505        });
 6506        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6507
 6508        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6509        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6510        assert_eq!(
 6511            mem::take(&mut *events.borrow_mut()),
 6512            [
 6513                ("editor1", Event::Edited),
 6514                ("editor1", Event::BufferEdited),
 6515                ("editor2", Event::BufferEdited),
 6516                ("editor1", Event::Dirtied),
 6517                ("editor2", Event::Dirtied)
 6518            ]
 6519        );
 6520
 6521        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6522        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6523        assert_eq!(
 6524            mem::take(&mut *events.borrow_mut()),
 6525            [
 6526                ("editor2", Event::Edited),
 6527                ("editor1", Event::BufferEdited),
 6528                ("editor2", Event::BufferEdited),
 6529            ]
 6530        );
 6531
 6532        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6533        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6534        assert_eq!(
 6535            mem::take(&mut *events.borrow_mut()),
 6536            [
 6537                ("editor1", Event::Edited),
 6538                ("editor1", Event::BufferEdited),
 6539                ("editor2", Event::BufferEdited),
 6540            ]
 6541        );
 6542
 6543        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6544        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6545        assert_eq!(
 6546            mem::take(&mut *events.borrow_mut()),
 6547            [
 6548                ("editor1", Event::Edited),
 6549                ("editor1", Event::BufferEdited),
 6550                ("editor2", Event::BufferEdited),
 6551            ]
 6552        );
 6553
 6554        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6555        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6556        assert_eq!(
 6557            mem::take(&mut *events.borrow_mut()),
 6558            [
 6559                ("editor2", Event::Edited),
 6560                ("editor1", Event::BufferEdited),
 6561                ("editor2", Event::BufferEdited),
 6562            ]
 6563        );
 6564
 6565        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6566        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6567        assert_eq!(
 6568            mem::take(&mut *events.borrow_mut()),
 6569            [
 6570                ("editor2", Event::Edited),
 6571                ("editor1", Event::BufferEdited),
 6572                ("editor2", Event::BufferEdited),
 6573            ]
 6574        );
 6575
 6576        // No event is emitted when the mutation is a no-op.
 6577        editor2.update(cx, |editor, cx| {
 6578            editor.select_ranges([0..0], None, cx);
 6579            editor.backspace(&Backspace, cx);
 6580        });
 6581        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6582    }
 6583
 6584    #[gpui::test]
 6585    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6586        cx.set_global(Settings::test(cx));
 6587        let mut now = Instant::now();
 6588        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6589        let group_interval = buffer.read(cx).transaction_group_interval();
 6590        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6591        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6592
 6593        editor.update(cx, |editor, cx| {
 6594            editor.start_transaction_at(now, cx);
 6595            editor.select_ranges([2..4], None, cx);
 6596            editor.insert("cd", cx);
 6597            editor.end_transaction_at(now, cx);
 6598            assert_eq!(editor.text(cx), "12cd56");
 6599            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 6600
 6601            editor.start_transaction_at(now, cx);
 6602            editor.select_ranges([4..5], None, cx);
 6603            editor.insert("e", cx);
 6604            editor.end_transaction_at(now, cx);
 6605            assert_eq!(editor.text(cx), "12cde6");
 6606            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6607
 6608            now += group_interval + Duration::from_millis(1);
 6609            editor.select_ranges([2..2], None, cx);
 6610
 6611            // Simulate an edit in another editor
 6612            buffer.update(cx, |buffer, cx| {
 6613                buffer.start_transaction_at(now, cx);
 6614                buffer.edit([0..1], "a", cx);
 6615                buffer.edit([1..1], "b", cx);
 6616                buffer.end_transaction_at(now, cx);
 6617            });
 6618
 6619            assert_eq!(editor.text(cx), "ab2cde6");
 6620            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
 6621
 6622            // Last transaction happened past the group interval in a different editor.
 6623            // Undo it individually and don't restore selections.
 6624            editor.undo(&Undo, cx);
 6625            assert_eq!(editor.text(cx), "12cde6");
 6626            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
 6627
 6628            // First two transactions happened within the group interval in this editor.
 6629            // Undo them together and restore selections.
 6630            editor.undo(&Undo, cx);
 6631            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6632            assert_eq!(editor.text(cx), "123456");
 6633            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
 6634
 6635            // Redo the first two transactions together.
 6636            editor.redo(&Redo, cx);
 6637            assert_eq!(editor.text(cx), "12cde6");
 6638            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6639
 6640            // Redo the last transaction on its own.
 6641            editor.redo(&Redo, cx);
 6642            assert_eq!(editor.text(cx), "ab2cde6");
 6643            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
 6644
 6645            // Test empty transactions.
 6646            editor.start_transaction_at(now, cx);
 6647            editor.end_transaction_at(now, cx);
 6648            editor.undo(&Undo, cx);
 6649            assert_eq!(editor.text(cx), "12cde6");
 6650        });
 6651    }
 6652
 6653    #[gpui::test]
 6654    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6655        cx.set_global(Settings::test(cx));
 6656
 6657        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6658        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6659        editor.update(cx, |view, cx| {
 6660            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6661        });
 6662        assert_eq!(
 6663            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6664            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6665        );
 6666
 6667        editor.update(cx, |view, cx| {
 6668            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6669        });
 6670
 6671        assert_eq!(
 6672            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6673            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6674        );
 6675
 6676        editor.update(cx, |view, cx| {
 6677            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6678        });
 6679
 6680        assert_eq!(
 6681            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6682            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6683        );
 6684
 6685        editor.update(cx, |view, cx| {
 6686            view.end_selection(cx);
 6687            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6688        });
 6689
 6690        assert_eq!(
 6691            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6692            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6693        );
 6694
 6695        editor.update(cx, |view, cx| {
 6696            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6697            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6698        });
 6699
 6700        assert_eq!(
 6701            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6702            [
 6703                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6704                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6705            ]
 6706        );
 6707
 6708        editor.update(cx, |view, cx| {
 6709            view.end_selection(cx);
 6710        });
 6711
 6712        assert_eq!(
 6713            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6714            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6715        );
 6716    }
 6717
 6718    #[gpui::test]
 6719    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6720        cx.set_global(Settings::test(cx));
 6721        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6722        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6723
 6724        view.update(cx, |view, cx| {
 6725            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6726            assert_eq!(
 6727                view.selected_display_ranges(cx),
 6728                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6729            );
 6730        });
 6731
 6732        view.update(cx, |view, cx| {
 6733            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6734            assert_eq!(
 6735                view.selected_display_ranges(cx),
 6736                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6737            );
 6738        });
 6739
 6740        view.update(cx, |view, cx| {
 6741            view.cancel(&Cancel, cx);
 6742            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6743            assert_eq!(
 6744                view.selected_display_ranges(cx),
 6745                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6746            );
 6747        });
 6748    }
 6749
 6750    #[gpui::test]
 6751    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6752        cx.set_global(Settings::test(cx));
 6753        use workspace::Item;
 6754        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6755        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6756
 6757        cx.add_window(Default::default(), |cx| {
 6758            let mut editor = build_editor(buffer.clone(), cx);
 6759            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6760
 6761            // Move the cursor a small distance.
 6762            // Nothing is added to the navigation history.
 6763            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
 6764            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
 6765            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6766
 6767            // Move the cursor a large distance.
 6768            // The history can jump back to the previous position.
 6769            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
 6770            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6771            editor.navigate(nav_entry.data.unwrap(), cx);
 6772            assert_eq!(nav_entry.item.id(), cx.view_id());
 6773            assert_eq!(
 6774                editor.selected_display_ranges(cx),
 6775                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6776            );
 6777            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6778
 6779            // Move the cursor a small distance via the mouse.
 6780            // Nothing is added to the navigation history.
 6781            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6782            editor.end_selection(cx);
 6783            assert_eq!(
 6784                editor.selected_display_ranges(cx),
 6785                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6786            );
 6787            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6788
 6789            // Move the cursor a large distance via the mouse.
 6790            // The history can jump back to the previous position.
 6791            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6792            editor.end_selection(cx);
 6793            assert_eq!(
 6794                editor.selected_display_ranges(cx),
 6795                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6796            );
 6797            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6798            editor.navigate(nav_entry.data.unwrap(), cx);
 6799            assert_eq!(nav_entry.item.id(), cx.view_id());
 6800            assert_eq!(
 6801                editor.selected_display_ranges(cx),
 6802                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6803            );
 6804            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6805
 6806            // Set scroll position to check later
 6807            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6808            let original_scroll_position = editor.scroll_position;
 6809            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6810
 6811            // Jump to the end of the document and adjust scroll
 6812            editor.move_to_end(&MoveToEnd, cx);
 6813            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6814            assert_ne!(editor.scroll_position, original_scroll_position);
 6815            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6816
 6817            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6818            editor.navigate(nav_entry.data.unwrap(), cx);
 6819            assert_eq!(editor.scroll_position, original_scroll_position);
 6820            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6821
 6822            editor
 6823        });
 6824    }
 6825
 6826    #[gpui::test]
 6827    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6828        cx.set_global(Settings::test(cx));
 6829        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6830        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6831
 6832        view.update(cx, |view, cx| {
 6833            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6834            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6835            view.end_selection(cx);
 6836
 6837            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6838            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6839            view.end_selection(cx);
 6840            assert_eq!(
 6841                view.selected_display_ranges(cx),
 6842                [
 6843                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6844                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6845                ]
 6846            );
 6847        });
 6848
 6849        view.update(cx, |view, cx| {
 6850            view.cancel(&Cancel, cx);
 6851            assert_eq!(
 6852                view.selected_display_ranges(cx),
 6853                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6854            );
 6855        });
 6856
 6857        view.update(cx, |view, cx| {
 6858            view.cancel(&Cancel, cx);
 6859            assert_eq!(
 6860                view.selected_display_ranges(cx),
 6861                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6862            );
 6863        });
 6864    }
 6865
 6866    #[gpui::test]
 6867    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6868        cx.set_global(Settings::test(cx));
 6869        let buffer = MultiBuffer::build_simple(
 6870            &"
 6871                impl Foo {
 6872                    // Hello!
 6873
 6874                    fn a() {
 6875                        1
 6876                    }
 6877
 6878                    fn b() {
 6879                        2
 6880                    }
 6881
 6882                    fn c() {
 6883                        3
 6884                    }
 6885                }
 6886            "
 6887            .unindent(),
 6888            cx,
 6889        );
 6890        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6891
 6892        view.update(cx, |view, cx| {
 6893            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 6894            view.fold(&Fold, cx);
 6895            assert_eq!(
 6896                view.display_text(cx),
 6897                "
 6898                    impl Foo {
 6899                        // Hello!
 6900
 6901                        fn a() {
 6902                            1
 6903                        }
 6904
 6905                        fn b() {…
 6906                        }
 6907
 6908                        fn c() {…
 6909                        }
 6910                    }
 6911                "
 6912                .unindent(),
 6913            );
 6914
 6915            view.fold(&Fold, cx);
 6916            assert_eq!(
 6917                view.display_text(cx),
 6918                "
 6919                    impl Foo {…
 6920                    }
 6921                "
 6922                .unindent(),
 6923            );
 6924
 6925            view.unfold_lines(&UnfoldLines, cx);
 6926            assert_eq!(
 6927                view.display_text(cx),
 6928                "
 6929                    impl Foo {
 6930                        // Hello!
 6931
 6932                        fn a() {
 6933                            1
 6934                        }
 6935
 6936                        fn b() {…
 6937                        }
 6938
 6939                        fn c() {…
 6940                        }
 6941                    }
 6942                "
 6943                .unindent(),
 6944            );
 6945
 6946            view.unfold_lines(&UnfoldLines, cx);
 6947            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6948        });
 6949    }
 6950
 6951    #[gpui::test]
 6952    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6953        cx.set_global(Settings::test(cx));
 6954        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6955        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6956
 6957        buffer.update(cx, |buffer, cx| {
 6958            buffer.edit(
 6959                vec![
 6960                    Point::new(1, 0)..Point::new(1, 0),
 6961                    Point::new(1, 1)..Point::new(1, 1),
 6962                ],
 6963                "\t",
 6964                cx,
 6965            );
 6966        });
 6967
 6968        view.update(cx, |view, cx| {
 6969            assert_eq!(
 6970                view.selected_display_ranges(cx),
 6971                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6972            );
 6973
 6974            view.move_down(&MoveDown, cx);
 6975            assert_eq!(
 6976                view.selected_display_ranges(cx),
 6977                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6978            );
 6979
 6980            view.move_right(&MoveRight, cx);
 6981            assert_eq!(
 6982                view.selected_display_ranges(cx),
 6983                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6984            );
 6985
 6986            view.move_left(&MoveLeft, cx);
 6987            assert_eq!(
 6988                view.selected_display_ranges(cx),
 6989                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6990            );
 6991
 6992            view.move_up(&MoveUp, cx);
 6993            assert_eq!(
 6994                view.selected_display_ranges(cx),
 6995                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6996            );
 6997
 6998            view.move_to_end(&MoveToEnd, cx);
 6999            assert_eq!(
 7000                view.selected_display_ranges(cx),
 7001                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7002            );
 7003
 7004            view.move_to_beginning(&MoveToBeginning, cx);
 7005            assert_eq!(
 7006                view.selected_display_ranges(cx),
 7007                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7008            );
 7009
 7010            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7011            view.select_to_beginning(&SelectToBeginning, cx);
 7012            assert_eq!(
 7013                view.selected_display_ranges(cx),
 7014                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7015            );
 7016
 7017            view.select_to_end(&SelectToEnd, cx);
 7018            assert_eq!(
 7019                view.selected_display_ranges(cx),
 7020                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7021            );
 7022        });
 7023    }
 7024
 7025    #[gpui::test]
 7026    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7027        cx.set_global(Settings::test(cx));
 7028        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7029        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7030
 7031        assert_eq!('ⓐ'.len_utf8(), 3);
 7032        assert_eq!('α'.len_utf8(), 2);
 7033
 7034        view.update(cx, |view, cx| {
 7035            view.fold_ranges(
 7036                vec![
 7037                    Point::new(0, 6)..Point::new(0, 12),
 7038                    Point::new(1, 2)..Point::new(1, 4),
 7039                    Point::new(2, 4)..Point::new(2, 8),
 7040                ],
 7041                cx,
 7042            );
 7043            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7044
 7045            view.move_right(&MoveRight, cx);
 7046            assert_eq!(
 7047                view.selected_display_ranges(cx),
 7048                &[empty_range(0, "".len())]
 7049            );
 7050            view.move_right(&MoveRight, cx);
 7051            assert_eq!(
 7052                view.selected_display_ranges(cx),
 7053                &[empty_range(0, "ⓐⓑ".len())]
 7054            );
 7055            view.move_right(&MoveRight, cx);
 7056            assert_eq!(
 7057                view.selected_display_ranges(cx),
 7058                &[empty_range(0, "ⓐⓑ…".len())]
 7059            );
 7060
 7061            view.move_down(&MoveDown, cx);
 7062            assert_eq!(
 7063                view.selected_display_ranges(cx),
 7064                &[empty_range(1, "ab…".len())]
 7065            );
 7066            view.move_left(&MoveLeft, cx);
 7067            assert_eq!(
 7068                view.selected_display_ranges(cx),
 7069                &[empty_range(1, "ab".len())]
 7070            );
 7071            view.move_left(&MoveLeft, cx);
 7072            assert_eq!(
 7073                view.selected_display_ranges(cx),
 7074                &[empty_range(1, "a".len())]
 7075            );
 7076
 7077            view.move_down(&MoveDown, cx);
 7078            assert_eq!(
 7079                view.selected_display_ranges(cx),
 7080                &[empty_range(2, "α".len())]
 7081            );
 7082            view.move_right(&MoveRight, cx);
 7083            assert_eq!(
 7084                view.selected_display_ranges(cx),
 7085                &[empty_range(2, "αβ".len())]
 7086            );
 7087            view.move_right(&MoveRight, cx);
 7088            assert_eq!(
 7089                view.selected_display_ranges(cx),
 7090                &[empty_range(2, "αβ…".len())]
 7091            );
 7092            view.move_right(&MoveRight, cx);
 7093            assert_eq!(
 7094                view.selected_display_ranges(cx),
 7095                &[empty_range(2, "αβ…ε".len())]
 7096            );
 7097
 7098            view.move_up(&MoveUp, cx);
 7099            assert_eq!(
 7100                view.selected_display_ranges(cx),
 7101                &[empty_range(1, "ab…e".len())]
 7102            );
 7103            view.move_up(&MoveUp, cx);
 7104            assert_eq!(
 7105                view.selected_display_ranges(cx),
 7106                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7107            );
 7108            view.move_left(&MoveLeft, cx);
 7109            assert_eq!(
 7110                view.selected_display_ranges(cx),
 7111                &[empty_range(0, "ⓐⓑ…".len())]
 7112            );
 7113            view.move_left(&MoveLeft, cx);
 7114            assert_eq!(
 7115                view.selected_display_ranges(cx),
 7116                &[empty_range(0, "ⓐⓑ".len())]
 7117            );
 7118            view.move_left(&MoveLeft, cx);
 7119            assert_eq!(
 7120                view.selected_display_ranges(cx),
 7121                &[empty_range(0, "".len())]
 7122            );
 7123        });
 7124    }
 7125
 7126    #[gpui::test]
 7127    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7128        cx.set_global(Settings::test(cx));
 7129        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7130        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7131        view.update(cx, |view, cx| {
 7132            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7133            view.move_down(&MoveDown, cx);
 7134            assert_eq!(
 7135                view.selected_display_ranges(cx),
 7136                &[empty_range(1, "abcd".len())]
 7137            );
 7138
 7139            view.move_down(&MoveDown, cx);
 7140            assert_eq!(
 7141                view.selected_display_ranges(cx),
 7142                &[empty_range(2, "αβγ".len())]
 7143            );
 7144
 7145            view.move_down(&MoveDown, cx);
 7146            assert_eq!(
 7147                view.selected_display_ranges(cx),
 7148                &[empty_range(3, "abcd".len())]
 7149            );
 7150
 7151            view.move_down(&MoveDown, cx);
 7152            assert_eq!(
 7153                view.selected_display_ranges(cx),
 7154                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7155            );
 7156
 7157            view.move_up(&MoveUp, cx);
 7158            assert_eq!(
 7159                view.selected_display_ranges(cx),
 7160                &[empty_range(3, "abcd".len())]
 7161            );
 7162
 7163            view.move_up(&MoveUp, cx);
 7164            assert_eq!(
 7165                view.selected_display_ranges(cx),
 7166                &[empty_range(2, "αβγ".len())]
 7167            );
 7168        });
 7169    }
 7170
 7171    #[gpui::test]
 7172    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7173        cx.set_global(Settings::test(cx));
 7174        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7175        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7176        view.update(cx, |view, cx| {
 7177            view.select_display_ranges(
 7178                &[
 7179                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7180                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7181                ],
 7182                cx,
 7183            );
 7184        });
 7185
 7186        view.update(cx, |view, cx| {
 7187            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7188            assert_eq!(
 7189                view.selected_display_ranges(cx),
 7190                &[
 7191                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7192                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7193                ]
 7194            );
 7195        });
 7196
 7197        view.update(cx, |view, cx| {
 7198            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7199            assert_eq!(
 7200                view.selected_display_ranges(cx),
 7201                &[
 7202                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7203                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7204                ]
 7205            );
 7206        });
 7207
 7208        view.update(cx, |view, cx| {
 7209            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7210            assert_eq!(
 7211                view.selected_display_ranges(cx),
 7212                &[
 7213                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7214                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7215                ]
 7216            );
 7217        });
 7218
 7219        view.update(cx, |view, cx| {
 7220            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7221            assert_eq!(
 7222                view.selected_display_ranges(cx),
 7223                &[
 7224                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7225                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7226                ]
 7227            );
 7228        });
 7229
 7230        // Moving to the end of line again is a no-op.
 7231        view.update(cx, |view, cx| {
 7232            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7233            assert_eq!(
 7234                view.selected_display_ranges(cx),
 7235                &[
 7236                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7237                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7238                ]
 7239            );
 7240        });
 7241
 7242        view.update(cx, |view, cx| {
 7243            view.move_left(&MoveLeft, cx);
 7244            view.select_to_beginning_of_line(
 7245                &SelectToBeginningOfLine {
 7246                    stop_at_soft_wraps: true,
 7247                },
 7248                cx,
 7249            );
 7250            assert_eq!(
 7251                view.selected_display_ranges(cx),
 7252                &[
 7253                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7254                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7255                ]
 7256            );
 7257        });
 7258
 7259        view.update(cx, |view, cx| {
 7260            view.select_to_beginning_of_line(
 7261                &SelectToBeginningOfLine {
 7262                    stop_at_soft_wraps: true,
 7263                },
 7264                cx,
 7265            );
 7266            assert_eq!(
 7267                view.selected_display_ranges(cx),
 7268                &[
 7269                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7270                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7271                ]
 7272            );
 7273        });
 7274
 7275        view.update(cx, |view, cx| {
 7276            view.select_to_beginning_of_line(
 7277                &SelectToBeginningOfLine {
 7278                    stop_at_soft_wraps: true,
 7279                },
 7280                cx,
 7281            );
 7282            assert_eq!(
 7283                view.selected_display_ranges(cx),
 7284                &[
 7285                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7286                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7287                ]
 7288            );
 7289        });
 7290
 7291        view.update(cx, |view, cx| {
 7292            view.select_to_end_of_line(
 7293                &SelectToEndOfLine {
 7294                    stop_at_soft_wraps: true,
 7295                },
 7296                cx,
 7297            );
 7298            assert_eq!(
 7299                view.selected_display_ranges(cx),
 7300                &[
 7301                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7302                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7303                ]
 7304            );
 7305        });
 7306
 7307        view.update(cx, |view, cx| {
 7308            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7309            assert_eq!(view.display_text(cx), "ab\n  de");
 7310            assert_eq!(
 7311                view.selected_display_ranges(cx),
 7312                &[
 7313                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7314                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7315                ]
 7316            );
 7317        });
 7318
 7319        view.update(cx, |view, cx| {
 7320            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7321            assert_eq!(view.display_text(cx), "\n");
 7322            assert_eq!(
 7323                view.selected_display_ranges(cx),
 7324                &[
 7325                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7326                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7327                ]
 7328            );
 7329        });
 7330    }
 7331
 7332    #[gpui::test]
 7333    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7334        cx.set_global(Settings::test(cx));
 7335        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7336        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7337        view.update(cx, |view, cx| {
 7338            view.select_display_ranges(
 7339                &[
 7340                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7341                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7342                ],
 7343                cx,
 7344            );
 7345
 7346            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7347            assert_selection_ranges(
 7348                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7349                vec![('<', '>'), ('[', ']')],
 7350                view,
 7351                cx,
 7352            );
 7353
 7354            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7355            assert_selection_ranges(
 7356                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7357                vec![('<', '>'), ('[', ']')],
 7358                view,
 7359                cx,
 7360            );
 7361
 7362            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7363            assert_selection_ranges(
 7364                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7365                vec![('<', '>'), ('[', ']')],
 7366                view,
 7367                cx,
 7368            );
 7369
 7370            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7371            assert_selection_ranges(
 7372                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7373                vec![('<', '>'), ('[', ']')],
 7374                view,
 7375                cx,
 7376            );
 7377
 7378            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7379            assert_selection_ranges(
 7380                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7381                vec![('<', '>'), ('[', ']')],
 7382                view,
 7383                cx,
 7384            );
 7385
 7386            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7387            assert_selection_ranges(
 7388                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7389                vec![('<', '>'), ('[', ']')],
 7390                view,
 7391                cx,
 7392            );
 7393
 7394            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7395            assert_selection_ranges(
 7396                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7397                vec![('<', '>'), ('[', ']')],
 7398                view,
 7399                cx,
 7400            );
 7401
 7402            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7403            assert_selection_ranges(
 7404                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7405                vec![('<', '>'), ('[', ']')],
 7406                view,
 7407                cx,
 7408            );
 7409
 7410            view.move_right(&MoveRight, cx);
 7411            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7412            assert_selection_ranges(
 7413                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7414                vec![('<', '>'), ('[', ']')],
 7415                view,
 7416                cx,
 7417            );
 7418
 7419            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7420            assert_selection_ranges(
 7421                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7422                vec![('<', '>'), ('[', ']')],
 7423                view,
 7424                cx,
 7425            );
 7426
 7427            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7428            assert_selection_ranges(
 7429                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7430                vec![('<', '>'), ('[', ']')],
 7431                view,
 7432                cx,
 7433            );
 7434        });
 7435    }
 7436
 7437    #[gpui::test]
 7438    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7439        cx.set_global(Settings::test(cx));
 7440        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7441        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7442
 7443        view.update(cx, |view, cx| {
 7444            view.set_wrap_width(Some(140.), cx);
 7445            assert_eq!(
 7446                view.display_text(cx),
 7447                "use one::{\n    two::three::\n    four::five\n};"
 7448            );
 7449
 7450            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7451
 7452            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7453            assert_eq!(
 7454                view.selected_display_ranges(cx),
 7455                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7456            );
 7457
 7458            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7459            assert_eq!(
 7460                view.selected_display_ranges(cx),
 7461                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7462            );
 7463
 7464            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7465            assert_eq!(
 7466                view.selected_display_ranges(cx),
 7467                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7468            );
 7469
 7470            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7471            assert_eq!(
 7472                view.selected_display_ranges(cx),
 7473                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7474            );
 7475
 7476            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7477            assert_eq!(
 7478                view.selected_display_ranges(cx),
 7479                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7480            );
 7481
 7482            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7483            assert_eq!(
 7484                view.selected_display_ranges(cx),
 7485                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7486            );
 7487        });
 7488    }
 7489
 7490    #[gpui::test]
 7491    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7492        cx.set_global(Settings::test(cx));
 7493        let (text, ranges) = marked_text_ranges("one [two three] four");
 7494        let buffer = MultiBuffer::build_simple(&text, cx);
 7495
 7496        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7497
 7498        editor.update(cx, |editor, cx| {
 7499            editor.select_ranges(ranges, None, cx);
 7500            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7501            assert_eq!(editor.text(cx), " four");
 7502        });
 7503    }
 7504
 7505    #[gpui::test]
 7506    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7507        cx.set_global(Settings::test(cx));
 7508        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7509        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7510
 7511        view.update(cx, |view, cx| {
 7512            view.select_display_ranges(
 7513                &[
 7514                    // an empty selection - the preceding word fragment is deleted
 7515                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7516                    // characters selected - they are deleted
 7517                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7518                ],
 7519                cx,
 7520            );
 7521            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7522        });
 7523
 7524        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7525
 7526        view.update(cx, |view, cx| {
 7527            view.select_display_ranges(
 7528                &[
 7529                    // an empty selection - the following word fragment is deleted
 7530                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7531                    // characters selected - they are deleted
 7532                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7533                ],
 7534                cx,
 7535            );
 7536            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7537        });
 7538
 7539        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7540    }
 7541
 7542    #[gpui::test]
 7543    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7544        cx.set_global(Settings::test(cx));
 7545        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7546        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7547
 7548        view.update(cx, |view, cx| {
 7549            view.select_display_ranges(
 7550                &[
 7551                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7552                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7553                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7554                ],
 7555                cx,
 7556            );
 7557
 7558            view.newline(&Newline, cx);
 7559            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7560        });
 7561    }
 7562
 7563    #[gpui::test]
 7564    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7565        cx.set_global(Settings::test(cx));
 7566        let buffer = MultiBuffer::build_simple(
 7567            "
 7568                a
 7569                b(
 7570                    X
 7571                )
 7572                c(
 7573                    X
 7574                )
 7575            "
 7576            .unindent()
 7577            .as_str(),
 7578            cx,
 7579        );
 7580
 7581        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7582            let mut editor = build_editor(buffer.clone(), cx);
 7583            editor.select_ranges(
 7584                [
 7585                    Point::new(2, 4)..Point::new(2, 5),
 7586                    Point::new(5, 4)..Point::new(5, 5),
 7587                ],
 7588                None,
 7589                cx,
 7590            );
 7591            editor
 7592        });
 7593
 7594        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7595        buffer.update(cx, |buffer, cx| {
 7596            buffer.edit(
 7597                [
 7598                    Point::new(1, 2)..Point::new(3, 0),
 7599                    Point::new(4, 2)..Point::new(6, 0),
 7600                ],
 7601                "",
 7602                cx,
 7603            );
 7604            assert_eq!(
 7605                buffer.read(cx).text(),
 7606                "
 7607                    a
 7608                    b()
 7609                    c()
 7610                "
 7611                .unindent()
 7612            );
 7613        });
 7614
 7615        editor.update(cx, |editor, cx| {
 7616            assert_eq!(
 7617                editor.selected_ranges(cx),
 7618                &[
 7619                    Point::new(1, 2)..Point::new(1, 2),
 7620                    Point::new(2, 2)..Point::new(2, 2),
 7621                ],
 7622            );
 7623
 7624            editor.newline(&Newline, cx);
 7625            assert_eq!(
 7626                editor.text(cx),
 7627                "
 7628                    a
 7629                    b(
 7630                    )
 7631                    c(
 7632                    )
 7633                "
 7634                .unindent()
 7635            );
 7636
 7637            // The selections are moved after the inserted newlines
 7638            assert_eq!(
 7639                editor.selected_ranges(cx),
 7640                &[
 7641                    Point::new(2, 0)..Point::new(2, 0),
 7642                    Point::new(4, 0)..Point::new(4, 0),
 7643                ],
 7644            );
 7645        });
 7646    }
 7647
 7648    #[gpui::test]
 7649    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7650        cx.set_global(Settings::test(cx));
 7651        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7652        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7653            let mut editor = build_editor(buffer.clone(), cx);
 7654            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7655            editor
 7656        });
 7657
 7658        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7659        buffer.update(cx, |buffer, cx| {
 7660            buffer.edit([2..5, 10..13, 18..21], "", cx);
 7661            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7662        });
 7663
 7664        editor.update(cx, |editor, cx| {
 7665            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7666
 7667            editor.insert("Z", cx);
 7668            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7669
 7670            // The selections are moved after the inserted characters
 7671            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7672        });
 7673    }
 7674
 7675    #[gpui::test]
 7676    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7677        cx.set_global(Settings::test(cx));
 7678        let buffer = MultiBuffer::build_simple(
 7679            indoc! {"
 7680                  one two
 7681                three
 7682                 four"},
 7683            cx,
 7684        );
 7685        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7686
 7687        view.update(cx, |view, cx| {
 7688            // two selections on the same line
 7689            select_ranges(
 7690                view,
 7691                indoc! {"
 7692                      [one] [two]
 7693                    three
 7694                     four"},
 7695                cx,
 7696            );
 7697
 7698            // indent from mid-tabstop to full tabstop
 7699            view.tab(&Tab, cx);
 7700            assert_text_with_selections(
 7701                view,
 7702                indoc! {"
 7703                        [one] [two]
 7704                    three
 7705                     four"},
 7706                cx,
 7707            );
 7708
 7709            // outdent from 1 tabstop to 0 tabstops
 7710            view.tab_prev(&TabPrev, cx);
 7711            assert_text_with_selections(
 7712                view,
 7713                indoc! {"
 7714                    [one] [two]
 7715                    three
 7716                     four"},
 7717                cx,
 7718            );
 7719
 7720            // select across line ending
 7721            select_ranges(
 7722                view,
 7723                indoc! {"
 7724                    one two
 7725                    t[hree
 7726                    ] four"},
 7727                cx,
 7728            );
 7729
 7730            // indent and outdent affect only the preceding line
 7731            view.tab(&Tab, cx);
 7732            assert_text_with_selections(
 7733                view,
 7734                indoc! {"
 7735                    one two
 7736                        t[hree
 7737                    ] four"},
 7738                cx,
 7739            );
 7740            view.tab_prev(&TabPrev, cx);
 7741            assert_text_with_selections(
 7742                view,
 7743                indoc! {"
 7744                    one two
 7745                    t[hree
 7746                    ] four"},
 7747                cx,
 7748            );
 7749
 7750            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7751            select_ranges(
 7752                view,
 7753                indoc! {"
 7754                    one two
 7755                    []three
 7756                     four"},
 7757                cx,
 7758            );
 7759            view.tab(&Tab, cx);
 7760            assert_text_with_selections(
 7761                view,
 7762                indoc! {"
 7763                    one two
 7764                        []three
 7765                     four"},
 7766                cx,
 7767            );
 7768
 7769            select_ranges(
 7770                view,
 7771                indoc! {"
 7772                    one two
 7773                    []    three
 7774                     four"},
 7775                cx,
 7776            );
 7777            view.tab_prev(&TabPrev, cx);
 7778            assert_text_with_selections(
 7779                view,
 7780                indoc! {"
 7781                    one two
 7782                    []three
 7783                     four"},
 7784                cx,
 7785            );
 7786        });
 7787    }
 7788
 7789    #[gpui::test]
 7790    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7791        cx.set_global(
 7792            Settings::test(cx)
 7793                .with_overrides(
 7794                    "TOML",
 7795                    LanguageOverride {
 7796                        tab_size: Some(2),
 7797                        ..Default::default()
 7798                    },
 7799                )
 7800                .with_overrides(
 7801                    "Rust",
 7802                    LanguageOverride {
 7803                        tab_size: Some(4),
 7804                        ..Default::default()
 7805                    },
 7806                ),
 7807        );
 7808        let toml_language = Arc::new(Language::new(
 7809            LanguageConfig {
 7810                name: "TOML".into(),
 7811                ..Default::default()
 7812            },
 7813            None,
 7814        ));
 7815        let rust_language = Arc::new(Language::new(
 7816            LanguageConfig {
 7817                name: "Rust".into(),
 7818                ..Default::default()
 7819            },
 7820            None,
 7821        ));
 7822
 7823        let toml_buffer = cx
 7824            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7825        let rust_buffer = cx.add_model(|cx| {
 7826            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7827        });
 7828        let multibuffer = cx.add_model(|cx| {
 7829            let mut multibuffer = MultiBuffer::new(0);
 7830            multibuffer.push_excerpts(
 7831                toml_buffer.clone(),
 7832                [Point::new(0, 0)..Point::new(2, 0)],
 7833                cx,
 7834            );
 7835            multibuffer.push_excerpts(
 7836                rust_buffer.clone(),
 7837                [Point::new(0, 0)..Point::new(1, 0)],
 7838                cx,
 7839            );
 7840            multibuffer
 7841        });
 7842
 7843        cx.add_window(Default::default(), |cx| {
 7844            let mut editor = build_editor(multibuffer, cx);
 7845
 7846            assert_eq!(
 7847                editor.text(cx),
 7848                indoc! {"
 7849                    a = 1
 7850                    b = 2
 7851
 7852                    const c: usize = 3;
 7853                "}
 7854            );
 7855
 7856            select_ranges(
 7857                &mut editor,
 7858                indoc! {"
 7859                    [a] = 1
 7860                    b = 2
 7861
 7862                    [const c:] usize = 3;
 7863                "},
 7864                cx,
 7865            );
 7866
 7867            editor.tab(&Tab, cx);
 7868            assert_text_with_selections(
 7869                &mut editor,
 7870                indoc! {"
 7871                      [a] = 1
 7872                    b = 2
 7873
 7874                        [const c:] usize = 3;
 7875                "},
 7876                cx,
 7877            );
 7878            editor.tab_prev(&TabPrev, cx);
 7879            assert_text_with_selections(
 7880                &mut editor,
 7881                indoc! {"
 7882                    [a] = 1
 7883                    b = 2
 7884
 7885                    [const c:] usize = 3;
 7886                "},
 7887                cx,
 7888            );
 7889
 7890            editor
 7891        });
 7892    }
 7893
 7894    #[gpui::test]
 7895    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 7896        cx.set_global(Settings::test(cx));
 7897        let (_, view) = cx.add_window(Default::default(), |cx| {
 7898            build_editor(MultiBuffer::build_simple("", cx), cx)
 7899        });
 7900
 7901        view.update(cx, |view, cx| {
 7902            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7903            view.select_display_ranges(
 7904                &[
 7905                    // an empty selection - the preceding character is deleted
 7906                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7907                    // one character selected - it is deleted
 7908                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7909                    // a line suffix selected - it is deleted
 7910                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7911                ],
 7912                cx,
 7913            );
 7914            view.backspace(&Backspace, cx);
 7915            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 7916
 7917            view.set_text("    one\n        two\n        three\n   four", cx);
 7918            view.select_display_ranges(
 7919                &[
 7920                    // cursors at the the end of leading indent - last indent is deleted
 7921                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 7922                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 7923                    // cursors inside leading indent - overlapping indent deletions are coalesced
 7924                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7925                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 7926                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 7927                    // cursor at the beginning of a line - preceding newline is deleted
 7928                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7929                    // selection inside leading indent - only the selected character is deleted
 7930                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 7931                ],
 7932                cx,
 7933            );
 7934            view.backspace(&Backspace, cx);
 7935            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 7936        });
 7937    }
 7938
 7939    #[gpui::test]
 7940    fn test_delete(cx: &mut gpui::MutableAppContext) {
 7941        cx.set_global(Settings::test(cx));
 7942        let buffer =
 7943            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7944        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7945
 7946        view.update(cx, |view, cx| {
 7947            view.select_display_ranges(
 7948                &[
 7949                    // an empty selection - the following character is deleted
 7950                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7951                    // one character selected - it is deleted
 7952                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7953                    // a line suffix selected - it is deleted
 7954                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7955                ],
 7956                cx,
 7957            );
 7958            view.delete(&Delete, cx);
 7959        });
 7960
 7961        assert_eq!(
 7962            buffer.read(cx).read(cx).text(),
 7963            "on two three\nfou five six\nseven ten\n"
 7964        );
 7965    }
 7966
 7967    #[gpui::test]
 7968    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7969        cx.set_global(Settings::test(cx));
 7970        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7971        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7972        view.update(cx, |view, cx| {
 7973            view.select_display_ranges(
 7974                &[
 7975                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7976                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7977                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7978                ],
 7979                cx,
 7980            );
 7981            view.delete_line(&DeleteLine, cx);
 7982            assert_eq!(view.display_text(cx), "ghi");
 7983            assert_eq!(
 7984                view.selected_display_ranges(cx),
 7985                vec![
 7986                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7987                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7988                ]
 7989            );
 7990        });
 7991
 7992        cx.set_global(Settings::test(cx));
 7993        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7994        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7995        view.update(cx, |view, cx| {
 7996            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 7997            view.delete_line(&DeleteLine, cx);
 7998            assert_eq!(view.display_text(cx), "ghi\n");
 7999            assert_eq!(
 8000                view.selected_display_ranges(cx),
 8001                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8002            );
 8003        });
 8004    }
 8005
 8006    #[gpui::test]
 8007    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8008        cx.set_global(Settings::test(cx));
 8009        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8010        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8011        view.update(cx, |view, cx| {
 8012            view.select_display_ranges(
 8013                &[
 8014                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8015                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8016                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8017                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8018                ],
 8019                cx,
 8020            );
 8021            view.duplicate_line(&DuplicateLine, cx);
 8022            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8023            assert_eq!(
 8024                view.selected_display_ranges(cx),
 8025                vec![
 8026                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8027                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8028                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8029                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8030                ]
 8031            );
 8032        });
 8033
 8034        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8035        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8036        view.update(cx, |view, cx| {
 8037            view.select_display_ranges(
 8038                &[
 8039                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8040                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8041                ],
 8042                cx,
 8043            );
 8044            view.duplicate_line(&DuplicateLine, cx);
 8045            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8046            assert_eq!(
 8047                view.selected_display_ranges(cx),
 8048                vec![
 8049                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8050                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8051                ]
 8052            );
 8053        });
 8054    }
 8055
 8056    #[gpui::test]
 8057    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8058        cx.set_global(Settings::test(cx));
 8059        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8060        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8061        view.update(cx, |view, cx| {
 8062            view.fold_ranges(
 8063                vec![
 8064                    Point::new(0, 2)..Point::new(1, 2),
 8065                    Point::new(2, 3)..Point::new(4, 1),
 8066                    Point::new(7, 0)..Point::new(8, 4),
 8067                ],
 8068                cx,
 8069            );
 8070            view.select_display_ranges(
 8071                &[
 8072                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8073                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8074                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8075                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8076                ],
 8077                cx,
 8078            );
 8079            assert_eq!(
 8080                view.display_text(cx),
 8081                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8082            );
 8083
 8084            view.move_line_up(&MoveLineUp, cx);
 8085            assert_eq!(
 8086                view.display_text(cx),
 8087                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8088            );
 8089            assert_eq!(
 8090                view.selected_display_ranges(cx),
 8091                vec![
 8092                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8093                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8094                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8095                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8096                ]
 8097            );
 8098        });
 8099
 8100        view.update(cx, |view, cx| {
 8101            view.move_line_down(&MoveLineDown, cx);
 8102            assert_eq!(
 8103                view.display_text(cx),
 8104                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8105            );
 8106            assert_eq!(
 8107                view.selected_display_ranges(cx),
 8108                vec![
 8109                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8110                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8111                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8112                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8113                ]
 8114            );
 8115        });
 8116
 8117        view.update(cx, |view, cx| {
 8118            view.move_line_down(&MoveLineDown, cx);
 8119            assert_eq!(
 8120                view.display_text(cx),
 8121                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8122            );
 8123            assert_eq!(
 8124                view.selected_display_ranges(cx),
 8125                vec![
 8126                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8127                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8128                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8129                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8130                ]
 8131            );
 8132        });
 8133
 8134        view.update(cx, |view, cx| {
 8135            view.move_line_up(&MoveLineUp, cx);
 8136            assert_eq!(
 8137                view.display_text(cx),
 8138                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8139            );
 8140            assert_eq!(
 8141                view.selected_display_ranges(cx),
 8142                vec![
 8143                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8144                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8145                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8146                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8147                ]
 8148            );
 8149        });
 8150    }
 8151
 8152    #[gpui::test]
 8153    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8154        cx.set_global(Settings::test(cx));
 8155        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8156        let snapshot = buffer.read(cx).snapshot(cx);
 8157        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8158        editor.update(cx, |editor, cx| {
 8159            editor.insert_blocks(
 8160                [BlockProperties {
 8161                    position: snapshot.anchor_after(Point::new(2, 0)),
 8162                    disposition: BlockDisposition::Below,
 8163                    height: 1,
 8164                    render: Arc::new(|_| Empty::new().boxed()),
 8165                }],
 8166                cx,
 8167            );
 8168            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8169            editor.move_line_down(&MoveLineDown, cx);
 8170        });
 8171    }
 8172
 8173    #[gpui::test]
 8174    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8175        cx.set_global(Settings::test(cx));
 8176        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8177        let view = cx
 8178            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8179            .1;
 8180
 8181        // Cut with three selections. Clipboard text is divided into three slices.
 8182        view.update(cx, |view, cx| {
 8183            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8184            view.cut(&Cut, cx);
 8185            assert_eq!(view.display_text(cx), "two four six ");
 8186        });
 8187
 8188        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8189        view.update(cx, |view, cx| {
 8190            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8191            view.paste(&Paste, cx);
 8192            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8193            assert_eq!(
 8194                view.selected_display_ranges(cx),
 8195                &[
 8196                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8197                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8198                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8199                ]
 8200            );
 8201        });
 8202
 8203        // Paste again but with only two cursors. Since the number of cursors doesn't
 8204        // match the number of slices in the clipboard, the entire clipboard text
 8205        // is pasted at each cursor.
 8206        view.update(cx, |view, cx| {
 8207            view.select_ranges(vec![0..0, 31..31], None, cx);
 8208            view.handle_input(&Input("( ".into()), cx);
 8209            view.paste(&Paste, cx);
 8210            view.handle_input(&Input(") ".into()), cx);
 8211            assert_eq!(
 8212                view.display_text(cx),
 8213                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8214            );
 8215        });
 8216
 8217        view.update(cx, |view, cx| {
 8218            view.select_ranges(vec![0..0], None, cx);
 8219            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8220            assert_eq!(
 8221                view.display_text(cx),
 8222                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8223            );
 8224        });
 8225
 8226        // Cut with three selections, one of which is full-line.
 8227        view.update(cx, |view, cx| {
 8228            view.select_display_ranges(
 8229                &[
 8230                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8231                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8232                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8233                ],
 8234                cx,
 8235            );
 8236            view.cut(&Cut, cx);
 8237            assert_eq!(
 8238                view.display_text(cx),
 8239                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8240            );
 8241        });
 8242
 8243        // Paste with three selections, noticing how the copied selection that was full-line
 8244        // gets inserted before the second cursor.
 8245        view.update(cx, |view, cx| {
 8246            view.select_display_ranges(
 8247                &[
 8248                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8249                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8250                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8251                ],
 8252                cx,
 8253            );
 8254            view.paste(&Paste, cx);
 8255            assert_eq!(
 8256                view.display_text(cx),
 8257                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8258            );
 8259            assert_eq!(
 8260                view.selected_display_ranges(cx),
 8261                &[
 8262                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8263                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8264                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8265                ]
 8266            );
 8267        });
 8268
 8269        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8270        view.update(cx, |view, cx| {
 8271            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8272            view.copy(&Copy, cx);
 8273        });
 8274
 8275        // Paste with three selections, noticing how the copied full-line selection is inserted
 8276        // before the empty selections but replaces the selection that is non-empty.
 8277        view.update(cx, |view, cx| {
 8278            view.select_display_ranges(
 8279                &[
 8280                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8281                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8282                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8283                ],
 8284                cx,
 8285            );
 8286            view.paste(&Paste, cx);
 8287            assert_eq!(
 8288                view.display_text(cx),
 8289                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8290            );
 8291            assert_eq!(
 8292                view.selected_display_ranges(cx),
 8293                &[
 8294                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8295                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8296                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8297                ]
 8298            );
 8299        });
 8300    }
 8301
 8302    #[gpui::test]
 8303    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8304        cx.set_global(Settings::test(cx));
 8305        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8306        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8307        view.update(cx, |view, cx| {
 8308            view.select_all(&SelectAll, cx);
 8309            assert_eq!(
 8310                view.selected_display_ranges(cx),
 8311                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8312            );
 8313        });
 8314    }
 8315
 8316    #[gpui::test]
 8317    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8318        cx.set_global(Settings::test(cx));
 8319        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8320        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8321        view.update(cx, |view, cx| {
 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, 2)..DisplayPoint::new(4, 2),
 8328                ],
 8329                cx,
 8330            );
 8331            view.select_line(&SelectLine, cx);
 8332            assert_eq!(
 8333                view.selected_display_ranges(cx),
 8334                vec![
 8335                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8336                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8337                ]
 8338            );
 8339        });
 8340
 8341        view.update(cx, |view, cx| {
 8342            view.select_line(&SelectLine, cx);
 8343            assert_eq!(
 8344                view.selected_display_ranges(cx),
 8345                vec![
 8346                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8347                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8348                ]
 8349            );
 8350        });
 8351
 8352        view.update(cx, |view, cx| {
 8353            view.select_line(&SelectLine, cx);
 8354            assert_eq!(
 8355                view.selected_display_ranges(cx),
 8356                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8357            );
 8358        });
 8359    }
 8360
 8361    #[gpui::test]
 8362    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8363        cx.set_global(Settings::test(cx));
 8364        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8365        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8366        view.update(cx, |view, cx| {
 8367            view.fold_ranges(
 8368                vec![
 8369                    Point::new(0, 2)..Point::new(1, 2),
 8370                    Point::new(2, 3)..Point::new(4, 1),
 8371                    Point::new(7, 0)..Point::new(8, 4),
 8372                ],
 8373                cx,
 8374            );
 8375            view.select_display_ranges(
 8376                &[
 8377                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8378                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8379                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8380                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8381                ],
 8382                cx,
 8383            );
 8384            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8385        });
 8386
 8387        view.update(cx, |view, cx| {
 8388            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8389            assert_eq!(
 8390                view.display_text(cx),
 8391                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8392            );
 8393            assert_eq!(
 8394                view.selected_display_ranges(cx),
 8395                [
 8396                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8397                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8398                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8399                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8400                ]
 8401            );
 8402        });
 8403
 8404        view.update(cx, |view, cx| {
 8405            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8406            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8407            assert_eq!(
 8408                view.display_text(cx),
 8409                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8410            );
 8411            assert_eq!(
 8412                view.selected_display_ranges(cx),
 8413                [
 8414                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8415                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8416                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8417                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8418                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8419                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8420                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8421                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8422                ]
 8423            );
 8424        });
 8425    }
 8426
 8427    #[gpui::test]
 8428    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8429        cx.set_global(Settings::test(cx));
 8430        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8431        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8432
 8433        view.update(cx, |view, cx| {
 8434            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8435        });
 8436        view.update(cx, |view, cx| {
 8437            view.add_selection_above(&AddSelectionAbove, cx);
 8438            assert_eq!(
 8439                view.selected_display_ranges(cx),
 8440                vec![
 8441                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8442                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8443                ]
 8444            );
 8445        });
 8446
 8447        view.update(cx, |view, cx| {
 8448            view.add_selection_above(&AddSelectionAbove, cx);
 8449            assert_eq!(
 8450                view.selected_display_ranges(cx),
 8451                vec![
 8452                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8453                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8454                ]
 8455            );
 8456        });
 8457
 8458        view.update(cx, |view, cx| {
 8459            view.add_selection_below(&AddSelectionBelow, cx);
 8460            assert_eq!(
 8461                view.selected_display_ranges(cx),
 8462                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8463            );
 8464
 8465            view.undo_selection(&UndoSelection, cx);
 8466            assert_eq!(
 8467                view.selected_display_ranges(cx),
 8468                vec![
 8469                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8470                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8471                ]
 8472            );
 8473
 8474            view.redo_selection(&RedoSelection, cx);
 8475            assert_eq!(
 8476                view.selected_display_ranges(cx),
 8477                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8478            );
 8479        });
 8480
 8481        view.update(cx, |view, cx| {
 8482            view.add_selection_below(&AddSelectionBelow, cx);
 8483            assert_eq!(
 8484                view.selected_display_ranges(cx),
 8485                vec![
 8486                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8487                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8488                ]
 8489            );
 8490        });
 8491
 8492        view.update(cx, |view, cx| {
 8493            view.add_selection_below(&AddSelectionBelow, cx);
 8494            assert_eq!(
 8495                view.selected_display_ranges(cx),
 8496                vec![
 8497                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8498                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8499                ]
 8500            );
 8501        });
 8502
 8503        view.update(cx, |view, cx| {
 8504            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8505        });
 8506        view.update(cx, |view, cx| {
 8507            view.add_selection_below(&AddSelectionBelow, cx);
 8508            assert_eq!(
 8509                view.selected_display_ranges(cx),
 8510                vec![
 8511                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8512                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8513                ]
 8514            );
 8515        });
 8516
 8517        view.update(cx, |view, cx| {
 8518            view.add_selection_below(&AddSelectionBelow, cx);
 8519            assert_eq!(
 8520                view.selected_display_ranges(cx),
 8521                vec![
 8522                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8523                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8524                ]
 8525            );
 8526        });
 8527
 8528        view.update(cx, |view, cx| {
 8529            view.add_selection_above(&AddSelectionAbove, cx);
 8530            assert_eq!(
 8531                view.selected_display_ranges(cx),
 8532                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8533            );
 8534        });
 8535
 8536        view.update(cx, |view, cx| {
 8537            view.add_selection_above(&AddSelectionAbove, cx);
 8538            assert_eq!(
 8539                view.selected_display_ranges(cx),
 8540                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8541            );
 8542        });
 8543
 8544        view.update(cx, |view, cx| {
 8545            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8546            view.add_selection_below(&AddSelectionBelow, cx);
 8547            assert_eq!(
 8548                view.selected_display_ranges(cx),
 8549                vec![
 8550                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8551                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8552                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8553                ]
 8554            );
 8555        });
 8556
 8557        view.update(cx, |view, cx| {
 8558            view.add_selection_below(&AddSelectionBelow, cx);
 8559            assert_eq!(
 8560                view.selected_display_ranges(cx),
 8561                vec![
 8562                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8563                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8564                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8565                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8566                ]
 8567            );
 8568        });
 8569
 8570        view.update(cx, |view, cx| {
 8571            view.add_selection_above(&AddSelectionAbove, cx);
 8572            assert_eq!(
 8573                view.selected_display_ranges(cx),
 8574                vec![
 8575                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8576                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8577                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8578                ]
 8579            );
 8580        });
 8581
 8582        view.update(cx, |view, cx| {
 8583            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8584        });
 8585        view.update(cx, |view, cx| {
 8586            view.add_selection_above(&AddSelectionAbove, cx);
 8587            assert_eq!(
 8588                view.selected_display_ranges(cx),
 8589                vec![
 8590                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8591                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8592                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8593                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8594                ]
 8595            );
 8596        });
 8597
 8598        view.update(cx, |view, cx| {
 8599            view.add_selection_below(&AddSelectionBelow, cx);
 8600            assert_eq!(
 8601                view.selected_display_ranges(cx),
 8602                vec![
 8603                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8604                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8605                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8606                ]
 8607            );
 8608        });
 8609    }
 8610
 8611    #[gpui::test]
 8612    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8613        cx.set_global(Settings::test(cx));
 8614
 8615        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8616        let buffer = MultiBuffer::build_simple(&text, cx);
 8617        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8618
 8619        view.update(cx, |view, cx| {
 8620            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8621            view.select_next(
 8622                &SelectNext {
 8623                    replace_newest: false,
 8624                },
 8625                cx,
 8626            );
 8627            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8628
 8629            view.select_next(
 8630                &SelectNext {
 8631                    replace_newest: false,
 8632                },
 8633                cx,
 8634            );
 8635            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8636
 8637            view.undo_selection(&UndoSelection, cx);
 8638            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8639
 8640            view.redo_selection(&RedoSelection, cx);
 8641            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8642
 8643            view.select_next(
 8644                &SelectNext {
 8645                    replace_newest: false,
 8646                },
 8647                cx,
 8648            );
 8649            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8650
 8651            view.select_next(
 8652                &SelectNext {
 8653                    replace_newest: false,
 8654                },
 8655                cx,
 8656            );
 8657            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8658        });
 8659    }
 8660
 8661    #[gpui::test]
 8662    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8663        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8664        let language = Arc::new(Language::new(
 8665            LanguageConfig::default(),
 8666            Some(tree_sitter_rust::language()),
 8667        ));
 8668
 8669        let text = r#"
 8670            use mod1::mod2::{mod3, mod4};
 8671
 8672            fn fn_1(param1: bool, param2: &str) {
 8673                let var1 = "text";
 8674            }
 8675        "#
 8676        .unindent();
 8677
 8678        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8679        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8680        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8681        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8682            .await;
 8683
 8684        view.update(cx, |view, cx| {
 8685            view.select_display_ranges(
 8686                &[
 8687                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8688                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8689                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8690                ],
 8691                cx,
 8692            );
 8693            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8694        });
 8695        assert_eq!(
 8696            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8697            &[
 8698                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8699                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8700                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8701            ]
 8702        );
 8703
 8704        view.update(cx, |view, cx| {
 8705            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8706        });
 8707        assert_eq!(
 8708            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8709            &[
 8710                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8711                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8712            ]
 8713        );
 8714
 8715        view.update(cx, |view, cx| {
 8716            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8717        });
 8718        assert_eq!(
 8719            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8720            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8721        );
 8722
 8723        // Trying to expand the selected syntax node one more time has no effect.
 8724        view.update(cx, |view, cx| {
 8725            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8726        });
 8727        assert_eq!(
 8728            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8729            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8730        );
 8731
 8732        view.update(cx, |view, cx| {
 8733            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8734        });
 8735        assert_eq!(
 8736            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8737            &[
 8738                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8739                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8740            ]
 8741        );
 8742
 8743        view.update(cx, |view, cx| {
 8744            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8745        });
 8746        assert_eq!(
 8747            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8748            &[
 8749                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8750                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8751                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8752            ]
 8753        );
 8754
 8755        view.update(cx, |view, cx| {
 8756            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8757        });
 8758        assert_eq!(
 8759            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8760            &[
 8761                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8762                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8763                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8764            ]
 8765        );
 8766
 8767        // Trying to shrink the selected syntax node one more time has no effect.
 8768        view.update(cx, |view, cx| {
 8769            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8770        });
 8771        assert_eq!(
 8772            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8773            &[
 8774                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8775                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8776                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8777            ]
 8778        );
 8779
 8780        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8781        // a fold.
 8782        view.update(cx, |view, cx| {
 8783            view.fold_ranges(
 8784                vec![
 8785                    Point::new(0, 21)..Point::new(0, 24),
 8786                    Point::new(3, 20)..Point::new(3, 22),
 8787                ],
 8788                cx,
 8789            );
 8790            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8791        });
 8792        assert_eq!(
 8793            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8794            &[
 8795                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8796                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8797                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8798            ]
 8799        );
 8800    }
 8801
 8802    #[gpui::test]
 8803    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8804        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8805        let language = Arc::new(
 8806            Language::new(
 8807                LanguageConfig {
 8808                    brackets: vec![
 8809                        BracketPair {
 8810                            start: "{".to_string(),
 8811                            end: "}".to_string(),
 8812                            close: false,
 8813                            newline: true,
 8814                        },
 8815                        BracketPair {
 8816                            start: "(".to_string(),
 8817                            end: ")".to_string(),
 8818                            close: false,
 8819                            newline: true,
 8820                        },
 8821                    ],
 8822                    ..Default::default()
 8823                },
 8824                Some(tree_sitter_rust::language()),
 8825            )
 8826            .with_indents_query(
 8827                r#"
 8828                (_ "(" ")" @end) @indent
 8829                (_ "{" "}" @end) @indent
 8830                "#,
 8831            )
 8832            .unwrap(),
 8833        );
 8834
 8835        let text = "fn a() {}";
 8836
 8837        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8838        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8839        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8840        editor
 8841            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8842            .await;
 8843
 8844        editor.update(cx, |editor, cx| {
 8845            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 8846            editor.newline(&Newline, cx);
 8847            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8848            assert_eq!(
 8849                editor.selected_ranges(cx),
 8850                &[
 8851                    Point::new(1, 4)..Point::new(1, 4),
 8852                    Point::new(3, 4)..Point::new(3, 4),
 8853                    Point::new(5, 0)..Point::new(5, 0)
 8854                ]
 8855            );
 8856        });
 8857    }
 8858
 8859    #[gpui::test]
 8860    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8861        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8862        let language = Arc::new(Language::new(
 8863            LanguageConfig {
 8864                brackets: vec![
 8865                    BracketPair {
 8866                        start: "{".to_string(),
 8867                        end: "}".to_string(),
 8868                        close: true,
 8869                        newline: true,
 8870                    },
 8871                    BracketPair {
 8872                        start: "/*".to_string(),
 8873                        end: " */".to_string(),
 8874                        close: true,
 8875                        newline: true,
 8876                    },
 8877                ],
 8878                autoclose_before: "})]".to_string(),
 8879                ..Default::default()
 8880            },
 8881            Some(tree_sitter_rust::language()),
 8882        ));
 8883
 8884        let text = r#"
 8885            a
 8886
 8887            /
 8888
 8889        "#
 8890        .unindent();
 8891
 8892        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8893        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8894        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8895        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8896            .await;
 8897
 8898        view.update(cx, |view, cx| {
 8899            view.select_display_ranges(
 8900                &[
 8901                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8902                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8903                ],
 8904                cx,
 8905            );
 8906
 8907            view.handle_input(&Input("{".to_string()), cx);
 8908            view.handle_input(&Input("{".to_string()), cx);
 8909            view.handle_input(&Input("{".to_string()), cx);
 8910            assert_eq!(
 8911                view.text(cx),
 8912                "
 8913                {{{}}}
 8914                {{{}}}
 8915                /
 8916
 8917                "
 8918                .unindent()
 8919            );
 8920
 8921            view.move_right(&MoveRight, cx);
 8922            view.handle_input(&Input("}".to_string()), cx);
 8923            view.handle_input(&Input("}".to_string()), cx);
 8924            view.handle_input(&Input("}".to_string()), cx);
 8925            assert_eq!(
 8926                view.text(cx),
 8927                "
 8928                {{{}}}}
 8929                {{{}}}}
 8930                /
 8931
 8932                "
 8933                .unindent()
 8934            );
 8935
 8936            view.undo(&Undo, cx);
 8937            view.handle_input(&Input("/".to_string()), cx);
 8938            view.handle_input(&Input("*".to_string()), cx);
 8939            assert_eq!(
 8940                view.text(cx),
 8941                "
 8942                /* */
 8943                /* */
 8944                /
 8945
 8946                "
 8947                .unindent()
 8948            );
 8949
 8950            view.undo(&Undo, cx);
 8951            view.select_display_ranges(
 8952                &[
 8953                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8954                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8955                ],
 8956                cx,
 8957            );
 8958            view.handle_input(&Input("*".to_string()), cx);
 8959            assert_eq!(
 8960                view.text(cx),
 8961                "
 8962                a
 8963
 8964                /*
 8965                *
 8966                "
 8967                .unindent()
 8968            );
 8969
 8970            // Don't autoclose if the next character isn't whitespace and isn't
 8971            // listed in the language's "autoclose_before" section.
 8972            view.finalize_last_transaction(cx);
 8973            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 8974            view.handle_input(&Input("{".to_string()), cx);
 8975            assert_eq!(
 8976                view.text(cx),
 8977                "
 8978                {a
 8979
 8980                /*
 8981                *
 8982                "
 8983                .unindent()
 8984            );
 8985
 8986            view.undo(&Undo, cx);
 8987            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 8988            view.handle_input(&Input("{".to_string()), cx);
 8989            assert_eq!(
 8990                view.text(cx),
 8991                "
 8992                {a}
 8993
 8994                /*
 8995                *
 8996                "
 8997                .unindent()
 8998            );
 8999            assert_eq!(
 9000                view.selected_display_ranges(cx),
 9001                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9002            );
 9003        });
 9004    }
 9005
 9006    #[gpui::test]
 9007    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9008        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9009
 9010        let text = "
 9011            a. b
 9012            a. b
 9013            a. b
 9014        "
 9015        .unindent();
 9016        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9017        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9018
 9019        editor.update(cx, |editor, cx| {
 9020            let buffer = &editor.snapshot(cx).buffer_snapshot;
 9021            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9022            let insertion_ranges = [
 9023                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 9024                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 9025                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 9026            ];
 9027
 9028            editor
 9029                .insert_snippet(&insertion_ranges, snippet, cx)
 9030                .unwrap();
 9031            assert_eq!(
 9032                editor.text(cx),
 9033                "
 9034                    a.f(one, two, three) b
 9035                    a.f(one, two, three) b
 9036                    a.f(one, two, three) b
 9037                "
 9038                .unindent()
 9039            );
 9040            assert_eq!(
 9041                editor.selected_ranges::<Point>(cx),
 9042                &[
 9043                    Point::new(0, 4)..Point::new(0, 7),
 9044                    Point::new(0, 14)..Point::new(0, 19),
 9045                    Point::new(1, 4)..Point::new(1, 7),
 9046                    Point::new(1, 14)..Point::new(1, 19),
 9047                    Point::new(2, 4)..Point::new(2, 7),
 9048                    Point::new(2, 14)..Point::new(2, 19),
 9049                ]
 9050            );
 9051
 9052            // Can't move earlier than the first tab stop
 9053            editor.move_to_prev_snippet_tabstop(cx);
 9054            assert_eq!(
 9055                editor.selected_ranges::<Point>(cx),
 9056                &[
 9057                    Point::new(0, 4)..Point::new(0, 7),
 9058                    Point::new(0, 14)..Point::new(0, 19),
 9059                    Point::new(1, 4)..Point::new(1, 7),
 9060                    Point::new(1, 14)..Point::new(1, 19),
 9061                    Point::new(2, 4)..Point::new(2, 7),
 9062                    Point::new(2, 14)..Point::new(2, 19),
 9063                ]
 9064            );
 9065
 9066            assert!(editor.move_to_next_snippet_tabstop(cx));
 9067            assert_eq!(
 9068                editor.selected_ranges::<Point>(cx),
 9069                &[
 9070                    Point::new(0, 9)..Point::new(0, 12),
 9071                    Point::new(1, 9)..Point::new(1, 12),
 9072                    Point::new(2, 9)..Point::new(2, 12)
 9073                ]
 9074            );
 9075
 9076            editor.move_to_prev_snippet_tabstop(cx);
 9077            assert_eq!(
 9078                editor.selected_ranges::<Point>(cx),
 9079                &[
 9080                    Point::new(0, 4)..Point::new(0, 7),
 9081                    Point::new(0, 14)..Point::new(0, 19),
 9082                    Point::new(1, 4)..Point::new(1, 7),
 9083                    Point::new(1, 14)..Point::new(1, 19),
 9084                    Point::new(2, 4)..Point::new(2, 7),
 9085                    Point::new(2, 14)..Point::new(2, 19),
 9086                ]
 9087            );
 9088
 9089            assert!(editor.move_to_next_snippet_tabstop(cx));
 9090            assert!(editor.move_to_next_snippet_tabstop(cx));
 9091            assert_eq!(
 9092                editor.selected_ranges::<Point>(cx),
 9093                &[
 9094                    Point::new(0, 20)..Point::new(0, 20),
 9095                    Point::new(1, 20)..Point::new(1, 20),
 9096                    Point::new(2, 20)..Point::new(2, 20)
 9097                ]
 9098            );
 9099
 9100            // As soon as the last tab stop is reached, snippet state is gone
 9101            editor.move_to_prev_snippet_tabstop(cx);
 9102            assert_eq!(
 9103                editor.selected_ranges::<Point>(cx),
 9104                &[
 9105                    Point::new(0, 20)..Point::new(0, 20),
 9106                    Point::new(1, 20)..Point::new(1, 20),
 9107                    Point::new(2, 20)..Point::new(2, 20)
 9108                ]
 9109            );
 9110        });
 9111    }
 9112
 9113    #[gpui::test]
 9114    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9115        cx.foreground().forbid_parking();
 9116        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9117
 9118        let mut language = Language::new(
 9119            LanguageConfig {
 9120                name: "Rust".into(),
 9121                path_suffixes: vec!["rs".to_string()],
 9122                ..Default::default()
 9123            },
 9124            Some(tree_sitter_rust::language()),
 9125        );
 9126        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9127            capabilities: lsp::ServerCapabilities {
 9128                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9129                ..Default::default()
 9130            },
 9131            ..Default::default()
 9132        });
 9133
 9134        let fs = FakeFs::new(cx.background().clone());
 9135        fs.insert_file("/file.rs", Default::default()).await;
 9136
 9137        let project = Project::test(fs, cx);
 9138        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9139
 9140        let worktree_id = project
 9141            .update(cx, |project, cx| {
 9142                project.find_or_create_local_worktree("/file.rs", true, cx)
 9143            })
 9144            .await
 9145            .unwrap()
 9146            .0
 9147            .read_with(cx, |tree, _| tree.id());
 9148        let buffer = project
 9149            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9150            .await
 9151            .unwrap();
 9152
 9153        cx.foreground().start_waiting();
 9154        let fake_server = fake_servers.next().await.unwrap();
 9155
 9156        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9157        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9158        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9159        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9160
 9161        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9162        fake_server
 9163            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9164                assert_eq!(
 9165                    params.text_document.uri,
 9166                    lsp::Url::from_file_path("/file.rs").unwrap()
 9167                );
 9168                assert_eq!(params.options.tab_size, 4);
 9169                Ok(Some(vec![lsp::TextEdit::new(
 9170                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9171                    ", ".to_string(),
 9172                )]))
 9173            })
 9174            .next()
 9175            .await;
 9176        cx.foreground().start_waiting();
 9177        save.await.unwrap();
 9178        assert_eq!(
 9179            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9180            "one, two\nthree\n"
 9181        );
 9182        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9183
 9184        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9185        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9186
 9187        // Ensure we can still save even if formatting hangs.
 9188        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9189            assert_eq!(
 9190                params.text_document.uri,
 9191                lsp::Url::from_file_path("/file.rs").unwrap()
 9192            );
 9193            futures::future::pending::<()>().await;
 9194            unreachable!()
 9195        });
 9196        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9197        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9198        cx.foreground().start_waiting();
 9199        save.await.unwrap();
 9200        assert_eq!(
 9201            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9202            "one\ntwo\nthree\n"
 9203        );
 9204        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9205
 9206        // Set rust language override and assert overriden tabsize is sent to language server
 9207        cx.update(|cx| {
 9208            cx.update_global::<Settings, _, _>(|settings, _| {
 9209                settings.language_overrides.insert(
 9210                    "Rust".into(),
 9211                    LanguageOverride {
 9212                        tab_size: Some(8),
 9213                        ..Default::default()
 9214                    },
 9215                );
 9216            })
 9217        });
 9218
 9219        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9220        fake_server
 9221            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9222                assert_eq!(
 9223                    params.text_document.uri,
 9224                    lsp::Url::from_file_path("/file.rs").unwrap()
 9225                );
 9226                assert_eq!(params.options.tab_size, 8);
 9227                Ok(Some(vec![]))
 9228            })
 9229            .next()
 9230            .await;
 9231        cx.foreground().start_waiting();
 9232        save.await.unwrap();
 9233    }
 9234
 9235    #[gpui::test]
 9236    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9237        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9238
 9239        let mut language = Language::new(
 9240            LanguageConfig {
 9241                name: "Rust".into(),
 9242                path_suffixes: vec!["rs".to_string()],
 9243                ..Default::default()
 9244            },
 9245            Some(tree_sitter_rust::language()),
 9246        );
 9247        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9248            capabilities: lsp::ServerCapabilities {
 9249                completion_provider: Some(lsp::CompletionOptions {
 9250                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9251                    ..Default::default()
 9252                }),
 9253                ..Default::default()
 9254            },
 9255            ..Default::default()
 9256        });
 9257
 9258        let text = "
 9259            one
 9260            two
 9261            three
 9262        "
 9263        .unindent();
 9264
 9265        let fs = FakeFs::new(cx.background().clone());
 9266        fs.insert_file("/file.rs", text).await;
 9267
 9268        let project = Project::test(fs, cx);
 9269        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9270
 9271        let worktree_id = project
 9272            .update(cx, |project, cx| {
 9273                project.find_or_create_local_worktree("/file.rs", true, cx)
 9274            })
 9275            .await
 9276            .unwrap()
 9277            .0
 9278            .read_with(cx, |tree, _| tree.id());
 9279        let buffer = project
 9280            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9281            .await
 9282            .unwrap();
 9283        let mut fake_server = fake_servers.next().await.unwrap();
 9284
 9285        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9286        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9287
 9288        editor.update(cx, |editor, cx| {
 9289            editor.project = Some(project);
 9290            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9291            editor.handle_input(&Input(".".to_string()), cx);
 9292        });
 9293
 9294        handle_completion_request(
 9295            &mut fake_server,
 9296            "/file.rs",
 9297            Point::new(0, 4),
 9298            vec![
 9299                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9300                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9301            ],
 9302        )
 9303        .await;
 9304        editor
 9305            .condition(&cx, |editor, _| editor.context_menu_visible())
 9306            .await;
 9307
 9308        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9309            editor.move_down(&MoveDown, cx);
 9310            let apply_additional_edits = editor
 9311                .confirm_completion(&ConfirmCompletion::default(), cx)
 9312                .unwrap();
 9313            assert_eq!(
 9314                editor.text(cx),
 9315                "
 9316                    one.second_completion
 9317                    two
 9318                    three
 9319                "
 9320                .unindent()
 9321            );
 9322            apply_additional_edits
 9323        });
 9324
 9325        handle_resolve_completion_request(
 9326            &mut fake_server,
 9327            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9328        )
 9329        .await;
 9330        apply_additional_edits.await.unwrap();
 9331        assert_eq!(
 9332            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9333            "
 9334                one.second_completion
 9335                two
 9336                three
 9337                additional edit
 9338            "
 9339            .unindent()
 9340        );
 9341
 9342        editor.update(cx, |editor, cx| {
 9343            editor.select_ranges(
 9344                [
 9345                    Point::new(1, 3)..Point::new(1, 3),
 9346                    Point::new(2, 5)..Point::new(2, 5),
 9347                ],
 9348                None,
 9349                cx,
 9350            );
 9351
 9352            editor.handle_input(&Input(" ".to_string()), cx);
 9353            assert!(editor.context_menu.is_none());
 9354            editor.handle_input(&Input("s".to_string()), cx);
 9355            assert!(editor.context_menu.is_none());
 9356        });
 9357
 9358        handle_completion_request(
 9359            &mut fake_server,
 9360            "/file.rs",
 9361            Point::new(2, 7),
 9362            vec![
 9363                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9364                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9365                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9366            ],
 9367        )
 9368        .await;
 9369        editor
 9370            .condition(&cx, |editor, _| editor.context_menu_visible())
 9371            .await;
 9372
 9373        editor.update(cx, |editor, cx| {
 9374            editor.handle_input(&Input("i".to_string()), cx);
 9375        });
 9376
 9377        handle_completion_request(
 9378            &mut fake_server,
 9379            "/file.rs",
 9380            Point::new(2, 8),
 9381            vec![
 9382                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9383                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9384                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9385            ],
 9386        )
 9387        .await;
 9388        editor
 9389            .condition(&cx, |editor, _| editor.context_menu_visible())
 9390            .await;
 9391
 9392        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9393            let apply_additional_edits = editor
 9394                .confirm_completion(&ConfirmCompletion::default(), cx)
 9395                .unwrap();
 9396            assert_eq!(
 9397                editor.text(cx),
 9398                "
 9399                    one.second_completion
 9400                    two sixth_completion
 9401                    three sixth_completion
 9402                    additional edit
 9403                "
 9404                .unindent()
 9405            );
 9406            apply_additional_edits
 9407        });
 9408        handle_resolve_completion_request(&mut fake_server, None).await;
 9409        apply_additional_edits.await.unwrap();
 9410
 9411        async fn handle_completion_request(
 9412            fake: &mut FakeLanguageServer,
 9413            path: &'static str,
 9414            position: Point,
 9415            completions: Vec<(Range<Point>, &'static str)>,
 9416        ) {
 9417            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9418                let completions = completions.clone();
 9419                async move {
 9420                    assert_eq!(
 9421                        params.text_document_position.text_document.uri,
 9422                        lsp::Url::from_file_path(path).unwrap()
 9423                    );
 9424                    assert_eq!(
 9425                        params.text_document_position.position,
 9426                        lsp::Position::new(position.row, position.column)
 9427                    );
 9428                    Ok(Some(lsp::CompletionResponse::Array(
 9429                        completions
 9430                            .iter()
 9431                            .map(|(range, new_text)| lsp::CompletionItem {
 9432                                label: new_text.to_string(),
 9433                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9434                                    range: lsp::Range::new(
 9435                                        lsp::Position::new(range.start.row, range.start.column),
 9436                                        lsp::Position::new(range.start.row, range.start.column),
 9437                                    ),
 9438                                    new_text: new_text.to_string(),
 9439                                })),
 9440                                ..Default::default()
 9441                            })
 9442                            .collect(),
 9443                    )))
 9444                }
 9445            })
 9446            .next()
 9447            .await;
 9448        }
 9449
 9450        async fn handle_resolve_completion_request(
 9451            fake: &mut FakeLanguageServer,
 9452            edit: Option<(Range<Point>, &'static str)>,
 9453        ) {
 9454            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9455                let edit = edit.clone();
 9456                async move {
 9457                    Ok(lsp::CompletionItem {
 9458                        additional_text_edits: edit.map(|(range, new_text)| {
 9459                            vec![lsp::TextEdit::new(
 9460                                lsp::Range::new(
 9461                                    lsp::Position::new(range.start.row, range.start.column),
 9462                                    lsp::Position::new(range.end.row, range.end.column),
 9463                                ),
 9464                                new_text.to_string(),
 9465                            )]
 9466                        }),
 9467                        ..Default::default()
 9468                    })
 9469                }
 9470            })
 9471            .next()
 9472            .await;
 9473        }
 9474    }
 9475
 9476    #[gpui::test]
 9477    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9478        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9479        let language = Arc::new(Language::new(
 9480            LanguageConfig {
 9481                line_comment: Some("// ".to_string()),
 9482                ..Default::default()
 9483            },
 9484            Some(tree_sitter_rust::language()),
 9485        ));
 9486
 9487        let text = "
 9488            fn a() {
 9489                //b();
 9490                // c();
 9491                //  d();
 9492            }
 9493        "
 9494        .unindent();
 9495
 9496        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9497        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9498        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9499
 9500        view.update(cx, |editor, cx| {
 9501            // If multiple selections intersect a line, the line is only
 9502            // toggled once.
 9503            editor.select_display_ranges(
 9504                &[
 9505                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9506                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9507                ],
 9508                cx,
 9509            );
 9510            editor.toggle_comments(&ToggleComments, cx);
 9511            assert_eq!(
 9512                editor.text(cx),
 9513                "
 9514                    fn a() {
 9515                        b();
 9516                        c();
 9517                         d();
 9518                    }
 9519                "
 9520                .unindent()
 9521            );
 9522
 9523            // The comment prefix is inserted at the same column for every line
 9524            // in a selection.
 9525            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9526            editor.toggle_comments(&ToggleComments, cx);
 9527            assert_eq!(
 9528                editor.text(cx),
 9529                "
 9530                    fn a() {
 9531                        // b();
 9532                        // c();
 9533                        //  d();
 9534                    }
 9535                "
 9536                .unindent()
 9537            );
 9538
 9539            // If a selection ends at the beginning of a line, that line is not toggled.
 9540            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9541            editor.toggle_comments(&ToggleComments, cx);
 9542            assert_eq!(
 9543                editor.text(cx),
 9544                "
 9545                        fn a() {
 9546                            // b();
 9547                            c();
 9548                            //  d();
 9549                        }
 9550                    "
 9551                .unindent()
 9552            );
 9553        });
 9554    }
 9555
 9556    #[gpui::test]
 9557    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9558        cx.set_global(Settings::test(cx));
 9559        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9560        let multibuffer = cx.add_model(|cx| {
 9561            let mut multibuffer = MultiBuffer::new(0);
 9562            multibuffer.push_excerpts(
 9563                buffer.clone(),
 9564                [
 9565                    Point::new(0, 0)..Point::new(0, 4),
 9566                    Point::new(1, 0)..Point::new(1, 4),
 9567                ],
 9568                cx,
 9569            );
 9570            multibuffer
 9571        });
 9572
 9573        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9574
 9575        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9576        view.update(cx, |view, cx| {
 9577            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9578            view.select_ranges(
 9579                [
 9580                    Point::new(0, 0)..Point::new(0, 0),
 9581                    Point::new(1, 0)..Point::new(1, 0),
 9582                ],
 9583                None,
 9584                cx,
 9585            );
 9586
 9587            view.handle_input(&Input("X".to_string()), cx);
 9588            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9589            assert_eq!(
 9590                view.selected_ranges(cx),
 9591                [
 9592                    Point::new(0, 1)..Point::new(0, 1),
 9593                    Point::new(1, 1)..Point::new(1, 1),
 9594                ]
 9595            )
 9596        });
 9597    }
 9598
 9599    #[gpui::test]
 9600    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9601        cx.set_global(Settings::test(cx));
 9602        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9603        let multibuffer = cx.add_model(|cx| {
 9604            let mut multibuffer = MultiBuffer::new(0);
 9605            multibuffer.push_excerpts(
 9606                buffer,
 9607                [
 9608                    Point::new(0, 0)..Point::new(1, 4),
 9609                    Point::new(1, 0)..Point::new(2, 4),
 9610                ],
 9611                cx,
 9612            );
 9613            multibuffer
 9614        });
 9615
 9616        assert_eq!(
 9617            multibuffer.read(cx).read(cx).text(),
 9618            "aaaa\nbbbb\nbbbb\ncccc"
 9619        );
 9620
 9621        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9622        view.update(cx, |view, cx| {
 9623            view.select_ranges(
 9624                [
 9625                    Point::new(1, 1)..Point::new(1, 1),
 9626                    Point::new(2, 3)..Point::new(2, 3),
 9627                ],
 9628                None,
 9629                cx,
 9630            );
 9631
 9632            view.handle_input(&Input("X".to_string()), cx);
 9633            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9634            assert_eq!(
 9635                view.selected_ranges(cx),
 9636                [
 9637                    Point::new(1, 2)..Point::new(1, 2),
 9638                    Point::new(2, 5)..Point::new(2, 5),
 9639                ]
 9640            );
 9641
 9642            view.newline(&Newline, cx);
 9643            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9644            assert_eq!(
 9645                view.selected_ranges(cx),
 9646                [
 9647                    Point::new(2, 0)..Point::new(2, 0),
 9648                    Point::new(6, 0)..Point::new(6, 0),
 9649                ]
 9650            );
 9651        });
 9652    }
 9653
 9654    #[gpui::test]
 9655    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9656        cx.set_global(Settings::test(cx));
 9657        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9658        let mut excerpt1_id = None;
 9659        let multibuffer = cx.add_model(|cx| {
 9660            let mut multibuffer = MultiBuffer::new(0);
 9661            excerpt1_id = multibuffer
 9662                .push_excerpts(
 9663                    buffer.clone(),
 9664                    [
 9665                        Point::new(0, 0)..Point::new(1, 4),
 9666                        Point::new(1, 0)..Point::new(2, 4),
 9667                    ],
 9668                    cx,
 9669                )
 9670                .into_iter()
 9671                .next();
 9672            multibuffer
 9673        });
 9674        assert_eq!(
 9675            multibuffer.read(cx).read(cx).text(),
 9676            "aaaa\nbbbb\nbbbb\ncccc"
 9677        );
 9678        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9679            let mut editor = build_editor(multibuffer.clone(), cx);
 9680            let snapshot = editor.snapshot(cx);
 9681            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9682            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9683            assert_eq!(
 9684                editor.selected_ranges(cx),
 9685                [
 9686                    Point::new(1, 3)..Point::new(1, 3),
 9687                    Point::new(2, 1)..Point::new(2, 1),
 9688                ]
 9689            );
 9690            editor
 9691        });
 9692
 9693        // Refreshing selections is a no-op when excerpts haven't changed.
 9694        editor.update(cx, |editor, cx| {
 9695            editor.refresh_selections(cx);
 9696            assert_eq!(
 9697                editor.selected_ranges(cx),
 9698                [
 9699                    Point::new(1, 3)..Point::new(1, 3),
 9700                    Point::new(2, 1)..Point::new(2, 1),
 9701                ]
 9702            );
 9703        });
 9704
 9705        multibuffer.update(cx, |multibuffer, cx| {
 9706            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9707        });
 9708        editor.update(cx, |editor, cx| {
 9709            // Removing an excerpt causes the first selection to become degenerate.
 9710            assert_eq!(
 9711                editor.selected_ranges(cx),
 9712                [
 9713                    Point::new(0, 0)..Point::new(0, 0),
 9714                    Point::new(0, 1)..Point::new(0, 1)
 9715                ]
 9716            );
 9717
 9718            // Refreshing selections will relocate the first selection to the original buffer
 9719            // location.
 9720            editor.refresh_selections(cx);
 9721            assert_eq!(
 9722                editor.selected_ranges(cx),
 9723                [
 9724                    Point::new(0, 1)..Point::new(0, 1),
 9725                    Point::new(0, 3)..Point::new(0, 3)
 9726                ]
 9727            );
 9728            assert!(editor.pending_selection.is_some());
 9729        });
 9730    }
 9731
 9732    #[gpui::test]
 9733    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9734        cx.set_global(Settings::test(cx));
 9735        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9736        let mut excerpt1_id = None;
 9737        let multibuffer = cx.add_model(|cx| {
 9738            let mut multibuffer = MultiBuffer::new(0);
 9739            excerpt1_id = multibuffer
 9740                .push_excerpts(
 9741                    buffer.clone(),
 9742                    [
 9743                        Point::new(0, 0)..Point::new(1, 4),
 9744                        Point::new(1, 0)..Point::new(2, 4),
 9745                    ],
 9746                    cx,
 9747                )
 9748                .into_iter()
 9749                .next();
 9750            multibuffer
 9751        });
 9752        assert_eq!(
 9753            multibuffer.read(cx).read(cx).text(),
 9754            "aaaa\nbbbb\nbbbb\ncccc"
 9755        );
 9756        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9757            let mut editor = build_editor(multibuffer.clone(), cx);
 9758            let snapshot = editor.snapshot(cx);
 9759            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9760            assert_eq!(
 9761                editor.selected_ranges(cx),
 9762                [Point::new(1, 3)..Point::new(1, 3)]
 9763            );
 9764            editor
 9765        });
 9766
 9767        multibuffer.update(cx, |multibuffer, cx| {
 9768            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9769        });
 9770        editor.update(cx, |editor, cx| {
 9771            assert_eq!(
 9772                editor.selected_ranges(cx),
 9773                [Point::new(0, 0)..Point::new(0, 0)]
 9774            );
 9775
 9776            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9777            editor.refresh_selections(cx);
 9778            assert_eq!(
 9779                editor.selected_ranges(cx),
 9780                [Point::new(0, 3)..Point::new(0, 3)]
 9781            );
 9782            assert!(editor.pending_selection.is_some());
 9783        });
 9784    }
 9785
 9786    #[gpui::test]
 9787    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9788        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9789        let language = Arc::new(Language::new(
 9790            LanguageConfig {
 9791                brackets: vec![
 9792                    BracketPair {
 9793                        start: "{".to_string(),
 9794                        end: "}".to_string(),
 9795                        close: true,
 9796                        newline: true,
 9797                    },
 9798                    BracketPair {
 9799                        start: "/* ".to_string(),
 9800                        end: " */".to_string(),
 9801                        close: true,
 9802                        newline: true,
 9803                    },
 9804                ],
 9805                ..Default::default()
 9806            },
 9807            Some(tree_sitter_rust::language()),
 9808        ));
 9809
 9810        let text = concat!(
 9811            "{   }\n",     // Suppress rustfmt
 9812            "  x\n",       //
 9813            "  /*   */\n", //
 9814            "x\n",         //
 9815            "{{} }\n",     //
 9816        );
 9817
 9818        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9819        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9820        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9821        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9822            .await;
 9823
 9824        view.update(cx, |view, cx| {
 9825            view.select_display_ranges(
 9826                &[
 9827                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9828                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9829                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9830                ],
 9831                cx,
 9832            );
 9833            view.newline(&Newline, cx);
 9834
 9835            assert_eq!(
 9836                view.buffer().read(cx).read(cx).text(),
 9837                concat!(
 9838                    "{ \n",    // Suppress rustfmt
 9839                    "\n",      //
 9840                    "}\n",     //
 9841                    "  x\n",   //
 9842                    "  /* \n", //
 9843                    "  \n",    //
 9844                    "  */\n",  //
 9845                    "x\n",     //
 9846                    "{{} \n",  //
 9847                    "}\n",     //
 9848                )
 9849            );
 9850        });
 9851    }
 9852
 9853    #[gpui::test]
 9854    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9855        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9856
 9857        cx.set_global(Settings::test(cx));
 9858        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9859
 9860        editor.update(cx, |editor, cx| {
 9861            struct Type1;
 9862            struct Type2;
 9863
 9864            let buffer = buffer.read(cx).snapshot(cx);
 9865
 9866            let anchor_range = |range: Range<Point>| {
 9867                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9868            };
 9869
 9870            editor.highlight_background::<Type1>(
 9871                vec![
 9872                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
 9873                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
 9874                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
 9875                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
 9876                ],
 9877                |_| Color::red(),
 9878                cx,
 9879            );
 9880            editor.highlight_background::<Type2>(
 9881                vec![
 9882                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
 9883                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
 9884                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
 9885                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
 9886                ],
 9887                |_| Color::green(),
 9888                cx,
 9889            );
 9890
 9891            let snapshot = editor.snapshot(cx);
 9892            let mut highlighted_ranges = editor.background_highlights_in_range(
 9893                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
 9894                &snapshot,
 9895                cx.global::<Settings>().theme.as_ref(),
 9896            );
 9897            // Enforce a consistent ordering based on color without relying on the ordering of the
 9898            // highlight's `TypeId` which is non-deterministic.
 9899            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9900            assert_eq!(
 9901                highlighted_ranges,
 9902                &[
 9903                    (
 9904                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9905                        Color::green(),
 9906                    ),
 9907                    (
 9908                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9909                        Color::green(),
 9910                    ),
 9911                    (
 9912                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9913                        Color::red(),
 9914                    ),
 9915                    (
 9916                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9917                        Color::red(),
 9918                    ),
 9919                ]
 9920            );
 9921            assert_eq!(
 9922                editor.background_highlights_in_range(
 9923                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9924                    &snapshot,
 9925                    cx.global::<Settings>().theme.as_ref(),
 9926                ),
 9927                &[(
 9928                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9929                    Color::red(),
 9930                )]
 9931            );
 9932        });
 9933    }
 9934
 9935    #[gpui::test]
 9936    fn test_following(cx: &mut gpui::MutableAppContext) {
 9937        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9938
 9939        cx.set_global(Settings::test(cx));
 9940
 9941        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9942        let (_, follower) = cx.add_window(
 9943            WindowOptions {
 9944                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
 9945                ..Default::default()
 9946            },
 9947            |cx| build_editor(buffer.clone(), cx),
 9948        );
 9949
 9950        let pending_update = Rc::new(RefCell::new(None));
 9951        follower.update(cx, {
 9952            let update = pending_update.clone();
 9953            |_, cx| {
 9954                cx.subscribe(&leader, move |_, leader, event, cx| {
 9955                    leader
 9956                        .read(cx)
 9957                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
 9958                })
 9959                .detach();
 9960            }
 9961        });
 9962
 9963        // Update the selections only
 9964        leader.update(cx, |leader, cx| {
 9965            leader.select_ranges([1..1], None, 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![1..1]);
 9973
 9974        // Update the scroll position only
 9975        leader.update(cx, |leader, cx| {
 9976            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9977        });
 9978        follower.update(cx, |follower, cx| {
 9979            follower
 9980                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9981                .unwrap();
 9982        });
 9983        assert_eq!(
 9984            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
 9985            vec2f(1.5, 3.5)
 9986        );
 9987
 9988        // Update the selections and scroll position
 9989        leader.update(cx, |leader, cx| {
 9990            leader.select_ranges([0..0], None, cx);
 9991            leader.request_autoscroll(Autoscroll::Newest, cx);
 9992            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9993        });
 9994        follower.update(cx, |follower, cx| {
 9995            let initial_scroll_position = follower.scroll_position(cx);
 9996            follower
 9997                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9998                .unwrap();
 9999            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10000            assert!(follower.autoscroll_request.is_some());
10001        });
10002        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
10003
10004        // Creating a pending selection that precedes another selection
10005        leader.update(cx, |leader, cx| {
10006            leader.select_ranges([1..1], None, cx);
10007            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10008        });
10009        follower.update(cx, |follower, cx| {
10010            follower
10011                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10012                .unwrap();
10013        });
10014        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
10015
10016        // Extend the pending selection so that it surrounds another selection
10017        leader.update(cx, |leader, cx| {
10018            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10019        });
10020        follower.update(cx, |follower, cx| {
10021            follower
10022                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10023                .unwrap();
10024        });
10025        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
10026    }
10027
10028    #[test]
10029    fn test_combine_syntax_and_fuzzy_match_highlights() {
10030        let string = "abcdefghijklmnop";
10031        let syntax_ranges = [
10032            (
10033                0..3,
10034                HighlightStyle {
10035                    color: Some(Color::red()),
10036                    ..Default::default()
10037                },
10038            ),
10039            (
10040                4..8,
10041                HighlightStyle {
10042                    color: Some(Color::green()),
10043                    ..Default::default()
10044                },
10045            ),
10046        ];
10047        let match_indices = [4, 6, 7, 8];
10048        assert_eq!(
10049            combine_syntax_and_fuzzy_match_highlights(
10050                &string,
10051                Default::default(),
10052                syntax_ranges.into_iter(),
10053                &match_indices,
10054            ),
10055            &[
10056                (
10057                    0..3,
10058                    HighlightStyle {
10059                        color: Some(Color::red()),
10060                        ..Default::default()
10061                    },
10062                ),
10063                (
10064                    4..5,
10065                    HighlightStyle {
10066                        color: Some(Color::green()),
10067                        weight: Some(fonts::Weight::BOLD),
10068                        ..Default::default()
10069                    },
10070                ),
10071                (
10072                    5..6,
10073                    HighlightStyle {
10074                        color: Some(Color::green()),
10075                        ..Default::default()
10076                    },
10077                ),
10078                (
10079                    6..8,
10080                    HighlightStyle {
10081                        color: Some(Color::green()),
10082                        weight: Some(fonts::Weight::BOLD),
10083                        ..Default::default()
10084                    },
10085                ),
10086                (
10087                    8..9,
10088                    HighlightStyle {
10089                        weight: Some(fonts::Weight::BOLD),
10090                        ..Default::default()
10091                    },
10092                ),
10093            ]
10094        );
10095    }
10096
10097    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10098        let point = DisplayPoint::new(row as u32, column as u32);
10099        point..point
10100    }
10101
10102    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10103        Editor::new(EditorMode::Full, buffer, None, None, cx)
10104    }
10105
10106    fn assert_selection_ranges(
10107        marked_text: &str,
10108        selection_marker_pairs: Vec<(char, char)>,
10109        view: &mut Editor,
10110        cx: &mut ViewContext<Editor>,
10111    ) {
10112        let snapshot = view.snapshot(cx).display_snapshot;
10113        let mut marker_chars = Vec::new();
10114        for (start, end) in selection_marker_pairs.iter() {
10115            marker_chars.push(*start);
10116            marker_chars.push(*end);
10117        }
10118        let (_, markers) = marked_text_by(marked_text, marker_chars);
10119        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10120            .iter()
10121            .map(|(start, end)| {
10122                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10123                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10124                start..end
10125            })
10126            .collect();
10127        assert_eq!(
10128            view.selected_display_ranges(cx),
10129            &asserted_ranges[..],
10130            "Assert selections are {}",
10131            marked_text
10132        );
10133    }
10134}
10135
10136trait RangeExt<T> {
10137    fn sorted(&self) -> Range<T>;
10138    fn to_inclusive(&self) -> RangeInclusive<T>;
10139}
10140
10141impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10142    fn sorted(&self) -> Self {
10143        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10144    }
10145
10146    fn to_inclusive(&self) -> RangeInclusive<T> {
10147        self.start.clone()..=self.end.clone()
10148    }
10149}