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