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