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