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