editor.rs

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