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.select_to_beginning_of_line(
 3795                &SelectToBeginningOfLine {
 3796                    stop_at_soft_wraps: false,
 3797                },
 3798                cx,
 3799            );
 3800            this.backspace(&Backspace, cx);
 3801        });
 3802    }
 3803
 3804    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 3805        self.move_cursors(cx, |map, head, _| {
 3806            (movement::line_end(map, head, true), SelectionGoal::None)
 3807        });
 3808    }
 3809
 3810    pub fn select_to_end_of_line(
 3811        &mut self,
 3812        action: &SelectToEndOfLine,
 3813        cx: &mut ViewContext<Self>,
 3814    ) {
 3815        self.move_selection_heads(cx, |map, head, _| {
 3816            (
 3817                movement::line_end(map, head, action.stop_at_soft_wraps),
 3818                SelectionGoal::None,
 3819            )
 3820        });
 3821    }
 3822
 3823    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 3824        self.transact(cx, |this, cx| {
 3825            this.select_to_end_of_line(
 3826                &SelectToEndOfLine {
 3827                    stop_at_soft_wraps: false,
 3828                },
 3829                cx,
 3830            );
 3831            this.delete(&Delete, cx);
 3832        });
 3833    }
 3834
 3835    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 3836        self.transact(cx, |this, cx| {
 3837            this.select_to_end_of_line(
 3838                &SelectToEndOfLine {
 3839                    stop_at_soft_wraps: false,
 3840                },
 3841                cx,
 3842            );
 3843            this.cut(&Cut, cx);
 3844        });
 3845    }
 3846
 3847    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 3848        if matches!(self.mode, EditorMode::SingleLine) {
 3849            cx.propagate_action();
 3850            return;
 3851        }
 3852
 3853        let selection = Selection {
 3854            id: post_inc(&mut self.next_selection_id),
 3855            start: 0,
 3856            end: 0,
 3857            reversed: false,
 3858            goal: SelectionGoal::None,
 3859        };
 3860        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3861    }
 3862
 3863    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 3864        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
 3865        selection.set_head(Point::zero(), SelectionGoal::None);
 3866        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3867    }
 3868
 3869    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 3870        if matches!(self.mode, EditorMode::SingleLine) {
 3871            cx.propagate_action();
 3872            return;
 3873        }
 3874
 3875        let cursor = self.buffer.read(cx).read(cx).len();
 3876        let selection = Selection {
 3877            id: post_inc(&mut self.next_selection_id),
 3878            start: cursor,
 3879            end: cursor,
 3880            reversed: false,
 3881            goal: SelectionGoal::None,
 3882        };
 3883        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3884    }
 3885
 3886    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 3887        self.nav_history = nav_history;
 3888    }
 3889
 3890    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 3891        self.nav_history.as_ref()
 3892    }
 3893
 3894    fn push_to_nav_history(
 3895        &self,
 3896        position: Anchor,
 3897        new_position: Option<Point>,
 3898        cx: &mut ViewContext<Self>,
 3899    ) {
 3900        if let Some(nav_history) = &self.nav_history {
 3901            let buffer = self.buffer.read(cx).read(cx);
 3902            let offset = position.to_offset(&buffer);
 3903            let point = position.to_point(&buffer);
 3904            let scroll_top_offset = self.scroll_top_anchor.to_offset(&buffer);
 3905            drop(buffer);
 3906
 3907            if let Some(new_position) = new_position {
 3908                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 3909                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 3910                    return;
 3911                }
 3912            }
 3913
 3914            nav_history.push(Some(NavigationData {
 3915                cursor_anchor: position,
 3916                cursor_offset: offset,
 3917                scroll_position: self.scroll_position,
 3918                scroll_top_anchor: self.scroll_top_anchor.clone(),
 3919                scroll_top_offset,
 3920            }));
 3921        }
 3922    }
 3923
 3924    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 3925        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
 3926        selection.set_head(self.buffer.read(cx).read(cx).len(), SelectionGoal::None);
 3927        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3928    }
 3929
 3930    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 3931        let selection = Selection {
 3932            id: post_inc(&mut self.next_selection_id),
 3933            start: 0,
 3934            end: self.buffer.read(cx).read(cx).len(),
 3935            reversed: false,
 3936            goal: SelectionGoal::None,
 3937        };
 3938        self.update_selections(vec![selection], None, cx);
 3939    }
 3940
 3941    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 3942        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3943        let mut selections = self.local_selections::<Point>(cx);
 3944        let max_point = display_map.buffer_snapshot.max_point();
 3945        for selection in &mut selections {
 3946            let rows = selection.spanned_rows(true, &display_map);
 3947            selection.start = Point::new(rows.start, 0);
 3948            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 3949            selection.reversed = false;
 3950        }
 3951        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 3952    }
 3953
 3954    pub fn split_selection_into_lines(
 3955        &mut self,
 3956        _: &SplitSelectionIntoLines,
 3957        cx: &mut ViewContext<Self>,
 3958    ) {
 3959        let mut to_unfold = Vec::new();
 3960        let mut new_selections = Vec::new();
 3961        {
 3962            let selections = self.local_selections::<Point>(cx);
 3963            let buffer = self.buffer.read(cx).read(cx);
 3964            for selection in selections {
 3965                for row in selection.start.row..selection.end.row {
 3966                    let cursor = Point::new(row, buffer.line_len(row));
 3967                    new_selections.push(Selection {
 3968                        id: post_inc(&mut self.next_selection_id),
 3969                        start: cursor,
 3970                        end: cursor,
 3971                        reversed: false,
 3972                        goal: SelectionGoal::None,
 3973                    });
 3974                }
 3975                new_selections.push(Selection {
 3976                    id: selection.id,
 3977                    start: selection.end,
 3978                    end: selection.end,
 3979                    reversed: false,
 3980                    goal: SelectionGoal::None,
 3981                });
 3982                to_unfold.push(selection.start..selection.end);
 3983            }
 3984        }
 3985        self.unfold_ranges(to_unfold, true, cx);
 3986        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 3987    }
 3988
 3989    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 3990        self.add_selection(true, cx);
 3991    }
 3992
 3993    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 3994        self.add_selection(false, cx);
 3995    }
 3996
 3997    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 3998        self.push_to_selection_history();
 3999        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4000        let mut selections = self.local_selections::<Point>(cx);
 4001        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4002            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4003            let range = oldest_selection.display_range(&display_map).sorted();
 4004            let columns = cmp::min(range.start.column(), range.end.column())
 4005                ..cmp::max(range.start.column(), range.end.column());
 4006
 4007            selections.clear();
 4008            let mut stack = Vec::new();
 4009            for row in range.start.row()..=range.end.row() {
 4010                if let Some(selection) = self.build_columnar_selection(
 4011                    &display_map,
 4012                    row,
 4013                    &columns,
 4014                    oldest_selection.reversed,
 4015                ) {
 4016                    stack.push(selection.id);
 4017                    selections.push(selection);
 4018                }
 4019            }
 4020
 4021            if above {
 4022                stack.reverse();
 4023            }
 4024
 4025            AddSelectionsState { above, stack }
 4026        });
 4027
 4028        let last_added_selection = *state.stack.last().unwrap();
 4029        let mut new_selections = Vec::new();
 4030        if above == state.above {
 4031            let end_row = if above {
 4032                0
 4033            } else {
 4034                display_map.max_point().row()
 4035            };
 4036
 4037            'outer: for selection in selections {
 4038                if selection.id == last_added_selection {
 4039                    let range = selection.display_range(&display_map).sorted();
 4040                    debug_assert_eq!(range.start.row(), range.end.row());
 4041                    let mut row = range.start.row();
 4042                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4043                    {
 4044                        start..end
 4045                    } else {
 4046                        cmp::min(range.start.column(), range.end.column())
 4047                            ..cmp::max(range.start.column(), range.end.column())
 4048                    };
 4049
 4050                    while row != end_row {
 4051                        if above {
 4052                            row -= 1;
 4053                        } else {
 4054                            row += 1;
 4055                        }
 4056
 4057                        if let Some(new_selection) = self.build_columnar_selection(
 4058                            &display_map,
 4059                            row,
 4060                            &columns,
 4061                            selection.reversed,
 4062                        ) {
 4063                            state.stack.push(new_selection.id);
 4064                            if above {
 4065                                new_selections.push(new_selection);
 4066                                new_selections.push(selection);
 4067                            } else {
 4068                                new_selections.push(selection);
 4069                                new_selections.push(new_selection);
 4070                            }
 4071
 4072                            continue 'outer;
 4073                        }
 4074                    }
 4075                }
 4076
 4077                new_selections.push(selection);
 4078            }
 4079        } else {
 4080            new_selections = selections;
 4081            new_selections.retain(|s| s.id != last_added_selection);
 4082            state.stack.pop();
 4083        }
 4084
 4085        self.update_selections(new_selections, Some(Autoscroll::Newest), cx);
 4086        if state.stack.len() > 1 {
 4087            self.add_selections_state = Some(state);
 4088        }
 4089    }
 4090
 4091    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4092        self.push_to_selection_history();
 4093        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4094        let buffer = &display_map.buffer_snapshot;
 4095        let mut selections = self.local_selections::<usize>(cx);
 4096        if let Some(mut select_next_state) = self.select_next_state.take() {
 4097            let query = &select_next_state.query;
 4098            if !select_next_state.done {
 4099                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4100                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4101                let mut next_selected_range = None;
 4102
 4103                let bytes_after_last_selection =
 4104                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4105                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4106                let query_matches = query
 4107                    .stream_find_iter(bytes_after_last_selection)
 4108                    .map(|result| (last_selection.end, result))
 4109                    .chain(
 4110                        query
 4111                            .stream_find_iter(bytes_before_first_selection)
 4112                            .map(|result| (0, result)),
 4113                    );
 4114                for (start_offset, query_match) in query_matches {
 4115                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4116                    let offset_range =
 4117                        start_offset + query_match.start()..start_offset + query_match.end();
 4118                    let display_range = offset_range.start.to_display_point(&display_map)
 4119                        ..offset_range.end.to_display_point(&display_map);
 4120
 4121                    if !select_next_state.wordwise
 4122                        || (!movement::is_inside_word(&display_map, display_range.start)
 4123                            && !movement::is_inside_word(&display_map, display_range.end))
 4124                    {
 4125                        next_selected_range = Some(offset_range);
 4126                        break;
 4127                    }
 4128                }
 4129
 4130                if let Some(next_selected_range) = next_selected_range {
 4131                    if action.replace_newest {
 4132                        if let Some(newest_id) =
 4133                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
 4134                        {
 4135                            selections.retain(|s| s.id != newest_id);
 4136                        }
 4137                    }
 4138                    selections.push(Selection {
 4139                        id: post_inc(&mut self.next_selection_id),
 4140                        start: next_selected_range.start,
 4141                        end: next_selected_range.end,
 4142                        reversed: false,
 4143                        goal: SelectionGoal::None,
 4144                    });
 4145                    self.unfold_ranges([next_selected_range], false, cx);
 4146                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4147                } else {
 4148                    select_next_state.done = true;
 4149                }
 4150            }
 4151
 4152            self.select_next_state = Some(select_next_state);
 4153        } else if selections.len() == 1 {
 4154            let selection = selections.last_mut().unwrap();
 4155            if selection.start == selection.end {
 4156                let word_range = movement::surrounding_word(
 4157                    &display_map,
 4158                    selection.start.to_display_point(&display_map),
 4159                );
 4160                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4161                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4162                selection.goal = SelectionGoal::None;
 4163                selection.reversed = false;
 4164
 4165                let query = buffer
 4166                    .text_for_range(selection.start..selection.end)
 4167                    .collect::<String>();
 4168                let select_state = SelectNextState {
 4169                    query: AhoCorasick::new_auto_configured(&[query]),
 4170                    wordwise: true,
 4171                    done: false,
 4172                };
 4173                self.unfold_ranges([selection.start..selection.end], false, cx);
 4174                self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4175                self.select_next_state = Some(select_state);
 4176            } else {
 4177                let query = buffer
 4178                    .text_for_range(selection.start..selection.end)
 4179                    .collect::<String>();
 4180                self.select_next_state = Some(SelectNextState {
 4181                    query: AhoCorasick::new_auto_configured(&[query]),
 4182                    wordwise: false,
 4183                    done: false,
 4184                });
 4185                self.select_next(action, cx);
 4186            }
 4187        }
 4188    }
 4189
 4190    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4191        self.transact(cx, |this, cx| {
 4192            let mut selections = this.local_selections::<Point>(cx);
 4193            let mut all_selection_lines_are_comments = true;
 4194            let mut edit_ranges = Vec::new();
 4195            let mut last_toggled_row = None;
 4196            this.buffer.update(cx, |buffer, cx| {
 4197                // TODO: Handle selections that cross excerpts
 4198                for selection in &mut selections {
 4199                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
 4200                    // as that portion won't be used for detecting if a line is a comment.
 4201                    let full_comment_prefix = if let Some(prefix) = buffer
 4202                        .language_at(selection.start, cx)
 4203                        .and_then(|l| l.line_comment_prefix())
 4204                    {
 4205                        prefix.to_string()
 4206                    } else {
 4207                        return;
 4208                    };
 4209                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4210                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4211                    edit_ranges.clear();
 4212                    let snapshot = buffer.snapshot(cx);
 4213
 4214                    let end_row =
 4215                        if selection.end.row > selection.start.row && selection.end.column == 0 {
 4216                            selection.end.row
 4217                        } else {
 4218                            selection.end.row + 1
 4219                        };
 4220
 4221                    for row in selection.start.row..end_row {
 4222                        // If multiple selections contain a given row, avoid processing that
 4223                        // row more than once.
 4224                        if last_toggled_row == Some(row) {
 4225                            continue;
 4226                        } else {
 4227                            last_toggled_row = Some(row);
 4228                        }
 4229
 4230                        if snapshot.is_line_blank(row) {
 4231                            continue;
 4232                        }
 4233
 4234                        let start = Point::new(row, snapshot.indent_column_for_line(row));
 4235                        let mut line_bytes = snapshot
 4236                            .bytes_in_range(start..snapshot.max_point())
 4237                            .flatten()
 4238                            .copied();
 4239
 4240                        // If this line currently begins with the line comment prefix, then record
 4241                        // the range containing the prefix.
 4242                        if all_selection_lines_are_comments
 4243                            && line_bytes
 4244                                .by_ref()
 4245                                .take(comment_prefix.len())
 4246                                .eq(comment_prefix.bytes())
 4247                        {
 4248                            // Include any whitespace that matches the comment prefix.
 4249                            let matching_whitespace_len = line_bytes
 4250                                .zip(comment_prefix_whitespace.bytes())
 4251                                .take_while(|(a, b)| a == b)
 4252                                .count()
 4253                                as u32;
 4254                            let end = Point::new(
 4255                                row,
 4256                                start.column
 4257                                    + comment_prefix.len() as u32
 4258                                    + matching_whitespace_len,
 4259                            );
 4260                            edit_ranges.push(start..end);
 4261                        }
 4262                        // If this line does not begin with the line comment prefix, then record
 4263                        // the position where the prefix should be inserted.
 4264                        else {
 4265                            all_selection_lines_are_comments = false;
 4266                            edit_ranges.push(start..start);
 4267                        }
 4268                    }
 4269
 4270                    if !edit_ranges.is_empty() {
 4271                        if all_selection_lines_are_comments {
 4272                            buffer.edit(edit_ranges.iter().cloned(), "", cx);
 4273                        } else {
 4274                            let min_column =
 4275                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
 4276                            let edit_ranges = edit_ranges.iter().map(|range| {
 4277                                let position = Point::new(range.start.row, min_column);
 4278                                position..position
 4279                            });
 4280                            buffer.edit(edit_ranges, &full_comment_prefix, cx);
 4281                        }
 4282                    }
 4283                }
 4284            });
 4285
 4286            this.update_selections(
 4287                this.local_selections::<usize>(cx),
 4288                Some(Autoscroll::Fit),
 4289                cx,
 4290            );
 4291        });
 4292    }
 4293
 4294    pub fn select_larger_syntax_node(
 4295        &mut self,
 4296        _: &SelectLargerSyntaxNode,
 4297        cx: &mut ViewContext<Self>,
 4298    ) {
 4299        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
 4300        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4301        let buffer = self.buffer.read(cx).snapshot(cx);
 4302
 4303        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4304        let mut selected_larger_node = false;
 4305        let new_selections = old_selections
 4306            .iter()
 4307            .map(|selection| {
 4308                let old_range = selection.start..selection.end;
 4309                let mut new_range = old_range.clone();
 4310                while let Some(containing_range) =
 4311                    buffer.range_for_syntax_ancestor(new_range.clone())
 4312                {
 4313                    new_range = containing_range;
 4314                    if !display_map.intersects_fold(new_range.start)
 4315                        && !display_map.intersects_fold(new_range.end)
 4316                    {
 4317                        break;
 4318                    }
 4319                }
 4320
 4321                selected_larger_node |= new_range != old_range;
 4322                Selection {
 4323                    id: selection.id,
 4324                    start: new_range.start,
 4325                    end: new_range.end,
 4326                    goal: SelectionGoal::None,
 4327                    reversed: selection.reversed,
 4328                }
 4329            })
 4330            .collect::<Vec<_>>();
 4331
 4332        if selected_larger_node {
 4333            stack.push(old_selections);
 4334            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4335        }
 4336        self.select_larger_syntax_node_stack = stack;
 4337    }
 4338
 4339    pub fn select_smaller_syntax_node(
 4340        &mut self,
 4341        _: &SelectSmallerSyntaxNode,
 4342        cx: &mut ViewContext<Self>,
 4343    ) {
 4344        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4345        if let Some(selections) = stack.pop() {
 4346            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
 4347        }
 4348        self.select_larger_syntax_node_stack = stack;
 4349    }
 4350
 4351    pub fn move_to_enclosing_bracket(
 4352        &mut self,
 4353        _: &MoveToEnclosingBracket,
 4354        cx: &mut ViewContext<Self>,
 4355    ) {
 4356        let mut selections = self.local_selections::<usize>(cx);
 4357        let buffer = self.buffer.read(cx).snapshot(cx);
 4358        for selection in &mut selections {
 4359            if let Some((open_range, close_range)) =
 4360                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4361            {
 4362                let close_range = close_range.to_inclusive();
 4363                let destination = if close_range.contains(&selection.start)
 4364                    && close_range.contains(&selection.end)
 4365                {
 4366                    open_range.end
 4367                } else {
 4368                    *close_range.start()
 4369                };
 4370                selection.start = destination;
 4371                selection.end = destination;
 4372            }
 4373        }
 4374
 4375        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4376    }
 4377
 4378    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4379        self.end_selection(cx);
 4380        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4381        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4382            self.set_selections(entry.selections, None, true, cx);
 4383            self.select_next_state = entry.select_next_state;
 4384            self.add_selections_state = entry.add_selections_state;
 4385            self.request_autoscroll(Autoscroll::Newest, cx);
 4386        }
 4387        self.selection_history.mode = SelectionHistoryMode::Normal;
 4388    }
 4389
 4390    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4391        self.end_selection(cx);
 4392        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4393        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4394            self.set_selections(entry.selections, None, true, cx);
 4395            self.select_next_state = entry.select_next_state;
 4396            self.add_selections_state = entry.add_selections_state;
 4397            self.request_autoscroll(Autoscroll::Newest, cx);
 4398        }
 4399        self.selection_history.mode = SelectionHistoryMode::Normal;
 4400    }
 4401
 4402    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
 4403        self.go_to_diagnostic(Direction::Next, cx)
 4404    }
 4405
 4406    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4407        self.go_to_diagnostic(Direction::Prev, cx)
 4408    }
 4409
 4410    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4411        let buffer = self.buffer.read(cx).snapshot(cx);
 4412        let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
 4413        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4414            active_diagnostics
 4415                .primary_range
 4416                .to_offset(&buffer)
 4417                .to_inclusive()
 4418        });
 4419        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4420            if active_primary_range.contains(&selection.head()) {
 4421                *active_primary_range.end()
 4422            } else {
 4423                selection.head()
 4424            }
 4425        } else {
 4426            selection.head()
 4427        };
 4428
 4429        loop {
 4430            let mut diagnostics = if direction == Direction::Prev {
 4431                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4432            } else {
 4433                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4434            };
 4435            let group = diagnostics.find_map(|entry| {
 4436                if entry.diagnostic.is_primary
 4437                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4438                    && !entry.range.is_empty()
 4439                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4440                {
 4441                    Some((entry.range, entry.diagnostic.group_id))
 4442                } else {
 4443                    None
 4444                }
 4445            });
 4446
 4447            if let Some((primary_range, group_id)) = group {
 4448                self.activate_diagnostics(group_id, cx);
 4449                self.update_selections(
 4450                    vec![Selection {
 4451                        id: selection.id,
 4452                        start: primary_range.start,
 4453                        end: primary_range.start,
 4454                        reversed: false,
 4455                        goal: SelectionGoal::None,
 4456                    }],
 4457                    Some(Autoscroll::Center),
 4458                    cx,
 4459                );
 4460                break;
 4461            } else {
 4462                // Cycle around to the start of the buffer, potentially moving back to the start of
 4463                // the currently active diagnostic.
 4464                active_primary_range.take();
 4465                if direction == Direction::Prev {
 4466                    if search_start == buffer.len() {
 4467                        break;
 4468                    } else {
 4469                        search_start = buffer.len();
 4470                    }
 4471                } else {
 4472                    if search_start == 0 {
 4473                        break;
 4474                    } else {
 4475                        search_start = 0;
 4476                    }
 4477                }
 4478            }
 4479        }
 4480    }
 4481
 4482    pub fn go_to_definition(
 4483        workspace: &mut Workspace,
 4484        _: &GoToDefinition,
 4485        cx: &mut ViewContext<Workspace>,
 4486    ) {
 4487        let active_item = workspace.active_item(cx);
 4488        let editor_handle = if let Some(editor) = active_item
 4489            .as_ref()
 4490            .and_then(|item| item.act_as::<Self>(cx))
 4491        {
 4492            editor
 4493        } else {
 4494            return;
 4495        };
 4496
 4497        let editor = editor_handle.read(cx);
 4498        let head = editor.newest_selection::<usize>(cx).head();
 4499        let (buffer, head) =
 4500            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
 4501                text_anchor
 4502            } else {
 4503                return;
 4504            };
 4505
 4506        let project = workspace.project().clone();
 4507        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
 4508        cx.spawn(|workspace, mut cx| async move {
 4509            let definitions = definitions.await?;
 4510            workspace.update(&mut cx, |workspace, cx| {
 4511                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 4512                for definition in definitions {
 4513                    let range = definition.range.to_offset(definition.buffer.read(cx));
 4514
 4515                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
 4516                    target_editor_handle.update(cx, |target_editor, cx| {
 4517                        // When selecting a definition in a different buffer, disable the nav history
 4518                        // to avoid creating a history entry at the previous cursor location.
 4519                        if editor_handle != target_editor_handle {
 4520                            nav_history.borrow_mut().disable();
 4521                        }
 4522                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
 4523                        nav_history.borrow_mut().enable();
 4524                    });
 4525                }
 4526            });
 4527
 4528            Ok::<(), anyhow::Error>(())
 4529        })
 4530        .detach_and_log_err(cx);
 4531    }
 4532
 4533    pub fn find_all_references(
 4534        workspace: &mut Workspace,
 4535        _: &FindAllReferences,
 4536        cx: &mut ViewContext<Workspace>,
 4537    ) -> Option<Task<Result<()>>> {
 4538        let active_item = workspace.active_item(cx)?;
 4539        let editor_handle = active_item.act_as::<Self>(cx)?;
 4540
 4541        let editor = editor_handle.read(cx);
 4542        let head = editor.newest_selection::<usize>(cx).head();
 4543        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
 4544        let replica_id = editor.replica_id(cx);
 4545
 4546        let project = workspace.project().clone();
 4547        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4548        Some(cx.spawn(|workspace, mut cx| async move {
 4549            let mut locations = references.await?;
 4550            if locations.is_empty() {
 4551                return Ok(());
 4552            }
 4553
 4554            locations.sort_by_key(|location| location.buffer.id());
 4555            let mut locations = locations.into_iter().peekable();
 4556            let mut ranges_to_highlight = Vec::new();
 4557
 4558            let excerpt_buffer = cx.add_model(|cx| {
 4559                let mut symbol_name = None;
 4560                let mut multibuffer = MultiBuffer::new(replica_id);
 4561                while let Some(location) = locations.next() {
 4562                    let buffer = location.buffer.read(cx);
 4563                    let mut ranges_for_buffer = Vec::new();
 4564                    let range = location.range.to_offset(buffer);
 4565                    ranges_for_buffer.push(range.clone());
 4566                    if symbol_name.is_none() {
 4567                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4568                    }
 4569
 4570                    while let Some(next_location) = locations.peek() {
 4571                        if next_location.buffer == location.buffer {
 4572                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4573                            locations.next();
 4574                        } else {
 4575                            break;
 4576                        }
 4577                    }
 4578
 4579                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4580                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4581                        location.buffer.clone(),
 4582                        ranges_for_buffer,
 4583                        1,
 4584                        cx,
 4585                    ));
 4586                }
 4587                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4588            });
 4589
 4590            workspace.update(&mut cx, |workspace, cx| {
 4591                let editor =
 4592                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4593                editor.update(cx, |editor, cx| {
 4594                    editor.highlight_background::<Self>(
 4595                        ranges_to_highlight,
 4596                        |theme| theme.editor.highlighted_line_background,
 4597                        cx,
 4598                    );
 4599                });
 4600                workspace.add_item(Box::new(editor), cx);
 4601            });
 4602
 4603            Ok(())
 4604        }))
 4605    }
 4606
 4607    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4608        use language::ToOffset as _;
 4609
 4610        let project = self.project.clone()?;
 4611        let selection = self.newest_anchor_selection().clone();
 4612        let (cursor_buffer, cursor_buffer_position) = self
 4613            .buffer
 4614            .read(cx)
 4615            .text_anchor_for_position(selection.head(), cx)?;
 4616        let (tail_buffer, _) = self
 4617            .buffer
 4618            .read(cx)
 4619            .text_anchor_for_position(selection.tail(), cx)?;
 4620        if tail_buffer != cursor_buffer {
 4621            return None;
 4622        }
 4623
 4624        let snapshot = cursor_buffer.read(cx).snapshot();
 4625        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4626        let prepare_rename = project.update(cx, |project, cx| {
 4627            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4628        });
 4629
 4630        Some(cx.spawn(|this, mut cx| async move {
 4631            let rename_range = if let Some(range) = prepare_rename.await? {
 4632                Some(range)
 4633            } else {
 4634                this.read_with(&cx, |this, cx| {
 4635                    let buffer = this.buffer.read(cx).snapshot(cx);
 4636                    let mut buffer_highlights = this
 4637                        .document_highlights_for_position(selection.head(), &buffer)
 4638                        .filter(|highlight| {
 4639                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4640                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4641                        });
 4642                    buffer_highlights
 4643                        .next()
 4644                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4645                })
 4646            };
 4647            if let Some(rename_range) = rename_range {
 4648                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4649                let cursor_offset_in_rename_range =
 4650                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4651
 4652                this.update(&mut cx, |this, cx| {
 4653                    this.take_rename(false, cx);
 4654                    let style = this.style(cx);
 4655                    let buffer = this.buffer.read(cx).read(cx);
 4656                    let cursor_offset = selection.head().to_offset(&buffer);
 4657                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4658                    let rename_end = rename_start + rename_buffer_range.len();
 4659                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4660                    let mut old_highlight_id = None;
 4661                    let old_name = buffer
 4662                        .chunks(rename_start..rename_end, true)
 4663                        .map(|chunk| {
 4664                            if old_highlight_id.is_none() {
 4665                                old_highlight_id = chunk.syntax_highlight_id;
 4666                            }
 4667                            chunk.text
 4668                        })
 4669                        .collect();
 4670
 4671                    drop(buffer);
 4672
 4673                    // Position the selection in the rename editor so that it matches the current selection.
 4674                    this.show_local_selections = false;
 4675                    let rename_editor = cx.add_view(|cx| {
 4676                        let mut editor = Editor::single_line(None, cx);
 4677                        if let Some(old_highlight_id) = old_highlight_id {
 4678                            editor.override_text_style =
 4679                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4680                        }
 4681                        editor
 4682                            .buffer
 4683                            .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
 4684                        editor.select_all(&SelectAll, cx);
 4685                        editor
 4686                    });
 4687
 4688                    let ranges = this
 4689                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4690                        .into_iter()
 4691                        .flat_map(|(_, ranges)| ranges)
 4692                        .chain(
 4693                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4694                                .into_iter()
 4695                                .flat_map(|(_, ranges)| ranges),
 4696                        )
 4697                        .collect();
 4698
 4699                    this.highlight_text::<Rename>(
 4700                        ranges,
 4701                        HighlightStyle {
 4702                            fade_out: Some(style.rename_fade),
 4703                            ..Default::default()
 4704                        },
 4705                        cx,
 4706                    );
 4707                    cx.focus(&rename_editor);
 4708                    let block_id = this.insert_blocks(
 4709                        [BlockProperties {
 4710                            position: range.start.clone(),
 4711                            height: 1,
 4712                            render: Arc::new({
 4713                                let editor = rename_editor.clone();
 4714                                move |cx: &BlockContext| {
 4715                                    ChildView::new(editor.clone())
 4716                                        .contained()
 4717                                        .with_padding_left(cx.anchor_x)
 4718                                        .boxed()
 4719                                }
 4720                            }),
 4721                            disposition: BlockDisposition::Below,
 4722                        }],
 4723                        cx,
 4724                    )[0];
 4725                    this.pending_rename = Some(RenameState {
 4726                        range,
 4727                        old_name,
 4728                        editor: rename_editor,
 4729                        block_id,
 4730                    });
 4731                });
 4732            }
 4733
 4734            Ok(())
 4735        }))
 4736    }
 4737
 4738    pub fn confirm_rename(
 4739        workspace: &mut Workspace,
 4740        _: &ConfirmRename,
 4741        cx: &mut ViewContext<Workspace>,
 4742    ) -> Option<Task<Result<()>>> {
 4743        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4744
 4745        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4746            let rename = editor.take_rename(false, cx)?;
 4747            let buffer = editor.buffer.read(cx);
 4748            let (start_buffer, start) =
 4749                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4750            let (end_buffer, end) =
 4751                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4752            if start_buffer == end_buffer {
 4753                let new_name = rename.editor.read(cx).text(cx);
 4754                Some((start_buffer, start..end, rename.old_name, new_name))
 4755            } else {
 4756                None
 4757            }
 4758        })?;
 4759
 4760        let rename = workspace.project().clone().update(cx, |project, cx| {
 4761            project.perform_rename(
 4762                buffer.clone(),
 4763                range.start.clone(),
 4764                new_name.clone(),
 4765                true,
 4766                cx,
 4767            )
 4768        });
 4769
 4770        Some(cx.spawn(|workspace, mut cx| async move {
 4771            let project_transaction = rename.await?;
 4772            Self::open_project_transaction(
 4773                editor.clone(),
 4774                workspace,
 4775                project_transaction,
 4776                format!("Rename: {}{}", old_name, new_name),
 4777                cx.clone(),
 4778            )
 4779            .await?;
 4780
 4781            editor.update(&mut cx, |editor, cx| {
 4782                editor.refresh_document_highlights(cx);
 4783            });
 4784            Ok(())
 4785        }))
 4786    }
 4787
 4788    fn take_rename(
 4789        &mut self,
 4790        moving_cursor: bool,
 4791        cx: &mut ViewContext<Self>,
 4792    ) -> Option<RenameState> {
 4793        let rename = self.pending_rename.take()?;
 4794        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4795        self.clear_text_highlights::<Rename>(cx);
 4796        self.show_local_selections = true;
 4797
 4798        if moving_cursor {
 4799            let cursor_in_rename_editor =
 4800                rename.editor.read(cx).newest_selection::<usize>(cx).head();
 4801
 4802            // Update the selection to match the position of the selection inside
 4803            // the rename editor.
 4804            let snapshot = self.buffer.read(cx).read(cx);
 4805            let rename_range = rename.range.to_offset(&snapshot);
 4806            let cursor_in_editor = snapshot
 4807                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4808                .min(rename_range.end);
 4809            drop(snapshot);
 4810
 4811            self.update_selections(
 4812                vec![Selection {
 4813                    id: self.newest_anchor_selection().id,
 4814                    start: cursor_in_editor,
 4815                    end: cursor_in_editor,
 4816                    reversed: false,
 4817                    goal: SelectionGoal::None,
 4818                }],
 4819                None,
 4820                cx,
 4821            );
 4822        }
 4823
 4824        Some(rename)
 4825    }
 4826
 4827    #[cfg(any(test, feature = "test-support"))]
 4828    pub fn pending_rename(&self) -> Option<&RenameState> {
 4829        self.pending_rename.as_ref()
 4830    }
 4831
 4832    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4833        if let Some(project) = self.project.clone() {
 4834            self.buffer.update(cx, |multi_buffer, cx| {
 4835                project.update(cx, |project, cx| {
 4836                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4837                });
 4838            })
 4839        }
 4840    }
 4841
 4842    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4843        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4844            let buffer = self.buffer.read(cx).snapshot(cx);
 4845            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4846            let is_valid = buffer
 4847                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4848                .any(|entry| {
 4849                    entry.diagnostic.is_primary
 4850                        && !entry.range.is_empty()
 4851                        && entry.range.start == primary_range_start
 4852                        && entry.diagnostic.message == active_diagnostics.primary_message
 4853                });
 4854
 4855            if is_valid != active_diagnostics.is_valid {
 4856                active_diagnostics.is_valid = is_valid;
 4857                let mut new_styles = HashMap::default();
 4858                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4859                    new_styles.insert(
 4860                        *block_id,
 4861                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4862                    );
 4863                }
 4864                self.display_map
 4865                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4866            }
 4867        }
 4868    }
 4869
 4870    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4871        self.dismiss_diagnostics(cx);
 4872        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4873            let buffer = self.buffer.read(cx).snapshot(cx);
 4874
 4875            let mut primary_range = None;
 4876            let mut primary_message = None;
 4877            let mut group_end = Point::zero();
 4878            let diagnostic_group = buffer
 4879                .diagnostic_group::<Point>(group_id)
 4880                .map(|entry| {
 4881                    if entry.range.end > group_end {
 4882                        group_end = entry.range.end;
 4883                    }
 4884                    if entry.diagnostic.is_primary {
 4885                        primary_range = Some(entry.range.clone());
 4886                        primary_message = Some(entry.diagnostic.message.clone());
 4887                    }
 4888                    entry
 4889                })
 4890                .collect::<Vec<_>>();
 4891            let primary_range = primary_range.unwrap();
 4892            let primary_message = primary_message.unwrap();
 4893            let primary_range =
 4894                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 4895
 4896            let blocks = display_map
 4897                .insert_blocks(
 4898                    diagnostic_group.iter().map(|entry| {
 4899                        let diagnostic = entry.diagnostic.clone();
 4900                        let message_height = diagnostic.message.lines().count() as u8;
 4901                        BlockProperties {
 4902                            position: buffer.anchor_after(entry.range.start),
 4903                            height: message_height,
 4904                            render: diagnostic_block_renderer(diagnostic, true),
 4905                            disposition: BlockDisposition::Below,
 4906                        }
 4907                    }),
 4908                    cx,
 4909                )
 4910                .into_iter()
 4911                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 4912                .collect();
 4913
 4914            Some(ActiveDiagnosticGroup {
 4915                primary_range,
 4916                primary_message,
 4917                blocks,
 4918                is_valid: true,
 4919            })
 4920        });
 4921    }
 4922
 4923    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 4924        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 4925            self.display_map.update(cx, |display_map, cx| {
 4926                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 4927            });
 4928            cx.notify();
 4929        }
 4930    }
 4931
 4932    fn build_columnar_selection(
 4933        &mut self,
 4934        display_map: &DisplaySnapshot,
 4935        row: u32,
 4936        columns: &Range<u32>,
 4937        reversed: bool,
 4938    ) -> Option<Selection<Point>> {
 4939        let is_empty = columns.start == columns.end;
 4940        let line_len = display_map.line_len(row);
 4941        if columns.start < line_len || (is_empty && columns.start == line_len) {
 4942            let start = DisplayPoint::new(row, columns.start);
 4943            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
 4944            Some(Selection {
 4945                id: post_inc(&mut self.next_selection_id),
 4946                start: start.to_point(display_map),
 4947                end: end.to_point(display_map),
 4948                reversed,
 4949                goal: SelectionGoal::ColumnRange {
 4950                    start: columns.start,
 4951                    end: columns.end,
 4952                },
 4953            })
 4954        } else {
 4955            None
 4956        }
 4957    }
 4958
 4959    pub fn local_selections_in_range(
 4960        &self,
 4961        range: Range<Anchor>,
 4962        display_map: &DisplaySnapshot,
 4963    ) -> Vec<Selection<Point>> {
 4964        let buffer = &display_map.buffer_snapshot;
 4965
 4966        let start_ix = match self
 4967            .selections
 4968            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
 4969        {
 4970            Ok(ix) | Err(ix) => ix,
 4971        };
 4972        let end_ix = match self
 4973            .selections
 4974            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
 4975        {
 4976            Ok(ix) => ix + 1,
 4977            Err(ix) => ix,
 4978        };
 4979
 4980        fn point_selection(
 4981            selection: &Selection<Anchor>,
 4982            buffer: &MultiBufferSnapshot,
 4983        ) -> Selection<Point> {
 4984            let start = selection.start.to_point(&buffer);
 4985            let end = selection.end.to_point(&buffer);
 4986            Selection {
 4987                id: selection.id,
 4988                start,
 4989                end,
 4990                reversed: selection.reversed,
 4991                goal: selection.goal,
 4992            }
 4993        }
 4994
 4995        self.selections[start_ix..end_ix]
 4996            .iter()
 4997            .chain(
 4998                self.pending_selection
 4999                    .as_ref()
 5000                    .map(|pending| &pending.selection),
 5001            )
 5002            .map(|s| point_selection(s, &buffer))
 5003            .collect()
 5004    }
 5005
 5006    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
 5007    where
 5008        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
 5009    {
 5010        let buffer = self.buffer.read(cx).snapshot(cx);
 5011        let mut selections = self
 5012            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
 5013            .peekable();
 5014
 5015        let mut pending_selection = self.pending_selection::<D>(&buffer);
 5016
 5017        iter::from_fn(move || {
 5018            if let Some(pending) = pending_selection.as_mut() {
 5019                while let Some(next_selection) = selections.peek() {
 5020                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 5021                        let next_selection = selections.next().unwrap();
 5022                        if next_selection.start < pending.start {
 5023                            pending.start = next_selection.start;
 5024                        }
 5025                        if next_selection.end > pending.end {
 5026                            pending.end = next_selection.end;
 5027                        }
 5028                    } else if next_selection.end < pending.start {
 5029                        return selections.next();
 5030                    } else {
 5031                        break;
 5032                    }
 5033                }
 5034
 5035                pending_selection.take()
 5036            } else {
 5037                selections.next()
 5038            }
 5039        })
 5040        .collect()
 5041    }
 5042
 5043    fn resolve_selections<'a, D, I>(
 5044        &self,
 5045        selections: I,
 5046        snapshot: &MultiBufferSnapshot,
 5047    ) -> impl 'a + Iterator<Item = Selection<D>>
 5048    where
 5049        D: TextDimension + Ord + Sub<D, Output = D>,
 5050        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 5051    {
 5052        let (to_summarize, selections) = selections.into_iter().tee();
 5053        let mut summaries = snapshot
 5054            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
 5055            .into_iter();
 5056        selections.map(move |s| Selection {
 5057            id: s.id,
 5058            start: summaries.next().unwrap(),
 5059            end: summaries.next().unwrap(),
 5060            reversed: s.reversed,
 5061            goal: s.goal,
 5062        })
 5063    }
 5064
 5065    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5066        &self,
 5067        snapshot: &MultiBufferSnapshot,
 5068    ) -> Option<Selection<D>> {
 5069        self.pending_selection
 5070            .as_ref()
 5071            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
 5072    }
 5073
 5074    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5075        &self,
 5076        selection: &Selection<Anchor>,
 5077        buffer: &MultiBufferSnapshot,
 5078    ) -> Selection<D> {
 5079        Selection {
 5080            id: selection.id,
 5081            start: selection.start.summary::<D>(&buffer),
 5082            end: selection.end.summary::<D>(&buffer),
 5083            reversed: selection.reversed,
 5084            goal: selection.goal,
 5085        }
 5086    }
 5087
 5088    fn selection_count<'a>(&self) -> usize {
 5089        let mut count = self.selections.len();
 5090        if self.pending_selection.is_some() {
 5091            count += 1;
 5092        }
 5093        count
 5094    }
 5095
 5096    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5097        &self,
 5098        cx: &AppContext,
 5099    ) -> Selection<D> {
 5100        let snapshot = self.buffer.read(cx).read(cx);
 5101        self.selections
 5102            .iter()
 5103            .min_by_key(|s| s.id)
 5104            .map(|selection| self.resolve_selection(selection, &snapshot))
 5105            .or_else(|| self.pending_selection(&snapshot))
 5106            .unwrap()
 5107    }
 5108
 5109    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5110        &self,
 5111        cx: &AppContext,
 5112    ) -> Selection<D> {
 5113        self.resolve_selection(
 5114            self.newest_anchor_selection(),
 5115            &self.buffer.read(cx).read(cx),
 5116        )
 5117    }
 5118
 5119    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
 5120        &self,
 5121        snapshot: &MultiBufferSnapshot,
 5122    ) -> Selection<D> {
 5123        self.resolve_selection(self.newest_anchor_selection(), snapshot)
 5124    }
 5125
 5126    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
 5127        self.pending_selection
 5128            .as_ref()
 5129            .map(|s| &s.selection)
 5130            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
 5131            .unwrap()
 5132    }
 5133
 5134    pub fn update_selections<T>(
 5135        &mut self,
 5136        mut selections: Vec<Selection<T>>,
 5137        autoscroll: Option<Autoscroll>,
 5138        cx: &mut ViewContext<Self>,
 5139    ) where
 5140        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
 5141    {
 5142        let buffer = self.buffer.read(cx).snapshot(cx);
 5143        selections.sort_unstable_by_key(|s| s.start);
 5144
 5145        // Merge overlapping selections.
 5146        let mut i = 1;
 5147        while i < selections.len() {
 5148            if selections[i - 1].end >= selections[i].start {
 5149                let removed = selections.remove(i);
 5150                if removed.start < selections[i - 1].start {
 5151                    selections[i - 1].start = removed.start;
 5152                }
 5153                if removed.end > selections[i - 1].end {
 5154                    selections[i - 1].end = removed.end;
 5155                }
 5156            } else {
 5157                i += 1;
 5158            }
 5159        }
 5160
 5161        if let Some(autoscroll) = autoscroll {
 5162            self.request_autoscroll(autoscroll, cx);
 5163        }
 5164
 5165        self.set_selections(
 5166            Arc::from_iter(selections.into_iter().map(|selection| {
 5167                let end_bias = if selection.end > selection.start {
 5168                    Bias::Left
 5169                } else {
 5170                    Bias::Right
 5171                };
 5172                Selection {
 5173                    id: selection.id,
 5174                    start: buffer.anchor_after(selection.start),
 5175                    end: buffer.anchor_at(selection.end, end_bias),
 5176                    reversed: selection.reversed,
 5177                    goal: selection.goal,
 5178                }
 5179            })),
 5180            None,
 5181            true,
 5182            cx,
 5183        );
 5184    }
 5185
 5186    pub fn set_selections_from_remote(
 5187        &mut self,
 5188        mut selections: Vec<Selection<Anchor>>,
 5189        cx: &mut ViewContext<Self>,
 5190    ) {
 5191        let buffer = self.buffer.read(cx);
 5192        let buffer = buffer.read(cx);
 5193        selections.sort_by(|a, b| {
 5194            a.start
 5195                .cmp(&b.start, &*buffer)
 5196                .then_with(|| b.end.cmp(&a.end, &*buffer))
 5197        });
 5198
 5199        // Merge overlapping selections
 5200        let mut i = 1;
 5201        while i < selections.len() {
 5202            if selections[i - 1]
 5203                .end
 5204                .cmp(&selections[i].start, &*buffer)
 5205                .is_ge()
 5206            {
 5207                let removed = selections.remove(i);
 5208                if removed
 5209                    .start
 5210                    .cmp(&selections[i - 1].start, &*buffer)
 5211                    .is_lt()
 5212                {
 5213                    selections[i - 1].start = removed.start;
 5214                }
 5215                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
 5216                    selections[i - 1].end = removed.end;
 5217                }
 5218            } else {
 5219                i += 1;
 5220            }
 5221        }
 5222
 5223        drop(buffer);
 5224        self.set_selections(selections.into(), None, false, cx);
 5225    }
 5226
 5227    /// Compute new ranges for any selections that were located in excerpts that have
 5228    /// since been removed.
 5229    ///
 5230    /// Returns a `HashMap` indicating which selections whose former head position
 5231    /// was no longer present. The keys of the map are selection ids. The values are
 5232    /// the id of the new excerpt where the head of the selection has been moved.
 5233    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
 5234        let snapshot = self.buffer.read(cx).read(cx);
 5235        let mut selections_with_lost_position = HashMap::default();
 5236
 5237        let mut pending_selection = self.pending_selection.take();
 5238        if let Some(pending) = pending_selection.as_mut() {
 5239            let anchors =
 5240                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
 5241            let (_, start, kept_start) = anchors[0].clone();
 5242            let (_, end, kept_end) = anchors[1].clone();
 5243            let kept_head = if pending.selection.reversed {
 5244                kept_start
 5245            } else {
 5246                kept_end
 5247            };
 5248            if !kept_head {
 5249                selections_with_lost_position.insert(
 5250                    pending.selection.id,
 5251                    pending.selection.head().excerpt_id.clone(),
 5252                );
 5253            }
 5254
 5255            pending.selection.start = start;
 5256            pending.selection.end = end;
 5257        }
 5258
 5259        let anchors_with_status = snapshot.refresh_anchors(
 5260            self.selections
 5261                .iter()
 5262                .flat_map(|selection| [&selection.start, &selection.end]),
 5263        );
 5264        self.selections = anchors_with_status
 5265            .chunks(2)
 5266            .map(|selection_anchors| {
 5267                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
 5268                let (_, end, kept_end) = selection_anchors[1].clone();
 5269                let selection = &self.selections[anchor_ix / 2];
 5270                let kept_head = if selection.reversed {
 5271                    kept_start
 5272                } else {
 5273                    kept_end
 5274                };
 5275                if !kept_head {
 5276                    selections_with_lost_position
 5277                        .insert(selection.id, selection.head().excerpt_id.clone());
 5278                }
 5279
 5280                Selection {
 5281                    id: selection.id,
 5282                    start,
 5283                    end,
 5284                    reversed: selection.reversed,
 5285                    goal: selection.goal,
 5286                }
 5287            })
 5288            .collect();
 5289        drop(snapshot);
 5290
 5291        let new_selections = self.local_selections::<usize>(cx);
 5292        if !new_selections.is_empty() {
 5293            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 5294        }
 5295        self.pending_selection = pending_selection;
 5296
 5297        selections_with_lost_position
 5298    }
 5299
 5300    fn set_selections(
 5301        &mut self,
 5302        selections: Arc<[Selection<Anchor>]>,
 5303        pending_selection: Option<PendingSelection>,
 5304        local: bool,
 5305        cx: &mut ViewContext<Self>,
 5306    ) {
 5307        assert!(
 5308            !selections.is_empty() || pending_selection.is_some(),
 5309            "must have at least one selection"
 5310        );
 5311
 5312        let old_cursor_position = self.newest_anchor_selection().head();
 5313
 5314        self.push_to_selection_history();
 5315        self.selections = selections;
 5316        self.pending_selection = pending_selection;
 5317        if self.focused && self.leader_replica_id.is_none() {
 5318            self.buffer.update(cx, |buffer, cx| {
 5319                buffer.set_active_selections(&self.selections, cx)
 5320            });
 5321        }
 5322
 5323        let display_map = self
 5324            .display_map
 5325            .update(cx, |display_map, cx| display_map.snapshot(cx));
 5326        let buffer = &display_map.buffer_snapshot;
 5327        self.add_selections_state = None;
 5328        self.select_next_state = None;
 5329        self.select_larger_syntax_node_stack.clear();
 5330        self.autoclose_stack.invalidate(&self.selections, &buffer);
 5331        self.snippet_stack.invalidate(&self.selections, &buffer);
 5332        self.take_rename(false, cx);
 5333
 5334        let new_cursor_position = self.newest_anchor_selection().head();
 5335
 5336        self.push_to_nav_history(
 5337            old_cursor_position.clone(),
 5338            Some(new_cursor_position.to_point(&buffer)),
 5339            cx,
 5340        );
 5341
 5342        if local {
 5343            let completion_menu = match self.context_menu.as_mut() {
 5344                Some(ContextMenu::Completions(menu)) => Some(menu),
 5345                _ => {
 5346                    self.context_menu.take();
 5347                    None
 5348                }
 5349            };
 5350
 5351            if let Some(completion_menu) = completion_menu {
 5352                let cursor_position = new_cursor_position.to_offset(&buffer);
 5353                let (word_range, kind) =
 5354                    buffer.surrounding_word(completion_menu.initial_position.clone());
 5355                if kind == Some(CharKind::Word)
 5356                    && word_range.to_inclusive().contains(&cursor_position)
 5357                {
 5358                    let query = Self::completion_query(&buffer, cursor_position);
 5359                    cx.background()
 5360                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 5361                    self.show_completions(&ShowCompletions, cx);
 5362                } else {
 5363                    self.hide_context_menu(cx);
 5364                }
 5365            }
 5366
 5367            if old_cursor_position.to_display_point(&display_map).row()
 5368                != new_cursor_position.to_display_point(&display_map).row()
 5369            {
 5370                self.available_code_actions.take();
 5371            }
 5372            self.refresh_code_actions(cx);
 5373            self.refresh_document_highlights(cx);
 5374        }
 5375
 5376        self.pause_cursor_blinking(cx);
 5377        cx.emit(Event::SelectionsChanged { local });
 5378    }
 5379
 5380    fn push_to_selection_history(&mut self) {
 5381        self.selection_history.push(SelectionHistoryEntry {
 5382            selections: self.selections.clone(),
 5383            select_next_state: self.select_next_state.clone(),
 5384            add_selections_state: self.add_selections_state.clone(),
 5385        });
 5386    }
 5387
 5388    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5389        self.autoscroll_request = Some((autoscroll, true));
 5390        cx.notify();
 5391    }
 5392
 5393    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5394        self.autoscroll_request = Some((autoscroll, false));
 5395        cx.notify();
 5396    }
 5397
 5398    pub fn transact(
 5399        &mut self,
 5400        cx: &mut ViewContext<Self>,
 5401        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5402    ) {
 5403        self.start_transaction_at(Instant::now(), cx);
 5404        update(self, cx);
 5405        self.end_transaction_at(Instant::now(), cx);
 5406    }
 5407
 5408    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5409        self.end_selection(cx);
 5410        if let Some(tx_id) = self
 5411            .buffer
 5412            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5413        {
 5414            self.selection_history
 5415                .insert_transaction(tx_id, self.selections.clone());
 5416        }
 5417    }
 5418
 5419    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5420        if let Some(tx_id) = self
 5421            .buffer
 5422            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5423        {
 5424            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5425                *end_selections = Some(self.selections.clone());
 5426            } else {
 5427                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5428            }
 5429
 5430            cx.emit(Event::Edited);
 5431        }
 5432    }
 5433
 5434    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5435        log::info!("Editor::page_up");
 5436    }
 5437
 5438    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5439        log::info!("Editor::page_down");
 5440    }
 5441
 5442    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5443        let mut fold_ranges = Vec::new();
 5444
 5445        let selections = self.local_selections::<Point>(cx);
 5446        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5447        for selection in selections {
 5448            let range = selection.display_range(&display_map).sorted();
 5449            let buffer_start_row = range.start.to_point(&display_map).row;
 5450
 5451            for row in (0..=range.end.row()).rev() {
 5452                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5453                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5454                    if fold_range.end.row >= buffer_start_row {
 5455                        fold_ranges.push(fold_range);
 5456                        if row <= range.start.row() {
 5457                            break;
 5458                        }
 5459                    }
 5460                }
 5461            }
 5462        }
 5463
 5464        self.fold_ranges(fold_ranges, cx);
 5465    }
 5466
 5467    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5468        let selections = self.local_selections::<Point>(cx);
 5469        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5470        let buffer = &display_map.buffer_snapshot;
 5471        let ranges = selections
 5472            .iter()
 5473            .map(|s| {
 5474                let range = s.display_range(&display_map).sorted();
 5475                let mut start = range.start.to_point(&display_map);
 5476                let mut end = range.end.to_point(&display_map);
 5477                start.column = 0;
 5478                end.column = buffer.line_len(end.row);
 5479                start..end
 5480            })
 5481            .collect::<Vec<_>>();
 5482        self.unfold_ranges(ranges, true, cx);
 5483    }
 5484
 5485    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5486        let max_point = display_map.max_point();
 5487        if display_row >= max_point.row() {
 5488            false
 5489        } else {
 5490            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5491            if is_blank {
 5492                false
 5493            } else {
 5494                for display_row in display_row + 1..=max_point.row() {
 5495                    let (indent, is_blank) = display_map.line_indent(display_row);
 5496                    if !is_blank {
 5497                        return indent > start_indent;
 5498                    }
 5499                }
 5500                false
 5501            }
 5502        }
 5503    }
 5504
 5505    fn foldable_range_for_line(
 5506        &self,
 5507        display_map: &DisplaySnapshot,
 5508        start_row: u32,
 5509    ) -> Range<Point> {
 5510        let max_point = display_map.max_point();
 5511
 5512        let (start_indent, _) = display_map.line_indent(start_row);
 5513        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5514        let mut end = None;
 5515        for row in start_row + 1..=max_point.row() {
 5516            let (indent, is_blank) = display_map.line_indent(row);
 5517            if !is_blank && indent <= start_indent {
 5518                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5519                break;
 5520            }
 5521        }
 5522
 5523        let end = end.unwrap_or(max_point);
 5524        return start.to_point(display_map)..end.to_point(display_map);
 5525    }
 5526
 5527    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5528        let selections = self.local_selections::<Point>(cx);
 5529        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5530        self.fold_ranges(ranges, cx);
 5531    }
 5532
 5533    pub fn fold_ranges<T: ToOffset>(
 5534        &mut self,
 5535        ranges: impl IntoIterator<Item = Range<T>>,
 5536        cx: &mut ViewContext<Self>,
 5537    ) {
 5538        let mut ranges = ranges.into_iter().peekable();
 5539        if ranges.peek().is_some() {
 5540            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5541            self.request_autoscroll(Autoscroll::Fit, cx);
 5542            cx.notify();
 5543        }
 5544    }
 5545
 5546    pub fn unfold_ranges<T: ToOffset>(
 5547        &mut self,
 5548        ranges: impl IntoIterator<Item = Range<T>>,
 5549        inclusive: bool,
 5550        cx: &mut ViewContext<Self>,
 5551    ) {
 5552        let mut ranges = ranges.into_iter().peekable();
 5553        if ranges.peek().is_some() {
 5554            self.display_map
 5555                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5556            self.request_autoscroll(Autoscroll::Fit, cx);
 5557            cx.notify();
 5558        }
 5559    }
 5560
 5561    pub fn insert_blocks(
 5562        &mut self,
 5563        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5564        cx: &mut ViewContext<Self>,
 5565    ) -> Vec<BlockId> {
 5566        let blocks = self
 5567            .display_map
 5568            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5569        self.request_autoscroll(Autoscroll::Fit, cx);
 5570        blocks
 5571    }
 5572
 5573    pub fn replace_blocks(
 5574        &mut self,
 5575        blocks: HashMap<BlockId, RenderBlock>,
 5576        cx: &mut ViewContext<Self>,
 5577    ) {
 5578        self.display_map
 5579            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5580        self.request_autoscroll(Autoscroll::Fit, cx);
 5581    }
 5582
 5583    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5584        self.display_map.update(cx, |display_map, cx| {
 5585            display_map.remove_blocks(block_ids, cx)
 5586        });
 5587    }
 5588
 5589    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5590        self.display_map
 5591            .update(cx, |map, cx| map.snapshot(cx))
 5592            .longest_row()
 5593    }
 5594
 5595    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5596        self.display_map
 5597            .update(cx, |map, cx| map.snapshot(cx))
 5598            .max_point()
 5599    }
 5600
 5601    pub fn text(&self, cx: &AppContext) -> String {
 5602        self.buffer.read(cx).read(cx).text()
 5603    }
 5604
 5605    pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
 5606        self.transact(cx, |this, cx| {
 5607            this.buffer
 5608                .read(cx)
 5609                .as_singleton()
 5610                .expect("you can only call set_text on editors for singleton buffers")
 5611                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5612        });
 5613    }
 5614
 5615    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5616        self.display_map
 5617            .update(cx, |map, cx| map.snapshot(cx))
 5618            .text()
 5619    }
 5620
 5621    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5622        let language_name = self
 5623            .buffer
 5624            .read(cx)
 5625            .as_singleton()
 5626            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5627            .map(|l| l.name());
 5628
 5629        let settings = cx.global::<Settings>();
 5630        let mode = self
 5631            .soft_wrap_mode_override
 5632            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5633        match mode {
 5634            settings::SoftWrap::None => SoftWrap::None,
 5635            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5636            settings::SoftWrap::PreferredLineLength => {
 5637                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5638            }
 5639        }
 5640    }
 5641
 5642    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5643        self.soft_wrap_mode_override = Some(mode);
 5644        cx.notify();
 5645    }
 5646
 5647    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5648        self.display_map
 5649            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5650    }
 5651
 5652    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5653        self.highlighted_rows = rows;
 5654    }
 5655
 5656    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5657        self.highlighted_rows.clone()
 5658    }
 5659
 5660    pub fn highlight_background<T: 'static>(
 5661        &mut self,
 5662        ranges: Vec<Range<Anchor>>,
 5663        color_fetcher: fn(&Theme) -> Color,
 5664        cx: &mut ViewContext<Self>,
 5665    ) {
 5666        self.background_highlights
 5667            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5668        cx.notify();
 5669    }
 5670
 5671    pub fn clear_background_highlights<T: 'static>(
 5672        &mut self,
 5673        cx: &mut ViewContext<Self>,
 5674    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5675        cx.notify();
 5676        self.background_highlights.remove(&TypeId::of::<T>())
 5677    }
 5678
 5679    #[cfg(feature = "test-support")]
 5680    pub fn all_background_highlights(
 5681        &mut self,
 5682        cx: &mut ViewContext<Self>,
 5683    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5684        let snapshot = self.snapshot(cx);
 5685        let buffer = &snapshot.buffer_snapshot;
 5686        let start = buffer.anchor_before(0);
 5687        let end = buffer.anchor_after(buffer.len());
 5688        let theme = cx.global::<Settings>().theme.as_ref();
 5689        self.background_highlights_in_range(start..end, &snapshot, theme)
 5690    }
 5691
 5692    fn document_highlights_for_position<'a>(
 5693        &'a self,
 5694        position: Anchor,
 5695        buffer: &'a MultiBufferSnapshot,
 5696    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5697        let read_highlights = self
 5698            .background_highlights
 5699            .get(&TypeId::of::<DocumentHighlightRead>())
 5700            .map(|h| &h.1);
 5701        let write_highlights = self
 5702            .background_highlights
 5703            .get(&TypeId::of::<DocumentHighlightRead>())
 5704            .map(|h| &h.1);
 5705        let left_position = position.bias_left(buffer);
 5706        let right_position = position.bias_right(buffer);
 5707        read_highlights
 5708            .into_iter()
 5709            .chain(write_highlights)
 5710            .flat_map(move |ranges| {
 5711                let start_ix = match ranges.binary_search_by(|probe| {
 5712                    let cmp = probe.end.cmp(&left_position, &buffer);
 5713                    if cmp.is_ge() {
 5714                        Ordering::Greater
 5715                    } else {
 5716                        Ordering::Less
 5717                    }
 5718                }) {
 5719                    Ok(i) | Err(i) => i,
 5720                };
 5721
 5722                let right_position = right_position.clone();
 5723                ranges[start_ix..]
 5724                    .iter()
 5725                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5726            })
 5727    }
 5728
 5729    pub fn background_highlights_in_range(
 5730        &self,
 5731        search_range: Range<Anchor>,
 5732        display_snapshot: &DisplaySnapshot,
 5733        theme: &Theme,
 5734    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5735        let mut results = Vec::new();
 5736        let buffer = &display_snapshot.buffer_snapshot;
 5737        for (color_fetcher, ranges) in self.background_highlights.values() {
 5738            let color = color_fetcher(theme);
 5739            let start_ix = match ranges.binary_search_by(|probe| {
 5740                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5741                if cmp.is_gt() {
 5742                    Ordering::Greater
 5743                } else {
 5744                    Ordering::Less
 5745                }
 5746            }) {
 5747                Ok(i) | Err(i) => i,
 5748            };
 5749            for range in &ranges[start_ix..] {
 5750                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5751                    break;
 5752                }
 5753                let start = range
 5754                    .start
 5755                    .to_point(buffer)
 5756                    .to_display_point(display_snapshot);
 5757                let end = range
 5758                    .end
 5759                    .to_point(buffer)
 5760                    .to_display_point(display_snapshot);
 5761                results.push((start..end, color))
 5762            }
 5763        }
 5764        results
 5765    }
 5766
 5767    pub fn highlight_text<T: 'static>(
 5768        &mut self,
 5769        ranges: Vec<Range<Anchor>>,
 5770        style: HighlightStyle,
 5771        cx: &mut ViewContext<Self>,
 5772    ) {
 5773        self.display_map.update(cx, |map, _| {
 5774            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5775        });
 5776        cx.notify();
 5777    }
 5778
 5779    pub fn clear_text_highlights<T: 'static>(
 5780        &mut self,
 5781        cx: &mut ViewContext<Self>,
 5782    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5783        cx.notify();
 5784        self.display_map
 5785            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5786    }
 5787
 5788    fn next_blink_epoch(&mut self) -> usize {
 5789        self.blink_epoch += 1;
 5790        self.blink_epoch
 5791    }
 5792
 5793    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5794        if !self.focused {
 5795            return;
 5796        }
 5797
 5798        self.show_local_cursors = true;
 5799        cx.notify();
 5800
 5801        let epoch = self.next_blink_epoch();
 5802        cx.spawn(|this, mut cx| {
 5803            let this = this.downgrade();
 5804            async move {
 5805                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5806                if let Some(this) = this.upgrade(&cx) {
 5807                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5808                }
 5809            }
 5810        })
 5811        .detach();
 5812    }
 5813
 5814    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5815        if epoch == self.blink_epoch {
 5816            self.blinking_paused = false;
 5817            self.blink_cursors(epoch, cx);
 5818        }
 5819    }
 5820
 5821    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5822        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5823            self.show_local_cursors = !self.show_local_cursors;
 5824            cx.notify();
 5825
 5826            let epoch = self.next_blink_epoch();
 5827            cx.spawn(|this, mut cx| {
 5828                let this = this.downgrade();
 5829                async move {
 5830                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5831                    if let Some(this) = this.upgrade(&cx) {
 5832                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5833                    }
 5834                }
 5835            })
 5836            .detach();
 5837        }
 5838    }
 5839
 5840    pub fn show_local_cursors(&self) -> bool {
 5841        self.show_local_cursors && self.focused
 5842    }
 5843
 5844    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5845        cx.notify();
 5846    }
 5847
 5848    fn on_buffer_event(
 5849        &mut self,
 5850        _: ModelHandle<MultiBuffer>,
 5851        event: &language::Event,
 5852        cx: &mut ViewContext<Self>,
 5853    ) {
 5854        match event {
 5855            language::Event::Edited => {
 5856                self.refresh_active_diagnostics(cx);
 5857                self.refresh_code_actions(cx);
 5858                cx.emit(Event::BufferEdited);
 5859            }
 5860            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5861            language::Event::Dirtied => cx.emit(Event::Dirtied),
 5862            language::Event::Saved => cx.emit(Event::Saved),
 5863            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5864            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5865            language::Event::Closed => cx.emit(Event::Closed),
 5866            language::Event::DiagnosticsUpdated => {
 5867                self.refresh_active_diagnostics(cx);
 5868            }
 5869            _ => {}
 5870        }
 5871    }
 5872
 5873    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5874        cx.notify();
 5875    }
 5876
 5877    pub fn set_searchable(&mut self, searchable: bool) {
 5878        self.searchable = searchable;
 5879    }
 5880
 5881    pub fn searchable(&self) -> bool {
 5882        self.searchable
 5883    }
 5884
 5885    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5886        let active_item = workspace.active_item(cx);
 5887        let editor_handle = if let Some(editor) = active_item
 5888            .as_ref()
 5889            .and_then(|item| item.act_as::<Self>(cx))
 5890        {
 5891            editor
 5892        } else {
 5893            cx.propagate_action();
 5894            return;
 5895        };
 5896
 5897        let editor = editor_handle.read(cx);
 5898        let buffer = editor.buffer.read(cx);
 5899        if buffer.is_singleton() {
 5900            cx.propagate_action();
 5901            return;
 5902        }
 5903
 5904        let mut new_selections_by_buffer = HashMap::default();
 5905        for selection in editor.local_selections::<usize>(cx) {
 5906            for (buffer, mut range) in
 5907                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5908            {
 5909                if selection.reversed {
 5910                    mem::swap(&mut range.start, &mut range.end);
 5911                }
 5912                new_selections_by_buffer
 5913                    .entry(buffer)
 5914                    .or_insert(Vec::new())
 5915                    .push(range)
 5916            }
 5917        }
 5918
 5919        editor_handle.update(cx, |editor, cx| {
 5920            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
 5921        });
 5922        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 5923        nav_history.borrow_mut().disable();
 5924
 5925        // We defer the pane interaction because we ourselves are a workspace item
 5926        // and activating a new item causes the pane to call a method on us reentrantly,
 5927        // which panics if we're on the stack.
 5928        cx.defer(move |workspace, cx| {
 5929            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5930                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5931                editor.update(cx, |editor, cx| {
 5932                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
 5933                });
 5934            }
 5935
 5936            nav_history.borrow_mut().enable();
 5937        });
 5938    }
 5939}
 5940
 5941impl EditorSnapshot {
 5942    pub fn is_focused(&self) -> bool {
 5943        self.is_focused
 5944    }
 5945
 5946    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5947        self.placeholder_text.as_ref()
 5948    }
 5949
 5950    pub fn scroll_position(&self) -> Vector2F {
 5951        compute_scroll_position(
 5952            &self.display_snapshot,
 5953            self.scroll_position,
 5954            &self.scroll_top_anchor,
 5955        )
 5956    }
 5957}
 5958
 5959impl Deref for EditorSnapshot {
 5960    type Target = DisplaySnapshot;
 5961
 5962    fn deref(&self) -> &Self::Target {
 5963        &self.display_snapshot
 5964    }
 5965}
 5966
 5967fn compute_scroll_position(
 5968    snapshot: &DisplaySnapshot,
 5969    mut scroll_position: Vector2F,
 5970    scroll_top_anchor: &Anchor,
 5971) -> Vector2F {
 5972    if *scroll_top_anchor != Anchor::min() {
 5973        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5974        scroll_position.set_y(scroll_top + scroll_position.y());
 5975    } else {
 5976        scroll_position.set_y(0.);
 5977    }
 5978    scroll_position
 5979}
 5980
 5981#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5982pub enum Event {
 5983    Activate,
 5984    BufferEdited,
 5985    Edited,
 5986    Reparsed,
 5987    Blurred,
 5988    Dirtied,
 5989    Saved,
 5990    TitleChanged,
 5991    SelectionsChanged { local: bool },
 5992    ScrollPositionChanged { local: bool },
 5993    Closed,
 5994}
 5995
 5996pub struct EditorFocused(pub ViewHandle<Editor>);
 5997pub struct EditorBlurred(pub ViewHandle<Editor>);
 5998pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5999
 6000impl Entity for Editor {
 6001    type Event = Event;
 6002
 6003    fn release(&mut self, cx: &mut MutableAppContext) {
 6004        cx.emit_global(EditorReleased(self.handle.clone()));
 6005    }
 6006}
 6007
 6008impl View for Editor {
 6009    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6010        let style = self.style(cx);
 6011        self.display_map.update(cx, |map, cx| {
 6012            map.set_font(style.text.font_id, style.text.font_size, cx)
 6013        });
 6014        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 6015    }
 6016
 6017    fn ui_name() -> &'static str {
 6018        "Editor"
 6019    }
 6020
 6021    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 6022        let focused_event = EditorFocused(cx.handle());
 6023        cx.emit_global(focused_event);
 6024        if let Some(rename) = self.pending_rename.as_ref() {
 6025            cx.focus(&rename.editor);
 6026        } else {
 6027            self.focused = true;
 6028            self.blink_cursors(self.blink_epoch, cx);
 6029            self.buffer.update(cx, |buffer, cx| {
 6030                buffer.finalize_last_transaction(cx);
 6031                if self.leader_replica_id.is_none() {
 6032                    buffer.set_active_selections(&self.selections, cx);
 6033                }
 6034            });
 6035        }
 6036    }
 6037
 6038    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6039        let blurred_event = EditorBlurred(cx.handle());
 6040        cx.emit_global(blurred_event);
 6041        self.focused = false;
 6042        self.buffer
 6043            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6044        self.hide_context_menu(cx);
 6045        cx.emit(Event::Blurred);
 6046        cx.notify();
 6047    }
 6048
 6049    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6050        let mut context = Self::default_keymap_context();
 6051        let mode = match self.mode {
 6052            EditorMode::SingleLine => "single_line",
 6053            EditorMode::AutoHeight { .. } => "auto_height",
 6054            EditorMode::Full => "full",
 6055        };
 6056        context.map.insert("mode".into(), mode.into());
 6057        if self.pending_rename.is_some() {
 6058            context.set.insert("renaming".into());
 6059        }
 6060        match self.context_menu.as_ref() {
 6061            Some(ContextMenu::Completions(_)) => {
 6062                context.set.insert("showing_completions".into());
 6063            }
 6064            Some(ContextMenu::CodeActions(_)) => {
 6065                context.set.insert("showing_code_actions".into());
 6066            }
 6067            None => {}
 6068        }
 6069
 6070        for layer in self.keymap_context_layers.values() {
 6071            context.extend(layer);
 6072        }
 6073
 6074        context
 6075    }
 6076}
 6077
 6078fn build_style(
 6079    settings: &Settings,
 6080    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6081    override_text_style: Option<&OverrideTextStyle>,
 6082    cx: &AppContext,
 6083) -> EditorStyle {
 6084    let font_cache = cx.font_cache();
 6085
 6086    let mut theme = settings.theme.editor.clone();
 6087    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6088        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6089        theme.text_color = field_editor_theme.text.color;
 6090        theme.selection = field_editor_theme.selection;
 6091        theme.background = field_editor_theme
 6092            .container
 6093            .background_color
 6094            .unwrap_or_default();
 6095        EditorStyle {
 6096            text: field_editor_theme.text,
 6097            placeholder_text: field_editor_theme.placeholder_text,
 6098            theme,
 6099        }
 6100    } else {
 6101        let font_family_id = settings.buffer_font_family;
 6102        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6103        let font_properties = Default::default();
 6104        let font_id = font_cache
 6105            .select_font(font_family_id, &font_properties)
 6106            .unwrap();
 6107        let font_size = settings.buffer_font_size;
 6108        EditorStyle {
 6109            text: TextStyle {
 6110                color: settings.theme.editor.text_color,
 6111                font_family_name,
 6112                font_family_id,
 6113                font_id,
 6114                font_size,
 6115                font_properties,
 6116                underline: Default::default(),
 6117            },
 6118            placeholder_text: None,
 6119            theme,
 6120        }
 6121    };
 6122
 6123    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6124        if let Some(highlighted) = style
 6125            .text
 6126            .clone()
 6127            .highlight(highlight_style, font_cache)
 6128            .log_err()
 6129        {
 6130            style.text = highlighted;
 6131        }
 6132    }
 6133
 6134    style
 6135}
 6136
 6137trait SelectionExt {
 6138    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6139    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6140    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6141    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6142        -> Range<u32>;
 6143}
 6144
 6145impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6146    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6147        let start = self.start.to_point(buffer);
 6148        let end = self.end.to_point(buffer);
 6149        if self.reversed {
 6150            end..start
 6151        } else {
 6152            start..end
 6153        }
 6154    }
 6155
 6156    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6157        let start = self.start.to_offset(buffer);
 6158        let end = self.end.to_offset(buffer);
 6159        if self.reversed {
 6160            end..start
 6161        } else {
 6162            start..end
 6163        }
 6164    }
 6165
 6166    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6167        let start = self
 6168            .start
 6169            .to_point(&map.buffer_snapshot)
 6170            .to_display_point(map);
 6171        let end = self
 6172            .end
 6173            .to_point(&map.buffer_snapshot)
 6174            .to_display_point(map);
 6175        if self.reversed {
 6176            end..start
 6177        } else {
 6178            start..end
 6179        }
 6180    }
 6181
 6182    fn spanned_rows(
 6183        &self,
 6184        include_end_if_at_line_start: bool,
 6185        map: &DisplaySnapshot,
 6186    ) -> Range<u32> {
 6187        let start = self.start.to_point(&map.buffer_snapshot);
 6188        let mut end = self.end.to_point(&map.buffer_snapshot);
 6189        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6190            end.row -= 1;
 6191        }
 6192
 6193        let buffer_start = map.prev_line_boundary(start).0;
 6194        let buffer_end = map.next_line_boundary(end).0;
 6195        buffer_start.row..buffer_end.row + 1
 6196    }
 6197}
 6198
 6199impl<T: InvalidationRegion> InvalidationStack<T> {
 6200    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6201    where
 6202        S: Clone + ToOffset,
 6203    {
 6204        while let Some(region) = self.last() {
 6205            let all_selections_inside_invalidation_ranges =
 6206                if selections.len() == region.ranges().len() {
 6207                    selections
 6208                        .iter()
 6209                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6210                        .all(|(selection, invalidation_range)| {
 6211                            let head = selection.head().to_offset(&buffer);
 6212                            invalidation_range.start <= head && invalidation_range.end >= head
 6213                        })
 6214                } else {
 6215                    false
 6216                };
 6217
 6218            if all_selections_inside_invalidation_ranges {
 6219                break;
 6220            } else {
 6221                self.pop();
 6222            }
 6223        }
 6224    }
 6225}
 6226
 6227impl<T> Default for InvalidationStack<T> {
 6228    fn default() -> Self {
 6229        Self(Default::default())
 6230    }
 6231}
 6232
 6233impl<T> Deref for InvalidationStack<T> {
 6234    type Target = Vec<T>;
 6235
 6236    fn deref(&self) -> &Self::Target {
 6237        &self.0
 6238    }
 6239}
 6240
 6241impl<T> DerefMut for InvalidationStack<T> {
 6242    fn deref_mut(&mut self) -> &mut Self::Target {
 6243        &mut self.0
 6244    }
 6245}
 6246
 6247impl InvalidationRegion for BracketPairState {
 6248    fn ranges(&self) -> &[Range<Anchor>] {
 6249        &self.ranges
 6250    }
 6251}
 6252
 6253impl InvalidationRegion for SnippetState {
 6254    fn ranges(&self) -> &[Range<Anchor>] {
 6255        &self.ranges[self.active_index]
 6256    }
 6257}
 6258
 6259impl Deref for EditorStyle {
 6260    type Target = theme::Editor;
 6261
 6262    fn deref(&self) -> &Self::Target {
 6263        &self.theme
 6264    }
 6265}
 6266
 6267pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6268    let mut highlighted_lines = Vec::new();
 6269    for line in diagnostic.message.lines() {
 6270        highlighted_lines.push(highlight_diagnostic_message(line));
 6271    }
 6272
 6273    Arc::new(move |cx: &BlockContext| {
 6274        let settings = cx.global::<Settings>();
 6275        let theme = &settings.theme.editor;
 6276        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6277        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6278        Flex::column()
 6279            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6280                Label::new(
 6281                    line.clone(),
 6282                    style.message.clone().with_font_size(font_size),
 6283                )
 6284                .with_highlights(highlights.clone())
 6285                .contained()
 6286                .with_margin_left(cx.anchor_x)
 6287                .boxed()
 6288            }))
 6289            .aligned()
 6290            .left()
 6291            .boxed()
 6292    })
 6293}
 6294
 6295pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6296    let mut message_without_backticks = String::new();
 6297    let mut prev_offset = 0;
 6298    let mut inside_block = false;
 6299    let mut highlights = Vec::new();
 6300    for (match_ix, (offset, _)) in message
 6301        .match_indices('`')
 6302        .chain([(message.len(), "")])
 6303        .enumerate()
 6304    {
 6305        message_without_backticks.push_str(&message[prev_offset..offset]);
 6306        if inside_block {
 6307            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6308        }
 6309
 6310        inside_block = !inside_block;
 6311        prev_offset = offset + 1;
 6312    }
 6313
 6314    (message_without_backticks, highlights)
 6315}
 6316
 6317pub fn diagnostic_style(
 6318    severity: DiagnosticSeverity,
 6319    valid: bool,
 6320    theme: &theme::Editor,
 6321) -> DiagnosticStyle {
 6322    match (severity, valid) {
 6323        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6324        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6325        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6326        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6327        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6328        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6329        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6330        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6331        _ => theme.invalid_hint_diagnostic.clone(),
 6332    }
 6333}
 6334
 6335pub fn combine_syntax_and_fuzzy_match_highlights(
 6336    text: &str,
 6337    default_style: HighlightStyle,
 6338    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6339    match_indices: &[usize],
 6340) -> Vec<(Range<usize>, HighlightStyle)> {
 6341    let mut result = Vec::new();
 6342    let mut match_indices = match_indices.iter().copied().peekable();
 6343
 6344    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6345    {
 6346        syntax_highlight.weight = None;
 6347
 6348        // Add highlights for any fuzzy match characters before the next
 6349        // syntax highlight range.
 6350        while let Some(&match_index) = match_indices.peek() {
 6351            if match_index >= range.start {
 6352                break;
 6353            }
 6354            match_indices.next();
 6355            let end_index = char_ix_after(match_index, text);
 6356            let mut match_style = default_style;
 6357            match_style.weight = Some(fonts::Weight::BOLD);
 6358            result.push((match_index..end_index, match_style));
 6359        }
 6360
 6361        if range.start == usize::MAX {
 6362            break;
 6363        }
 6364
 6365        // Add highlights for any fuzzy match characters within the
 6366        // syntax highlight range.
 6367        let mut offset = range.start;
 6368        while let Some(&match_index) = match_indices.peek() {
 6369            if match_index >= range.end {
 6370                break;
 6371            }
 6372
 6373            match_indices.next();
 6374            if match_index > offset {
 6375                result.push((offset..match_index, syntax_highlight));
 6376            }
 6377
 6378            let mut end_index = char_ix_after(match_index, text);
 6379            while let Some(&next_match_index) = match_indices.peek() {
 6380                if next_match_index == end_index && next_match_index < range.end {
 6381                    end_index = char_ix_after(next_match_index, text);
 6382                    match_indices.next();
 6383                } else {
 6384                    break;
 6385                }
 6386            }
 6387
 6388            let mut match_style = syntax_highlight;
 6389            match_style.weight = Some(fonts::Weight::BOLD);
 6390            result.push((match_index..end_index, match_style));
 6391            offset = end_index;
 6392        }
 6393
 6394        if offset < range.end {
 6395            result.push((offset..range.end, syntax_highlight));
 6396        }
 6397    }
 6398
 6399    fn char_ix_after(ix: usize, text: &str) -> usize {
 6400        ix + text[ix..].chars().next().unwrap().len_utf8()
 6401    }
 6402
 6403    result
 6404}
 6405
 6406pub fn styled_runs_for_code_label<'a>(
 6407    label: &'a CodeLabel,
 6408    syntax_theme: &'a theme::SyntaxTheme,
 6409) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6410    let fade_out = HighlightStyle {
 6411        fade_out: Some(0.35),
 6412        ..Default::default()
 6413    };
 6414
 6415    let mut prev_end = label.filter_range.end;
 6416    label
 6417        .runs
 6418        .iter()
 6419        .enumerate()
 6420        .flat_map(move |(ix, (range, highlight_id))| {
 6421            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6422                style
 6423            } else {
 6424                return Default::default();
 6425            };
 6426            let mut muted_style = style.clone();
 6427            muted_style.highlight(fade_out);
 6428
 6429            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6430            if range.start >= label.filter_range.end {
 6431                if range.start > prev_end {
 6432                    runs.push((prev_end..range.start, fade_out));
 6433                }
 6434                runs.push((range.clone(), muted_style));
 6435            } else if range.end <= label.filter_range.end {
 6436                runs.push((range.clone(), style));
 6437            } else {
 6438                runs.push((range.start..label.filter_range.end, style));
 6439                runs.push((label.filter_range.end..range.end, muted_style));
 6440            }
 6441            prev_end = cmp::max(prev_end, range.end);
 6442
 6443            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6444                runs.push((prev_end..label.text.len(), fade_out));
 6445            }
 6446
 6447            runs
 6448        })
 6449}
 6450
 6451#[cfg(test)]
 6452mod tests {
 6453    use crate::test::{assert_text_with_selections, select_ranges};
 6454
 6455    use super::*;
 6456    use gpui::{
 6457        geometry::rect::RectF,
 6458        platform::{WindowBounds, WindowOptions},
 6459    };
 6460    use indoc::indoc;
 6461    use language::{FakeLspAdapter, LanguageConfig};
 6462    use lsp::FakeLanguageServer;
 6463    use project::FakeFs;
 6464    use settings::LanguageOverride;
 6465    use smol::stream::StreamExt;
 6466    use std::{cell::RefCell, rc::Rc, time::Instant};
 6467    use text::Point;
 6468    use unindent::Unindent;
 6469    use util::test::{marked_text_by, marked_text_ranges, sample_text};
 6470    use workspace::{FollowableItem, ItemHandle};
 6471
 6472    #[gpui::test]
 6473    fn test_edit_events(cx: &mut MutableAppContext) {
 6474        cx.set_global(Settings::test(cx));
 6475        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6476
 6477        let events = Rc::new(RefCell::new(Vec::new()));
 6478        let (_, editor1) = cx.add_window(Default::default(), {
 6479            let events = events.clone();
 6480            |cx| {
 6481                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6482                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6483                        events.borrow_mut().push(("editor1", *event));
 6484                    }
 6485                })
 6486                .detach();
 6487                Editor::for_buffer(buffer.clone(), None, cx)
 6488            }
 6489        });
 6490        let (_, editor2) = cx.add_window(Default::default(), {
 6491            let events = events.clone();
 6492            |cx| {
 6493                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6494                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6495                        events.borrow_mut().push(("editor2", *event));
 6496                    }
 6497                })
 6498                .detach();
 6499                Editor::for_buffer(buffer.clone(), None, cx)
 6500            }
 6501        });
 6502        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6503
 6504        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6505        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6506        assert_eq!(
 6507            mem::take(&mut *events.borrow_mut()),
 6508            [
 6509                ("editor1", Event::Edited),
 6510                ("editor1", Event::BufferEdited),
 6511                ("editor2", Event::BufferEdited),
 6512                ("editor1", Event::Dirtied),
 6513                ("editor2", Event::Dirtied)
 6514            ]
 6515        );
 6516
 6517        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6518        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6519        assert_eq!(
 6520            mem::take(&mut *events.borrow_mut()),
 6521            [
 6522                ("editor2", Event::Edited),
 6523                ("editor1", Event::BufferEdited),
 6524                ("editor2", Event::BufferEdited),
 6525            ]
 6526        );
 6527
 6528        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6529        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6530        assert_eq!(
 6531            mem::take(&mut *events.borrow_mut()),
 6532            [
 6533                ("editor1", Event::Edited),
 6534                ("editor1", Event::BufferEdited),
 6535                ("editor2", Event::BufferEdited),
 6536            ]
 6537        );
 6538
 6539        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6540        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6541        assert_eq!(
 6542            mem::take(&mut *events.borrow_mut()),
 6543            [
 6544                ("editor1", Event::Edited),
 6545                ("editor1", Event::BufferEdited),
 6546                ("editor2", Event::BufferEdited),
 6547            ]
 6548        );
 6549
 6550        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6551        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6552        assert_eq!(
 6553            mem::take(&mut *events.borrow_mut()),
 6554            [
 6555                ("editor2", Event::Edited),
 6556                ("editor1", Event::BufferEdited),
 6557                ("editor2", Event::BufferEdited),
 6558            ]
 6559        );
 6560
 6561        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6562        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6563        assert_eq!(
 6564            mem::take(&mut *events.borrow_mut()),
 6565            [
 6566                ("editor2", Event::Edited),
 6567                ("editor1", Event::BufferEdited),
 6568                ("editor2", Event::BufferEdited),
 6569            ]
 6570        );
 6571
 6572        // No event is emitted when the mutation is a no-op.
 6573        editor2.update(cx, |editor, cx| {
 6574            editor.select_ranges([0..0], None, cx);
 6575            editor.backspace(&Backspace, cx);
 6576        });
 6577        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6578    }
 6579
 6580    #[gpui::test]
 6581    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6582        cx.set_global(Settings::test(cx));
 6583        let mut now = Instant::now();
 6584        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6585        let group_interval = buffer.read(cx).transaction_group_interval();
 6586        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6587        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6588
 6589        editor.update(cx, |editor, cx| {
 6590            editor.start_transaction_at(now, cx);
 6591            editor.select_ranges([2..4], None, cx);
 6592            editor.insert("cd", cx);
 6593            editor.end_transaction_at(now, cx);
 6594            assert_eq!(editor.text(cx), "12cd56");
 6595            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 6596
 6597            editor.start_transaction_at(now, cx);
 6598            editor.select_ranges([4..5], None, cx);
 6599            editor.insert("e", cx);
 6600            editor.end_transaction_at(now, cx);
 6601            assert_eq!(editor.text(cx), "12cde6");
 6602            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6603
 6604            now += group_interval + Duration::from_millis(1);
 6605            editor.select_ranges([2..2], None, cx);
 6606
 6607            // Simulate an edit in another editor
 6608            buffer.update(cx, |buffer, cx| {
 6609                buffer.start_transaction_at(now, cx);
 6610                buffer.edit([0..1], "a", cx);
 6611                buffer.edit([1..1], "b", cx);
 6612                buffer.end_transaction_at(now, cx);
 6613            });
 6614
 6615            assert_eq!(editor.text(cx), "ab2cde6");
 6616            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
 6617
 6618            // Last transaction happened past the group interval in a different editor.
 6619            // Undo it individually and don't restore selections.
 6620            editor.undo(&Undo, cx);
 6621            assert_eq!(editor.text(cx), "12cde6");
 6622            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
 6623
 6624            // First two transactions happened within the group interval in this editor.
 6625            // Undo them together and restore selections.
 6626            editor.undo(&Undo, cx);
 6627            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6628            assert_eq!(editor.text(cx), "123456");
 6629            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
 6630
 6631            // Redo the first two transactions together.
 6632            editor.redo(&Redo, cx);
 6633            assert_eq!(editor.text(cx), "12cde6");
 6634            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6635
 6636            // Redo the last transaction on its own.
 6637            editor.redo(&Redo, cx);
 6638            assert_eq!(editor.text(cx), "ab2cde6");
 6639            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
 6640
 6641            // Test empty transactions.
 6642            editor.start_transaction_at(now, cx);
 6643            editor.end_transaction_at(now, cx);
 6644            editor.undo(&Undo, cx);
 6645            assert_eq!(editor.text(cx), "12cde6");
 6646        });
 6647    }
 6648
 6649    #[gpui::test]
 6650    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6651        cx.set_global(Settings::test(cx));
 6652
 6653        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6654        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6655        editor.update(cx, |view, cx| {
 6656            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6657        });
 6658        assert_eq!(
 6659            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6660            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6661        );
 6662
 6663        editor.update(cx, |view, cx| {
 6664            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6665        });
 6666
 6667        assert_eq!(
 6668            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6669            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6670        );
 6671
 6672        editor.update(cx, |view, cx| {
 6673            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6674        });
 6675
 6676        assert_eq!(
 6677            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6678            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6679        );
 6680
 6681        editor.update(cx, |view, cx| {
 6682            view.end_selection(cx);
 6683            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6684        });
 6685
 6686        assert_eq!(
 6687            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6688            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6689        );
 6690
 6691        editor.update(cx, |view, cx| {
 6692            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6693            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6694        });
 6695
 6696        assert_eq!(
 6697            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6698            [
 6699                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6700                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6701            ]
 6702        );
 6703
 6704        editor.update(cx, |view, cx| {
 6705            view.end_selection(cx);
 6706        });
 6707
 6708        assert_eq!(
 6709            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6710            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6711        );
 6712    }
 6713
 6714    #[gpui::test]
 6715    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6716        cx.set_global(Settings::test(cx));
 6717        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6718        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6719
 6720        view.update(cx, |view, cx| {
 6721            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6722            assert_eq!(
 6723                view.selected_display_ranges(cx),
 6724                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6725            );
 6726        });
 6727
 6728        view.update(cx, |view, cx| {
 6729            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6730            assert_eq!(
 6731                view.selected_display_ranges(cx),
 6732                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6733            );
 6734        });
 6735
 6736        view.update(cx, |view, cx| {
 6737            view.cancel(&Cancel, cx);
 6738            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6739            assert_eq!(
 6740                view.selected_display_ranges(cx),
 6741                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6742            );
 6743        });
 6744    }
 6745
 6746    #[gpui::test]
 6747    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6748        cx.set_global(Settings::test(cx));
 6749        use workspace::Item;
 6750        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6751        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6752
 6753        cx.add_window(Default::default(), |cx| {
 6754            let mut editor = build_editor(buffer.clone(), cx);
 6755            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6756
 6757            // Move the cursor a small distance.
 6758            // Nothing is added to the navigation history.
 6759            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
 6760            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
 6761            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6762
 6763            // Move the cursor a large distance.
 6764            // The history can jump back to the previous position.
 6765            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
 6766            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6767            editor.navigate(nav_entry.data.unwrap(), cx);
 6768            assert_eq!(nav_entry.item.id(), cx.view_id());
 6769            assert_eq!(
 6770                editor.selected_display_ranges(cx),
 6771                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6772            );
 6773            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6774
 6775            // Move the cursor a small distance via the mouse.
 6776            // Nothing is added to the navigation history.
 6777            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6778            editor.end_selection(cx);
 6779            assert_eq!(
 6780                editor.selected_display_ranges(cx),
 6781                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6782            );
 6783            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6784
 6785            // Move the cursor a large distance via the mouse.
 6786            // The history can jump back to the previous position.
 6787            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6788            editor.end_selection(cx);
 6789            assert_eq!(
 6790                editor.selected_display_ranges(cx),
 6791                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6792            );
 6793            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6794            editor.navigate(nav_entry.data.unwrap(), cx);
 6795            assert_eq!(nav_entry.item.id(), cx.view_id());
 6796            assert_eq!(
 6797                editor.selected_display_ranges(cx),
 6798                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6799            );
 6800            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6801
 6802            // Set scroll position to check later
 6803            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6804            let original_scroll_position = editor.scroll_position;
 6805            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6806
 6807            // Jump to the end of the document and adjust scroll
 6808            editor.move_to_end(&MoveToEnd, cx);
 6809            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6810            assert_ne!(editor.scroll_position, original_scroll_position);
 6811            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6812
 6813            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6814            editor.navigate(nav_entry.data.unwrap(), cx);
 6815            assert_eq!(editor.scroll_position, original_scroll_position);
 6816            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6817
 6818            editor
 6819        });
 6820    }
 6821
 6822    #[gpui::test]
 6823    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6824        cx.set_global(Settings::test(cx));
 6825        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6826        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6827
 6828        view.update(cx, |view, cx| {
 6829            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6830            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6831            view.end_selection(cx);
 6832
 6833            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6834            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6835            view.end_selection(cx);
 6836            assert_eq!(
 6837                view.selected_display_ranges(cx),
 6838                [
 6839                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6840                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6841                ]
 6842            );
 6843        });
 6844
 6845        view.update(cx, |view, cx| {
 6846            view.cancel(&Cancel, cx);
 6847            assert_eq!(
 6848                view.selected_display_ranges(cx),
 6849                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6850            );
 6851        });
 6852
 6853        view.update(cx, |view, cx| {
 6854            view.cancel(&Cancel, cx);
 6855            assert_eq!(
 6856                view.selected_display_ranges(cx),
 6857                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6858            );
 6859        });
 6860    }
 6861
 6862    #[gpui::test]
 6863    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6864        cx.set_global(Settings::test(cx));
 6865        let buffer = MultiBuffer::build_simple(
 6866            &"
 6867                impl Foo {
 6868                    // Hello!
 6869
 6870                    fn a() {
 6871                        1
 6872                    }
 6873
 6874                    fn b() {
 6875                        2
 6876                    }
 6877
 6878                    fn c() {
 6879                        3
 6880                    }
 6881                }
 6882            "
 6883            .unindent(),
 6884            cx,
 6885        );
 6886        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6887
 6888        view.update(cx, |view, cx| {
 6889            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 6890            view.fold(&Fold, cx);
 6891            assert_eq!(
 6892                view.display_text(cx),
 6893                "
 6894                    impl Foo {
 6895                        // Hello!
 6896
 6897                        fn a() {
 6898                            1
 6899                        }
 6900
 6901                        fn b() {…
 6902                        }
 6903
 6904                        fn c() {…
 6905                        }
 6906                    }
 6907                "
 6908                .unindent(),
 6909            );
 6910
 6911            view.fold(&Fold, cx);
 6912            assert_eq!(
 6913                view.display_text(cx),
 6914                "
 6915                    impl Foo {…
 6916                    }
 6917                "
 6918                .unindent(),
 6919            );
 6920
 6921            view.unfold_lines(&UnfoldLines, cx);
 6922            assert_eq!(
 6923                view.display_text(cx),
 6924                "
 6925                    impl Foo {
 6926                        // Hello!
 6927
 6928                        fn a() {
 6929                            1
 6930                        }
 6931
 6932                        fn b() {…
 6933                        }
 6934
 6935                        fn c() {…
 6936                        }
 6937                    }
 6938                "
 6939                .unindent(),
 6940            );
 6941
 6942            view.unfold_lines(&UnfoldLines, cx);
 6943            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6944        });
 6945    }
 6946
 6947    #[gpui::test]
 6948    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6949        cx.set_global(Settings::test(cx));
 6950        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6951        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6952
 6953        buffer.update(cx, |buffer, cx| {
 6954            buffer.edit(
 6955                vec![
 6956                    Point::new(1, 0)..Point::new(1, 0),
 6957                    Point::new(1, 1)..Point::new(1, 1),
 6958                ],
 6959                "\t",
 6960                cx,
 6961            );
 6962        });
 6963
 6964        view.update(cx, |view, cx| {
 6965            assert_eq!(
 6966                view.selected_display_ranges(cx),
 6967                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6968            );
 6969
 6970            view.move_down(&MoveDown, cx);
 6971            assert_eq!(
 6972                view.selected_display_ranges(cx),
 6973                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6974            );
 6975
 6976            view.move_right(&MoveRight, cx);
 6977            assert_eq!(
 6978                view.selected_display_ranges(cx),
 6979                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6980            );
 6981
 6982            view.move_left(&MoveLeft, cx);
 6983            assert_eq!(
 6984                view.selected_display_ranges(cx),
 6985                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6986            );
 6987
 6988            view.move_up(&MoveUp, cx);
 6989            assert_eq!(
 6990                view.selected_display_ranges(cx),
 6991                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6992            );
 6993
 6994            view.move_to_end(&MoveToEnd, cx);
 6995            assert_eq!(
 6996                view.selected_display_ranges(cx),
 6997                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 6998            );
 6999
 7000            view.move_to_beginning(&MoveToBeginning, cx);
 7001            assert_eq!(
 7002                view.selected_display_ranges(cx),
 7003                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7004            );
 7005
 7006            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7007            view.select_to_beginning(&SelectToBeginning, cx);
 7008            assert_eq!(
 7009                view.selected_display_ranges(cx),
 7010                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7011            );
 7012
 7013            view.select_to_end(&SelectToEnd, cx);
 7014            assert_eq!(
 7015                view.selected_display_ranges(cx),
 7016                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7017            );
 7018        });
 7019    }
 7020
 7021    #[gpui::test]
 7022    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7023        cx.set_global(Settings::test(cx));
 7024        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7025        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7026
 7027        assert_eq!('ⓐ'.len_utf8(), 3);
 7028        assert_eq!('α'.len_utf8(), 2);
 7029
 7030        view.update(cx, |view, cx| {
 7031            view.fold_ranges(
 7032                vec![
 7033                    Point::new(0, 6)..Point::new(0, 12),
 7034                    Point::new(1, 2)..Point::new(1, 4),
 7035                    Point::new(2, 4)..Point::new(2, 8),
 7036                ],
 7037                cx,
 7038            );
 7039            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7040
 7041            view.move_right(&MoveRight, cx);
 7042            assert_eq!(
 7043                view.selected_display_ranges(cx),
 7044                &[empty_range(0, "".len())]
 7045            );
 7046            view.move_right(&MoveRight, cx);
 7047            assert_eq!(
 7048                view.selected_display_ranges(cx),
 7049                &[empty_range(0, "ⓐⓑ".len())]
 7050            );
 7051            view.move_right(&MoveRight, cx);
 7052            assert_eq!(
 7053                view.selected_display_ranges(cx),
 7054                &[empty_range(0, "ⓐⓑ…".len())]
 7055            );
 7056
 7057            view.move_down(&MoveDown, cx);
 7058            assert_eq!(
 7059                view.selected_display_ranges(cx),
 7060                &[empty_range(1, "ab…".len())]
 7061            );
 7062            view.move_left(&MoveLeft, cx);
 7063            assert_eq!(
 7064                view.selected_display_ranges(cx),
 7065                &[empty_range(1, "ab".len())]
 7066            );
 7067            view.move_left(&MoveLeft, cx);
 7068            assert_eq!(
 7069                view.selected_display_ranges(cx),
 7070                &[empty_range(1, "a".len())]
 7071            );
 7072
 7073            view.move_down(&MoveDown, cx);
 7074            assert_eq!(
 7075                view.selected_display_ranges(cx),
 7076                &[empty_range(2, "α".len())]
 7077            );
 7078            view.move_right(&MoveRight, cx);
 7079            assert_eq!(
 7080                view.selected_display_ranges(cx),
 7081                &[empty_range(2, "αβ".len())]
 7082            );
 7083            view.move_right(&MoveRight, cx);
 7084            assert_eq!(
 7085                view.selected_display_ranges(cx),
 7086                &[empty_range(2, "αβ…".len())]
 7087            );
 7088            view.move_right(&MoveRight, cx);
 7089            assert_eq!(
 7090                view.selected_display_ranges(cx),
 7091                &[empty_range(2, "αβ…ε".len())]
 7092            );
 7093
 7094            view.move_up(&MoveUp, cx);
 7095            assert_eq!(
 7096                view.selected_display_ranges(cx),
 7097                &[empty_range(1, "ab…e".len())]
 7098            );
 7099            view.move_up(&MoveUp, cx);
 7100            assert_eq!(
 7101                view.selected_display_ranges(cx),
 7102                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7103            );
 7104            view.move_left(&MoveLeft, cx);
 7105            assert_eq!(
 7106                view.selected_display_ranges(cx),
 7107                &[empty_range(0, "ⓐⓑ…".len())]
 7108            );
 7109            view.move_left(&MoveLeft, cx);
 7110            assert_eq!(
 7111                view.selected_display_ranges(cx),
 7112                &[empty_range(0, "ⓐⓑ".len())]
 7113            );
 7114            view.move_left(&MoveLeft, cx);
 7115            assert_eq!(
 7116                view.selected_display_ranges(cx),
 7117                &[empty_range(0, "".len())]
 7118            );
 7119        });
 7120    }
 7121
 7122    #[gpui::test]
 7123    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7124        cx.set_global(Settings::test(cx));
 7125        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7126        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7127        view.update(cx, |view, cx| {
 7128            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7129            view.move_down(&MoveDown, cx);
 7130            assert_eq!(
 7131                view.selected_display_ranges(cx),
 7132                &[empty_range(1, "abcd".len())]
 7133            );
 7134
 7135            view.move_down(&MoveDown, cx);
 7136            assert_eq!(
 7137                view.selected_display_ranges(cx),
 7138                &[empty_range(2, "αβγ".len())]
 7139            );
 7140
 7141            view.move_down(&MoveDown, cx);
 7142            assert_eq!(
 7143                view.selected_display_ranges(cx),
 7144                &[empty_range(3, "abcd".len())]
 7145            );
 7146
 7147            view.move_down(&MoveDown, cx);
 7148            assert_eq!(
 7149                view.selected_display_ranges(cx),
 7150                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7151            );
 7152
 7153            view.move_up(&MoveUp, cx);
 7154            assert_eq!(
 7155                view.selected_display_ranges(cx),
 7156                &[empty_range(3, "abcd".len())]
 7157            );
 7158
 7159            view.move_up(&MoveUp, cx);
 7160            assert_eq!(
 7161                view.selected_display_ranges(cx),
 7162                &[empty_range(2, "αβγ".len())]
 7163            );
 7164        });
 7165    }
 7166
 7167    #[gpui::test]
 7168    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7169        cx.set_global(Settings::test(cx));
 7170        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7171        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7172        view.update(cx, |view, cx| {
 7173            view.select_display_ranges(
 7174                &[
 7175                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7176                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7177                ],
 7178                cx,
 7179            );
 7180        });
 7181
 7182        view.update(cx, |view, cx| {
 7183            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7184            assert_eq!(
 7185                view.selected_display_ranges(cx),
 7186                &[
 7187                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7188                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7189                ]
 7190            );
 7191        });
 7192
 7193        view.update(cx, |view, cx| {
 7194            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7195            assert_eq!(
 7196                view.selected_display_ranges(cx),
 7197                &[
 7198                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7199                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7200                ]
 7201            );
 7202        });
 7203
 7204        view.update(cx, |view, cx| {
 7205            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7206            assert_eq!(
 7207                view.selected_display_ranges(cx),
 7208                &[
 7209                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7210                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7211                ]
 7212            );
 7213        });
 7214
 7215        view.update(cx, |view, cx| {
 7216            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7217            assert_eq!(
 7218                view.selected_display_ranges(cx),
 7219                &[
 7220                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7221                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7222                ]
 7223            );
 7224        });
 7225
 7226        // Moving to the end of line again is a no-op.
 7227        view.update(cx, |view, cx| {
 7228            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7229            assert_eq!(
 7230                view.selected_display_ranges(cx),
 7231                &[
 7232                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7233                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7234                ]
 7235            );
 7236        });
 7237
 7238        view.update(cx, |view, cx| {
 7239            view.move_left(&MoveLeft, cx);
 7240            view.select_to_beginning_of_line(
 7241                &SelectToBeginningOfLine {
 7242                    stop_at_soft_wraps: true,
 7243                },
 7244                cx,
 7245            );
 7246            assert_eq!(
 7247                view.selected_display_ranges(cx),
 7248                &[
 7249                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7250                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7251                ]
 7252            );
 7253        });
 7254
 7255        view.update(cx, |view, cx| {
 7256            view.select_to_beginning_of_line(
 7257                &SelectToBeginningOfLine {
 7258                    stop_at_soft_wraps: true,
 7259                },
 7260                cx,
 7261            );
 7262            assert_eq!(
 7263                view.selected_display_ranges(cx),
 7264                &[
 7265                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7266                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7267                ]
 7268            );
 7269        });
 7270
 7271        view.update(cx, |view, cx| {
 7272            view.select_to_beginning_of_line(
 7273                &SelectToBeginningOfLine {
 7274                    stop_at_soft_wraps: true,
 7275                },
 7276                cx,
 7277            );
 7278            assert_eq!(
 7279                view.selected_display_ranges(cx),
 7280                &[
 7281                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7282                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7283                ]
 7284            );
 7285        });
 7286
 7287        view.update(cx, |view, cx| {
 7288            view.select_to_end_of_line(
 7289                &SelectToEndOfLine {
 7290                    stop_at_soft_wraps: true,
 7291                },
 7292                cx,
 7293            );
 7294            assert_eq!(
 7295                view.selected_display_ranges(cx),
 7296                &[
 7297                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7298                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7299                ]
 7300            );
 7301        });
 7302
 7303        view.update(cx, |view, cx| {
 7304            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7305            assert_eq!(view.display_text(cx), "ab\n  de");
 7306            assert_eq!(
 7307                view.selected_display_ranges(cx),
 7308                &[
 7309                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7310                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7311                ]
 7312            );
 7313        });
 7314
 7315        view.update(cx, |view, cx| {
 7316            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7317            assert_eq!(view.display_text(cx), "\n");
 7318            assert_eq!(
 7319                view.selected_display_ranges(cx),
 7320                &[
 7321                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7322                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7323                ]
 7324            );
 7325        });
 7326    }
 7327
 7328    #[gpui::test]
 7329    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7330        cx.set_global(Settings::test(cx));
 7331        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7332        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7333        view.update(cx, |view, cx| {
 7334            view.select_display_ranges(
 7335                &[
 7336                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7337                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7338                ],
 7339                cx,
 7340            );
 7341
 7342            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7343            assert_selection_ranges(
 7344                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7345                vec![('<', '>'), ('[', ']')],
 7346                view,
 7347                cx,
 7348            );
 7349
 7350            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7351            assert_selection_ranges(
 7352                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7353                vec![('<', '>'), ('[', ']')],
 7354                view,
 7355                cx,
 7356            );
 7357
 7358            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7359            assert_selection_ranges(
 7360                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7361                vec![('<', '>'), ('[', ']')],
 7362                view,
 7363                cx,
 7364            );
 7365
 7366            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7367            assert_selection_ranges(
 7368                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7369                vec![('<', '>'), ('[', ']')],
 7370                view,
 7371                cx,
 7372            );
 7373
 7374            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7375            assert_selection_ranges(
 7376                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7377                vec![('<', '>'), ('[', ']')],
 7378                view,
 7379                cx,
 7380            );
 7381
 7382            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7383            assert_selection_ranges(
 7384                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7385                vec![('<', '>'), ('[', ']')],
 7386                view,
 7387                cx,
 7388            );
 7389
 7390            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7391            assert_selection_ranges(
 7392                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7393                vec![('<', '>'), ('[', ']')],
 7394                view,
 7395                cx,
 7396            );
 7397
 7398            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7399            assert_selection_ranges(
 7400                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7401                vec![('<', '>'), ('[', ']')],
 7402                view,
 7403                cx,
 7404            );
 7405
 7406            view.move_right(&MoveRight, cx);
 7407            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7408            assert_selection_ranges(
 7409                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7410                vec![('<', '>'), ('[', ']')],
 7411                view,
 7412                cx,
 7413            );
 7414
 7415            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7416            assert_selection_ranges(
 7417                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7418                vec![('<', '>'), ('[', ']')],
 7419                view,
 7420                cx,
 7421            );
 7422
 7423            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7424            assert_selection_ranges(
 7425                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7426                vec![('<', '>'), ('[', ']')],
 7427                view,
 7428                cx,
 7429            );
 7430        });
 7431    }
 7432
 7433    #[gpui::test]
 7434    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7435        cx.set_global(Settings::test(cx));
 7436        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7437        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7438
 7439        view.update(cx, |view, cx| {
 7440            view.set_wrap_width(Some(140.), cx);
 7441            assert_eq!(
 7442                view.display_text(cx),
 7443                "use one::{\n    two::three::\n    four::five\n};"
 7444            );
 7445
 7446            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7447
 7448            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7449            assert_eq!(
 7450                view.selected_display_ranges(cx),
 7451                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7452            );
 7453
 7454            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7455            assert_eq!(
 7456                view.selected_display_ranges(cx),
 7457                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7458            );
 7459
 7460            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7461            assert_eq!(
 7462                view.selected_display_ranges(cx),
 7463                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7464            );
 7465
 7466            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7467            assert_eq!(
 7468                view.selected_display_ranges(cx),
 7469                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7470            );
 7471
 7472            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7473            assert_eq!(
 7474                view.selected_display_ranges(cx),
 7475                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7476            );
 7477
 7478            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7479            assert_eq!(
 7480                view.selected_display_ranges(cx),
 7481                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7482            );
 7483        });
 7484    }
 7485
 7486    #[gpui::test]
 7487    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7488        cx.set_global(Settings::test(cx));
 7489        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7490        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7491
 7492        view.update(cx, |view, cx| {
 7493            view.select_display_ranges(
 7494                &[
 7495                    // an empty selection - the preceding word fragment is deleted
 7496                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7497                    // characters selected - they are deleted
 7498                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7499                ],
 7500                cx,
 7501            );
 7502            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7503        });
 7504
 7505        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7506
 7507        view.update(cx, |view, cx| {
 7508            view.select_display_ranges(
 7509                &[
 7510                    // an empty selection - the following word fragment is deleted
 7511                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7512                    // characters selected - they are deleted
 7513                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7514                ],
 7515                cx,
 7516            );
 7517            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7518        });
 7519
 7520        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7521    }
 7522
 7523    #[gpui::test]
 7524    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7525        cx.set_global(Settings::test(cx));
 7526        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7527        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7528
 7529        view.update(cx, |view, cx| {
 7530            view.select_display_ranges(
 7531                &[
 7532                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7533                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7534                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7535                ],
 7536                cx,
 7537            );
 7538
 7539            view.newline(&Newline, cx);
 7540            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7541        });
 7542    }
 7543
 7544    #[gpui::test]
 7545    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7546        cx.set_global(Settings::test(cx));
 7547        let buffer = MultiBuffer::build_simple(
 7548            "
 7549                a
 7550                b(
 7551                    X
 7552                )
 7553                c(
 7554                    X
 7555                )
 7556            "
 7557            .unindent()
 7558            .as_str(),
 7559            cx,
 7560        );
 7561
 7562        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7563            let mut editor = build_editor(buffer.clone(), cx);
 7564            editor.select_ranges(
 7565                [
 7566                    Point::new(2, 4)..Point::new(2, 5),
 7567                    Point::new(5, 4)..Point::new(5, 5),
 7568                ],
 7569                None,
 7570                cx,
 7571            );
 7572            editor
 7573        });
 7574
 7575        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7576        buffer.update(cx, |buffer, cx| {
 7577            buffer.edit(
 7578                [
 7579                    Point::new(1, 2)..Point::new(3, 0),
 7580                    Point::new(4, 2)..Point::new(6, 0),
 7581                ],
 7582                "",
 7583                cx,
 7584            );
 7585            assert_eq!(
 7586                buffer.read(cx).text(),
 7587                "
 7588                    a
 7589                    b()
 7590                    c()
 7591                "
 7592                .unindent()
 7593            );
 7594        });
 7595
 7596        editor.update(cx, |editor, cx| {
 7597            assert_eq!(
 7598                editor.selected_ranges(cx),
 7599                &[
 7600                    Point::new(1, 2)..Point::new(1, 2),
 7601                    Point::new(2, 2)..Point::new(2, 2),
 7602                ],
 7603            );
 7604
 7605            editor.newline(&Newline, cx);
 7606            assert_eq!(
 7607                editor.text(cx),
 7608                "
 7609                    a
 7610                    b(
 7611                    )
 7612                    c(
 7613                    )
 7614                "
 7615                .unindent()
 7616            );
 7617
 7618            // The selections are moved after the inserted newlines
 7619            assert_eq!(
 7620                editor.selected_ranges(cx),
 7621                &[
 7622                    Point::new(2, 0)..Point::new(2, 0),
 7623                    Point::new(4, 0)..Point::new(4, 0),
 7624                ],
 7625            );
 7626        });
 7627    }
 7628
 7629    #[gpui::test]
 7630    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7631        cx.set_global(Settings::test(cx));
 7632        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7633        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7634            let mut editor = build_editor(buffer.clone(), cx);
 7635            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7636            editor
 7637        });
 7638
 7639        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7640        buffer.update(cx, |buffer, cx| {
 7641            buffer.edit([2..5, 10..13, 18..21], "", cx);
 7642            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7643        });
 7644
 7645        editor.update(cx, |editor, cx| {
 7646            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7647
 7648            editor.insert("Z", cx);
 7649            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7650
 7651            // The selections are moved after the inserted characters
 7652            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7653        });
 7654    }
 7655
 7656    #[gpui::test]
 7657    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7658        cx.set_global(Settings::test(cx));
 7659        let buffer = MultiBuffer::build_simple(
 7660            indoc! {"
 7661                  one two
 7662                three
 7663                 four"},
 7664            cx,
 7665        );
 7666        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7667
 7668        view.update(cx, |view, cx| {
 7669            // two selections on the same line
 7670            select_ranges(
 7671                view,
 7672                indoc! {"
 7673                      [one] [two]
 7674                    three
 7675                     four"},
 7676                cx,
 7677            );
 7678
 7679            // indent from mid-tabstop to full tabstop
 7680            view.tab(&Tab, cx);
 7681            assert_text_with_selections(
 7682                view,
 7683                indoc! {"
 7684                        [one] [two]
 7685                    three
 7686                     four"},
 7687                cx,
 7688            );
 7689
 7690            // outdent from 1 tabstop to 0 tabstops
 7691            view.tab_prev(&TabPrev, cx);
 7692            assert_text_with_selections(
 7693                view,
 7694                indoc! {"
 7695                    [one] [two]
 7696                    three
 7697                     four"},
 7698                cx,
 7699            );
 7700
 7701            // select across line ending
 7702            select_ranges(
 7703                view,
 7704                indoc! {"
 7705                    one two
 7706                    t[hree
 7707                    ] four"},
 7708                cx,
 7709            );
 7710
 7711            // indent and outdent affect only the preceding line
 7712            view.tab(&Tab, cx);
 7713            assert_text_with_selections(
 7714                view,
 7715                indoc! {"
 7716                    one two
 7717                        t[hree
 7718                    ] four"},
 7719                cx,
 7720            );
 7721            view.tab_prev(&TabPrev, cx);
 7722            assert_text_with_selections(
 7723                view,
 7724                indoc! {"
 7725                    one two
 7726                    t[hree
 7727                    ] four"},
 7728                cx,
 7729            );
 7730
 7731            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7732            select_ranges(
 7733                view,
 7734                indoc! {"
 7735                    one two
 7736                    []three
 7737                     four"},
 7738                cx,
 7739            );
 7740            view.tab(&Tab, cx);
 7741            assert_text_with_selections(
 7742                view,
 7743                indoc! {"
 7744                    one two
 7745                        []three
 7746                     four"},
 7747                cx,
 7748            );
 7749
 7750            select_ranges(
 7751                view,
 7752                indoc! {"
 7753                    one two
 7754                    []    three
 7755                     four"},
 7756                cx,
 7757            );
 7758            view.tab_prev(&TabPrev, cx);
 7759            assert_text_with_selections(
 7760                view,
 7761                indoc! {"
 7762                    one two
 7763                    []three
 7764                     four"},
 7765                cx,
 7766            );
 7767        });
 7768    }
 7769
 7770    #[gpui::test]
 7771    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7772        cx.set_global(
 7773            Settings::test(cx)
 7774                .with_overrides(
 7775                    "TOML",
 7776                    LanguageOverride {
 7777                        tab_size: Some(2),
 7778                        ..Default::default()
 7779                    },
 7780                )
 7781                .with_overrides(
 7782                    "Rust",
 7783                    LanguageOverride {
 7784                        tab_size: Some(4),
 7785                        ..Default::default()
 7786                    },
 7787                ),
 7788        );
 7789        let toml_language = Arc::new(Language::new(
 7790            LanguageConfig {
 7791                name: "TOML".into(),
 7792                ..Default::default()
 7793            },
 7794            None,
 7795        ));
 7796        let rust_language = Arc::new(Language::new(
 7797            LanguageConfig {
 7798                name: "Rust".into(),
 7799                ..Default::default()
 7800            },
 7801            None,
 7802        ));
 7803
 7804        let toml_buffer = cx
 7805            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7806        let rust_buffer = cx.add_model(|cx| {
 7807            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7808        });
 7809        let multibuffer = cx.add_model(|cx| {
 7810            let mut multibuffer = MultiBuffer::new(0);
 7811            multibuffer.push_excerpts(
 7812                toml_buffer.clone(),
 7813                [Point::new(0, 0)..Point::new(2, 0)],
 7814                cx,
 7815            );
 7816            multibuffer.push_excerpts(
 7817                rust_buffer.clone(),
 7818                [Point::new(0, 0)..Point::new(1, 0)],
 7819                cx,
 7820            );
 7821            multibuffer
 7822        });
 7823
 7824        cx.add_window(Default::default(), |cx| {
 7825            let mut editor = build_editor(multibuffer, cx);
 7826
 7827            assert_eq!(
 7828                editor.text(cx),
 7829                indoc! {"
 7830                    a = 1
 7831                    b = 2
 7832
 7833                    const c: usize = 3;
 7834                "}
 7835            );
 7836
 7837            select_ranges(
 7838                &mut editor,
 7839                indoc! {"
 7840                    [a] = 1
 7841                    b = 2
 7842
 7843                    [const c:] usize = 3;
 7844                "},
 7845                cx,
 7846            );
 7847
 7848            editor.tab(&Tab, cx);
 7849            assert_text_with_selections(
 7850                &mut editor,
 7851                indoc! {"
 7852                      [a] = 1
 7853                    b = 2
 7854
 7855                        [const c:] usize = 3;
 7856                "},
 7857                cx,
 7858            );
 7859            editor.tab_prev(&TabPrev, cx);
 7860            assert_text_with_selections(
 7861                &mut editor,
 7862                indoc! {"
 7863                    [a] = 1
 7864                    b = 2
 7865
 7866                    [const c:] usize = 3;
 7867                "},
 7868                cx,
 7869            );
 7870
 7871            editor
 7872        });
 7873    }
 7874
 7875    #[gpui::test]
 7876    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 7877        cx.set_global(Settings::test(cx));
 7878        let (_, view) = cx.add_window(Default::default(), |cx| {
 7879            build_editor(MultiBuffer::build_simple("", cx), cx)
 7880        });
 7881
 7882        view.update(cx, |view, cx| {
 7883            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7884            view.select_display_ranges(
 7885                &[
 7886                    // an empty selection - the preceding character is deleted
 7887                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7888                    // one character selected - it is deleted
 7889                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7890                    // a line suffix selected - it is deleted
 7891                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7892                ],
 7893                cx,
 7894            );
 7895            view.backspace(&Backspace, cx);
 7896            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 7897
 7898            view.set_text("    one\n        two\n        three\n   four", cx);
 7899            view.select_display_ranges(
 7900                &[
 7901                    // cursors at the the end of leading indent - last indent is deleted
 7902                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 7903                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 7904                    // cursors inside leading indent - overlapping indent deletions are coalesced
 7905                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7906                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 7907                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 7908                    // cursor at the beginning of a line - preceding newline is deleted
 7909                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7910                    // selection inside leading indent - only the selected character is deleted
 7911                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 7912                ],
 7913                cx,
 7914            );
 7915            view.backspace(&Backspace, cx);
 7916            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 7917        });
 7918    }
 7919
 7920    #[gpui::test]
 7921    fn test_delete(cx: &mut gpui::MutableAppContext) {
 7922        cx.set_global(Settings::test(cx));
 7923        let buffer =
 7924            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7925        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7926
 7927        view.update(cx, |view, cx| {
 7928            view.select_display_ranges(
 7929                &[
 7930                    // an empty selection - the following character is deleted
 7931                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7932                    // one character selected - it is deleted
 7933                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7934                    // a line suffix selected - it is deleted
 7935                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7936                ],
 7937                cx,
 7938            );
 7939            view.delete(&Delete, cx);
 7940        });
 7941
 7942        assert_eq!(
 7943            buffer.read(cx).read(cx).text(),
 7944            "on two three\nfou five six\nseven ten\n"
 7945        );
 7946    }
 7947
 7948    #[gpui::test]
 7949    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7950        cx.set_global(Settings::test(cx));
 7951        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7952        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7953        view.update(cx, |view, cx| {
 7954            view.select_display_ranges(
 7955                &[
 7956                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7957                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7958                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7959                ],
 7960                cx,
 7961            );
 7962            view.delete_line(&DeleteLine, cx);
 7963            assert_eq!(view.display_text(cx), "ghi");
 7964            assert_eq!(
 7965                view.selected_display_ranges(cx),
 7966                vec![
 7967                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7968                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7969                ]
 7970            );
 7971        });
 7972
 7973        cx.set_global(Settings::test(cx));
 7974        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7975        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7976        view.update(cx, |view, cx| {
 7977            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 7978            view.delete_line(&DeleteLine, cx);
 7979            assert_eq!(view.display_text(cx), "ghi\n");
 7980            assert_eq!(
 7981                view.selected_display_ranges(cx),
 7982                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7983            );
 7984        });
 7985    }
 7986
 7987    #[gpui::test]
 7988    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7989        cx.set_global(Settings::test(cx));
 7990        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7991        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7992        view.update(cx, |view, cx| {
 7993            view.select_display_ranges(
 7994                &[
 7995                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7996                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7997                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7998                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7999                ],
 8000                cx,
 8001            );
 8002            view.duplicate_line(&DuplicateLine, cx);
 8003            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8004            assert_eq!(
 8005                view.selected_display_ranges(cx),
 8006                vec![
 8007                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8008                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8009                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8010                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8011                ]
 8012            );
 8013        });
 8014
 8015        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8016        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8017        view.update(cx, |view, cx| {
 8018            view.select_display_ranges(
 8019                &[
 8020                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8021                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8022                ],
 8023                cx,
 8024            );
 8025            view.duplicate_line(&DuplicateLine, cx);
 8026            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8027            assert_eq!(
 8028                view.selected_display_ranges(cx),
 8029                vec![
 8030                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8031                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8032                ]
 8033            );
 8034        });
 8035    }
 8036
 8037    #[gpui::test]
 8038    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8039        cx.set_global(Settings::test(cx));
 8040        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8041        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8042        view.update(cx, |view, cx| {
 8043            view.fold_ranges(
 8044                vec![
 8045                    Point::new(0, 2)..Point::new(1, 2),
 8046                    Point::new(2, 3)..Point::new(4, 1),
 8047                    Point::new(7, 0)..Point::new(8, 4),
 8048                ],
 8049                cx,
 8050            );
 8051            view.select_display_ranges(
 8052                &[
 8053                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8054                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8055                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8056                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8057                ],
 8058                cx,
 8059            );
 8060            assert_eq!(
 8061                view.display_text(cx),
 8062                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8063            );
 8064
 8065            view.move_line_up(&MoveLineUp, cx);
 8066            assert_eq!(
 8067                view.display_text(cx),
 8068                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8069            );
 8070            assert_eq!(
 8071                view.selected_display_ranges(cx),
 8072                vec![
 8073                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8074                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8075                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8076                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8077                ]
 8078            );
 8079        });
 8080
 8081        view.update(cx, |view, cx| {
 8082            view.move_line_down(&MoveLineDown, cx);
 8083            assert_eq!(
 8084                view.display_text(cx),
 8085                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8086            );
 8087            assert_eq!(
 8088                view.selected_display_ranges(cx),
 8089                vec![
 8090                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8091                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8092                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8093                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8094                ]
 8095            );
 8096        });
 8097
 8098        view.update(cx, |view, cx| {
 8099            view.move_line_down(&MoveLineDown, cx);
 8100            assert_eq!(
 8101                view.display_text(cx),
 8102                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8103            );
 8104            assert_eq!(
 8105                view.selected_display_ranges(cx),
 8106                vec![
 8107                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8108                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8109                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8110                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8111                ]
 8112            );
 8113        });
 8114
 8115        view.update(cx, |view, cx| {
 8116            view.move_line_up(&MoveLineUp, cx);
 8117            assert_eq!(
 8118                view.display_text(cx),
 8119                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8120            );
 8121            assert_eq!(
 8122                view.selected_display_ranges(cx),
 8123                vec![
 8124                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8125                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8126                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8127                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8128                ]
 8129            );
 8130        });
 8131    }
 8132
 8133    #[gpui::test]
 8134    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8135        cx.set_global(Settings::test(cx));
 8136        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8137        let snapshot = buffer.read(cx).snapshot(cx);
 8138        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8139        editor.update(cx, |editor, cx| {
 8140            editor.insert_blocks(
 8141                [BlockProperties {
 8142                    position: snapshot.anchor_after(Point::new(2, 0)),
 8143                    disposition: BlockDisposition::Below,
 8144                    height: 1,
 8145                    render: Arc::new(|_| Empty::new().boxed()),
 8146                }],
 8147                cx,
 8148            );
 8149            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8150            editor.move_line_down(&MoveLineDown, cx);
 8151        });
 8152    }
 8153
 8154    #[gpui::test]
 8155    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8156        cx.set_global(Settings::test(cx));
 8157        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8158        let view = cx
 8159            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8160            .1;
 8161
 8162        // Cut with three selections. Clipboard text is divided into three slices.
 8163        view.update(cx, |view, cx| {
 8164            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8165            view.cut(&Cut, cx);
 8166            assert_eq!(view.display_text(cx), "two four six ");
 8167        });
 8168
 8169        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8170        view.update(cx, |view, cx| {
 8171            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8172            view.paste(&Paste, cx);
 8173            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8174            assert_eq!(
 8175                view.selected_display_ranges(cx),
 8176                &[
 8177                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8178                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8179                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8180                ]
 8181            );
 8182        });
 8183
 8184        // Paste again but with only two cursors. Since the number of cursors doesn't
 8185        // match the number of slices in the clipboard, the entire clipboard text
 8186        // is pasted at each cursor.
 8187        view.update(cx, |view, cx| {
 8188            view.select_ranges(vec![0..0, 31..31], None, cx);
 8189            view.handle_input(&Input("( ".into()), cx);
 8190            view.paste(&Paste, cx);
 8191            view.handle_input(&Input(") ".into()), cx);
 8192            assert_eq!(
 8193                view.display_text(cx),
 8194                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8195            );
 8196        });
 8197
 8198        view.update(cx, |view, cx| {
 8199            view.select_ranges(vec![0..0], None, cx);
 8200            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8201            assert_eq!(
 8202                view.display_text(cx),
 8203                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8204            );
 8205        });
 8206
 8207        // Cut with three selections, one of which is full-line.
 8208        view.update(cx, |view, cx| {
 8209            view.select_display_ranges(
 8210                &[
 8211                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8212                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8213                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8214                ],
 8215                cx,
 8216            );
 8217            view.cut(&Cut, cx);
 8218            assert_eq!(
 8219                view.display_text(cx),
 8220                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8221            );
 8222        });
 8223
 8224        // Paste with three selections, noticing how the copied selection that was full-line
 8225        // gets inserted before the second cursor.
 8226        view.update(cx, |view, cx| {
 8227            view.select_display_ranges(
 8228                &[
 8229                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8230                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8231                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8232                ],
 8233                cx,
 8234            );
 8235            view.paste(&Paste, cx);
 8236            assert_eq!(
 8237                view.display_text(cx),
 8238                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8239            );
 8240            assert_eq!(
 8241                view.selected_display_ranges(cx),
 8242                &[
 8243                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8244                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8245                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8246                ]
 8247            );
 8248        });
 8249
 8250        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8251        view.update(cx, |view, cx| {
 8252            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8253            view.copy(&Copy, cx);
 8254        });
 8255
 8256        // Paste with three selections, noticing how the copied full-line selection is inserted
 8257        // before the empty selections but replaces the selection that is non-empty.
 8258        view.update(cx, |view, cx| {
 8259            view.select_display_ranges(
 8260                &[
 8261                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8262                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8263                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8264                ],
 8265                cx,
 8266            );
 8267            view.paste(&Paste, cx);
 8268            assert_eq!(
 8269                view.display_text(cx),
 8270                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8271            );
 8272            assert_eq!(
 8273                view.selected_display_ranges(cx),
 8274                &[
 8275                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8276                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8277                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8278                ]
 8279            );
 8280        });
 8281    }
 8282
 8283    #[gpui::test]
 8284    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8285        cx.set_global(Settings::test(cx));
 8286        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8287        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8288        view.update(cx, |view, cx| {
 8289            view.select_all(&SelectAll, cx);
 8290            assert_eq!(
 8291                view.selected_display_ranges(cx),
 8292                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8293            );
 8294        });
 8295    }
 8296
 8297    #[gpui::test]
 8298    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8299        cx.set_global(Settings::test(cx));
 8300        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8301        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8302        view.update(cx, |view, cx| {
 8303            view.select_display_ranges(
 8304                &[
 8305                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8306                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8307                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8308                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8309                ],
 8310                cx,
 8311            );
 8312            view.select_line(&SelectLine, cx);
 8313            assert_eq!(
 8314                view.selected_display_ranges(cx),
 8315                vec![
 8316                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8317                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8318                ]
 8319            );
 8320        });
 8321
 8322        view.update(cx, |view, cx| {
 8323            view.select_line(&SelectLine, cx);
 8324            assert_eq!(
 8325                view.selected_display_ranges(cx),
 8326                vec![
 8327                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8328                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8329                ]
 8330            );
 8331        });
 8332
 8333        view.update(cx, |view, cx| {
 8334            view.select_line(&SelectLine, cx);
 8335            assert_eq!(
 8336                view.selected_display_ranges(cx),
 8337                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8338            );
 8339        });
 8340    }
 8341
 8342    #[gpui::test]
 8343    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8344        cx.set_global(Settings::test(cx));
 8345        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8346        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8347        view.update(cx, |view, cx| {
 8348            view.fold_ranges(
 8349                vec![
 8350                    Point::new(0, 2)..Point::new(1, 2),
 8351                    Point::new(2, 3)..Point::new(4, 1),
 8352                    Point::new(7, 0)..Point::new(8, 4),
 8353                ],
 8354                cx,
 8355            );
 8356            view.select_display_ranges(
 8357                &[
 8358                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8359                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8360                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8361                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8362                ],
 8363                cx,
 8364            );
 8365            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8366        });
 8367
 8368        view.update(cx, |view, cx| {
 8369            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8370            assert_eq!(
 8371                view.display_text(cx),
 8372                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8373            );
 8374            assert_eq!(
 8375                view.selected_display_ranges(cx),
 8376                [
 8377                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8378                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8379                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8380                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8381                ]
 8382            );
 8383        });
 8384
 8385        view.update(cx, |view, cx| {
 8386            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8387            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8388            assert_eq!(
 8389                view.display_text(cx),
 8390                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8391            );
 8392            assert_eq!(
 8393                view.selected_display_ranges(cx),
 8394                [
 8395                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8396                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8397                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8398                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8399                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8400                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8401                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8402                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8403                ]
 8404            );
 8405        });
 8406    }
 8407
 8408    #[gpui::test]
 8409    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8410        cx.set_global(Settings::test(cx));
 8411        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8412        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8413
 8414        view.update(cx, |view, cx| {
 8415            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8416        });
 8417        view.update(cx, |view, cx| {
 8418            view.add_selection_above(&AddSelectionAbove, cx);
 8419            assert_eq!(
 8420                view.selected_display_ranges(cx),
 8421                vec![
 8422                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8423                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8424                ]
 8425            );
 8426        });
 8427
 8428        view.update(cx, |view, cx| {
 8429            view.add_selection_above(&AddSelectionAbove, cx);
 8430            assert_eq!(
 8431                view.selected_display_ranges(cx),
 8432                vec![
 8433                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8434                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 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![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8444            );
 8445
 8446            view.undo_selection(&UndoSelection, cx);
 8447            assert_eq!(
 8448                view.selected_display_ranges(cx),
 8449                vec![
 8450                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8451                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8452                ]
 8453            );
 8454
 8455            view.redo_selection(&RedoSelection, cx);
 8456            assert_eq!(
 8457                view.selected_display_ranges(cx),
 8458                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8459            );
 8460        });
 8461
 8462        view.update(cx, |view, cx| {
 8463            view.add_selection_below(&AddSelectionBelow, cx);
 8464            assert_eq!(
 8465                view.selected_display_ranges(cx),
 8466                vec![
 8467                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8468                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8469                ]
 8470            );
 8471        });
 8472
 8473        view.update(cx, |view, cx| {
 8474            view.add_selection_below(&AddSelectionBelow, cx);
 8475            assert_eq!(
 8476                view.selected_display_ranges(cx),
 8477                vec![
 8478                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8479                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8480                ]
 8481            );
 8482        });
 8483
 8484        view.update(cx, |view, cx| {
 8485            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8486        });
 8487        view.update(cx, |view, cx| {
 8488            view.add_selection_below(&AddSelectionBelow, cx);
 8489            assert_eq!(
 8490                view.selected_display_ranges(cx),
 8491                vec![
 8492                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8493                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8494                ]
 8495            );
 8496        });
 8497
 8498        view.update(cx, |view, cx| {
 8499            view.add_selection_below(&AddSelectionBelow, cx);
 8500            assert_eq!(
 8501                view.selected_display_ranges(cx),
 8502                vec![
 8503                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8504                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8505                ]
 8506            );
 8507        });
 8508
 8509        view.update(cx, |view, cx| {
 8510            view.add_selection_above(&AddSelectionAbove, cx);
 8511            assert_eq!(
 8512                view.selected_display_ranges(cx),
 8513                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 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![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8522            );
 8523        });
 8524
 8525        view.update(cx, |view, cx| {
 8526            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8527            view.add_selection_below(&AddSelectionBelow, cx);
 8528            assert_eq!(
 8529                view.selected_display_ranges(cx),
 8530                vec![
 8531                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8532                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8533                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8534                ]
 8535            );
 8536        });
 8537
 8538        view.update(cx, |view, cx| {
 8539            view.add_selection_below(&AddSelectionBelow, cx);
 8540            assert_eq!(
 8541                view.selected_display_ranges(cx),
 8542                vec![
 8543                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8544                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8545                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8546                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8547                ]
 8548            );
 8549        });
 8550
 8551        view.update(cx, |view, cx| {
 8552            view.add_selection_above(&AddSelectionAbove, cx);
 8553            assert_eq!(
 8554                view.selected_display_ranges(cx),
 8555                vec![
 8556                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8557                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8558                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8559                ]
 8560            );
 8561        });
 8562
 8563        view.update(cx, |view, cx| {
 8564            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8565        });
 8566        view.update(cx, |view, cx| {
 8567            view.add_selection_above(&AddSelectionAbove, cx);
 8568            assert_eq!(
 8569                view.selected_display_ranges(cx),
 8570                vec![
 8571                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8572                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8573                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8574                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8575                ]
 8576            );
 8577        });
 8578
 8579        view.update(cx, |view, cx| {
 8580            view.add_selection_below(&AddSelectionBelow, cx);
 8581            assert_eq!(
 8582                view.selected_display_ranges(cx),
 8583                vec![
 8584                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8585                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8586                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8587                ]
 8588            );
 8589        });
 8590    }
 8591
 8592    #[gpui::test]
 8593    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8594        cx.set_global(Settings::test(cx));
 8595
 8596        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8597        let buffer = MultiBuffer::build_simple(&text, cx);
 8598        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8599
 8600        view.update(cx, |view, cx| {
 8601            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8602            view.select_next(
 8603                &SelectNext {
 8604                    replace_newest: false,
 8605                },
 8606                cx,
 8607            );
 8608            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8609
 8610            view.select_next(
 8611                &SelectNext {
 8612                    replace_newest: false,
 8613                },
 8614                cx,
 8615            );
 8616            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8617
 8618            view.undo_selection(&UndoSelection, cx);
 8619            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8620
 8621            view.redo_selection(&RedoSelection, cx);
 8622            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8623
 8624            view.select_next(
 8625                &SelectNext {
 8626                    replace_newest: false,
 8627                },
 8628                cx,
 8629            );
 8630            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8631
 8632            view.select_next(
 8633                &SelectNext {
 8634                    replace_newest: false,
 8635                },
 8636                cx,
 8637            );
 8638            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8639        });
 8640    }
 8641
 8642    #[gpui::test]
 8643    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8644        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8645        let language = Arc::new(Language::new(
 8646            LanguageConfig::default(),
 8647            Some(tree_sitter_rust::language()),
 8648        ));
 8649
 8650        let text = r#"
 8651            use mod1::mod2::{mod3, mod4};
 8652
 8653            fn fn_1(param1: bool, param2: &str) {
 8654                let var1 = "text";
 8655            }
 8656        "#
 8657        .unindent();
 8658
 8659        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8660        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8661        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8662        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8663            .await;
 8664
 8665        view.update(cx, |view, cx| {
 8666            view.select_display_ranges(
 8667                &[
 8668                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8669                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8670                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8671                ],
 8672                cx,
 8673            );
 8674            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8675        });
 8676        assert_eq!(
 8677            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8678            &[
 8679                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8680                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8681                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8682            ]
 8683        );
 8684
 8685        view.update(cx, |view, cx| {
 8686            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8687        });
 8688        assert_eq!(
 8689            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8690            &[
 8691                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8692                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8693            ]
 8694        );
 8695
 8696        view.update(cx, |view, cx| {
 8697            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8698        });
 8699        assert_eq!(
 8700            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8701            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8702        );
 8703
 8704        // Trying to expand the selected syntax node one more time has no effect.
 8705        view.update(cx, |view, cx| {
 8706            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8707        });
 8708        assert_eq!(
 8709            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8710            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8711        );
 8712
 8713        view.update(cx, |view, cx| {
 8714            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8715        });
 8716        assert_eq!(
 8717            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8718            &[
 8719                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8720                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8721            ]
 8722        );
 8723
 8724        view.update(cx, |view, cx| {
 8725            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8726        });
 8727        assert_eq!(
 8728            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8729            &[
 8730                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8731                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8732                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8733            ]
 8734        );
 8735
 8736        view.update(cx, |view, cx| {
 8737            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8738        });
 8739        assert_eq!(
 8740            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8741            &[
 8742                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8743                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8744                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8745            ]
 8746        );
 8747
 8748        // Trying to shrink the selected syntax node one more time has no effect.
 8749        view.update(cx, |view, cx| {
 8750            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8751        });
 8752        assert_eq!(
 8753            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8754            &[
 8755                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8756                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8757                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8758            ]
 8759        );
 8760
 8761        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8762        // a fold.
 8763        view.update(cx, |view, cx| {
 8764            view.fold_ranges(
 8765                vec![
 8766                    Point::new(0, 21)..Point::new(0, 24),
 8767                    Point::new(3, 20)..Point::new(3, 22),
 8768                ],
 8769                cx,
 8770            );
 8771            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8772        });
 8773        assert_eq!(
 8774            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8775            &[
 8776                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8777                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8778                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8779            ]
 8780        );
 8781    }
 8782
 8783    #[gpui::test]
 8784    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8785        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8786        let language = Arc::new(
 8787            Language::new(
 8788                LanguageConfig {
 8789                    brackets: vec![
 8790                        BracketPair {
 8791                            start: "{".to_string(),
 8792                            end: "}".to_string(),
 8793                            close: false,
 8794                            newline: true,
 8795                        },
 8796                        BracketPair {
 8797                            start: "(".to_string(),
 8798                            end: ")".to_string(),
 8799                            close: false,
 8800                            newline: true,
 8801                        },
 8802                    ],
 8803                    ..Default::default()
 8804                },
 8805                Some(tree_sitter_rust::language()),
 8806            )
 8807            .with_indents_query(
 8808                r#"
 8809                (_ "(" ")" @end) @indent
 8810                (_ "{" "}" @end) @indent
 8811                "#,
 8812            )
 8813            .unwrap(),
 8814        );
 8815
 8816        let text = "fn a() {}";
 8817
 8818        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8819        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8820        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8821        editor
 8822            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8823            .await;
 8824
 8825        editor.update(cx, |editor, cx| {
 8826            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 8827            editor.newline(&Newline, cx);
 8828            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8829            assert_eq!(
 8830                editor.selected_ranges(cx),
 8831                &[
 8832                    Point::new(1, 4)..Point::new(1, 4),
 8833                    Point::new(3, 4)..Point::new(3, 4),
 8834                    Point::new(5, 0)..Point::new(5, 0)
 8835                ]
 8836            );
 8837        });
 8838    }
 8839
 8840    #[gpui::test]
 8841    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8842        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8843        let language = Arc::new(Language::new(
 8844            LanguageConfig {
 8845                brackets: vec![
 8846                    BracketPair {
 8847                        start: "{".to_string(),
 8848                        end: "}".to_string(),
 8849                        close: true,
 8850                        newline: true,
 8851                    },
 8852                    BracketPair {
 8853                        start: "/*".to_string(),
 8854                        end: " */".to_string(),
 8855                        close: true,
 8856                        newline: true,
 8857                    },
 8858                ],
 8859                autoclose_before: "})]".to_string(),
 8860                ..Default::default()
 8861            },
 8862            Some(tree_sitter_rust::language()),
 8863        ));
 8864
 8865        let text = r#"
 8866            a
 8867
 8868            /
 8869
 8870        "#
 8871        .unindent();
 8872
 8873        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8874        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8875        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8876        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8877            .await;
 8878
 8879        view.update(cx, |view, cx| {
 8880            view.select_display_ranges(
 8881                &[
 8882                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8883                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8884                ],
 8885                cx,
 8886            );
 8887
 8888            view.handle_input(&Input("{".to_string()), cx);
 8889            view.handle_input(&Input("{".to_string()), cx);
 8890            view.handle_input(&Input("{".to_string()), cx);
 8891            assert_eq!(
 8892                view.text(cx),
 8893                "
 8894                {{{}}}
 8895                {{{}}}
 8896                /
 8897
 8898                "
 8899                .unindent()
 8900            );
 8901
 8902            view.move_right(&MoveRight, cx);
 8903            view.handle_input(&Input("}".to_string()), cx);
 8904            view.handle_input(&Input("}".to_string()), cx);
 8905            view.handle_input(&Input("}".to_string()), cx);
 8906            assert_eq!(
 8907                view.text(cx),
 8908                "
 8909                {{{}}}}
 8910                {{{}}}}
 8911                /
 8912
 8913                "
 8914                .unindent()
 8915            );
 8916
 8917            view.undo(&Undo, cx);
 8918            view.handle_input(&Input("/".to_string()), cx);
 8919            view.handle_input(&Input("*".to_string()), cx);
 8920            assert_eq!(
 8921                view.text(cx),
 8922                "
 8923                /* */
 8924                /* */
 8925                /
 8926
 8927                "
 8928                .unindent()
 8929            );
 8930
 8931            view.undo(&Undo, cx);
 8932            view.select_display_ranges(
 8933                &[
 8934                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8935                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8936                ],
 8937                cx,
 8938            );
 8939            view.handle_input(&Input("*".to_string()), cx);
 8940            assert_eq!(
 8941                view.text(cx),
 8942                "
 8943                a
 8944
 8945                /*
 8946                *
 8947                "
 8948                .unindent()
 8949            );
 8950
 8951            // Don't autoclose if the next character isn't whitespace and isn't
 8952            // listed in the language's "autoclose_before" section.
 8953            view.finalize_last_transaction(cx);
 8954            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 8955            view.handle_input(&Input("{".to_string()), cx);
 8956            assert_eq!(
 8957                view.text(cx),
 8958                "
 8959                {a
 8960
 8961                /*
 8962                *
 8963                "
 8964                .unindent()
 8965            );
 8966
 8967            view.undo(&Undo, cx);
 8968            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 8969            view.handle_input(&Input("{".to_string()), cx);
 8970            assert_eq!(
 8971                view.text(cx),
 8972                "
 8973                {a}
 8974
 8975                /*
 8976                *
 8977                "
 8978                .unindent()
 8979            );
 8980            assert_eq!(
 8981                view.selected_display_ranges(cx),
 8982                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8983            );
 8984        });
 8985    }
 8986
 8987    #[gpui::test]
 8988    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 8989        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8990
 8991        let text = "
 8992            a. b
 8993            a. b
 8994            a. b
 8995        "
 8996        .unindent();
 8997        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 8998        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8999
 9000        editor.update(cx, |editor, cx| {
 9001            let buffer = &editor.snapshot(cx).buffer_snapshot;
 9002            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9003            let insertion_ranges = [
 9004                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 9005                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 9006                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 9007            ];
 9008
 9009            editor
 9010                .insert_snippet(&insertion_ranges, snippet, cx)
 9011                .unwrap();
 9012            assert_eq!(
 9013                editor.text(cx),
 9014                "
 9015                    a.f(one, two, three) b
 9016                    a.f(one, two, three) b
 9017                    a.f(one, two, three) b
 9018                "
 9019                .unindent()
 9020            );
 9021            assert_eq!(
 9022                editor.selected_ranges::<Point>(cx),
 9023                &[
 9024                    Point::new(0, 4)..Point::new(0, 7),
 9025                    Point::new(0, 14)..Point::new(0, 19),
 9026                    Point::new(1, 4)..Point::new(1, 7),
 9027                    Point::new(1, 14)..Point::new(1, 19),
 9028                    Point::new(2, 4)..Point::new(2, 7),
 9029                    Point::new(2, 14)..Point::new(2, 19),
 9030                ]
 9031            );
 9032
 9033            // Can't move earlier than the first tab stop
 9034            editor.move_to_prev_snippet_tabstop(cx);
 9035            assert_eq!(
 9036                editor.selected_ranges::<Point>(cx),
 9037                &[
 9038                    Point::new(0, 4)..Point::new(0, 7),
 9039                    Point::new(0, 14)..Point::new(0, 19),
 9040                    Point::new(1, 4)..Point::new(1, 7),
 9041                    Point::new(1, 14)..Point::new(1, 19),
 9042                    Point::new(2, 4)..Point::new(2, 7),
 9043                    Point::new(2, 14)..Point::new(2, 19),
 9044                ]
 9045            );
 9046
 9047            assert!(editor.move_to_next_snippet_tabstop(cx));
 9048            assert_eq!(
 9049                editor.selected_ranges::<Point>(cx),
 9050                &[
 9051                    Point::new(0, 9)..Point::new(0, 12),
 9052                    Point::new(1, 9)..Point::new(1, 12),
 9053                    Point::new(2, 9)..Point::new(2, 12)
 9054                ]
 9055            );
 9056
 9057            editor.move_to_prev_snippet_tabstop(cx);
 9058            assert_eq!(
 9059                editor.selected_ranges::<Point>(cx),
 9060                &[
 9061                    Point::new(0, 4)..Point::new(0, 7),
 9062                    Point::new(0, 14)..Point::new(0, 19),
 9063                    Point::new(1, 4)..Point::new(1, 7),
 9064                    Point::new(1, 14)..Point::new(1, 19),
 9065                    Point::new(2, 4)..Point::new(2, 7),
 9066                    Point::new(2, 14)..Point::new(2, 19),
 9067                ]
 9068            );
 9069
 9070            assert!(editor.move_to_next_snippet_tabstop(cx));
 9071            assert!(editor.move_to_next_snippet_tabstop(cx));
 9072            assert_eq!(
 9073                editor.selected_ranges::<Point>(cx),
 9074                &[
 9075                    Point::new(0, 20)..Point::new(0, 20),
 9076                    Point::new(1, 20)..Point::new(1, 20),
 9077                    Point::new(2, 20)..Point::new(2, 20)
 9078                ]
 9079            );
 9080
 9081            // As soon as the last tab stop is reached, snippet state is gone
 9082            editor.move_to_prev_snippet_tabstop(cx);
 9083            assert_eq!(
 9084                editor.selected_ranges::<Point>(cx),
 9085                &[
 9086                    Point::new(0, 20)..Point::new(0, 20),
 9087                    Point::new(1, 20)..Point::new(1, 20),
 9088                    Point::new(2, 20)..Point::new(2, 20)
 9089                ]
 9090            );
 9091        });
 9092    }
 9093
 9094    #[gpui::test]
 9095    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9096        cx.foreground().forbid_parking();
 9097        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9098
 9099        let mut language = Language::new(
 9100            LanguageConfig {
 9101                name: "Rust".into(),
 9102                path_suffixes: vec!["rs".to_string()],
 9103                ..Default::default()
 9104            },
 9105            Some(tree_sitter_rust::language()),
 9106        );
 9107        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9108            capabilities: lsp::ServerCapabilities {
 9109                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9110                ..Default::default()
 9111            },
 9112            ..Default::default()
 9113        });
 9114
 9115        let fs = FakeFs::new(cx.background().clone());
 9116        fs.insert_file("/file.rs", Default::default()).await;
 9117
 9118        let project = Project::test(fs, cx);
 9119        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9120
 9121        let worktree_id = project
 9122            .update(cx, |project, cx| {
 9123                project.find_or_create_local_worktree("/file.rs", true, cx)
 9124            })
 9125            .await
 9126            .unwrap()
 9127            .0
 9128            .read_with(cx, |tree, _| tree.id());
 9129        let buffer = project
 9130            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9131            .await
 9132            .unwrap();
 9133
 9134        cx.foreground().start_waiting();
 9135        let fake_server = fake_servers.next().await.unwrap();
 9136
 9137        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9138        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9139        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9140        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9141
 9142        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9143        fake_server
 9144            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9145                assert_eq!(
 9146                    params.text_document.uri,
 9147                    lsp::Url::from_file_path("/file.rs").unwrap()
 9148                );
 9149                assert_eq!(params.options.tab_size, 4);
 9150                Ok(Some(vec![lsp::TextEdit::new(
 9151                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9152                    ", ".to_string(),
 9153                )]))
 9154            })
 9155            .next()
 9156            .await;
 9157        cx.foreground().start_waiting();
 9158        save.await.unwrap();
 9159        assert_eq!(
 9160            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9161            "one, two\nthree\n"
 9162        );
 9163        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9164
 9165        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9166        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9167
 9168        // Ensure we can still save even if formatting hangs.
 9169        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9170            assert_eq!(
 9171                params.text_document.uri,
 9172                lsp::Url::from_file_path("/file.rs").unwrap()
 9173            );
 9174            futures::future::pending::<()>().await;
 9175            unreachable!()
 9176        });
 9177        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9178        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9179        cx.foreground().start_waiting();
 9180        save.await.unwrap();
 9181        assert_eq!(
 9182            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9183            "one\ntwo\nthree\n"
 9184        );
 9185        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9186
 9187        // Set rust language override and assert overriden tabsize is sent to language server
 9188        cx.update(|cx| {
 9189            cx.update_global::<Settings, _, _>(|settings, _| {
 9190                settings.language_overrides.insert(
 9191                    "Rust".into(),
 9192                    LanguageOverride {
 9193                        tab_size: Some(8),
 9194                        ..Default::default()
 9195                    },
 9196                );
 9197            })
 9198        });
 9199
 9200        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9201        fake_server
 9202            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9203                assert_eq!(
 9204                    params.text_document.uri,
 9205                    lsp::Url::from_file_path("/file.rs").unwrap()
 9206                );
 9207                assert_eq!(params.options.tab_size, 8);
 9208                Ok(Some(vec![]))
 9209            })
 9210            .next()
 9211            .await;
 9212        cx.foreground().start_waiting();
 9213        save.await.unwrap();
 9214    }
 9215
 9216    #[gpui::test]
 9217    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9218        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9219
 9220        let mut language = Language::new(
 9221            LanguageConfig {
 9222                name: "Rust".into(),
 9223                path_suffixes: vec!["rs".to_string()],
 9224                ..Default::default()
 9225            },
 9226            Some(tree_sitter_rust::language()),
 9227        );
 9228        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9229            capabilities: lsp::ServerCapabilities {
 9230                completion_provider: Some(lsp::CompletionOptions {
 9231                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9232                    ..Default::default()
 9233                }),
 9234                ..Default::default()
 9235            },
 9236            ..Default::default()
 9237        });
 9238
 9239        let text = "
 9240            one
 9241            two
 9242            three
 9243        "
 9244        .unindent();
 9245
 9246        let fs = FakeFs::new(cx.background().clone());
 9247        fs.insert_file("/file.rs", text).await;
 9248
 9249        let project = Project::test(fs, cx);
 9250        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9251
 9252        let worktree_id = project
 9253            .update(cx, |project, cx| {
 9254                project.find_or_create_local_worktree("/file.rs", true, cx)
 9255            })
 9256            .await
 9257            .unwrap()
 9258            .0
 9259            .read_with(cx, |tree, _| tree.id());
 9260        let buffer = project
 9261            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9262            .await
 9263            .unwrap();
 9264        let mut fake_server = fake_servers.next().await.unwrap();
 9265
 9266        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9267        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9268
 9269        editor.update(cx, |editor, cx| {
 9270            editor.project = Some(project);
 9271            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9272            editor.handle_input(&Input(".".to_string()), cx);
 9273        });
 9274
 9275        handle_completion_request(
 9276            &mut fake_server,
 9277            "/file.rs",
 9278            Point::new(0, 4),
 9279            vec![
 9280                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9281                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9282            ],
 9283        )
 9284        .await;
 9285        editor
 9286            .condition(&cx, |editor, _| editor.context_menu_visible())
 9287            .await;
 9288
 9289        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9290            editor.move_down(&MoveDown, cx);
 9291            let apply_additional_edits = editor
 9292                .confirm_completion(&ConfirmCompletion::default(), cx)
 9293                .unwrap();
 9294            assert_eq!(
 9295                editor.text(cx),
 9296                "
 9297                    one.second_completion
 9298                    two
 9299                    three
 9300                "
 9301                .unindent()
 9302            );
 9303            apply_additional_edits
 9304        });
 9305
 9306        handle_resolve_completion_request(
 9307            &mut fake_server,
 9308            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9309        )
 9310        .await;
 9311        apply_additional_edits.await.unwrap();
 9312        assert_eq!(
 9313            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9314            "
 9315                one.second_completion
 9316                two
 9317                three
 9318                additional edit
 9319            "
 9320            .unindent()
 9321        );
 9322
 9323        editor.update(cx, |editor, cx| {
 9324            editor.select_ranges(
 9325                [
 9326                    Point::new(1, 3)..Point::new(1, 3),
 9327                    Point::new(2, 5)..Point::new(2, 5),
 9328                ],
 9329                None,
 9330                cx,
 9331            );
 9332
 9333            editor.handle_input(&Input(" ".to_string()), cx);
 9334            assert!(editor.context_menu.is_none());
 9335            editor.handle_input(&Input("s".to_string()), cx);
 9336            assert!(editor.context_menu.is_none());
 9337        });
 9338
 9339        handle_completion_request(
 9340            &mut fake_server,
 9341            "/file.rs",
 9342            Point::new(2, 7),
 9343            vec![
 9344                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9345                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9346                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9347            ],
 9348        )
 9349        .await;
 9350        editor
 9351            .condition(&cx, |editor, _| editor.context_menu_visible())
 9352            .await;
 9353
 9354        editor.update(cx, |editor, cx| {
 9355            editor.handle_input(&Input("i".to_string()), cx);
 9356        });
 9357
 9358        handle_completion_request(
 9359            &mut fake_server,
 9360            "/file.rs",
 9361            Point::new(2, 8),
 9362            vec![
 9363                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9364                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9365                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9366            ],
 9367        )
 9368        .await;
 9369        editor
 9370            .condition(&cx, |editor, _| editor.context_menu_visible())
 9371            .await;
 9372
 9373        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9374            let apply_additional_edits = editor
 9375                .confirm_completion(&ConfirmCompletion::default(), cx)
 9376                .unwrap();
 9377            assert_eq!(
 9378                editor.text(cx),
 9379                "
 9380                    one.second_completion
 9381                    two sixth_completion
 9382                    three sixth_completion
 9383                    additional edit
 9384                "
 9385                .unindent()
 9386            );
 9387            apply_additional_edits
 9388        });
 9389        handle_resolve_completion_request(&mut fake_server, None).await;
 9390        apply_additional_edits.await.unwrap();
 9391
 9392        async fn handle_completion_request(
 9393            fake: &mut FakeLanguageServer,
 9394            path: &'static str,
 9395            position: Point,
 9396            completions: Vec<(Range<Point>, &'static str)>,
 9397        ) {
 9398            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9399                let completions = completions.clone();
 9400                async move {
 9401                    assert_eq!(
 9402                        params.text_document_position.text_document.uri,
 9403                        lsp::Url::from_file_path(path).unwrap()
 9404                    );
 9405                    assert_eq!(
 9406                        params.text_document_position.position,
 9407                        lsp::Position::new(position.row, position.column)
 9408                    );
 9409                    Ok(Some(lsp::CompletionResponse::Array(
 9410                        completions
 9411                            .iter()
 9412                            .map(|(range, new_text)| lsp::CompletionItem {
 9413                                label: new_text.to_string(),
 9414                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9415                                    range: lsp::Range::new(
 9416                                        lsp::Position::new(range.start.row, range.start.column),
 9417                                        lsp::Position::new(range.start.row, range.start.column),
 9418                                    ),
 9419                                    new_text: new_text.to_string(),
 9420                                })),
 9421                                ..Default::default()
 9422                            })
 9423                            .collect(),
 9424                    )))
 9425                }
 9426            })
 9427            .next()
 9428            .await;
 9429        }
 9430
 9431        async fn handle_resolve_completion_request(
 9432            fake: &mut FakeLanguageServer,
 9433            edit: Option<(Range<Point>, &'static str)>,
 9434        ) {
 9435            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9436                let edit = edit.clone();
 9437                async move {
 9438                    Ok(lsp::CompletionItem {
 9439                        additional_text_edits: edit.map(|(range, new_text)| {
 9440                            vec![lsp::TextEdit::new(
 9441                                lsp::Range::new(
 9442                                    lsp::Position::new(range.start.row, range.start.column),
 9443                                    lsp::Position::new(range.end.row, range.end.column),
 9444                                ),
 9445                                new_text.to_string(),
 9446                            )]
 9447                        }),
 9448                        ..Default::default()
 9449                    })
 9450                }
 9451            })
 9452            .next()
 9453            .await;
 9454        }
 9455    }
 9456
 9457    #[gpui::test]
 9458    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9459        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9460        let language = Arc::new(Language::new(
 9461            LanguageConfig {
 9462                line_comment: Some("// ".to_string()),
 9463                ..Default::default()
 9464            },
 9465            Some(tree_sitter_rust::language()),
 9466        ));
 9467
 9468        let text = "
 9469            fn a() {
 9470                //b();
 9471                // c();
 9472                //  d();
 9473            }
 9474        "
 9475        .unindent();
 9476
 9477        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9478        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9479        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9480
 9481        view.update(cx, |editor, cx| {
 9482            // If multiple selections intersect a line, the line is only
 9483            // toggled once.
 9484            editor.select_display_ranges(
 9485                &[
 9486                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9487                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9488                ],
 9489                cx,
 9490            );
 9491            editor.toggle_comments(&ToggleComments, cx);
 9492            assert_eq!(
 9493                editor.text(cx),
 9494                "
 9495                    fn a() {
 9496                        b();
 9497                        c();
 9498                         d();
 9499                    }
 9500                "
 9501                .unindent()
 9502            );
 9503
 9504            // The comment prefix is inserted at the same column for every line
 9505            // in a selection.
 9506            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9507            editor.toggle_comments(&ToggleComments, cx);
 9508            assert_eq!(
 9509                editor.text(cx),
 9510                "
 9511                    fn a() {
 9512                        // b();
 9513                        // c();
 9514                        //  d();
 9515                    }
 9516                "
 9517                .unindent()
 9518            );
 9519
 9520            // If a selection ends at the beginning of a line, that line is not toggled.
 9521            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9522            editor.toggle_comments(&ToggleComments, cx);
 9523            assert_eq!(
 9524                editor.text(cx),
 9525                "
 9526                        fn a() {
 9527                            // b();
 9528                            c();
 9529                            //  d();
 9530                        }
 9531                    "
 9532                .unindent()
 9533            );
 9534        });
 9535    }
 9536
 9537    #[gpui::test]
 9538    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9539        cx.set_global(Settings::test(cx));
 9540        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9541        let multibuffer = cx.add_model(|cx| {
 9542            let mut multibuffer = MultiBuffer::new(0);
 9543            multibuffer.push_excerpts(
 9544                buffer.clone(),
 9545                [
 9546                    Point::new(0, 0)..Point::new(0, 4),
 9547                    Point::new(1, 0)..Point::new(1, 4),
 9548                ],
 9549                cx,
 9550            );
 9551            multibuffer
 9552        });
 9553
 9554        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9555
 9556        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9557        view.update(cx, |view, cx| {
 9558            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9559            view.select_ranges(
 9560                [
 9561                    Point::new(0, 0)..Point::new(0, 0),
 9562                    Point::new(1, 0)..Point::new(1, 0),
 9563                ],
 9564                None,
 9565                cx,
 9566            );
 9567
 9568            view.handle_input(&Input("X".to_string()), cx);
 9569            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9570            assert_eq!(
 9571                view.selected_ranges(cx),
 9572                [
 9573                    Point::new(0, 1)..Point::new(0, 1),
 9574                    Point::new(1, 1)..Point::new(1, 1),
 9575                ]
 9576            )
 9577        });
 9578    }
 9579
 9580    #[gpui::test]
 9581    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9582        cx.set_global(Settings::test(cx));
 9583        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9584        let multibuffer = cx.add_model(|cx| {
 9585            let mut multibuffer = MultiBuffer::new(0);
 9586            multibuffer.push_excerpts(
 9587                buffer,
 9588                [
 9589                    Point::new(0, 0)..Point::new(1, 4),
 9590                    Point::new(1, 0)..Point::new(2, 4),
 9591                ],
 9592                cx,
 9593            );
 9594            multibuffer
 9595        });
 9596
 9597        assert_eq!(
 9598            multibuffer.read(cx).read(cx).text(),
 9599            "aaaa\nbbbb\nbbbb\ncccc"
 9600        );
 9601
 9602        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9603        view.update(cx, |view, cx| {
 9604            view.select_ranges(
 9605                [
 9606                    Point::new(1, 1)..Point::new(1, 1),
 9607                    Point::new(2, 3)..Point::new(2, 3),
 9608                ],
 9609                None,
 9610                cx,
 9611            );
 9612
 9613            view.handle_input(&Input("X".to_string()), cx);
 9614            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9615            assert_eq!(
 9616                view.selected_ranges(cx),
 9617                [
 9618                    Point::new(1, 2)..Point::new(1, 2),
 9619                    Point::new(2, 5)..Point::new(2, 5),
 9620                ]
 9621            );
 9622
 9623            view.newline(&Newline, cx);
 9624            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9625            assert_eq!(
 9626                view.selected_ranges(cx),
 9627                [
 9628                    Point::new(2, 0)..Point::new(2, 0),
 9629                    Point::new(6, 0)..Point::new(6, 0),
 9630                ]
 9631            );
 9632        });
 9633    }
 9634
 9635    #[gpui::test]
 9636    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9637        cx.set_global(Settings::test(cx));
 9638        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9639        let mut excerpt1_id = None;
 9640        let multibuffer = cx.add_model(|cx| {
 9641            let mut multibuffer = MultiBuffer::new(0);
 9642            excerpt1_id = multibuffer
 9643                .push_excerpts(
 9644                    buffer.clone(),
 9645                    [
 9646                        Point::new(0, 0)..Point::new(1, 4),
 9647                        Point::new(1, 0)..Point::new(2, 4),
 9648                    ],
 9649                    cx,
 9650                )
 9651                .into_iter()
 9652                .next();
 9653            multibuffer
 9654        });
 9655        assert_eq!(
 9656            multibuffer.read(cx).read(cx).text(),
 9657            "aaaa\nbbbb\nbbbb\ncccc"
 9658        );
 9659        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9660            let mut editor = build_editor(multibuffer.clone(), cx);
 9661            let snapshot = editor.snapshot(cx);
 9662            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9663            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9664            assert_eq!(
 9665                editor.selected_ranges(cx),
 9666                [
 9667                    Point::new(1, 3)..Point::new(1, 3),
 9668                    Point::new(2, 1)..Point::new(2, 1),
 9669                ]
 9670            );
 9671            editor
 9672        });
 9673
 9674        // Refreshing selections is a no-op when excerpts haven't changed.
 9675        editor.update(cx, |editor, cx| {
 9676            editor.refresh_selections(cx);
 9677            assert_eq!(
 9678                editor.selected_ranges(cx),
 9679                [
 9680                    Point::new(1, 3)..Point::new(1, 3),
 9681                    Point::new(2, 1)..Point::new(2, 1),
 9682                ]
 9683            );
 9684        });
 9685
 9686        multibuffer.update(cx, |multibuffer, cx| {
 9687            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9688        });
 9689        editor.update(cx, |editor, cx| {
 9690            // Removing an excerpt causes the first selection to become degenerate.
 9691            assert_eq!(
 9692                editor.selected_ranges(cx),
 9693                [
 9694                    Point::new(0, 0)..Point::new(0, 0),
 9695                    Point::new(0, 1)..Point::new(0, 1)
 9696                ]
 9697            );
 9698
 9699            // Refreshing selections will relocate the first selection to the original buffer
 9700            // location.
 9701            editor.refresh_selections(cx);
 9702            assert_eq!(
 9703                editor.selected_ranges(cx),
 9704                [
 9705                    Point::new(0, 1)..Point::new(0, 1),
 9706                    Point::new(0, 3)..Point::new(0, 3)
 9707                ]
 9708            );
 9709            assert!(editor.pending_selection.is_some());
 9710        });
 9711    }
 9712
 9713    #[gpui::test]
 9714    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9715        cx.set_global(Settings::test(cx));
 9716        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9717        let mut excerpt1_id = None;
 9718        let multibuffer = cx.add_model(|cx| {
 9719            let mut multibuffer = MultiBuffer::new(0);
 9720            excerpt1_id = multibuffer
 9721                .push_excerpts(
 9722                    buffer.clone(),
 9723                    [
 9724                        Point::new(0, 0)..Point::new(1, 4),
 9725                        Point::new(1, 0)..Point::new(2, 4),
 9726                    ],
 9727                    cx,
 9728                )
 9729                .into_iter()
 9730                .next();
 9731            multibuffer
 9732        });
 9733        assert_eq!(
 9734            multibuffer.read(cx).read(cx).text(),
 9735            "aaaa\nbbbb\nbbbb\ncccc"
 9736        );
 9737        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9738            let mut editor = build_editor(multibuffer.clone(), cx);
 9739            let snapshot = editor.snapshot(cx);
 9740            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9741            assert_eq!(
 9742                editor.selected_ranges(cx),
 9743                [Point::new(1, 3)..Point::new(1, 3)]
 9744            );
 9745            editor
 9746        });
 9747
 9748        multibuffer.update(cx, |multibuffer, cx| {
 9749            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9750        });
 9751        editor.update(cx, |editor, cx| {
 9752            assert_eq!(
 9753                editor.selected_ranges(cx),
 9754                [Point::new(0, 0)..Point::new(0, 0)]
 9755            );
 9756
 9757            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9758            editor.refresh_selections(cx);
 9759            assert_eq!(
 9760                editor.selected_ranges(cx),
 9761                [Point::new(0, 3)..Point::new(0, 3)]
 9762            );
 9763            assert!(editor.pending_selection.is_some());
 9764        });
 9765    }
 9766
 9767    #[gpui::test]
 9768    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9769        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9770        let language = Arc::new(Language::new(
 9771            LanguageConfig {
 9772                brackets: vec![
 9773                    BracketPair {
 9774                        start: "{".to_string(),
 9775                        end: "}".to_string(),
 9776                        close: true,
 9777                        newline: true,
 9778                    },
 9779                    BracketPair {
 9780                        start: "/* ".to_string(),
 9781                        end: " */".to_string(),
 9782                        close: true,
 9783                        newline: true,
 9784                    },
 9785                ],
 9786                ..Default::default()
 9787            },
 9788            Some(tree_sitter_rust::language()),
 9789        ));
 9790
 9791        let text = concat!(
 9792            "{   }\n",     // Suppress rustfmt
 9793            "  x\n",       //
 9794            "  /*   */\n", //
 9795            "x\n",         //
 9796            "{{} }\n",     //
 9797        );
 9798
 9799        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9800        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9801        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9802        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9803            .await;
 9804
 9805        view.update(cx, |view, cx| {
 9806            view.select_display_ranges(
 9807                &[
 9808                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9809                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9810                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9811                ],
 9812                cx,
 9813            );
 9814            view.newline(&Newline, cx);
 9815
 9816            assert_eq!(
 9817                view.buffer().read(cx).read(cx).text(),
 9818                concat!(
 9819                    "{ \n",    // Suppress rustfmt
 9820                    "\n",      //
 9821                    "}\n",     //
 9822                    "  x\n",   //
 9823                    "  /* \n", //
 9824                    "  \n",    //
 9825                    "  */\n",  //
 9826                    "x\n",     //
 9827                    "{{} \n",  //
 9828                    "}\n",     //
 9829                )
 9830            );
 9831        });
 9832    }
 9833
 9834    #[gpui::test]
 9835    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9836        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9837
 9838        cx.set_global(Settings::test(cx));
 9839        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9840
 9841        editor.update(cx, |editor, cx| {
 9842            struct Type1;
 9843            struct Type2;
 9844
 9845            let buffer = buffer.read(cx).snapshot(cx);
 9846
 9847            let anchor_range = |range: Range<Point>| {
 9848                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9849            };
 9850
 9851            editor.highlight_background::<Type1>(
 9852                vec![
 9853                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
 9854                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
 9855                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
 9856                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
 9857                ],
 9858                |_| Color::red(),
 9859                cx,
 9860            );
 9861            editor.highlight_background::<Type2>(
 9862                vec![
 9863                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
 9864                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
 9865                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
 9866                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
 9867                ],
 9868                |_| Color::green(),
 9869                cx,
 9870            );
 9871
 9872            let snapshot = editor.snapshot(cx);
 9873            let mut highlighted_ranges = editor.background_highlights_in_range(
 9874                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
 9875                &snapshot,
 9876                cx.global::<Settings>().theme.as_ref(),
 9877            );
 9878            // Enforce a consistent ordering based on color without relying on the ordering of the
 9879            // highlight's `TypeId` which is non-deterministic.
 9880            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9881            assert_eq!(
 9882                highlighted_ranges,
 9883                &[
 9884                    (
 9885                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9886                        Color::green(),
 9887                    ),
 9888                    (
 9889                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9890                        Color::green(),
 9891                    ),
 9892                    (
 9893                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9894                        Color::red(),
 9895                    ),
 9896                    (
 9897                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9898                        Color::red(),
 9899                    ),
 9900                ]
 9901            );
 9902            assert_eq!(
 9903                editor.background_highlights_in_range(
 9904                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9905                    &snapshot,
 9906                    cx.global::<Settings>().theme.as_ref(),
 9907                ),
 9908                &[(
 9909                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9910                    Color::red(),
 9911                )]
 9912            );
 9913        });
 9914    }
 9915
 9916    #[gpui::test]
 9917    fn test_following(cx: &mut gpui::MutableAppContext) {
 9918        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9919
 9920        cx.set_global(Settings::test(cx));
 9921
 9922        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9923        let (_, follower) = cx.add_window(
 9924            WindowOptions {
 9925                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
 9926                ..Default::default()
 9927            },
 9928            |cx| build_editor(buffer.clone(), cx),
 9929        );
 9930
 9931        let pending_update = Rc::new(RefCell::new(None));
 9932        follower.update(cx, {
 9933            let update = pending_update.clone();
 9934            |_, cx| {
 9935                cx.subscribe(&leader, move |_, leader, event, cx| {
 9936                    leader
 9937                        .read(cx)
 9938                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
 9939                })
 9940                .detach();
 9941            }
 9942        });
 9943
 9944        // Update the selections only
 9945        leader.update(cx, |leader, cx| {
 9946            leader.select_ranges([1..1], None, cx);
 9947        });
 9948        follower.update(cx, |follower, cx| {
 9949            follower
 9950                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9951                .unwrap();
 9952        });
 9953        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
 9954
 9955        // Update the scroll position only
 9956        leader.update(cx, |leader, cx| {
 9957            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9958        });
 9959        follower.update(cx, |follower, cx| {
 9960            follower
 9961                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9962                .unwrap();
 9963        });
 9964        assert_eq!(
 9965            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
 9966            vec2f(1.5, 3.5)
 9967        );
 9968
 9969        // Update the selections and scroll position
 9970        leader.update(cx, |leader, cx| {
 9971            leader.select_ranges([0..0], None, cx);
 9972            leader.request_autoscroll(Autoscroll::Newest, cx);
 9973            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9974        });
 9975        follower.update(cx, |follower, cx| {
 9976            let initial_scroll_position = follower.scroll_position(cx);
 9977            follower
 9978                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9979                .unwrap();
 9980            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
 9981            assert!(follower.autoscroll_request.is_some());
 9982        });
 9983        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
 9984
 9985        // Creating a pending selection that precedes another selection
 9986        leader.update(cx, |leader, cx| {
 9987            leader.select_ranges([1..1], None, cx);
 9988            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
 9989        });
 9990        follower.update(cx, |follower, cx| {
 9991            follower
 9992                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9993                .unwrap();
 9994        });
 9995        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
 9996
 9997        // Extend the pending selection so that it surrounds another selection
 9998        leader.update(cx, |leader, cx| {
 9999            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10000        });
10001        follower.update(cx, |follower, cx| {
10002            follower
10003                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10004                .unwrap();
10005        });
10006        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
10007    }
10008
10009    #[test]
10010    fn test_combine_syntax_and_fuzzy_match_highlights() {
10011        let string = "abcdefghijklmnop";
10012        let syntax_ranges = [
10013            (
10014                0..3,
10015                HighlightStyle {
10016                    color: Some(Color::red()),
10017                    ..Default::default()
10018                },
10019            ),
10020            (
10021                4..8,
10022                HighlightStyle {
10023                    color: Some(Color::green()),
10024                    ..Default::default()
10025                },
10026            ),
10027        ];
10028        let match_indices = [4, 6, 7, 8];
10029        assert_eq!(
10030            combine_syntax_and_fuzzy_match_highlights(
10031                &string,
10032                Default::default(),
10033                syntax_ranges.into_iter(),
10034                &match_indices,
10035            ),
10036            &[
10037                (
10038                    0..3,
10039                    HighlightStyle {
10040                        color: Some(Color::red()),
10041                        ..Default::default()
10042                    },
10043                ),
10044                (
10045                    4..5,
10046                    HighlightStyle {
10047                        color: Some(Color::green()),
10048                        weight: Some(fonts::Weight::BOLD),
10049                        ..Default::default()
10050                    },
10051                ),
10052                (
10053                    5..6,
10054                    HighlightStyle {
10055                        color: Some(Color::green()),
10056                        ..Default::default()
10057                    },
10058                ),
10059                (
10060                    6..8,
10061                    HighlightStyle {
10062                        color: Some(Color::green()),
10063                        weight: Some(fonts::Weight::BOLD),
10064                        ..Default::default()
10065                    },
10066                ),
10067                (
10068                    8..9,
10069                    HighlightStyle {
10070                        weight: Some(fonts::Weight::BOLD),
10071                        ..Default::default()
10072                    },
10073                ),
10074            ]
10075        );
10076    }
10077
10078    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10079        let point = DisplayPoint::new(row as u32, column as u32);
10080        point..point
10081    }
10082
10083    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10084        Editor::new(EditorMode::Full, buffer, None, None, cx)
10085    }
10086
10087    fn assert_selection_ranges(
10088        marked_text: &str,
10089        selection_marker_pairs: Vec<(char, char)>,
10090        view: &mut Editor,
10091        cx: &mut ViewContext<Editor>,
10092    ) {
10093        let snapshot = view.snapshot(cx).display_snapshot;
10094        let mut marker_chars = Vec::new();
10095        for (start, end) in selection_marker_pairs.iter() {
10096            marker_chars.push(*start);
10097            marker_chars.push(*end);
10098        }
10099        let (_, markers) = marked_text_by(marked_text, marker_chars);
10100        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10101            .iter()
10102            .map(|(start, end)| {
10103                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10104                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10105                start..end
10106            })
10107            .collect();
10108        assert_eq!(
10109            view.selected_display_ranges(cx),
10110            &asserted_ranges[..],
10111            "Assert selections are {}",
10112            marked_text
10113        );
10114    }
10115}
10116
10117trait RangeExt<T> {
10118    fn sorted(&self) -> Range<T>;
10119    fn to_inclusive(&self) -> RangeInclusive<T>;
10120}
10121
10122impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10123    fn sorted(&self) -> Self {
10124        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10125    }
10126
10127    fn to_inclusive(&self) -> RangeInclusive<T> {
10128        self.start.clone()..=self.end.clone()
10129    }
10130}