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