editor.rs

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