editor.rs

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