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_point: 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_point: 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            editor
 6826        });
 6827    }
 6828
 6829    #[gpui::test]
 6830    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6831        cx.set_global(Settings::test(cx));
 6832        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6833        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6834
 6835        view.update(cx, |view, cx| {
 6836            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6837            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6838            view.end_selection(cx);
 6839
 6840            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6841            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6842            view.end_selection(cx);
 6843            assert_eq!(
 6844                view.selected_display_ranges(cx),
 6845                [
 6846                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6847                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6848                ]
 6849            );
 6850        });
 6851
 6852        view.update(cx, |view, cx| {
 6853            view.cancel(&Cancel, cx);
 6854            assert_eq!(
 6855                view.selected_display_ranges(cx),
 6856                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6857            );
 6858        });
 6859
 6860        view.update(cx, |view, cx| {
 6861            view.cancel(&Cancel, cx);
 6862            assert_eq!(
 6863                view.selected_display_ranges(cx),
 6864                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6865            );
 6866        });
 6867    }
 6868
 6869    #[gpui::test]
 6870    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6871        cx.set_global(Settings::test(cx));
 6872        let buffer = MultiBuffer::build_simple(
 6873            &"
 6874                impl Foo {
 6875                    // Hello!
 6876
 6877                    fn a() {
 6878                        1
 6879                    }
 6880
 6881                    fn b() {
 6882                        2
 6883                    }
 6884
 6885                    fn c() {
 6886                        3
 6887                    }
 6888                }
 6889            "
 6890            .unindent(),
 6891            cx,
 6892        );
 6893        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6894
 6895        view.update(cx, |view, cx| {
 6896            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 6897            view.fold(&Fold, cx);
 6898            assert_eq!(
 6899                view.display_text(cx),
 6900                "
 6901                    impl Foo {
 6902                        // Hello!
 6903
 6904                        fn a() {
 6905                            1
 6906                        }
 6907
 6908                        fn b() {…
 6909                        }
 6910
 6911                        fn c() {…
 6912                        }
 6913                    }
 6914                "
 6915                .unindent(),
 6916            );
 6917
 6918            view.fold(&Fold, cx);
 6919            assert_eq!(
 6920                view.display_text(cx),
 6921                "
 6922                    impl Foo {…
 6923                    }
 6924                "
 6925                .unindent(),
 6926            );
 6927
 6928            view.unfold_lines(&UnfoldLines, cx);
 6929            assert_eq!(
 6930                view.display_text(cx),
 6931                "
 6932                    impl Foo {
 6933                        // Hello!
 6934
 6935                        fn a() {
 6936                            1
 6937                        }
 6938
 6939                        fn b() {…
 6940                        }
 6941
 6942                        fn c() {…
 6943                        }
 6944                    }
 6945                "
 6946                .unindent(),
 6947            );
 6948
 6949            view.unfold_lines(&UnfoldLines, cx);
 6950            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6951        });
 6952    }
 6953
 6954    #[gpui::test]
 6955    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6956        cx.set_global(Settings::test(cx));
 6957        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6958        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6959
 6960        buffer.update(cx, |buffer, cx| {
 6961            buffer.edit(
 6962                vec![
 6963                    Point::new(1, 0)..Point::new(1, 0),
 6964                    Point::new(1, 1)..Point::new(1, 1),
 6965                ],
 6966                "\t",
 6967                cx,
 6968            );
 6969        });
 6970
 6971        view.update(cx, |view, cx| {
 6972            assert_eq!(
 6973                view.selected_display_ranges(cx),
 6974                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6975            );
 6976
 6977            view.move_down(&MoveDown, cx);
 6978            assert_eq!(
 6979                view.selected_display_ranges(cx),
 6980                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6981            );
 6982
 6983            view.move_right(&MoveRight, cx);
 6984            assert_eq!(
 6985                view.selected_display_ranges(cx),
 6986                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6987            );
 6988
 6989            view.move_left(&MoveLeft, cx);
 6990            assert_eq!(
 6991                view.selected_display_ranges(cx),
 6992                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6993            );
 6994
 6995            view.move_up(&MoveUp, cx);
 6996            assert_eq!(
 6997                view.selected_display_ranges(cx),
 6998                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6999            );
 7000
 7001            view.move_to_end(&MoveToEnd, cx);
 7002            assert_eq!(
 7003                view.selected_display_ranges(cx),
 7004                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7005            );
 7006
 7007            view.move_to_beginning(&MoveToBeginning, cx);
 7008            assert_eq!(
 7009                view.selected_display_ranges(cx),
 7010                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7011            );
 7012
 7013            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7014            view.select_to_beginning(&SelectToBeginning, cx);
 7015            assert_eq!(
 7016                view.selected_display_ranges(cx),
 7017                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7018            );
 7019
 7020            view.select_to_end(&SelectToEnd, cx);
 7021            assert_eq!(
 7022                view.selected_display_ranges(cx),
 7023                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7024            );
 7025        });
 7026    }
 7027
 7028    #[gpui::test]
 7029    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7030        cx.set_global(Settings::test(cx));
 7031        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7032        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7033
 7034        assert_eq!('ⓐ'.len_utf8(), 3);
 7035        assert_eq!('α'.len_utf8(), 2);
 7036
 7037        view.update(cx, |view, cx| {
 7038            view.fold_ranges(
 7039                vec![
 7040                    Point::new(0, 6)..Point::new(0, 12),
 7041                    Point::new(1, 2)..Point::new(1, 4),
 7042                    Point::new(2, 4)..Point::new(2, 8),
 7043                ],
 7044                cx,
 7045            );
 7046            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7047
 7048            view.move_right(&MoveRight, cx);
 7049            assert_eq!(
 7050                view.selected_display_ranges(cx),
 7051                &[empty_range(0, "".len())]
 7052            );
 7053            view.move_right(&MoveRight, cx);
 7054            assert_eq!(
 7055                view.selected_display_ranges(cx),
 7056                &[empty_range(0, "ⓐⓑ".len())]
 7057            );
 7058            view.move_right(&MoveRight, cx);
 7059            assert_eq!(
 7060                view.selected_display_ranges(cx),
 7061                &[empty_range(0, "ⓐⓑ…".len())]
 7062            );
 7063
 7064            view.move_down(&MoveDown, cx);
 7065            assert_eq!(
 7066                view.selected_display_ranges(cx),
 7067                &[empty_range(1, "ab…".len())]
 7068            );
 7069            view.move_left(&MoveLeft, cx);
 7070            assert_eq!(
 7071                view.selected_display_ranges(cx),
 7072                &[empty_range(1, "ab".len())]
 7073            );
 7074            view.move_left(&MoveLeft, cx);
 7075            assert_eq!(
 7076                view.selected_display_ranges(cx),
 7077                &[empty_range(1, "a".len())]
 7078            );
 7079
 7080            view.move_down(&MoveDown, cx);
 7081            assert_eq!(
 7082                view.selected_display_ranges(cx),
 7083                &[empty_range(2, "α".len())]
 7084            );
 7085            view.move_right(&MoveRight, cx);
 7086            assert_eq!(
 7087                view.selected_display_ranges(cx),
 7088                &[empty_range(2, "αβ".len())]
 7089            );
 7090            view.move_right(&MoveRight, cx);
 7091            assert_eq!(
 7092                view.selected_display_ranges(cx),
 7093                &[empty_range(2, "αβ…".len())]
 7094            );
 7095            view.move_right(&MoveRight, cx);
 7096            assert_eq!(
 7097                view.selected_display_ranges(cx),
 7098                &[empty_range(2, "αβ…ε".len())]
 7099            );
 7100
 7101            view.move_up(&MoveUp, cx);
 7102            assert_eq!(
 7103                view.selected_display_ranges(cx),
 7104                &[empty_range(1, "ab…e".len())]
 7105            );
 7106            view.move_up(&MoveUp, cx);
 7107            assert_eq!(
 7108                view.selected_display_ranges(cx),
 7109                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7110            );
 7111            view.move_left(&MoveLeft, cx);
 7112            assert_eq!(
 7113                view.selected_display_ranges(cx),
 7114                &[empty_range(0, "ⓐⓑ…".len())]
 7115            );
 7116            view.move_left(&MoveLeft, cx);
 7117            assert_eq!(
 7118                view.selected_display_ranges(cx),
 7119                &[empty_range(0, "ⓐⓑ".len())]
 7120            );
 7121            view.move_left(&MoveLeft, cx);
 7122            assert_eq!(
 7123                view.selected_display_ranges(cx),
 7124                &[empty_range(0, "".len())]
 7125            );
 7126        });
 7127    }
 7128
 7129    #[gpui::test]
 7130    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7131        cx.set_global(Settings::test(cx));
 7132        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7133        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7134        view.update(cx, |view, cx| {
 7135            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7136            view.move_down(&MoveDown, cx);
 7137            assert_eq!(
 7138                view.selected_display_ranges(cx),
 7139                &[empty_range(1, "abcd".len())]
 7140            );
 7141
 7142            view.move_down(&MoveDown, cx);
 7143            assert_eq!(
 7144                view.selected_display_ranges(cx),
 7145                &[empty_range(2, "αβγ".len())]
 7146            );
 7147
 7148            view.move_down(&MoveDown, cx);
 7149            assert_eq!(
 7150                view.selected_display_ranges(cx),
 7151                &[empty_range(3, "abcd".len())]
 7152            );
 7153
 7154            view.move_down(&MoveDown, cx);
 7155            assert_eq!(
 7156                view.selected_display_ranges(cx),
 7157                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7158            );
 7159
 7160            view.move_up(&MoveUp, cx);
 7161            assert_eq!(
 7162                view.selected_display_ranges(cx),
 7163                &[empty_range(3, "abcd".len())]
 7164            );
 7165
 7166            view.move_up(&MoveUp, cx);
 7167            assert_eq!(
 7168                view.selected_display_ranges(cx),
 7169                &[empty_range(2, "αβγ".len())]
 7170            );
 7171        });
 7172    }
 7173
 7174    #[gpui::test]
 7175    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7176        cx.set_global(Settings::test(cx));
 7177        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7178        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7179        view.update(cx, |view, cx| {
 7180            view.select_display_ranges(
 7181                &[
 7182                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7183                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7184                ],
 7185                cx,
 7186            );
 7187        });
 7188
 7189        view.update(cx, |view, cx| {
 7190            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7191            assert_eq!(
 7192                view.selected_display_ranges(cx),
 7193                &[
 7194                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7195                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7196                ]
 7197            );
 7198        });
 7199
 7200        view.update(cx, |view, cx| {
 7201            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7202            assert_eq!(
 7203                view.selected_display_ranges(cx),
 7204                &[
 7205                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7206                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7207                ]
 7208            );
 7209        });
 7210
 7211        view.update(cx, |view, cx| {
 7212            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7213            assert_eq!(
 7214                view.selected_display_ranges(cx),
 7215                &[
 7216                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7217                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7218                ]
 7219            );
 7220        });
 7221
 7222        view.update(cx, |view, cx| {
 7223            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7224            assert_eq!(
 7225                view.selected_display_ranges(cx),
 7226                &[
 7227                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7228                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7229                ]
 7230            );
 7231        });
 7232
 7233        // Moving to the end of line again is a no-op.
 7234        view.update(cx, |view, cx| {
 7235            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7236            assert_eq!(
 7237                view.selected_display_ranges(cx),
 7238                &[
 7239                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7240                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7241                ]
 7242            );
 7243        });
 7244
 7245        view.update(cx, |view, cx| {
 7246            view.move_left(&MoveLeft, cx);
 7247            view.select_to_beginning_of_line(
 7248                &SelectToBeginningOfLine {
 7249                    stop_at_soft_wraps: true,
 7250                },
 7251                cx,
 7252            );
 7253            assert_eq!(
 7254                view.selected_display_ranges(cx),
 7255                &[
 7256                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7257                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7258                ]
 7259            );
 7260        });
 7261
 7262        view.update(cx, |view, cx| {
 7263            view.select_to_beginning_of_line(
 7264                &SelectToBeginningOfLine {
 7265                    stop_at_soft_wraps: true,
 7266                },
 7267                cx,
 7268            );
 7269            assert_eq!(
 7270                view.selected_display_ranges(cx),
 7271                &[
 7272                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7273                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7274                ]
 7275            );
 7276        });
 7277
 7278        view.update(cx, |view, cx| {
 7279            view.select_to_beginning_of_line(
 7280                &SelectToBeginningOfLine {
 7281                    stop_at_soft_wraps: true,
 7282                },
 7283                cx,
 7284            );
 7285            assert_eq!(
 7286                view.selected_display_ranges(cx),
 7287                &[
 7288                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7289                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7290                ]
 7291            );
 7292        });
 7293
 7294        view.update(cx, |view, cx| {
 7295            view.select_to_end_of_line(
 7296                &SelectToEndOfLine {
 7297                    stop_at_soft_wraps: true,
 7298                },
 7299                cx,
 7300            );
 7301            assert_eq!(
 7302                view.selected_display_ranges(cx),
 7303                &[
 7304                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7305                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7306                ]
 7307            );
 7308        });
 7309
 7310        view.update(cx, |view, cx| {
 7311            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7312            assert_eq!(view.display_text(cx), "ab\n  de");
 7313            assert_eq!(
 7314                view.selected_display_ranges(cx),
 7315                &[
 7316                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7317                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7318                ]
 7319            );
 7320        });
 7321
 7322        view.update(cx, |view, cx| {
 7323            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7324            assert_eq!(view.display_text(cx), "\n");
 7325            assert_eq!(
 7326                view.selected_display_ranges(cx),
 7327                &[
 7328                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7329                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7330                ]
 7331            );
 7332        });
 7333    }
 7334
 7335    #[gpui::test]
 7336    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7337        cx.set_global(Settings::test(cx));
 7338        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7339        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7340        view.update(cx, |view, cx| {
 7341            view.select_display_ranges(
 7342                &[
 7343                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7344                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7345                ],
 7346                cx,
 7347            );
 7348
 7349            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7350            assert_selection_ranges(
 7351                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7352                vec![('<', '>'), ('[', ']')],
 7353                view,
 7354                cx,
 7355            );
 7356
 7357            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7358            assert_selection_ranges(
 7359                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7360                vec![('<', '>'), ('[', ']')],
 7361                view,
 7362                cx,
 7363            );
 7364
 7365            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7366            assert_selection_ranges(
 7367                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7368                vec![('<', '>'), ('[', ']')],
 7369                view,
 7370                cx,
 7371            );
 7372
 7373            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7374            assert_selection_ranges(
 7375                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7376                vec![('<', '>'), ('[', ']')],
 7377                view,
 7378                cx,
 7379            );
 7380
 7381            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7382            assert_selection_ranges(
 7383                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7384                vec![('<', '>'), ('[', ']')],
 7385                view,
 7386                cx,
 7387            );
 7388
 7389            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7390            assert_selection_ranges(
 7391                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7392                vec![('<', '>'), ('[', ']')],
 7393                view,
 7394                cx,
 7395            );
 7396
 7397            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7398            assert_selection_ranges(
 7399                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7400                vec![('<', '>'), ('[', ']')],
 7401                view,
 7402                cx,
 7403            );
 7404
 7405            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7406            assert_selection_ranges(
 7407                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7408                vec![('<', '>'), ('[', ']')],
 7409                view,
 7410                cx,
 7411            );
 7412
 7413            view.move_right(&MoveRight, cx);
 7414            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7415            assert_selection_ranges(
 7416                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7417                vec![('<', '>'), ('[', ']')],
 7418                view,
 7419                cx,
 7420            );
 7421
 7422            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7423            assert_selection_ranges(
 7424                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7425                vec![('<', '>'), ('[', ']')],
 7426                view,
 7427                cx,
 7428            );
 7429
 7430            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7431            assert_selection_ranges(
 7432                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7433                vec![('<', '>'), ('[', ']')],
 7434                view,
 7435                cx,
 7436            );
 7437        });
 7438    }
 7439
 7440    #[gpui::test]
 7441    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7442        cx.set_global(Settings::test(cx));
 7443        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7444        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7445
 7446        view.update(cx, |view, cx| {
 7447            view.set_wrap_width(Some(140.), cx);
 7448            assert_eq!(
 7449                view.display_text(cx),
 7450                "use one::{\n    two::three::\n    four::five\n};"
 7451            );
 7452
 7453            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7454
 7455            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7456            assert_eq!(
 7457                view.selected_display_ranges(cx),
 7458                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7459            );
 7460
 7461            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7462            assert_eq!(
 7463                view.selected_display_ranges(cx),
 7464                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7465            );
 7466
 7467            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7468            assert_eq!(
 7469                view.selected_display_ranges(cx),
 7470                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7471            );
 7472
 7473            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7474            assert_eq!(
 7475                view.selected_display_ranges(cx),
 7476                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7477            );
 7478
 7479            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7480            assert_eq!(
 7481                view.selected_display_ranges(cx),
 7482                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7483            );
 7484
 7485            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7486            assert_eq!(
 7487                view.selected_display_ranges(cx),
 7488                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7489            );
 7490        });
 7491    }
 7492
 7493    #[gpui::test]
 7494    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7495        cx.set_global(Settings::test(cx));
 7496        let (text, ranges) = marked_text_ranges("one [two three] four");
 7497        let buffer = MultiBuffer::build_simple(&text, cx);
 7498
 7499        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7500
 7501        editor.update(cx, |editor, cx| {
 7502            editor.select_ranges(ranges, None, cx);
 7503            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7504            assert_eq!(editor.text(cx), " four");
 7505        });
 7506    }
 7507
 7508    #[gpui::test]
 7509    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7510        cx.set_global(Settings::test(cx));
 7511        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7512        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7513
 7514        view.update(cx, |view, cx| {
 7515            view.select_display_ranges(
 7516                &[
 7517                    // an empty selection - the preceding word fragment is deleted
 7518                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7519                    // characters selected - they are deleted
 7520                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7521                ],
 7522                cx,
 7523            );
 7524            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7525        });
 7526
 7527        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7528
 7529        view.update(cx, |view, cx| {
 7530            view.select_display_ranges(
 7531                &[
 7532                    // an empty selection - the following word fragment is deleted
 7533                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7534                    // characters selected - they are deleted
 7535                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7536                ],
 7537                cx,
 7538            );
 7539            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7540        });
 7541
 7542        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7543    }
 7544
 7545    #[gpui::test]
 7546    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7547        cx.set_global(Settings::test(cx));
 7548        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7549        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7550
 7551        view.update(cx, |view, cx| {
 7552            view.select_display_ranges(
 7553                &[
 7554                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7555                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7556                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7557                ],
 7558                cx,
 7559            );
 7560
 7561            view.newline(&Newline, cx);
 7562            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7563        });
 7564    }
 7565
 7566    #[gpui::test]
 7567    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7568        cx.set_global(Settings::test(cx));
 7569        let buffer = MultiBuffer::build_simple(
 7570            "
 7571                a
 7572                b(
 7573                    X
 7574                )
 7575                c(
 7576                    X
 7577                )
 7578            "
 7579            .unindent()
 7580            .as_str(),
 7581            cx,
 7582        );
 7583
 7584        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7585            let mut editor = build_editor(buffer.clone(), cx);
 7586            editor.select_ranges(
 7587                [
 7588                    Point::new(2, 4)..Point::new(2, 5),
 7589                    Point::new(5, 4)..Point::new(5, 5),
 7590                ],
 7591                None,
 7592                cx,
 7593            );
 7594            editor
 7595        });
 7596
 7597        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7598        buffer.update(cx, |buffer, cx| {
 7599            buffer.edit(
 7600                [
 7601                    Point::new(1, 2)..Point::new(3, 0),
 7602                    Point::new(4, 2)..Point::new(6, 0),
 7603                ],
 7604                "",
 7605                cx,
 7606            );
 7607            assert_eq!(
 7608                buffer.read(cx).text(),
 7609                "
 7610                    a
 7611                    b()
 7612                    c()
 7613                "
 7614                .unindent()
 7615            );
 7616        });
 7617
 7618        editor.update(cx, |editor, cx| {
 7619            assert_eq!(
 7620                editor.selected_ranges(cx),
 7621                &[
 7622                    Point::new(1, 2)..Point::new(1, 2),
 7623                    Point::new(2, 2)..Point::new(2, 2),
 7624                ],
 7625            );
 7626
 7627            editor.newline(&Newline, cx);
 7628            assert_eq!(
 7629                editor.text(cx),
 7630                "
 7631                    a
 7632                    b(
 7633                    )
 7634                    c(
 7635                    )
 7636                "
 7637                .unindent()
 7638            );
 7639
 7640            // The selections are moved after the inserted newlines
 7641            assert_eq!(
 7642                editor.selected_ranges(cx),
 7643                &[
 7644                    Point::new(2, 0)..Point::new(2, 0),
 7645                    Point::new(4, 0)..Point::new(4, 0),
 7646                ],
 7647            );
 7648        });
 7649    }
 7650
 7651    #[gpui::test]
 7652    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7653        cx.set_global(Settings::test(cx));
 7654        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7655        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7656            let mut editor = build_editor(buffer.clone(), cx);
 7657            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7658            editor
 7659        });
 7660
 7661        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7662        buffer.update(cx, |buffer, cx| {
 7663            buffer.edit([2..5, 10..13, 18..21], "", cx);
 7664            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7665        });
 7666
 7667        editor.update(cx, |editor, cx| {
 7668            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7669
 7670            editor.insert("Z", cx);
 7671            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7672
 7673            // The selections are moved after the inserted characters
 7674            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7675        });
 7676    }
 7677
 7678    #[gpui::test]
 7679    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7680        cx.set_global(Settings::test(cx));
 7681        let buffer = MultiBuffer::build_simple(
 7682            indoc! {"
 7683                  one two
 7684                three
 7685                 four"},
 7686            cx,
 7687        );
 7688        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7689
 7690        view.update(cx, |view, cx| {
 7691            // two selections on the same line
 7692            select_ranges(
 7693                view,
 7694                indoc! {"
 7695                      [one] [two]
 7696                    three
 7697                     four"},
 7698                cx,
 7699            );
 7700
 7701            // indent from mid-tabstop to full tabstop
 7702            view.tab(&Tab, cx);
 7703            assert_text_with_selections(
 7704                view,
 7705                indoc! {"
 7706                        [one] [two]
 7707                    three
 7708                     four"},
 7709                cx,
 7710            );
 7711
 7712            // outdent from 1 tabstop to 0 tabstops
 7713            view.tab_prev(&TabPrev, cx);
 7714            assert_text_with_selections(
 7715                view,
 7716                indoc! {"
 7717                    [one] [two]
 7718                    three
 7719                     four"},
 7720                cx,
 7721            );
 7722
 7723            // select across line ending
 7724            select_ranges(
 7725                view,
 7726                indoc! {"
 7727                    one two
 7728                    t[hree
 7729                    ] four"},
 7730                cx,
 7731            );
 7732
 7733            // indent and outdent affect only the preceding line
 7734            view.tab(&Tab, cx);
 7735            assert_text_with_selections(
 7736                view,
 7737                indoc! {"
 7738                    one two
 7739                        t[hree
 7740                    ] four"},
 7741                cx,
 7742            );
 7743            view.tab_prev(&TabPrev, cx);
 7744            assert_text_with_selections(
 7745                view,
 7746                indoc! {"
 7747                    one two
 7748                    t[hree
 7749                    ] four"},
 7750                cx,
 7751            );
 7752
 7753            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7754            select_ranges(
 7755                view,
 7756                indoc! {"
 7757                    one two
 7758                    []three
 7759                     four"},
 7760                cx,
 7761            );
 7762            view.tab(&Tab, cx);
 7763            assert_text_with_selections(
 7764                view,
 7765                indoc! {"
 7766                    one two
 7767                        []three
 7768                     four"},
 7769                cx,
 7770            );
 7771
 7772            select_ranges(
 7773                view,
 7774                indoc! {"
 7775                    one two
 7776                    []    three
 7777                     four"},
 7778                cx,
 7779            );
 7780            view.tab_prev(&TabPrev, cx);
 7781            assert_text_with_selections(
 7782                view,
 7783                indoc! {"
 7784                    one two
 7785                    []three
 7786                     four"},
 7787                cx,
 7788            );
 7789        });
 7790    }
 7791
 7792    #[gpui::test]
 7793    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7794        cx.set_global(
 7795            Settings::test(cx)
 7796                .with_overrides(
 7797                    "TOML",
 7798                    LanguageOverride {
 7799                        tab_size: Some(2),
 7800                        ..Default::default()
 7801                    },
 7802                )
 7803                .with_overrides(
 7804                    "Rust",
 7805                    LanguageOverride {
 7806                        tab_size: Some(4),
 7807                        ..Default::default()
 7808                    },
 7809                ),
 7810        );
 7811        let toml_language = Arc::new(Language::new(
 7812            LanguageConfig {
 7813                name: "TOML".into(),
 7814                ..Default::default()
 7815            },
 7816            None,
 7817        ));
 7818        let rust_language = Arc::new(Language::new(
 7819            LanguageConfig {
 7820                name: "Rust".into(),
 7821                ..Default::default()
 7822            },
 7823            None,
 7824        ));
 7825
 7826        let toml_buffer = cx
 7827            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7828        let rust_buffer = cx.add_model(|cx| {
 7829            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7830        });
 7831        let multibuffer = cx.add_model(|cx| {
 7832            let mut multibuffer = MultiBuffer::new(0);
 7833            multibuffer.push_excerpts(
 7834                toml_buffer.clone(),
 7835                [Point::new(0, 0)..Point::new(2, 0)],
 7836                cx,
 7837            );
 7838            multibuffer.push_excerpts(
 7839                rust_buffer.clone(),
 7840                [Point::new(0, 0)..Point::new(1, 0)],
 7841                cx,
 7842            );
 7843            multibuffer
 7844        });
 7845
 7846        cx.add_window(Default::default(), |cx| {
 7847            let mut editor = build_editor(multibuffer, cx);
 7848
 7849            assert_eq!(
 7850                editor.text(cx),
 7851                indoc! {"
 7852                    a = 1
 7853                    b = 2
 7854
 7855                    const c: usize = 3;
 7856                "}
 7857            );
 7858
 7859            select_ranges(
 7860                &mut editor,
 7861                indoc! {"
 7862                    [a] = 1
 7863                    b = 2
 7864
 7865                    [const c:] usize = 3;
 7866                "},
 7867                cx,
 7868            );
 7869
 7870            editor.tab(&Tab, cx);
 7871            assert_text_with_selections(
 7872                &mut editor,
 7873                indoc! {"
 7874                      [a] = 1
 7875                    b = 2
 7876
 7877                        [const c:] usize = 3;
 7878                "},
 7879                cx,
 7880            );
 7881            editor.tab_prev(&TabPrev, cx);
 7882            assert_text_with_selections(
 7883                &mut editor,
 7884                indoc! {"
 7885                    [a] = 1
 7886                    b = 2
 7887
 7888                    [const c:] usize = 3;
 7889                "},
 7890                cx,
 7891            );
 7892
 7893            editor
 7894        });
 7895    }
 7896
 7897    #[gpui::test]
 7898    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 7899        cx.set_global(Settings::test(cx));
 7900        let (_, view) = cx.add_window(Default::default(), |cx| {
 7901            build_editor(MultiBuffer::build_simple("", cx), cx)
 7902        });
 7903
 7904        view.update(cx, |view, cx| {
 7905            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7906            view.select_display_ranges(
 7907                &[
 7908                    // an empty selection - the preceding character is deleted
 7909                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7910                    // one character selected - it is deleted
 7911                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7912                    // a line suffix selected - it is deleted
 7913                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7914                ],
 7915                cx,
 7916            );
 7917            view.backspace(&Backspace, cx);
 7918            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 7919
 7920            view.set_text("    one\n        two\n        three\n   four", cx);
 7921            view.select_display_ranges(
 7922                &[
 7923                    // cursors at the the end of leading indent - last indent is deleted
 7924                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 7925                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 7926                    // cursors inside leading indent - overlapping indent deletions are coalesced
 7927                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7928                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 7929                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 7930                    // cursor at the beginning of a line - preceding newline is deleted
 7931                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7932                    // selection inside leading indent - only the selected character is deleted
 7933                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 7934                ],
 7935                cx,
 7936            );
 7937            view.backspace(&Backspace, cx);
 7938            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 7939        });
 7940    }
 7941
 7942    #[gpui::test]
 7943    fn test_delete(cx: &mut gpui::MutableAppContext) {
 7944        cx.set_global(Settings::test(cx));
 7945        let buffer =
 7946            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7947        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7948
 7949        view.update(cx, |view, cx| {
 7950            view.select_display_ranges(
 7951                &[
 7952                    // an empty selection - the following character is deleted
 7953                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7954                    // one character selected - it is deleted
 7955                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7956                    // a line suffix selected - it is deleted
 7957                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7958                ],
 7959                cx,
 7960            );
 7961            view.delete(&Delete, cx);
 7962        });
 7963
 7964        assert_eq!(
 7965            buffer.read(cx).read(cx).text(),
 7966            "on two three\nfou five six\nseven ten\n"
 7967        );
 7968    }
 7969
 7970    #[gpui::test]
 7971    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7972        cx.set_global(Settings::test(cx));
 7973        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7974        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7975        view.update(cx, |view, cx| {
 7976            view.select_display_ranges(
 7977                &[
 7978                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7979                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7980                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7981                ],
 7982                cx,
 7983            );
 7984            view.delete_line(&DeleteLine, cx);
 7985            assert_eq!(view.display_text(cx), "ghi");
 7986            assert_eq!(
 7987                view.selected_display_ranges(cx),
 7988                vec![
 7989                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7990                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7991                ]
 7992            );
 7993        });
 7994
 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(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 8000            view.delete_line(&DeleteLine, cx);
 8001            assert_eq!(view.display_text(cx), "ghi\n");
 8002            assert_eq!(
 8003                view.selected_display_ranges(cx),
 8004                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8005            );
 8006        });
 8007    }
 8008
 8009    #[gpui::test]
 8010    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8011        cx.set_global(Settings::test(cx));
 8012        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8013        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8014        view.update(cx, |view, cx| {
 8015            view.select_display_ranges(
 8016                &[
 8017                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8018                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8019                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8020                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8021                ],
 8022                cx,
 8023            );
 8024            view.duplicate_line(&DuplicateLine, cx);
 8025            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8026            assert_eq!(
 8027                view.selected_display_ranges(cx),
 8028                vec![
 8029                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8030                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8031                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8032                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8033                ]
 8034            );
 8035        });
 8036
 8037        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8038        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8039        view.update(cx, |view, cx| {
 8040            view.select_display_ranges(
 8041                &[
 8042                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8043                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8044                ],
 8045                cx,
 8046            );
 8047            view.duplicate_line(&DuplicateLine, cx);
 8048            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8049            assert_eq!(
 8050                view.selected_display_ranges(cx),
 8051                vec![
 8052                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8053                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8054                ]
 8055            );
 8056        });
 8057    }
 8058
 8059    #[gpui::test]
 8060    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8061        cx.set_global(Settings::test(cx));
 8062        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8063        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8064        view.update(cx, |view, cx| {
 8065            view.fold_ranges(
 8066                vec![
 8067                    Point::new(0, 2)..Point::new(1, 2),
 8068                    Point::new(2, 3)..Point::new(4, 1),
 8069                    Point::new(7, 0)..Point::new(8, 4),
 8070                ],
 8071                cx,
 8072            );
 8073            view.select_display_ranges(
 8074                &[
 8075                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8076                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8077                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8078                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8079                ],
 8080                cx,
 8081            );
 8082            assert_eq!(
 8083                view.display_text(cx),
 8084                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8085            );
 8086
 8087            view.move_line_up(&MoveLineUp, cx);
 8088            assert_eq!(
 8089                view.display_text(cx),
 8090                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8091            );
 8092            assert_eq!(
 8093                view.selected_display_ranges(cx),
 8094                vec![
 8095                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8096                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8097                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8098                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8099                ]
 8100            );
 8101        });
 8102
 8103        view.update(cx, |view, cx| {
 8104            view.move_line_down(&MoveLineDown, cx);
 8105            assert_eq!(
 8106                view.display_text(cx),
 8107                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8108            );
 8109            assert_eq!(
 8110                view.selected_display_ranges(cx),
 8111                vec![
 8112                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8113                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8114                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8115                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8116                ]
 8117            );
 8118        });
 8119
 8120        view.update(cx, |view, cx| {
 8121            view.move_line_down(&MoveLineDown, cx);
 8122            assert_eq!(
 8123                view.display_text(cx),
 8124                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8125            );
 8126            assert_eq!(
 8127                view.selected_display_ranges(cx),
 8128                vec![
 8129                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8130                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8131                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8132                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8133                ]
 8134            );
 8135        });
 8136
 8137        view.update(cx, |view, cx| {
 8138            view.move_line_up(&MoveLineUp, cx);
 8139            assert_eq!(
 8140                view.display_text(cx),
 8141                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8142            );
 8143            assert_eq!(
 8144                view.selected_display_ranges(cx),
 8145                vec![
 8146                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8147                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8148                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8149                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8150                ]
 8151            );
 8152        });
 8153    }
 8154
 8155    #[gpui::test]
 8156    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8157        cx.set_global(Settings::test(cx));
 8158        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8159        let snapshot = buffer.read(cx).snapshot(cx);
 8160        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8161        editor.update(cx, |editor, cx| {
 8162            editor.insert_blocks(
 8163                [BlockProperties {
 8164                    position: snapshot.anchor_after(Point::new(2, 0)),
 8165                    disposition: BlockDisposition::Below,
 8166                    height: 1,
 8167                    render: Arc::new(|_| Empty::new().boxed()),
 8168                }],
 8169                cx,
 8170            );
 8171            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8172            editor.move_line_down(&MoveLineDown, cx);
 8173        });
 8174    }
 8175
 8176    #[gpui::test]
 8177    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8178        cx.set_global(Settings::test(cx));
 8179        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8180        let view = cx
 8181            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8182            .1;
 8183
 8184        // Cut with three selections. Clipboard text is divided into three slices.
 8185        view.update(cx, |view, cx| {
 8186            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8187            view.cut(&Cut, cx);
 8188            assert_eq!(view.display_text(cx), "two four six ");
 8189        });
 8190
 8191        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8192        view.update(cx, |view, cx| {
 8193            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8194            view.paste(&Paste, cx);
 8195            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8196            assert_eq!(
 8197                view.selected_display_ranges(cx),
 8198                &[
 8199                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8200                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8201                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8202                ]
 8203            );
 8204        });
 8205
 8206        // Paste again but with only two cursors. Since the number of cursors doesn't
 8207        // match the number of slices in the clipboard, the entire clipboard text
 8208        // is pasted at each cursor.
 8209        view.update(cx, |view, cx| {
 8210            view.select_ranges(vec![0..0, 31..31], None, cx);
 8211            view.handle_input(&Input("( ".into()), cx);
 8212            view.paste(&Paste, cx);
 8213            view.handle_input(&Input(") ".into()), cx);
 8214            assert_eq!(
 8215                view.display_text(cx),
 8216                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8217            );
 8218        });
 8219
 8220        view.update(cx, |view, cx| {
 8221            view.select_ranges(vec![0..0], None, cx);
 8222            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8223            assert_eq!(
 8224                view.display_text(cx),
 8225                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8226            );
 8227        });
 8228
 8229        // Cut with three selections, one of which is full-line.
 8230        view.update(cx, |view, cx| {
 8231            view.select_display_ranges(
 8232                &[
 8233                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8234                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8235                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8236                ],
 8237                cx,
 8238            );
 8239            view.cut(&Cut, cx);
 8240            assert_eq!(
 8241                view.display_text(cx),
 8242                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8243            );
 8244        });
 8245
 8246        // Paste with three selections, noticing how the copied selection that was full-line
 8247        // gets inserted before the second cursor.
 8248        view.update(cx, |view, cx| {
 8249            view.select_display_ranges(
 8250                &[
 8251                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8252                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8253                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8254                ],
 8255                cx,
 8256            );
 8257            view.paste(&Paste, cx);
 8258            assert_eq!(
 8259                view.display_text(cx),
 8260                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8261            );
 8262            assert_eq!(
 8263                view.selected_display_ranges(cx),
 8264                &[
 8265                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8266                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8267                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8268                ]
 8269            );
 8270        });
 8271
 8272        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8273        view.update(cx, |view, cx| {
 8274            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8275            view.copy(&Copy, cx);
 8276        });
 8277
 8278        // Paste with three selections, noticing how the copied full-line selection is inserted
 8279        // before the empty selections but replaces the selection that is non-empty.
 8280        view.update(cx, |view, cx| {
 8281            view.select_display_ranges(
 8282                &[
 8283                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8284                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8285                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8286                ],
 8287                cx,
 8288            );
 8289            view.paste(&Paste, cx);
 8290            assert_eq!(
 8291                view.display_text(cx),
 8292                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8293            );
 8294            assert_eq!(
 8295                view.selected_display_ranges(cx),
 8296                &[
 8297                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8298                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8299                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8300                ]
 8301            );
 8302        });
 8303    }
 8304
 8305    #[gpui::test]
 8306    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8307        cx.set_global(Settings::test(cx));
 8308        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8309        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8310        view.update(cx, |view, cx| {
 8311            view.select_all(&SelectAll, cx);
 8312            assert_eq!(
 8313                view.selected_display_ranges(cx),
 8314                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8315            );
 8316        });
 8317    }
 8318
 8319    #[gpui::test]
 8320    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8321        cx.set_global(Settings::test(cx));
 8322        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8323        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8324        view.update(cx, |view, cx| {
 8325            view.select_display_ranges(
 8326                &[
 8327                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8328                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8329                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8330                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8331                ],
 8332                cx,
 8333            );
 8334            view.select_line(&SelectLine, cx);
 8335            assert_eq!(
 8336                view.selected_display_ranges(cx),
 8337                vec![
 8338                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8339                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8340                ]
 8341            );
 8342        });
 8343
 8344        view.update(cx, |view, cx| {
 8345            view.select_line(&SelectLine, cx);
 8346            assert_eq!(
 8347                view.selected_display_ranges(cx),
 8348                vec![
 8349                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8350                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8351                ]
 8352            );
 8353        });
 8354
 8355        view.update(cx, |view, cx| {
 8356            view.select_line(&SelectLine, cx);
 8357            assert_eq!(
 8358                view.selected_display_ranges(cx),
 8359                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8360            );
 8361        });
 8362    }
 8363
 8364    #[gpui::test]
 8365    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8366        cx.set_global(Settings::test(cx));
 8367        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8368        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8369        view.update(cx, |view, cx| {
 8370            view.fold_ranges(
 8371                vec![
 8372                    Point::new(0, 2)..Point::new(1, 2),
 8373                    Point::new(2, 3)..Point::new(4, 1),
 8374                    Point::new(7, 0)..Point::new(8, 4),
 8375                ],
 8376                cx,
 8377            );
 8378            view.select_display_ranges(
 8379                &[
 8380                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8381                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8382                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8383                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8384                ],
 8385                cx,
 8386            );
 8387            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8388        });
 8389
 8390        view.update(cx, |view, cx| {
 8391            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8392            assert_eq!(
 8393                view.display_text(cx),
 8394                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8395            );
 8396            assert_eq!(
 8397                view.selected_display_ranges(cx),
 8398                [
 8399                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8400                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8401                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8402                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8403                ]
 8404            );
 8405        });
 8406
 8407        view.update(cx, |view, cx| {
 8408            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8409            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8410            assert_eq!(
 8411                view.display_text(cx),
 8412                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8413            );
 8414            assert_eq!(
 8415                view.selected_display_ranges(cx),
 8416                [
 8417                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8418                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8419                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8420                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8421                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8422                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8423                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8424                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8425                ]
 8426            );
 8427        });
 8428    }
 8429
 8430    #[gpui::test]
 8431    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8432        cx.set_global(Settings::test(cx));
 8433        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8434        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8435
 8436        view.update(cx, |view, cx| {
 8437            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8438        });
 8439        view.update(cx, |view, cx| {
 8440            view.add_selection_above(&AddSelectionAbove, cx);
 8441            assert_eq!(
 8442                view.selected_display_ranges(cx),
 8443                vec![
 8444                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8445                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8446                ]
 8447            );
 8448        });
 8449
 8450        view.update(cx, |view, cx| {
 8451            view.add_selection_above(&AddSelectionAbove, cx);
 8452            assert_eq!(
 8453                view.selected_display_ranges(cx),
 8454                vec![
 8455                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8456                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8457                ]
 8458            );
 8459        });
 8460
 8461        view.update(cx, |view, cx| {
 8462            view.add_selection_below(&AddSelectionBelow, cx);
 8463            assert_eq!(
 8464                view.selected_display_ranges(cx),
 8465                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8466            );
 8467
 8468            view.undo_selection(&UndoSelection, cx);
 8469            assert_eq!(
 8470                view.selected_display_ranges(cx),
 8471                vec![
 8472                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8473                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8474                ]
 8475            );
 8476
 8477            view.redo_selection(&RedoSelection, cx);
 8478            assert_eq!(
 8479                view.selected_display_ranges(cx),
 8480                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 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![
 8489                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8490                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8491                ]
 8492            );
 8493        });
 8494
 8495        view.update(cx, |view, cx| {
 8496            view.add_selection_below(&AddSelectionBelow, cx);
 8497            assert_eq!(
 8498                view.selected_display_ranges(cx),
 8499                vec![
 8500                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8501                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8502                ]
 8503            );
 8504        });
 8505
 8506        view.update(cx, |view, cx| {
 8507            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8508        });
 8509        view.update(cx, |view, cx| {
 8510            view.add_selection_below(&AddSelectionBelow, cx);
 8511            assert_eq!(
 8512                view.selected_display_ranges(cx),
 8513                vec![
 8514                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8515                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8516                ]
 8517            );
 8518        });
 8519
 8520        view.update(cx, |view, cx| {
 8521            view.add_selection_below(&AddSelectionBelow, cx);
 8522            assert_eq!(
 8523                view.selected_display_ranges(cx),
 8524                vec![
 8525                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8526                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8527                ]
 8528            );
 8529        });
 8530
 8531        view.update(cx, |view, cx| {
 8532            view.add_selection_above(&AddSelectionAbove, cx);
 8533            assert_eq!(
 8534                view.selected_display_ranges(cx),
 8535                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8536            );
 8537        });
 8538
 8539        view.update(cx, |view, cx| {
 8540            view.add_selection_above(&AddSelectionAbove, cx);
 8541            assert_eq!(
 8542                view.selected_display_ranges(cx),
 8543                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8544            );
 8545        });
 8546
 8547        view.update(cx, |view, cx| {
 8548            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8549            view.add_selection_below(&AddSelectionBelow, cx);
 8550            assert_eq!(
 8551                view.selected_display_ranges(cx),
 8552                vec![
 8553                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8554                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8555                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8556                ]
 8557            );
 8558        });
 8559
 8560        view.update(cx, |view, cx| {
 8561            view.add_selection_below(&AddSelectionBelow, cx);
 8562            assert_eq!(
 8563                view.selected_display_ranges(cx),
 8564                vec![
 8565                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8566                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8567                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8568                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8569                ]
 8570            );
 8571        });
 8572
 8573        view.update(cx, |view, cx| {
 8574            view.add_selection_above(&AddSelectionAbove, cx);
 8575            assert_eq!(
 8576                view.selected_display_ranges(cx),
 8577                vec![
 8578                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8579                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8580                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8581                ]
 8582            );
 8583        });
 8584
 8585        view.update(cx, |view, cx| {
 8586            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8587        });
 8588        view.update(cx, |view, cx| {
 8589            view.add_selection_above(&AddSelectionAbove, cx);
 8590            assert_eq!(
 8591                view.selected_display_ranges(cx),
 8592                vec![
 8593                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8594                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8595                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8596                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8597                ]
 8598            );
 8599        });
 8600
 8601        view.update(cx, |view, cx| {
 8602            view.add_selection_below(&AddSelectionBelow, cx);
 8603            assert_eq!(
 8604                view.selected_display_ranges(cx),
 8605                vec![
 8606                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8607                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8608                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8609                ]
 8610            );
 8611        });
 8612    }
 8613
 8614    #[gpui::test]
 8615    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8616        cx.set_global(Settings::test(cx));
 8617
 8618        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8619        let buffer = MultiBuffer::build_simple(&text, cx);
 8620        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8621
 8622        view.update(cx, |view, cx| {
 8623            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8624            view.select_next(
 8625                &SelectNext {
 8626                    replace_newest: false,
 8627                },
 8628                cx,
 8629            );
 8630            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8631
 8632            view.select_next(
 8633                &SelectNext {
 8634                    replace_newest: false,
 8635                },
 8636                cx,
 8637            );
 8638            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8639
 8640            view.undo_selection(&UndoSelection, cx);
 8641            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8642
 8643            view.redo_selection(&RedoSelection, cx);
 8644            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8645
 8646            view.select_next(
 8647                &SelectNext {
 8648                    replace_newest: false,
 8649                },
 8650                cx,
 8651            );
 8652            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8653
 8654            view.select_next(
 8655                &SelectNext {
 8656                    replace_newest: false,
 8657                },
 8658                cx,
 8659            );
 8660            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8661        });
 8662    }
 8663
 8664    #[gpui::test]
 8665    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8666        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8667        let language = Arc::new(Language::new(
 8668            LanguageConfig::default(),
 8669            Some(tree_sitter_rust::language()),
 8670        ));
 8671
 8672        let text = r#"
 8673            use mod1::mod2::{mod3, mod4};
 8674
 8675            fn fn_1(param1: bool, param2: &str) {
 8676                let var1 = "text";
 8677            }
 8678        "#
 8679        .unindent();
 8680
 8681        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8682        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8683        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8684        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8685            .await;
 8686
 8687        view.update(cx, |view, cx| {
 8688            view.select_display_ranges(
 8689                &[
 8690                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8691                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8692                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8693                ],
 8694                cx,
 8695            );
 8696            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8697        });
 8698        assert_eq!(
 8699            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8700            &[
 8701                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8702                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8703                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8704            ]
 8705        );
 8706
 8707        view.update(cx, |view, cx| {
 8708            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8709        });
 8710        assert_eq!(
 8711            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8712            &[
 8713                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8714                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8715            ]
 8716        );
 8717
 8718        view.update(cx, |view, cx| {
 8719            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8720        });
 8721        assert_eq!(
 8722            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8723            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8724        );
 8725
 8726        // Trying to expand the selected syntax node one more time has no effect.
 8727        view.update(cx, |view, cx| {
 8728            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8729        });
 8730        assert_eq!(
 8731            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8732            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8733        );
 8734
 8735        view.update(cx, |view, cx| {
 8736            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8737        });
 8738        assert_eq!(
 8739            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8740            &[
 8741                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8742                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8743            ]
 8744        );
 8745
 8746        view.update(cx, |view, cx| {
 8747            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8748        });
 8749        assert_eq!(
 8750            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8751            &[
 8752                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8753                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8754                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8755            ]
 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, 25)..DisplayPoint::new(0, 25),
 8765                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8766                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8767            ]
 8768        );
 8769
 8770        // Trying to shrink the selected syntax node one more time has no effect.
 8771        view.update(cx, |view, cx| {
 8772            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8773        });
 8774        assert_eq!(
 8775            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8776            &[
 8777                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8778                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8779                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8780            ]
 8781        );
 8782
 8783        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8784        // a fold.
 8785        view.update(cx, |view, cx| {
 8786            view.fold_ranges(
 8787                vec![
 8788                    Point::new(0, 21)..Point::new(0, 24),
 8789                    Point::new(3, 20)..Point::new(3, 22),
 8790                ],
 8791                cx,
 8792            );
 8793            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8794        });
 8795        assert_eq!(
 8796            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8797            &[
 8798                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8799                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8800                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8801            ]
 8802        );
 8803    }
 8804
 8805    #[gpui::test]
 8806    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8807        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8808        let language = Arc::new(
 8809            Language::new(
 8810                LanguageConfig {
 8811                    brackets: vec![
 8812                        BracketPair {
 8813                            start: "{".to_string(),
 8814                            end: "}".to_string(),
 8815                            close: false,
 8816                            newline: true,
 8817                        },
 8818                        BracketPair {
 8819                            start: "(".to_string(),
 8820                            end: ")".to_string(),
 8821                            close: false,
 8822                            newline: true,
 8823                        },
 8824                    ],
 8825                    ..Default::default()
 8826                },
 8827                Some(tree_sitter_rust::language()),
 8828            )
 8829            .with_indents_query(
 8830                r#"
 8831                (_ "(" ")" @end) @indent
 8832                (_ "{" "}" @end) @indent
 8833                "#,
 8834            )
 8835            .unwrap(),
 8836        );
 8837
 8838        let text = "fn a() {}";
 8839
 8840        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8841        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8842        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8843        editor
 8844            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8845            .await;
 8846
 8847        editor.update(cx, |editor, cx| {
 8848            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 8849            editor.newline(&Newline, cx);
 8850            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8851            assert_eq!(
 8852                editor.selected_ranges(cx),
 8853                &[
 8854                    Point::new(1, 4)..Point::new(1, 4),
 8855                    Point::new(3, 4)..Point::new(3, 4),
 8856                    Point::new(5, 0)..Point::new(5, 0)
 8857                ]
 8858            );
 8859        });
 8860    }
 8861
 8862    #[gpui::test]
 8863    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8864        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8865        let language = Arc::new(Language::new(
 8866            LanguageConfig {
 8867                brackets: vec![
 8868                    BracketPair {
 8869                        start: "{".to_string(),
 8870                        end: "}".to_string(),
 8871                        close: true,
 8872                        newline: true,
 8873                    },
 8874                    BracketPair {
 8875                        start: "/*".to_string(),
 8876                        end: " */".to_string(),
 8877                        close: true,
 8878                        newline: true,
 8879                    },
 8880                ],
 8881                autoclose_before: "})]".to_string(),
 8882                ..Default::default()
 8883            },
 8884            Some(tree_sitter_rust::language()),
 8885        ));
 8886
 8887        let text = r#"
 8888            a
 8889
 8890            /
 8891
 8892        "#
 8893        .unindent();
 8894
 8895        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8896        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8897        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8898        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8899            .await;
 8900
 8901        view.update(cx, |view, cx| {
 8902            view.select_display_ranges(
 8903                &[
 8904                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8905                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8906                ],
 8907                cx,
 8908            );
 8909
 8910            view.handle_input(&Input("{".to_string()), cx);
 8911            view.handle_input(&Input("{".to_string()), cx);
 8912            view.handle_input(&Input("{".to_string()), cx);
 8913            assert_eq!(
 8914                view.text(cx),
 8915                "
 8916                {{{}}}
 8917                {{{}}}
 8918                /
 8919
 8920                "
 8921                .unindent()
 8922            );
 8923
 8924            view.move_right(&MoveRight, cx);
 8925            view.handle_input(&Input("}".to_string()), cx);
 8926            view.handle_input(&Input("}".to_string()), cx);
 8927            view.handle_input(&Input("}".to_string()), cx);
 8928            assert_eq!(
 8929                view.text(cx),
 8930                "
 8931                {{{}}}}
 8932                {{{}}}}
 8933                /
 8934
 8935                "
 8936                .unindent()
 8937            );
 8938
 8939            view.undo(&Undo, cx);
 8940            view.handle_input(&Input("/".to_string()), cx);
 8941            view.handle_input(&Input("*".to_string()), cx);
 8942            assert_eq!(
 8943                view.text(cx),
 8944                "
 8945                /* */
 8946                /* */
 8947                /
 8948
 8949                "
 8950                .unindent()
 8951            );
 8952
 8953            view.undo(&Undo, cx);
 8954            view.select_display_ranges(
 8955                &[
 8956                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8957                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8958                ],
 8959                cx,
 8960            );
 8961            view.handle_input(&Input("*".to_string()), cx);
 8962            assert_eq!(
 8963                view.text(cx),
 8964                "
 8965                a
 8966
 8967                /*
 8968                *
 8969                "
 8970                .unindent()
 8971            );
 8972
 8973            // Don't autoclose if the next character isn't whitespace and isn't
 8974            // listed in the language's "autoclose_before" section.
 8975            view.finalize_last_transaction(cx);
 8976            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 8977            view.handle_input(&Input("{".to_string()), cx);
 8978            assert_eq!(
 8979                view.text(cx),
 8980                "
 8981                {a
 8982
 8983                /*
 8984                *
 8985                "
 8986                .unindent()
 8987            );
 8988
 8989            view.undo(&Undo, cx);
 8990            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 8991            view.handle_input(&Input("{".to_string()), cx);
 8992            assert_eq!(
 8993                view.text(cx),
 8994                "
 8995                {a}
 8996
 8997                /*
 8998                *
 8999                "
 9000                .unindent()
 9001            );
 9002            assert_eq!(
 9003                view.selected_display_ranges(cx),
 9004                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9005            );
 9006        });
 9007    }
 9008
 9009    #[gpui::test]
 9010    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9011        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9012
 9013        let text = "
 9014            a. b
 9015            a. b
 9016            a. b
 9017        "
 9018        .unindent();
 9019        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9020        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9021
 9022        editor.update(cx, |editor, cx| {
 9023            let buffer = &editor.snapshot(cx).buffer_snapshot;
 9024            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9025            let insertion_ranges = [
 9026                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 9027                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 9028                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 9029            ];
 9030
 9031            editor
 9032                .insert_snippet(&insertion_ranges, snippet, cx)
 9033                .unwrap();
 9034            assert_eq!(
 9035                editor.text(cx),
 9036                "
 9037                    a.f(one, two, three) b
 9038                    a.f(one, two, three) b
 9039                    a.f(one, two, three) b
 9040                "
 9041                .unindent()
 9042            );
 9043            assert_eq!(
 9044                editor.selected_ranges::<Point>(cx),
 9045                &[
 9046                    Point::new(0, 4)..Point::new(0, 7),
 9047                    Point::new(0, 14)..Point::new(0, 19),
 9048                    Point::new(1, 4)..Point::new(1, 7),
 9049                    Point::new(1, 14)..Point::new(1, 19),
 9050                    Point::new(2, 4)..Point::new(2, 7),
 9051                    Point::new(2, 14)..Point::new(2, 19),
 9052                ]
 9053            );
 9054
 9055            // Can't move earlier than the first tab stop
 9056            editor.move_to_prev_snippet_tabstop(cx);
 9057            assert_eq!(
 9058                editor.selected_ranges::<Point>(cx),
 9059                &[
 9060                    Point::new(0, 4)..Point::new(0, 7),
 9061                    Point::new(0, 14)..Point::new(0, 19),
 9062                    Point::new(1, 4)..Point::new(1, 7),
 9063                    Point::new(1, 14)..Point::new(1, 19),
 9064                    Point::new(2, 4)..Point::new(2, 7),
 9065                    Point::new(2, 14)..Point::new(2, 19),
 9066                ]
 9067            );
 9068
 9069            assert!(editor.move_to_next_snippet_tabstop(cx));
 9070            assert_eq!(
 9071                editor.selected_ranges::<Point>(cx),
 9072                &[
 9073                    Point::new(0, 9)..Point::new(0, 12),
 9074                    Point::new(1, 9)..Point::new(1, 12),
 9075                    Point::new(2, 9)..Point::new(2, 12)
 9076                ]
 9077            );
 9078
 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!(editor.move_to_next_snippet_tabstop(cx));
 9094            assert_eq!(
 9095                editor.selected_ranges::<Point>(cx),
 9096                &[
 9097                    Point::new(0, 20)..Point::new(0, 20),
 9098                    Point::new(1, 20)..Point::new(1, 20),
 9099                    Point::new(2, 20)..Point::new(2, 20)
 9100                ]
 9101            );
 9102
 9103            // As soon as the last tab stop is reached, snippet state is gone
 9104            editor.move_to_prev_snippet_tabstop(cx);
 9105            assert_eq!(
 9106                editor.selected_ranges::<Point>(cx),
 9107                &[
 9108                    Point::new(0, 20)..Point::new(0, 20),
 9109                    Point::new(1, 20)..Point::new(1, 20),
 9110                    Point::new(2, 20)..Point::new(2, 20)
 9111                ]
 9112            );
 9113        });
 9114    }
 9115
 9116    #[gpui::test]
 9117    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9118        cx.foreground().forbid_parking();
 9119        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9120
 9121        let mut language = Language::new(
 9122            LanguageConfig {
 9123                name: "Rust".into(),
 9124                path_suffixes: vec!["rs".to_string()],
 9125                ..Default::default()
 9126            },
 9127            Some(tree_sitter_rust::language()),
 9128        );
 9129        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9130            capabilities: lsp::ServerCapabilities {
 9131                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9132                ..Default::default()
 9133            },
 9134            ..Default::default()
 9135        });
 9136
 9137        let fs = FakeFs::new(cx.background().clone());
 9138        fs.insert_file("/file.rs", Default::default()).await;
 9139
 9140        let project = Project::test(fs, cx);
 9141        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9142
 9143        let worktree_id = project
 9144            .update(cx, |project, cx| {
 9145                project.find_or_create_local_worktree("/file.rs", true, cx)
 9146            })
 9147            .await
 9148            .unwrap()
 9149            .0
 9150            .read_with(cx, |tree, _| tree.id());
 9151        let buffer = project
 9152            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9153            .await
 9154            .unwrap();
 9155
 9156        cx.foreground().start_waiting();
 9157        let fake_server = fake_servers.next().await.unwrap();
 9158
 9159        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9160        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9161        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9162        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9163
 9164        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9165        fake_server
 9166            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9167                assert_eq!(
 9168                    params.text_document.uri,
 9169                    lsp::Url::from_file_path("/file.rs").unwrap()
 9170                );
 9171                assert_eq!(params.options.tab_size, 4);
 9172                Ok(Some(vec![lsp::TextEdit::new(
 9173                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9174                    ", ".to_string(),
 9175                )]))
 9176            })
 9177            .next()
 9178            .await;
 9179        cx.foreground().start_waiting();
 9180        save.await.unwrap();
 9181        assert_eq!(
 9182            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9183            "one, two\nthree\n"
 9184        );
 9185        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9186
 9187        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9188        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9189
 9190        // Ensure we can still save even if formatting hangs.
 9191        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9192            assert_eq!(
 9193                params.text_document.uri,
 9194                lsp::Url::from_file_path("/file.rs").unwrap()
 9195            );
 9196            futures::future::pending::<()>().await;
 9197            unreachable!()
 9198        });
 9199        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9200        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9201        cx.foreground().start_waiting();
 9202        save.await.unwrap();
 9203        assert_eq!(
 9204            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9205            "one\ntwo\nthree\n"
 9206        );
 9207        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9208
 9209        // Set rust language override and assert overriden tabsize is sent to language server
 9210        cx.update(|cx| {
 9211            cx.update_global::<Settings, _, _>(|settings, _| {
 9212                settings.language_overrides.insert(
 9213                    "Rust".into(),
 9214                    LanguageOverride {
 9215                        tab_size: Some(8),
 9216                        ..Default::default()
 9217                    },
 9218                );
 9219            })
 9220        });
 9221
 9222        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9223        fake_server
 9224            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9225                assert_eq!(
 9226                    params.text_document.uri,
 9227                    lsp::Url::from_file_path("/file.rs").unwrap()
 9228                );
 9229                assert_eq!(params.options.tab_size, 8);
 9230                Ok(Some(vec![]))
 9231            })
 9232            .next()
 9233            .await;
 9234        cx.foreground().start_waiting();
 9235        save.await.unwrap();
 9236    }
 9237
 9238    #[gpui::test]
 9239    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9240        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9241
 9242        let mut language = Language::new(
 9243            LanguageConfig {
 9244                name: "Rust".into(),
 9245                path_suffixes: vec!["rs".to_string()],
 9246                ..Default::default()
 9247            },
 9248            Some(tree_sitter_rust::language()),
 9249        );
 9250        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9251            capabilities: lsp::ServerCapabilities {
 9252                completion_provider: Some(lsp::CompletionOptions {
 9253                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9254                    ..Default::default()
 9255                }),
 9256                ..Default::default()
 9257            },
 9258            ..Default::default()
 9259        });
 9260
 9261        let text = "
 9262            one
 9263            two
 9264            three
 9265        "
 9266        .unindent();
 9267
 9268        let fs = FakeFs::new(cx.background().clone());
 9269        fs.insert_file("/file.rs", text).await;
 9270
 9271        let project = Project::test(fs, cx);
 9272        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9273
 9274        let worktree_id = project
 9275            .update(cx, |project, cx| {
 9276                project.find_or_create_local_worktree("/file.rs", true, cx)
 9277            })
 9278            .await
 9279            .unwrap()
 9280            .0
 9281            .read_with(cx, |tree, _| tree.id());
 9282        let buffer = project
 9283            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9284            .await
 9285            .unwrap();
 9286        let mut fake_server = fake_servers.next().await.unwrap();
 9287
 9288        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9289        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9290
 9291        editor.update(cx, |editor, cx| {
 9292            editor.project = Some(project);
 9293            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9294            editor.handle_input(&Input(".".to_string()), cx);
 9295        });
 9296
 9297        handle_completion_request(
 9298            &mut fake_server,
 9299            "/file.rs",
 9300            Point::new(0, 4),
 9301            vec![
 9302                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9303                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9304            ],
 9305        )
 9306        .await;
 9307        editor
 9308            .condition(&cx, |editor, _| editor.context_menu_visible())
 9309            .await;
 9310
 9311        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9312            editor.move_down(&MoveDown, cx);
 9313            let apply_additional_edits = editor
 9314                .confirm_completion(&ConfirmCompletion::default(), cx)
 9315                .unwrap();
 9316            assert_eq!(
 9317                editor.text(cx),
 9318                "
 9319                    one.second_completion
 9320                    two
 9321                    three
 9322                "
 9323                .unindent()
 9324            );
 9325            apply_additional_edits
 9326        });
 9327
 9328        handle_resolve_completion_request(
 9329            &mut fake_server,
 9330            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9331        )
 9332        .await;
 9333        apply_additional_edits.await.unwrap();
 9334        assert_eq!(
 9335            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9336            "
 9337                one.second_completion
 9338                two
 9339                three
 9340                additional edit
 9341            "
 9342            .unindent()
 9343        );
 9344
 9345        editor.update(cx, |editor, cx| {
 9346            editor.select_ranges(
 9347                [
 9348                    Point::new(1, 3)..Point::new(1, 3),
 9349                    Point::new(2, 5)..Point::new(2, 5),
 9350                ],
 9351                None,
 9352                cx,
 9353            );
 9354
 9355            editor.handle_input(&Input(" ".to_string()), cx);
 9356            assert!(editor.context_menu.is_none());
 9357            editor.handle_input(&Input("s".to_string()), cx);
 9358            assert!(editor.context_menu.is_none());
 9359        });
 9360
 9361        handle_completion_request(
 9362            &mut fake_server,
 9363            "/file.rs",
 9364            Point::new(2, 7),
 9365            vec![
 9366                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9367                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9368                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9369            ],
 9370        )
 9371        .await;
 9372        editor
 9373            .condition(&cx, |editor, _| editor.context_menu_visible())
 9374            .await;
 9375
 9376        editor.update(cx, |editor, cx| {
 9377            editor.handle_input(&Input("i".to_string()), cx);
 9378        });
 9379
 9380        handle_completion_request(
 9381            &mut fake_server,
 9382            "/file.rs",
 9383            Point::new(2, 8),
 9384            vec![
 9385                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9386                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9387                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9388            ],
 9389        )
 9390        .await;
 9391        editor
 9392            .condition(&cx, |editor, _| editor.context_menu_visible())
 9393            .await;
 9394
 9395        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9396            let apply_additional_edits = editor
 9397                .confirm_completion(&ConfirmCompletion::default(), cx)
 9398                .unwrap();
 9399            assert_eq!(
 9400                editor.text(cx),
 9401                "
 9402                    one.second_completion
 9403                    two sixth_completion
 9404                    three sixth_completion
 9405                    additional edit
 9406                "
 9407                .unindent()
 9408            );
 9409            apply_additional_edits
 9410        });
 9411        handle_resolve_completion_request(&mut fake_server, None).await;
 9412        apply_additional_edits.await.unwrap();
 9413
 9414        async fn handle_completion_request(
 9415            fake: &mut FakeLanguageServer,
 9416            path: &'static str,
 9417            position: Point,
 9418            completions: Vec<(Range<Point>, &'static str)>,
 9419        ) {
 9420            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9421                let completions = completions.clone();
 9422                async move {
 9423                    assert_eq!(
 9424                        params.text_document_position.text_document.uri,
 9425                        lsp::Url::from_file_path(path).unwrap()
 9426                    );
 9427                    assert_eq!(
 9428                        params.text_document_position.position,
 9429                        lsp::Position::new(position.row, position.column)
 9430                    );
 9431                    Ok(Some(lsp::CompletionResponse::Array(
 9432                        completions
 9433                            .iter()
 9434                            .map(|(range, new_text)| lsp::CompletionItem {
 9435                                label: new_text.to_string(),
 9436                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9437                                    range: lsp::Range::new(
 9438                                        lsp::Position::new(range.start.row, range.start.column),
 9439                                        lsp::Position::new(range.start.row, range.start.column),
 9440                                    ),
 9441                                    new_text: new_text.to_string(),
 9442                                })),
 9443                                ..Default::default()
 9444                            })
 9445                            .collect(),
 9446                    )))
 9447                }
 9448            })
 9449            .next()
 9450            .await;
 9451        }
 9452
 9453        async fn handle_resolve_completion_request(
 9454            fake: &mut FakeLanguageServer,
 9455            edit: Option<(Range<Point>, &'static str)>,
 9456        ) {
 9457            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9458                let edit = edit.clone();
 9459                async move {
 9460                    Ok(lsp::CompletionItem {
 9461                        additional_text_edits: edit.map(|(range, new_text)| {
 9462                            vec![lsp::TextEdit::new(
 9463                                lsp::Range::new(
 9464                                    lsp::Position::new(range.start.row, range.start.column),
 9465                                    lsp::Position::new(range.end.row, range.end.column),
 9466                                ),
 9467                                new_text.to_string(),
 9468                            )]
 9469                        }),
 9470                        ..Default::default()
 9471                    })
 9472                }
 9473            })
 9474            .next()
 9475            .await;
 9476        }
 9477    }
 9478
 9479    #[gpui::test]
 9480    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9481        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9482        let language = Arc::new(Language::new(
 9483            LanguageConfig {
 9484                line_comment: Some("// ".to_string()),
 9485                ..Default::default()
 9486            },
 9487            Some(tree_sitter_rust::language()),
 9488        ));
 9489
 9490        let text = "
 9491            fn a() {
 9492                //b();
 9493                // c();
 9494                //  d();
 9495            }
 9496        "
 9497        .unindent();
 9498
 9499        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9500        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9501        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9502
 9503        view.update(cx, |editor, cx| {
 9504            // If multiple selections intersect a line, the line is only
 9505            // toggled once.
 9506            editor.select_display_ranges(
 9507                &[
 9508                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9509                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9510                ],
 9511                cx,
 9512            );
 9513            editor.toggle_comments(&ToggleComments, cx);
 9514            assert_eq!(
 9515                editor.text(cx),
 9516                "
 9517                    fn a() {
 9518                        b();
 9519                        c();
 9520                         d();
 9521                    }
 9522                "
 9523                .unindent()
 9524            );
 9525
 9526            // The comment prefix is inserted at the same column for every line
 9527            // in a selection.
 9528            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9529            editor.toggle_comments(&ToggleComments, cx);
 9530            assert_eq!(
 9531                editor.text(cx),
 9532                "
 9533                    fn a() {
 9534                        // b();
 9535                        // c();
 9536                        //  d();
 9537                    }
 9538                "
 9539                .unindent()
 9540            );
 9541
 9542            // If a selection ends at the beginning of a line, that line is not toggled.
 9543            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9544            editor.toggle_comments(&ToggleComments, cx);
 9545            assert_eq!(
 9546                editor.text(cx),
 9547                "
 9548                        fn a() {
 9549                            // b();
 9550                            c();
 9551                            //  d();
 9552                        }
 9553                    "
 9554                .unindent()
 9555            );
 9556        });
 9557    }
 9558
 9559    #[gpui::test]
 9560    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9561        cx.set_global(Settings::test(cx));
 9562        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9563        let multibuffer = cx.add_model(|cx| {
 9564            let mut multibuffer = MultiBuffer::new(0);
 9565            multibuffer.push_excerpts(
 9566                buffer.clone(),
 9567                [
 9568                    Point::new(0, 0)..Point::new(0, 4),
 9569                    Point::new(1, 0)..Point::new(1, 4),
 9570                ],
 9571                cx,
 9572            );
 9573            multibuffer
 9574        });
 9575
 9576        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9577
 9578        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9579        view.update(cx, |view, cx| {
 9580            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9581            view.select_ranges(
 9582                [
 9583                    Point::new(0, 0)..Point::new(0, 0),
 9584                    Point::new(1, 0)..Point::new(1, 0),
 9585                ],
 9586                None,
 9587                cx,
 9588            );
 9589
 9590            view.handle_input(&Input("X".to_string()), cx);
 9591            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9592            assert_eq!(
 9593                view.selected_ranges(cx),
 9594                [
 9595                    Point::new(0, 1)..Point::new(0, 1),
 9596                    Point::new(1, 1)..Point::new(1, 1),
 9597                ]
 9598            )
 9599        });
 9600    }
 9601
 9602    #[gpui::test]
 9603    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9604        cx.set_global(Settings::test(cx));
 9605        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9606        let multibuffer = cx.add_model(|cx| {
 9607            let mut multibuffer = MultiBuffer::new(0);
 9608            multibuffer.push_excerpts(
 9609                buffer,
 9610                [
 9611                    Point::new(0, 0)..Point::new(1, 4),
 9612                    Point::new(1, 0)..Point::new(2, 4),
 9613                ],
 9614                cx,
 9615            );
 9616            multibuffer
 9617        });
 9618
 9619        assert_eq!(
 9620            multibuffer.read(cx).read(cx).text(),
 9621            "aaaa\nbbbb\nbbbb\ncccc"
 9622        );
 9623
 9624        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9625        view.update(cx, |view, cx| {
 9626            view.select_ranges(
 9627                [
 9628                    Point::new(1, 1)..Point::new(1, 1),
 9629                    Point::new(2, 3)..Point::new(2, 3),
 9630                ],
 9631                None,
 9632                cx,
 9633            );
 9634
 9635            view.handle_input(&Input("X".to_string()), cx);
 9636            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9637            assert_eq!(
 9638                view.selected_ranges(cx),
 9639                [
 9640                    Point::new(1, 2)..Point::new(1, 2),
 9641                    Point::new(2, 5)..Point::new(2, 5),
 9642                ]
 9643            );
 9644
 9645            view.newline(&Newline, cx);
 9646            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9647            assert_eq!(
 9648                view.selected_ranges(cx),
 9649                [
 9650                    Point::new(2, 0)..Point::new(2, 0),
 9651                    Point::new(6, 0)..Point::new(6, 0),
 9652                ]
 9653            );
 9654        });
 9655    }
 9656
 9657    #[gpui::test]
 9658    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9659        cx.set_global(Settings::test(cx));
 9660        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9661        let mut excerpt1_id = None;
 9662        let multibuffer = cx.add_model(|cx| {
 9663            let mut multibuffer = MultiBuffer::new(0);
 9664            excerpt1_id = multibuffer
 9665                .push_excerpts(
 9666                    buffer.clone(),
 9667                    [
 9668                        Point::new(0, 0)..Point::new(1, 4),
 9669                        Point::new(1, 0)..Point::new(2, 4),
 9670                    ],
 9671                    cx,
 9672                )
 9673                .into_iter()
 9674                .next();
 9675            multibuffer
 9676        });
 9677        assert_eq!(
 9678            multibuffer.read(cx).read(cx).text(),
 9679            "aaaa\nbbbb\nbbbb\ncccc"
 9680        );
 9681        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9682            let mut editor = build_editor(multibuffer.clone(), cx);
 9683            let snapshot = editor.snapshot(cx);
 9684            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9685            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9686            assert_eq!(
 9687                editor.selected_ranges(cx),
 9688                [
 9689                    Point::new(1, 3)..Point::new(1, 3),
 9690                    Point::new(2, 1)..Point::new(2, 1),
 9691                ]
 9692            );
 9693            editor
 9694        });
 9695
 9696        // Refreshing selections is a no-op when excerpts haven't changed.
 9697        editor.update(cx, |editor, cx| {
 9698            editor.refresh_selections(cx);
 9699            assert_eq!(
 9700                editor.selected_ranges(cx),
 9701                [
 9702                    Point::new(1, 3)..Point::new(1, 3),
 9703                    Point::new(2, 1)..Point::new(2, 1),
 9704                ]
 9705            );
 9706        });
 9707
 9708        multibuffer.update(cx, |multibuffer, cx| {
 9709            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9710        });
 9711        editor.update(cx, |editor, cx| {
 9712            // Removing an excerpt causes the first selection to become degenerate.
 9713            assert_eq!(
 9714                editor.selected_ranges(cx),
 9715                [
 9716                    Point::new(0, 0)..Point::new(0, 0),
 9717                    Point::new(0, 1)..Point::new(0, 1)
 9718                ]
 9719            );
 9720
 9721            // Refreshing selections will relocate the first selection to the original buffer
 9722            // location.
 9723            editor.refresh_selections(cx);
 9724            assert_eq!(
 9725                editor.selected_ranges(cx),
 9726                [
 9727                    Point::new(0, 1)..Point::new(0, 1),
 9728                    Point::new(0, 3)..Point::new(0, 3)
 9729                ]
 9730            );
 9731            assert!(editor.pending_selection.is_some());
 9732        });
 9733    }
 9734
 9735    #[gpui::test]
 9736    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9737        cx.set_global(Settings::test(cx));
 9738        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9739        let mut excerpt1_id = None;
 9740        let multibuffer = cx.add_model(|cx| {
 9741            let mut multibuffer = MultiBuffer::new(0);
 9742            excerpt1_id = multibuffer
 9743                .push_excerpts(
 9744                    buffer.clone(),
 9745                    [
 9746                        Point::new(0, 0)..Point::new(1, 4),
 9747                        Point::new(1, 0)..Point::new(2, 4),
 9748                    ],
 9749                    cx,
 9750                )
 9751                .into_iter()
 9752                .next();
 9753            multibuffer
 9754        });
 9755        assert_eq!(
 9756            multibuffer.read(cx).read(cx).text(),
 9757            "aaaa\nbbbb\nbbbb\ncccc"
 9758        );
 9759        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9760            let mut editor = build_editor(multibuffer.clone(), cx);
 9761            let snapshot = editor.snapshot(cx);
 9762            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9763            assert_eq!(
 9764                editor.selected_ranges(cx),
 9765                [Point::new(1, 3)..Point::new(1, 3)]
 9766            );
 9767            editor
 9768        });
 9769
 9770        multibuffer.update(cx, |multibuffer, cx| {
 9771            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9772        });
 9773        editor.update(cx, |editor, cx| {
 9774            assert_eq!(
 9775                editor.selected_ranges(cx),
 9776                [Point::new(0, 0)..Point::new(0, 0)]
 9777            );
 9778
 9779            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9780            editor.refresh_selections(cx);
 9781            assert_eq!(
 9782                editor.selected_ranges(cx),
 9783                [Point::new(0, 3)..Point::new(0, 3)]
 9784            );
 9785            assert!(editor.pending_selection.is_some());
 9786        });
 9787    }
 9788
 9789    #[gpui::test]
 9790    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9791        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9792        let language = Arc::new(Language::new(
 9793            LanguageConfig {
 9794                brackets: vec![
 9795                    BracketPair {
 9796                        start: "{".to_string(),
 9797                        end: "}".to_string(),
 9798                        close: true,
 9799                        newline: true,
 9800                    },
 9801                    BracketPair {
 9802                        start: "/* ".to_string(),
 9803                        end: " */".to_string(),
 9804                        close: true,
 9805                        newline: true,
 9806                    },
 9807                ],
 9808                ..Default::default()
 9809            },
 9810            Some(tree_sitter_rust::language()),
 9811        ));
 9812
 9813        let text = concat!(
 9814            "{   }\n",     // Suppress rustfmt
 9815            "  x\n",       //
 9816            "  /*   */\n", //
 9817            "x\n",         //
 9818            "{{} }\n",     //
 9819        );
 9820
 9821        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9822        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9823        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9824        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9825            .await;
 9826
 9827        view.update(cx, |view, cx| {
 9828            view.select_display_ranges(
 9829                &[
 9830                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9831                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9832                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9833                ],
 9834                cx,
 9835            );
 9836            view.newline(&Newline, cx);
 9837
 9838            assert_eq!(
 9839                view.buffer().read(cx).read(cx).text(),
 9840                concat!(
 9841                    "{ \n",    // Suppress rustfmt
 9842                    "\n",      //
 9843                    "}\n",     //
 9844                    "  x\n",   //
 9845                    "  /* \n", //
 9846                    "  \n",    //
 9847                    "  */\n",  //
 9848                    "x\n",     //
 9849                    "{{} \n",  //
 9850                    "}\n",     //
 9851                )
 9852            );
 9853        });
 9854    }
 9855
 9856    #[gpui::test]
 9857    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9858        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9859
 9860        cx.set_global(Settings::test(cx));
 9861        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9862
 9863        editor.update(cx, |editor, cx| {
 9864            struct Type1;
 9865            struct Type2;
 9866
 9867            let buffer = buffer.read(cx).snapshot(cx);
 9868
 9869            let anchor_range = |range: Range<Point>| {
 9870                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9871            };
 9872
 9873            editor.highlight_background::<Type1>(
 9874                vec![
 9875                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
 9876                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
 9877                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
 9878                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
 9879                ],
 9880                |_| Color::red(),
 9881                cx,
 9882            );
 9883            editor.highlight_background::<Type2>(
 9884                vec![
 9885                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
 9886                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
 9887                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
 9888                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
 9889                ],
 9890                |_| Color::green(),
 9891                cx,
 9892            );
 9893
 9894            let snapshot = editor.snapshot(cx);
 9895            let mut highlighted_ranges = editor.background_highlights_in_range(
 9896                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
 9897                &snapshot,
 9898                cx.global::<Settings>().theme.as_ref(),
 9899            );
 9900            // Enforce a consistent ordering based on color without relying on the ordering of the
 9901            // highlight's `TypeId` which is non-deterministic.
 9902            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9903            assert_eq!(
 9904                highlighted_ranges,
 9905                &[
 9906                    (
 9907                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9908                        Color::green(),
 9909                    ),
 9910                    (
 9911                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9912                        Color::green(),
 9913                    ),
 9914                    (
 9915                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9916                        Color::red(),
 9917                    ),
 9918                    (
 9919                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9920                        Color::red(),
 9921                    ),
 9922                ]
 9923            );
 9924            assert_eq!(
 9925                editor.background_highlights_in_range(
 9926                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9927                    &snapshot,
 9928                    cx.global::<Settings>().theme.as_ref(),
 9929                ),
 9930                &[(
 9931                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9932                    Color::red(),
 9933                )]
 9934            );
 9935        });
 9936    }
 9937
 9938    #[gpui::test]
 9939    fn test_following(cx: &mut gpui::MutableAppContext) {
 9940        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9941
 9942        cx.set_global(Settings::test(cx));
 9943
 9944        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9945        let (_, follower) = cx.add_window(
 9946            WindowOptions {
 9947                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
 9948                ..Default::default()
 9949            },
 9950            |cx| build_editor(buffer.clone(), cx),
 9951        );
 9952
 9953        let pending_update = Rc::new(RefCell::new(None));
 9954        follower.update(cx, {
 9955            let update = pending_update.clone();
 9956            |_, cx| {
 9957                cx.subscribe(&leader, move |_, leader, event, cx| {
 9958                    leader
 9959                        .read(cx)
 9960                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
 9961                })
 9962                .detach();
 9963            }
 9964        });
 9965
 9966        // Update the selections only
 9967        leader.update(cx, |leader, cx| {
 9968            leader.select_ranges([1..1], None, cx);
 9969        });
 9970        follower.update(cx, |follower, cx| {
 9971            follower
 9972                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9973                .unwrap();
 9974        });
 9975        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
 9976
 9977        // Update the scroll position only
 9978        leader.update(cx, |leader, cx| {
 9979            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9980        });
 9981        follower.update(cx, |follower, cx| {
 9982            follower
 9983                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9984                .unwrap();
 9985        });
 9986        assert_eq!(
 9987            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
 9988            vec2f(1.5, 3.5)
 9989        );
 9990
 9991        // Update the selections and scroll position
 9992        leader.update(cx, |leader, cx| {
 9993            leader.select_ranges([0..0], None, cx);
 9994            leader.request_autoscroll(Autoscroll::Newest, cx);
 9995            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9996        });
 9997        follower.update(cx, |follower, cx| {
 9998            let initial_scroll_position = follower.scroll_position(cx);
 9999            follower
10000                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10001                .unwrap();
10002            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10003            assert!(follower.autoscroll_request.is_some());
10004        });
10005        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
10006
10007        // Creating a pending selection that precedes another selection
10008        leader.update(cx, |leader, cx| {
10009            leader.select_ranges([1..1], None, cx);
10010            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10011        });
10012        follower.update(cx, |follower, cx| {
10013            follower
10014                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10015                .unwrap();
10016        });
10017        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
10018
10019        // Extend the pending selection so that it surrounds another selection
10020        leader.update(cx, |leader, cx| {
10021            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10022        });
10023        follower.update(cx, |follower, cx| {
10024            follower
10025                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10026                .unwrap();
10027        });
10028        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
10029    }
10030
10031    #[test]
10032    fn test_combine_syntax_and_fuzzy_match_highlights() {
10033        let string = "abcdefghijklmnop";
10034        let syntax_ranges = [
10035            (
10036                0..3,
10037                HighlightStyle {
10038                    color: Some(Color::red()),
10039                    ..Default::default()
10040                },
10041            ),
10042            (
10043                4..8,
10044                HighlightStyle {
10045                    color: Some(Color::green()),
10046                    ..Default::default()
10047                },
10048            ),
10049        ];
10050        let match_indices = [4, 6, 7, 8];
10051        assert_eq!(
10052            combine_syntax_and_fuzzy_match_highlights(
10053                &string,
10054                Default::default(),
10055                syntax_ranges.into_iter(),
10056                &match_indices,
10057            ),
10058            &[
10059                (
10060                    0..3,
10061                    HighlightStyle {
10062                        color: Some(Color::red()),
10063                        ..Default::default()
10064                    },
10065                ),
10066                (
10067                    4..5,
10068                    HighlightStyle {
10069                        color: Some(Color::green()),
10070                        weight: Some(fonts::Weight::BOLD),
10071                        ..Default::default()
10072                    },
10073                ),
10074                (
10075                    5..6,
10076                    HighlightStyle {
10077                        color: Some(Color::green()),
10078                        ..Default::default()
10079                    },
10080                ),
10081                (
10082                    6..8,
10083                    HighlightStyle {
10084                        color: Some(Color::green()),
10085                        weight: Some(fonts::Weight::BOLD),
10086                        ..Default::default()
10087                    },
10088                ),
10089                (
10090                    8..9,
10091                    HighlightStyle {
10092                        weight: Some(fonts::Weight::BOLD),
10093                        ..Default::default()
10094                    },
10095                ),
10096            ]
10097        );
10098    }
10099
10100    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10101        let point = DisplayPoint::new(row as u32, column as u32);
10102        point..point
10103    }
10104
10105    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10106        Editor::new(EditorMode::Full, buffer, None, None, cx)
10107    }
10108
10109    fn assert_selection_ranges(
10110        marked_text: &str,
10111        selection_marker_pairs: Vec<(char, char)>,
10112        view: &mut Editor,
10113        cx: &mut ViewContext<Editor>,
10114    ) {
10115        let snapshot = view.snapshot(cx).display_snapshot;
10116        let mut marker_chars = Vec::new();
10117        for (start, end) in selection_marker_pairs.iter() {
10118            marker_chars.push(*start);
10119            marker_chars.push(*end);
10120        }
10121        let (_, markers) = marked_text_by(marked_text, marker_chars);
10122        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10123            .iter()
10124            .map(|(start, end)| {
10125                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10126                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10127                start..end
10128            })
10129            .collect();
10130        assert_eq!(
10131            view.selected_display_ranges(cx),
10132            &asserted_ranges[..],
10133            "Assert selections are {}",
10134            marked_text
10135        );
10136    }
10137}
10138
10139trait RangeExt<T> {
10140    fn sorted(&self) -> Range<T>;
10141    fn to_inclusive(&self) -> RangeInclusive<T>;
10142}
10143
10144impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10145    fn sorted(&self) -> Self {
10146        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10147    }
10148
10149    fn to_inclusive(&self) -> RangeInclusive<T> {
10150        self.start.clone()..=self.end.clone()
10151    }
10152}