editor.rs

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