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