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