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