editor.rs

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