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