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 = display_map
 3399                        .buffer_snapshot
 3400                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3401                }
 3402
 3403                if transpose_offset == 0 {
 3404                    return;
 3405                }
 3406
 3407                *head.column_mut() += 1;
 3408                head = display_map.clip_point(head, Bias::Right);
 3409                selection.collapse_to(head, SelectionGoal::Column(head.column()));
 3410
 3411                let transpose_start = display_map
 3412                    .buffer_snapshot
 3413                    .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3414                if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 3415                    let transpose_end = display_map
 3416                        .buffer_snapshot
 3417                        .clip_offset(transpose_offset + 1, Bias::Right);
 3418                    if let Some(ch) = display_map.buffer_snapshot.chars_at(transpose_start).next() {
 3419                        edits.push((transpose_start..transpose_offset, String::new()));
 3420                        edits.push((transpose_end..transpose_end, ch.to_string()));
 3421                    }
 3422                }
 3423            });
 3424            this.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
 3425            this.update_selections(
 3426                this.local_selections::<usize>(cx),
 3427                Some(Autoscroll::Fit),
 3428                cx,
 3429            );
 3430        });
 3431    }
 3432
 3433    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 3434        let mut text = String::new();
 3435        let mut selections = self.local_selections::<Point>(cx);
 3436        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3437        {
 3438            let buffer = self.buffer.read(cx).read(cx);
 3439            let max_point = buffer.max_point();
 3440            for selection in &mut selections {
 3441                let is_entire_line = selection.is_empty();
 3442                if is_entire_line {
 3443                    selection.start = Point::new(selection.start.row, 0);
 3444                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 3445                    selection.goal = SelectionGoal::None;
 3446                }
 3447                let mut len = 0;
 3448                for chunk in buffer.text_for_range(selection.start..selection.end) {
 3449                    text.push_str(chunk);
 3450                    len += chunk.len();
 3451                }
 3452                clipboard_selections.push(ClipboardSelection {
 3453                    len,
 3454                    is_entire_line,
 3455                });
 3456            }
 3457        }
 3458
 3459        self.transact(cx, |this, cx| {
 3460            this.update_selections(selections, Some(Autoscroll::Fit), cx);
 3461            this.insert("", cx);
 3462            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3463        });
 3464    }
 3465
 3466    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 3467        let selections = self.local_selections::<Point>(cx);
 3468        let mut text = String::new();
 3469        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3470        {
 3471            let buffer = self.buffer.read(cx).read(cx);
 3472            let max_point = buffer.max_point();
 3473            for selection in selections.iter() {
 3474                let mut start = selection.start;
 3475                let mut end = selection.end;
 3476                let is_entire_line = selection.is_empty();
 3477                if is_entire_line {
 3478                    start = Point::new(start.row, 0);
 3479                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
 3480                }
 3481                let mut len = 0;
 3482                for chunk in buffer.text_for_range(start..end) {
 3483                    text.push_str(chunk);
 3484                    len += chunk.len();
 3485                }
 3486                clipboard_selections.push(ClipboardSelection {
 3487                    len,
 3488                    is_entire_line,
 3489                });
 3490            }
 3491        }
 3492
 3493        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3494    }
 3495
 3496    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 3497        self.transact(cx, |this, cx| {
 3498            if let Some(item) = cx.as_mut().read_from_clipboard() {
 3499                let mut clipboard_text = Cow::Borrowed(item.text());
 3500                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 3501                    let old_selections = this.local_selections::<usize>(cx);
 3502                    let all_selections_were_entire_line =
 3503                        clipboard_selections.iter().all(|s| s.is_entire_line);
 3504                    if clipboard_selections.len() != old_selections.len() {
 3505                        let mut newline_separated_text = String::new();
 3506                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
 3507                        let mut ix = 0;
 3508                        while let Some(clipboard_selection) = clipboard_selections.next() {
 3509                            newline_separated_text
 3510                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
 3511                            ix += clipboard_selection.len;
 3512                            if clipboard_selections.peek().is_some() {
 3513                                newline_separated_text.push('\n');
 3514                            }
 3515                        }
 3516                        clipboard_text = Cow::Owned(newline_separated_text);
 3517                    }
 3518
 3519                    this.buffer.update(cx, |buffer, cx| {
 3520                        let snapshot = buffer.read(cx);
 3521                        let mut start_offset = 0;
 3522                        let mut edits = Vec::new();
 3523                        for (ix, selection) in old_selections.iter().enumerate() {
 3524                            let to_insert;
 3525                            let entire_line;
 3526                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 3527                                let end_offset = start_offset + clipboard_selection.len;
 3528                                to_insert = &clipboard_text[start_offset..end_offset];
 3529                                entire_line = clipboard_selection.is_entire_line;
 3530                                start_offset = end_offset;
 3531                            } else {
 3532                                to_insert = clipboard_text.as_str();
 3533                                entire_line = all_selections_were_entire_line;
 3534                            }
 3535
 3536                            // If the corresponding selection was empty when this slice of the
 3537                            // clipboard text was written, then the entire line containing the
 3538                            // selection was copied. If this selection is also currently empty,
 3539                            // then paste the line before the current line of the buffer.
 3540                            let range = if selection.is_empty() && entire_line {
 3541                                let column = selection.start.to_point(&snapshot).column as usize;
 3542                                let line_start = selection.start - column;
 3543                                line_start..line_start
 3544                            } else {
 3545                                selection.start..selection.end
 3546                            };
 3547
 3548                            edits.push((range, to_insert));
 3549                        }
 3550                        drop(snapshot);
 3551                        buffer.edit_with_autoindent(edits, cx);
 3552                    });
 3553
 3554                    let selections = this.local_selections::<usize>(cx);
 3555                    this.update_selections(selections, Some(Autoscroll::Fit), cx);
 3556                } else {
 3557                    this.insert(&clipboard_text, cx);
 3558                }
 3559            }
 3560        });
 3561    }
 3562
 3563    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 3564        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 3565            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 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 redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 3574        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 3575            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 3576            {
 3577                self.set_selections(selections, None, true, cx);
 3578            }
 3579            self.request_autoscroll(Autoscroll::Fit, cx);
 3580            cx.emit(Event::Edited);
 3581        }
 3582    }
 3583
 3584    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 3585        self.buffer
 3586            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 3587    }
 3588
 3589    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 3590        self.move_selections(cx, |map, selection| {
 3591            let cursor = if selection.is_empty() {
 3592                movement::left(map, selection.start)
 3593            } else {
 3594                selection.start
 3595            };
 3596            selection.collapse_to(cursor, SelectionGoal::None);
 3597        });
 3598    }
 3599
 3600    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 3601        self.move_selection_heads(cx, |map, head, _| {
 3602            (movement::left(map, head), SelectionGoal::None)
 3603        });
 3604    }
 3605
 3606    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 3607        self.move_selections(cx, |map, selection| {
 3608            let cursor = if selection.is_empty() {
 3609                movement::right(map, selection.end)
 3610            } else {
 3611                selection.end
 3612            };
 3613            selection.collapse_to(cursor, SelectionGoal::None)
 3614        });
 3615    }
 3616
 3617    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 3618        self.move_selection_heads(cx, |map, head, _| {
 3619            (movement::right(map, head), SelectionGoal::None)
 3620        });
 3621    }
 3622
 3623    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 3624        if self.take_rename(true, cx).is_some() {
 3625            return;
 3626        }
 3627
 3628        if let Some(context_menu) = self.context_menu.as_mut() {
 3629            if context_menu.select_prev(cx) {
 3630                return;
 3631            }
 3632        }
 3633
 3634        if matches!(self.mode, EditorMode::SingleLine) {
 3635            cx.propagate_action();
 3636            return;
 3637        }
 3638
 3639        self.move_selections(cx, |map, selection| {
 3640            if !selection.is_empty() {
 3641                selection.goal = SelectionGoal::None;
 3642            }
 3643            let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false);
 3644            selection.collapse_to(cursor, goal);
 3645        });
 3646    }
 3647
 3648    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 3649        self.move_selection_heads(cx, |map, head, goal| movement::up(map, head, goal, false))
 3650    }
 3651
 3652    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 3653        self.take_rename(true, cx);
 3654
 3655        if let Some(context_menu) = self.context_menu.as_mut() {
 3656            if context_menu.select_next(cx) {
 3657                return;
 3658            }
 3659        }
 3660
 3661        if matches!(self.mode, EditorMode::SingleLine) {
 3662            cx.propagate_action();
 3663            return;
 3664        }
 3665
 3666        self.move_selections(cx, |map, selection| {
 3667            if !selection.is_empty() {
 3668                selection.goal = SelectionGoal::None;
 3669            }
 3670            let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false);
 3671            selection.collapse_to(cursor, goal);
 3672        });
 3673    }
 3674
 3675    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 3676        self.move_selection_heads(cx, |map, head, goal| movement::down(map, head, goal, false))
 3677    }
 3678
 3679    pub fn move_to_previous_word_start(
 3680        &mut self,
 3681        _: &MoveToPreviousWordStart,
 3682        cx: &mut ViewContext<Self>,
 3683    ) {
 3684        self.move_cursors(cx, |map, head, _| {
 3685            (
 3686                movement::previous_word_start(map, head),
 3687                SelectionGoal::None,
 3688            )
 3689        });
 3690    }
 3691
 3692    pub fn move_to_previous_subword_start(
 3693        &mut self,
 3694        _: &MoveToPreviousSubwordStart,
 3695        cx: &mut ViewContext<Self>,
 3696    ) {
 3697        self.move_cursors(cx, |map, head, _| {
 3698            (
 3699                movement::previous_subword_start(map, head),
 3700                SelectionGoal::None,
 3701            )
 3702        });
 3703    }
 3704
 3705    pub fn select_to_previous_word_start(
 3706        &mut self,
 3707        _: &SelectToPreviousWordStart,
 3708        cx: &mut ViewContext<Self>,
 3709    ) {
 3710        self.move_selection_heads(cx, |map, head, _| {
 3711            (
 3712                movement::previous_word_start(map, head),
 3713                SelectionGoal::None,
 3714            )
 3715        });
 3716    }
 3717
 3718    pub fn select_to_previous_subword_start(
 3719        &mut self,
 3720        _: &SelectToPreviousSubwordStart,
 3721        cx: &mut ViewContext<Self>,
 3722    ) {
 3723        self.move_selection_heads(cx, |map, head, _| {
 3724            (
 3725                movement::previous_subword_start(map, head),
 3726                SelectionGoal::None,
 3727            )
 3728        });
 3729    }
 3730
 3731    pub fn delete_to_previous_word_start(
 3732        &mut self,
 3733        _: &DeleteToPreviousWordStart,
 3734        cx: &mut ViewContext<Self>,
 3735    ) {
 3736        self.transact(cx, |this, cx| {
 3737            this.move_selections(cx, |map, selection| {
 3738                if selection.is_empty() {
 3739                    let cursor = movement::previous_word_start(map, selection.head());
 3740                    selection.set_head(cursor, SelectionGoal::None);
 3741                }
 3742            });
 3743            this.insert("", cx);
 3744        });
 3745    }
 3746
 3747    pub fn delete_to_previous_subword_start(
 3748        &mut self,
 3749        _: &DeleteToPreviousSubwordStart,
 3750        cx: &mut ViewContext<Self>,
 3751    ) {
 3752        self.transact(cx, |this, cx| {
 3753            this.move_selections(cx, |map, selection| {
 3754                if selection.is_empty() {
 3755                    let cursor = movement::previous_subword_start(map, selection.head());
 3756                    selection.set_head(cursor, SelectionGoal::None);
 3757                }
 3758            });
 3759            this.insert("", cx);
 3760        });
 3761    }
 3762
 3763    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 3764        self.move_cursors(cx, |map, head, _| {
 3765            (movement::next_word_end(map, head), SelectionGoal::None)
 3766        });
 3767    }
 3768
 3769    pub fn move_to_next_subword_end(
 3770        &mut self,
 3771        _: &MoveToNextSubwordEnd,
 3772        cx: &mut ViewContext<Self>,
 3773    ) {
 3774        self.move_cursors(cx, |map, head, _| {
 3775            (movement::next_subword_end(map, head), SelectionGoal::None)
 3776        });
 3777    }
 3778
 3779    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 3780        self.move_selection_heads(cx, |map, head, _| {
 3781            (movement::next_word_end(map, head), SelectionGoal::None)
 3782        });
 3783    }
 3784
 3785    pub fn select_to_next_subword_end(
 3786        &mut self,
 3787        _: &SelectToNextSubwordEnd,
 3788        cx: &mut ViewContext<Self>,
 3789    ) {
 3790        self.move_selection_heads(cx, |map, head, _| {
 3791            (movement::next_subword_end(map, head), SelectionGoal::None)
 3792        });
 3793    }
 3794
 3795    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 3796        self.transact(cx, |this, cx| {
 3797            this.move_selections(cx, |map, selection| {
 3798                if selection.is_empty() {
 3799                    let cursor = movement::next_word_end(map, selection.head());
 3800                    selection.set_head(cursor, SelectionGoal::None);
 3801                }
 3802            });
 3803            this.insert("", cx);
 3804        });
 3805    }
 3806
 3807    pub fn delete_to_next_subword_end(
 3808        &mut self,
 3809        _: &DeleteToNextSubwordEnd,
 3810        cx: &mut ViewContext<Self>,
 3811    ) {
 3812        self.transact(cx, |this, cx| {
 3813            this.move_selections(cx, |map, selection| {
 3814                if selection.is_empty() {
 3815                    let cursor = movement::next_subword_end(map, selection.head());
 3816                    selection.set_head(cursor, SelectionGoal::None);
 3817                }
 3818            });
 3819            this.insert("", cx);
 3820        });
 3821    }
 3822
 3823    pub fn move_to_beginning_of_line(
 3824        &mut self,
 3825        _: &MoveToBeginningOfLine,
 3826        cx: &mut ViewContext<Self>,
 3827    ) {
 3828        self.move_cursors(cx, |map, head, _| {
 3829            (
 3830                movement::line_beginning(map, head, true),
 3831                SelectionGoal::None,
 3832            )
 3833        });
 3834    }
 3835
 3836    pub fn select_to_beginning_of_line(
 3837        &mut self,
 3838        action: &SelectToBeginningOfLine,
 3839        cx: &mut ViewContext<Self>,
 3840    ) {
 3841        self.move_selection_heads(cx, |map, head, _| {
 3842            (
 3843                movement::line_beginning(map, head, action.stop_at_soft_wraps),
 3844                SelectionGoal::None,
 3845            )
 3846        });
 3847    }
 3848
 3849    pub fn delete_to_beginning_of_line(
 3850        &mut self,
 3851        _: &DeleteToBeginningOfLine,
 3852        cx: &mut ViewContext<Self>,
 3853    ) {
 3854        self.transact(cx, |this, cx| {
 3855            this.move_selections(cx, |_, selection| {
 3856                selection.reversed = true;
 3857            });
 3858
 3859            this.select_to_beginning_of_line(
 3860                &SelectToBeginningOfLine {
 3861                    stop_at_soft_wraps: false,
 3862                },
 3863                cx,
 3864            );
 3865            this.backspace(&Backspace, cx);
 3866        });
 3867    }
 3868
 3869    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 3870        self.move_cursors(cx, |map, head, _| {
 3871            (movement::line_end(map, head, true), SelectionGoal::None)
 3872        });
 3873    }
 3874
 3875    pub fn select_to_end_of_line(
 3876        &mut self,
 3877        action: &SelectToEndOfLine,
 3878        cx: &mut ViewContext<Self>,
 3879    ) {
 3880        self.move_selection_heads(cx, |map, head, _| {
 3881            (
 3882                movement::line_end(map, head, action.stop_at_soft_wraps),
 3883                SelectionGoal::None,
 3884            )
 3885        });
 3886    }
 3887
 3888    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 3889        self.transact(cx, |this, cx| {
 3890            this.select_to_end_of_line(
 3891                &SelectToEndOfLine {
 3892                    stop_at_soft_wraps: false,
 3893                },
 3894                cx,
 3895            );
 3896            this.delete(&Delete, cx);
 3897        });
 3898    }
 3899
 3900    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 3901        self.transact(cx, |this, cx| {
 3902            this.select_to_end_of_line(
 3903                &SelectToEndOfLine {
 3904                    stop_at_soft_wraps: false,
 3905                },
 3906                cx,
 3907            );
 3908            this.cut(&Cut, cx);
 3909        });
 3910    }
 3911
 3912    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 3913        if matches!(self.mode, EditorMode::SingleLine) {
 3914            cx.propagate_action();
 3915            return;
 3916        }
 3917
 3918        let selection = Selection {
 3919            id: post_inc(&mut self.next_selection_id),
 3920            start: 0,
 3921            end: 0,
 3922            reversed: false,
 3923            goal: SelectionGoal::None,
 3924        };
 3925        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3926    }
 3927
 3928    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 3929        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
 3930        selection.set_head(Point::zero(), SelectionGoal::None);
 3931        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3932    }
 3933
 3934    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 3935        if matches!(self.mode, EditorMode::SingleLine) {
 3936            cx.propagate_action();
 3937            return;
 3938        }
 3939
 3940        let cursor = self.buffer.read(cx).read(cx).len();
 3941        let selection = Selection {
 3942            id: post_inc(&mut self.next_selection_id),
 3943            start: cursor,
 3944            end: cursor,
 3945            reversed: false,
 3946            goal: SelectionGoal::None,
 3947        };
 3948        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3949    }
 3950
 3951    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 3952        self.nav_history = nav_history;
 3953    }
 3954
 3955    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 3956        self.nav_history.as_ref()
 3957    }
 3958
 3959    fn push_to_nav_history(
 3960        &self,
 3961        position: Anchor,
 3962        new_position: Option<Point>,
 3963        cx: &mut ViewContext<Self>,
 3964    ) {
 3965        if let Some(nav_history) = &self.nav_history {
 3966            let buffer = self.buffer.read(cx).read(cx);
 3967            let point = position.to_point(&buffer);
 3968            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
 3969            drop(buffer);
 3970
 3971            if let Some(new_position) = new_position {
 3972                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 3973                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 3974                    return;
 3975                }
 3976            }
 3977
 3978            nav_history.push(Some(NavigationData {
 3979                cursor_anchor: position,
 3980                cursor_position: point,
 3981                scroll_position: self.scroll_position,
 3982                scroll_top_anchor: self.scroll_top_anchor.clone(),
 3983                scroll_top_row,
 3984            }));
 3985        }
 3986    }
 3987
 3988    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 3989        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
 3990        selection.set_head(self.buffer.read(cx).read(cx).len(), SelectionGoal::None);
 3991        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3992    }
 3993
 3994    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 3995        let selection = Selection {
 3996            id: post_inc(&mut self.next_selection_id),
 3997            start: 0,
 3998            end: self.buffer.read(cx).read(cx).len(),
 3999            reversed: false,
 4000            goal: SelectionGoal::None,
 4001        };
 4002        self.update_selections(vec![selection], None, cx);
 4003    }
 4004
 4005    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 4006        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4007        let mut selections = self.local_selections::<Point>(cx);
 4008        let max_point = display_map.buffer_snapshot.max_point();
 4009        for selection in &mut selections {
 4010            let rows = selection.spanned_rows(true, &display_map);
 4011            selection.start = Point::new(rows.start, 0);
 4012            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 4013            selection.reversed = false;
 4014        }
 4015        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4016    }
 4017
 4018    pub fn split_selection_into_lines(
 4019        &mut self,
 4020        _: &SplitSelectionIntoLines,
 4021        cx: &mut ViewContext<Self>,
 4022    ) {
 4023        let mut to_unfold = Vec::new();
 4024        let mut new_selections = Vec::new();
 4025        {
 4026            let selections = self.local_selections::<Point>(cx);
 4027            let buffer = self.buffer.read(cx).read(cx);
 4028            for selection in selections {
 4029                for row in selection.start.row..selection.end.row {
 4030                    let cursor = Point::new(row, buffer.line_len(row));
 4031                    new_selections.push(Selection {
 4032                        id: post_inc(&mut self.next_selection_id),
 4033                        start: cursor,
 4034                        end: cursor,
 4035                        reversed: false,
 4036                        goal: SelectionGoal::None,
 4037                    });
 4038                }
 4039                new_selections.push(Selection {
 4040                    id: selection.id,
 4041                    start: selection.end,
 4042                    end: selection.end,
 4043                    reversed: false,
 4044                    goal: SelectionGoal::None,
 4045                });
 4046                to_unfold.push(selection.start..selection.end);
 4047            }
 4048        }
 4049        self.unfold_ranges(to_unfold, true, cx);
 4050        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4051    }
 4052
 4053    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 4054        self.add_selection(true, cx);
 4055    }
 4056
 4057    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 4058        self.add_selection(false, cx);
 4059    }
 4060
 4061    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 4062        self.push_to_selection_history();
 4063        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4064        let mut selections = self.local_selections::<Point>(cx);
 4065        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4066            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4067            let range = oldest_selection.display_range(&display_map).sorted();
 4068            let columns = cmp::min(range.start.column(), range.end.column())
 4069                ..cmp::max(range.start.column(), range.end.column());
 4070
 4071            selections.clear();
 4072            let mut stack = Vec::new();
 4073            for row in range.start.row()..=range.end.row() {
 4074                if let Some(selection) = self.build_columnar_selection(
 4075                    &display_map,
 4076                    row,
 4077                    &columns,
 4078                    oldest_selection.reversed,
 4079                ) {
 4080                    stack.push(selection.id);
 4081                    selections.push(selection);
 4082                }
 4083            }
 4084
 4085            if above {
 4086                stack.reverse();
 4087            }
 4088
 4089            AddSelectionsState { above, stack }
 4090        });
 4091
 4092        let last_added_selection = *state.stack.last().unwrap();
 4093        let mut new_selections = Vec::new();
 4094        if above == state.above {
 4095            let end_row = if above {
 4096                0
 4097            } else {
 4098                display_map.max_point().row()
 4099            };
 4100
 4101            'outer: for selection in selections {
 4102                if selection.id == last_added_selection {
 4103                    let range = selection.display_range(&display_map).sorted();
 4104                    debug_assert_eq!(range.start.row(), range.end.row());
 4105                    let mut row = range.start.row();
 4106                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4107                    {
 4108                        start..end
 4109                    } else {
 4110                        cmp::min(range.start.column(), range.end.column())
 4111                            ..cmp::max(range.start.column(), range.end.column())
 4112                    };
 4113
 4114                    while row != end_row {
 4115                        if above {
 4116                            row -= 1;
 4117                        } else {
 4118                            row += 1;
 4119                        }
 4120
 4121                        if let Some(new_selection) = self.build_columnar_selection(
 4122                            &display_map,
 4123                            row,
 4124                            &columns,
 4125                            selection.reversed,
 4126                        ) {
 4127                            state.stack.push(new_selection.id);
 4128                            if above {
 4129                                new_selections.push(new_selection);
 4130                                new_selections.push(selection);
 4131                            } else {
 4132                                new_selections.push(selection);
 4133                                new_selections.push(new_selection);
 4134                            }
 4135
 4136                            continue 'outer;
 4137                        }
 4138                    }
 4139                }
 4140
 4141                new_selections.push(selection);
 4142            }
 4143        } else {
 4144            new_selections = selections;
 4145            new_selections.retain(|s| s.id != last_added_selection);
 4146            state.stack.pop();
 4147        }
 4148
 4149        self.update_selections(new_selections, Some(Autoscroll::Newest), cx);
 4150        if state.stack.len() > 1 {
 4151            self.add_selections_state = Some(state);
 4152        }
 4153    }
 4154
 4155    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4156        self.push_to_selection_history();
 4157        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4158        let buffer = &display_map.buffer_snapshot;
 4159        let mut selections = self.local_selections::<usize>(cx);
 4160        if let Some(mut select_next_state) = self.select_next_state.take() {
 4161            let query = &select_next_state.query;
 4162            if !select_next_state.done {
 4163                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4164                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4165                let mut next_selected_range = None;
 4166
 4167                let bytes_after_last_selection =
 4168                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4169                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4170                let query_matches = query
 4171                    .stream_find_iter(bytes_after_last_selection)
 4172                    .map(|result| (last_selection.end, result))
 4173                    .chain(
 4174                        query
 4175                            .stream_find_iter(bytes_before_first_selection)
 4176                            .map(|result| (0, result)),
 4177                    );
 4178                for (start_offset, query_match) in query_matches {
 4179                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4180                    let offset_range =
 4181                        start_offset + query_match.start()..start_offset + query_match.end();
 4182                    let display_range = offset_range.start.to_display_point(&display_map)
 4183                        ..offset_range.end.to_display_point(&display_map);
 4184
 4185                    if !select_next_state.wordwise
 4186                        || (!movement::is_inside_word(&display_map, display_range.start)
 4187                            && !movement::is_inside_word(&display_map, display_range.end))
 4188                    {
 4189                        next_selected_range = Some(offset_range);
 4190                        break;
 4191                    }
 4192                }
 4193
 4194                if let Some(next_selected_range) = next_selected_range {
 4195                    if action.replace_newest {
 4196                        if let Some(newest_id) =
 4197                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
 4198                        {
 4199                            selections.retain(|s| s.id != newest_id);
 4200                        }
 4201                    }
 4202                    selections.push(Selection {
 4203                        id: post_inc(&mut self.next_selection_id),
 4204                        start: next_selected_range.start,
 4205                        end: next_selected_range.end,
 4206                        reversed: false,
 4207                        goal: SelectionGoal::None,
 4208                    });
 4209                    self.unfold_ranges([next_selected_range], false, cx);
 4210                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4211                } else {
 4212                    select_next_state.done = true;
 4213                }
 4214            }
 4215
 4216            self.select_next_state = Some(select_next_state);
 4217        } else if selections.len() == 1 {
 4218            let selection = selections.last_mut().unwrap();
 4219            if selection.start == selection.end {
 4220                let word_range = movement::surrounding_word(
 4221                    &display_map,
 4222                    selection.start.to_display_point(&display_map),
 4223                );
 4224                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4225                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4226                selection.goal = SelectionGoal::None;
 4227                selection.reversed = false;
 4228
 4229                let query = buffer
 4230                    .text_for_range(selection.start..selection.end)
 4231                    .collect::<String>();
 4232                let select_state = SelectNextState {
 4233                    query: AhoCorasick::new_auto_configured(&[query]),
 4234                    wordwise: true,
 4235                    done: false,
 4236                };
 4237                self.unfold_ranges([selection.start..selection.end], false, cx);
 4238                self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4239                self.select_next_state = Some(select_state);
 4240            } else {
 4241                let query = buffer
 4242                    .text_for_range(selection.start..selection.end)
 4243                    .collect::<String>();
 4244                self.select_next_state = Some(SelectNextState {
 4245                    query: AhoCorasick::new_auto_configured(&[query]),
 4246                    wordwise: false,
 4247                    done: false,
 4248                });
 4249                self.select_next(action, cx);
 4250            }
 4251        }
 4252    }
 4253
 4254    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4255        self.transact(cx, |this, cx| {
 4256            let mut selections = this.local_selections::<Point>(cx);
 4257            let mut all_selection_lines_are_comments = true;
 4258            let mut edit_ranges = Vec::new();
 4259            let mut last_toggled_row = None;
 4260            this.buffer.update(cx, |buffer, cx| {
 4261                // TODO: Handle selections that cross excerpts
 4262                for selection in &mut selections {
 4263                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
 4264                    // as that portion won't be used for detecting if a line is a comment.
 4265                    let full_comment_prefix: Arc<str> = if let Some(prefix) = buffer
 4266                        .language_at(selection.start, cx)
 4267                        .and_then(|l| l.line_comment_prefix())
 4268                    {
 4269                        prefix.into()
 4270                    } else {
 4271                        return;
 4272                    };
 4273                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4274                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4275                    edit_ranges.clear();
 4276                    let snapshot = buffer.snapshot(cx);
 4277
 4278                    let end_row =
 4279                        if selection.end.row > selection.start.row && selection.end.column == 0 {
 4280                            selection.end.row
 4281                        } else {
 4282                            selection.end.row + 1
 4283                        };
 4284
 4285                    for row in selection.start.row..end_row {
 4286                        // If multiple selections contain a given row, avoid processing that
 4287                        // row more than once.
 4288                        if last_toggled_row == Some(row) {
 4289                            continue;
 4290                        } else {
 4291                            last_toggled_row = Some(row);
 4292                        }
 4293
 4294                        if snapshot.is_line_blank(row) {
 4295                            continue;
 4296                        }
 4297
 4298                        let start = Point::new(row, snapshot.indent_column_for_line(row));
 4299                        let mut line_bytes = snapshot
 4300                            .bytes_in_range(start..snapshot.max_point())
 4301                            .flatten()
 4302                            .copied();
 4303
 4304                        // If this line currently begins with the line comment prefix, then record
 4305                        // the range containing the prefix.
 4306                        if all_selection_lines_are_comments
 4307                            && line_bytes
 4308                                .by_ref()
 4309                                .take(comment_prefix.len())
 4310                                .eq(comment_prefix.bytes())
 4311                        {
 4312                            // Include any whitespace that matches the comment prefix.
 4313                            let matching_whitespace_len = line_bytes
 4314                                .zip(comment_prefix_whitespace.bytes())
 4315                                .take_while(|(a, b)| a == b)
 4316                                .count()
 4317                                as u32;
 4318                            let end = Point::new(
 4319                                row,
 4320                                start.column
 4321                                    + comment_prefix.len() as u32
 4322                                    + matching_whitespace_len,
 4323                            );
 4324                            edit_ranges.push(start..end);
 4325                        }
 4326                        // If this line does not begin with the line comment prefix, then record
 4327                        // the position where the prefix should be inserted.
 4328                        else {
 4329                            all_selection_lines_are_comments = false;
 4330                            edit_ranges.push(start..start);
 4331                        }
 4332                    }
 4333
 4334                    if !edit_ranges.is_empty() {
 4335                        if all_selection_lines_are_comments {
 4336                            let empty_str: Arc<str> = "".into();
 4337                            buffer.edit(
 4338                                edit_ranges
 4339                                    .iter()
 4340                                    .cloned()
 4341                                    .map(|range| (range, empty_str.clone())),
 4342                                cx,
 4343                            );
 4344                        } else {
 4345                            let min_column =
 4346                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
 4347                            let edits = edit_ranges.iter().map(|range| {
 4348                                let position = Point::new(range.start.row, min_column);
 4349                                (position..position, full_comment_prefix.clone())
 4350                            });
 4351                            buffer.edit(edits, cx);
 4352                        }
 4353                    }
 4354                }
 4355            });
 4356
 4357            this.update_selections(
 4358                this.local_selections::<usize>(cx),
 4359                Some(Autoscroll::Fit),
 4360                cx,
 4361            );
 4362        });
 4363    }
 4364
 4365    pub fn select_larger_syntax_node(
 4366        &mut self,
 4367        _: &SelectLargerSyntaxNode,
 4368        cx: &mut ViewContext<Self>,
 4369    ) {
 4370        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
 4371        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4372        let buffer = self.buffer.read(cx).snapshot(cx);
 4373
 4374        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4375        let mut selected_larger_node = false;
 4376        let new_selections = old_selections
 4377            .iter()
 4378            .map(|selection| {
 4379                let old_range = selection.start..selection.end;
 4380                let mut new_range = old_range.clone();
 4381                while let Some(containing_range) =
 4382                    buffer.range_for_syntax_ancestor(new_range.clone())
 4383                {
 4384                    new_range = containing_range;
 4385                    if !display_map.intersects_fold(new_range.start)
 4386                        && !display_map.intersects_fold(new_range.end)
 4387                    {
 4388                        break;
 4389                    }
 4390                }
 4391
 4392                selected_larger_node |= new_range != old_range;
 4393                Selection {
 4394                    id: selection.id,
 4395                    start: new_range.start,
 4396                    end: new_range.end,
 4397                    goal: SelectionGoal::None,
 4398                    reversed: selection.reversed,
 4399                }
 4400            })
 4401            .collect::<Vec<_>>();
 4402
 4403        if selected_larger_node {
 4404            stack.push(old_selections);
 4405            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4406        }
 4407        self.select_larger_syntax_node_stack = stack;
 4408    }
 4409
 4410    pub fn select_smaller_syntax_node(
 4411        &mut self,
 4412        _: &SelectSmallerSyntaxNode,
 4413        cx: &mut ViewContext<Self>,
 4414    ) {
 4415        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4416        if let Some(selections) = stack.pop() {
 4417            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
 4418        }
 4419        self.select_larger_syntax_node_stack = stack;
 4420    }
 4421
 4422    pub fn move_to_enclosing_bracket(
 4423        &mut self,
 4424        _: &MoveToEnclosingBracket,
 4425        cx: &mut ViewContext<Self>,
 4426    ) {
 4427        let mut selections = self.local_selections::<usize>(cx);
 4428        let buffer = self.buffer.read(cx).snapshot(cx);
 4429        for selection in &mut selections {
 4430            if let Some((open_range, close_range)) =
 4431                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4432            {
 4433                let close_range = close_range.to_inclusive();
 4434                let destination = if close_range.contains(&selection.start)
 4435                    && close_range.contains(&selection.end)
 4436                {
 4437                    open_range.end
 4438                } else {
 4439                    *close_range.start()
 4440                };
 4441                selection.start = destination;
 4442                selection.end = destination;
 4443            }
 4444        }
 4445
 4446        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4447    }
 4448
 4449    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4450        self.end_selection(cx);
 4451        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4452        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4453            self.set_selections(entry.selections, None, true, cx);
 4454            self.select_next_state = entry.select_next_state;
 4455            self.add_selections_state = entry.add_selections_state;
 4456            self.request_autoscroll(Autoscroll::Newest, cx);
 4457        }
 4458        self.selection_history.mode = SelectionHistoryMode::Normal;
 4459    }
 4460
 4461    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4462        self.end_selection(cx);
 4463        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4464        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4465            self.set_selections(entry.selections, None, true, cx);
 4466            self.select_next_state = entry.select_next_state;
 4467            self.add_selections_state = entry.add_selections_state;
 4468            self.request_autoscroll(Autoscroll::Newest, cx);
 4469        }
 4470        self.selection_history.mode = SelectionHistoryMode::Normal;
 4471    }
 4472
 4473    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
 4474        self.go_to_diagnostic(Direction::Next, cx)
 4475    }
 4476
 4477    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4478        self.go_to_diagnostic(Direction::Prev, cx)
 4479    }
 4480
 4481    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4482        let buffer = self.buffer.read(cx).snapshot(cx);
 4483        let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
 4484        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4485            active_diagnostics
 4486                .primary_range
 4487                .to_offset(&buffer)
 4488                .to_inclusive()
 4489        });
 4490        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4491            if active_primary_range.contains(&selection.head()) {
 4492                *active_primary_range.end()
 4493            } else {
 4494                selection.head()
 4495            }
 4496        } else {
 4497            selection.head()
 4498        };
 4499
 4500        loop {
 4501            let mut diagnostics = if direction == Direction::Prev {
 4502                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4503            } else {
 4504                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4505            };
 4506            let group = diagnostics.find_map(|entry| {
 4507                if entry.diagnostic.is_primary
 4508                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4509                    && !entry.range.is_empty()
 4510                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4511                {
 4512                    Some((entry.range, entry.diagnostic.group_id))
 4513                } else {
 4514                    None
 4515                }
 4516            });
 4517
 4518            if let Some((primary_range, group_id)) = group {
 4519                self.activate_diagnostics(group_id, cx);
 4520                self.update_selections(
 4521                    vec![Selection {
 4522                        id: selection.id,
 4523                        start: primary_range.start,
 4524                        end: primary_range.start,
 4525                        reversed: false,
 4526                        goal: SelectionGoal::None,
 4527                    }],
 4528                    Some(Autoscroll::Center),
 4529                    cx,
 4530                );
 4531                break;
 4532            } else {
 4533                // Cycle around to the start of the buffer, potentially moving back to the start of
 4534                // the currently active diagnostic.
 4535                active_primary_range.take();
 4536                if direction == Direction::Prev {
 4537                    if search_start == buffer.len() {
 4538                        break;
 4539                    } else {
 4540                        search_start = buffer.len();
 4541                    }
 4542                } else {
 4543                    if search_start == 0 {
 4544                        break;
 4545                    } else {
 4546                        search_start = 0;
 4547                    }
 4548                }
 4549            }
 4550        }
 4551    }
 4552
 4553    pub fn go_to_definition(
 4554        workspace: &mut Workspace,
 4555        _: &GoToDefinition,
 4556        cx: &mut ViewContext<Workspace>,
 4557    ) {
 4558        let active_item = workspace.active_item(cx);
 4559        let editor_handle = if let Some(editor) = active_item
 4560            .as_ref()
 4561            .and_then(|item| item.act_as::<Self>(cx))
 4562        {
 4563            editor
 4564        } else {
 4565            return;
 4566        };
 4567
 4568        let editor = editor_handle.read(cx);
 4569        let head = editor.newest_selection::<usize>(cx).head();
 4570        let (buffer, head) =
 4571            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
 4572                text_anchor
 4573            } else {
 4574                return;
 4575            };
 4576
 4577        let project = workspace.project().clone();
 4578        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
 4579        cx.spawn(|workspace, mut cx| async move {
 4580            let definitions = definitions.await?;
 4581            workspace.update(&mut cx, |workspace, cx| {
 4582                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 4583                for definition in definitions {
 4584                    let range = definition.range.to_offset(definition.buffer.read(cx));
 4585
 4586                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
 4587                    target_editor_handle.update(cx, |target_editor, cx| {
 4588                        // When selecting a definition in a different buffer, disable the nav history
 4589                        // to avoid creating a history entry at the previous cursor location.
 4590                        if editor_handle != target_editor_handle {
 4591                            nav_history.borrow_mut().disable();
 4592                        }
 4593                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
 4594                        nav_history.borrow_mut().enable();
 4595                    });
 4596                }
 4597            });
 4598
 4599            Ok::<(), anyhow::Error>(())
 4600        })
 4601        .detach_and_log_err(cx);
 4602    }
 4603
 4604    pub fn find_all_references(
 4605        workspace: &mut Workspace,
 4606        _: &FindAllReferences,
 4607        cx: &mut ViewContext<Workspace>,
 4608    ) -> Option<Task<Result<()>>> {
 4609        let active_item = workspace.active_item(cx)?;
 4610        let editor_handle = active_item.act_as::<Self>(cx)?;
 4611
 4612        let editor = editor_handle.read(cx);
 4613        let head = editor.newest_selection::<usize>(cx).head();
 4614        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
 4615        let replica_id = editor.replica_id(cx);
 4616
 4617        let project = workspace.project().clone();
 4618        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4619        Some(cx.spawn(|workspace, mut cx| async move {
 4620            let mut locations = references.await?;
 4621            if locations.is_empty() {
 4622                return Ok(());
 4623            }
 4624
 4625            locations.sort_by_key(|location| location.buffer.id());
 4626            let mut locations = locations.into_iter().peekable();
 4627            let mut ranges_to_highlight = Vec::new();
 4628
 4629            let excerpt_buffer = cx.add_model(|cx| {
 4630                let mut symbol_name = None;
 4631                let mut multibuffer = MultiBuffer::new(replica_id);
 4632                while let Some(location) = locations.next() {
 4633                    let buffer = location.buffer.read(cx);
 4634                    let mut ranges_for_buffer = Vec::new();
 4635                    let range = location.range.to_offset(buffer);
 4636                    ranges_for_buffer.push(range.clone());
 4637                    if symbol_name.is_none() {
 4638                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4639                    }
 4640
 4641                    while let Some(next_location) = locations.peek() {
 4642                        if next_location.buffer == location.buffer {
 4643                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4644                            locations.next();
 4645                        } else {
 4646                            break;
 4647                        }
 4648                    }
 4649
 4650                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4651                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4652                        location.buffer.clone(),
 4653                        ranges_for_buffer,
 4654                        1,
 4655                        cx,
 4656                    ));
 4657                }
 4658                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4659            });
 4660
 4661            workspace.update(&mut cx, |workspace, cx| {
 4662                let editor =
 4663                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4664                editor.update(cx, |editor, cx| {
 4665                    editor.highlight_background::<Self>(
 4666                        ranges_to_highlight,
 4667                        |theme| theme.editor.highlighted_line_background,
 4668                        cx,
 4669                    );
 4670                });
 4671                workspace.add_item(Box::new(editor), cx);
 4672            });
 4673
 4674            Ok(())
 4675        }))
 4676    }
 4677
 4678    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4679        use language::ToOffset as _;
 4680
 4681        let project = self.project.clone()?;
 4682        let selection = self.newest_anchor_selection().clone();
 4683        let (cursor_buffer, cursor_buffer_position) = self
 4684            .buffer
 4685            .read(cx)
 4686            .text_anchor_for_position(selection.head(), cx)?;
 4687        let (tail_buffer, _) = self
 4688            .buffer
 4689            .read(cx)
 4690            .text_anchor_for_position(selection.tail(), cx)?;
 4691        if tail_buffer != cursor_buffer {
 4692            return None;
 4693        }
 4694
 4695        let snapshot = cursor_buffer.read(cx).snapshot();
 4696        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4697        let prepare_rename = project.update(cx, |project, cx| {
 4698            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4699        });
 4700
 4701        Some(cx.spawn(|this, mut cx| async move {
 4702            let rename_range = if let Some(range) = prepare_rename.await? {
 4703                Some(range)
 4704            } else {
 4705                this.read_with(&cx, |this, cx| {
 4706                    let buffer = this.buffer.read(cx).snapshot(cx);
 4707                    let mut buffer_highlights = this
 4708                        .document_highlights_for_position(selection.head(), &buffer)
 4709                        .filter(|highlight| {
 4710                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4711                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4712                        });
 4713                    buffer_highlights
 4714                        .next()
 4715                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4716                })
 4717            };
 4718            if let Some(rename_range) = rename_range {
 4719                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4720                let cursor_offset_in_rename_range =
 4721                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4722
 4723                this.update(&mut cx, |this, cx| {
 4724                    this.take_rename(false, cx);
 4725                    let style = this.style(cx);
 4726                    let buffer = this.buffer.read(cx).read(cx);
 4727                    let cursor_offset = selection.head().to_offset(&buffer);
 4728                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4729                    let rename_end = rename_start + rename_buffer_range.len();
 4730                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4731                    let mut old_highlight_id = None;
 4732                    let old_name: Arc<str> = buffer
 4733                        .chunks(rename_start..rename_end, true)
 4734                        .map(|chunk| {
 4735                            if old_highlight_id.is_none() {
 4736                                old_highlight_id = chunk.syntax_highlight_id;
 4737                            }
 4738                            chunk.text
 4739                        })
 4740                        .collect::<String>()
 4741                        .into();
 4742
 4743                    drop(buffer);
 4744
 4745                    // Position the selection in the rename editor so that it matches the current selection.
 4746                    this.show_local_selections = false;
 4747                    let rename_editor = cx.add_view(|cx| {
 4748                        let mut editor = Editor::single_line(None, cx);
 4749                        if let Some(old_highlight_id) = old_highlight_id {
 4750                            editor.override_text_style =
 4751                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4752                        }
 4753                        editor
 4754                            .buffer
 4755                            .update(cx, |buffer, cx| buffer.edit([(0..0, old_name.clone())], cx));
 4756                        editor.select_all(&SelectAll, cx);
 4757                        editor
 4758                    });
 4759
 4760                    let ranges = this
 4761                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4762                        .into_iter()
 4763                        .flat_map(|(_, ranges)| ranges)
 4764                        .chain(
 4765                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4766                                .into_iter()
 4767                                .flat_map(|(_, ranges)| ranges),
 4768                        )
 4769                        .collect();
 4770
 4771                    this.highlight_text::<Rename>(
 4772                        ranges,
 4773                        HighlightStyle {
 4774                            fade_out: Some(style.rename_fade),
 4775                            ..Default::default()
 4776                        },
 4777                        cx,
 4778                    );
 4779                    cx.focus(&rename_editor);
 4780                    let block_id = this.insert_blocks(
 4781                        [BlockProperties {
 4782                            position: range.start.clone(),
 4783                            height: 1,
 4784                            render: Arc::new({
 4785                                let editor = rename_editor.clone();
 4786                                move |cx: &BlockContext| {
 4787                                    ChildView::new(editor.clone())
 4788                                        .contained()
 4789                                        .with_padding_left(cx.anchor_x)
 4790                                        .boxed()
 4791                                }
 4792                            }),
 4793                            disposition: BlockDisposition::Below,
 4794                        }],
 4795                        cx,
 4796                    )[0];
 4797                    this.pending_rename = Some(RenameState {
 4798                        range,
 4799                        old_name,
 4800                        editor: rename_editor,
 4801                        block_id,
 4802                    });
 4803                });
 4804            }
 4805
 4806            Ok(())
 4807        }))
 4808    }
 4809
 4810    pub fn confirm_rename(
 4811        workspace: &mut Workspace,
 4812        _: &ConfirmRename,
 4813        cx: &mut ViewContext<Workspace>,
 4814    ) -> Option<Task<Result<()>>> {
 4815        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4816
 4817        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4818            let rename = editor.take_rename(false, cx)?;
 4819            let buffer = editor.buffer.read(cx);
 4820            let (start_buffer, start) =
 4821                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4822            let (end_buffer, end) =
 4823                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4824            if start_buffer == end_buffer {
 4825                let new_name = rename.editor.read(cx).text(cx);
 4826                Some((start_buffer, start..end, rename.old_name, new_name))
 4827            } else {
 4828                None
 4829            }
 4830        })?;
 4831
 4832        let rename = workspace.project().clone().update(cx, |project, cx| {
 4833            project.perform_rename(
 4834                buffer.clone(),
 4835                range.start.clone(),
 4836                new_name.clone(),
 4837                true,
 4838                cx,
 4839            )
 4840        });
 4841
 4842        Some(cx.spawn(|workspace, mut cx| async move {
 4843            let project_transaction = rename.await?;
 4844            Self::open_project_transaction(
 4845                editor.clone(),
 4846                workspace,
 4847                project_transaction,
 4848                format!("Rename: {}{}", old_name, new_name),
 4849                cx.clone(),
 4850            )
 4851            .await?;
 4852
 4853            editor.update(&mut cx, |editor, cx| {
 4854                editor.refresh_document_highlights(cx);
 4855            });
 4856            Ok(())
 4857        }))
 4858    }
 4859
 4860    fn take_rename(
 4861        &mut self,
 4862        moving_cursor: bool,
 4863        cx: &mut ViewContext<Self>,
 4864    ) -> Option<RenameState> {
 4865        let rename = self.pending_rename.take()?;
 4866        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4867        self.clear_text_highlights::<Rename>(cx);
 4868        self.show_local_selections = true;
 4869
 4870        if moving_cursor {
 4871            let cursor_in_rename_editor =
 4872                rename.editor.read(cx).newest_selection::<usize>(cx).head();
 4873
 4874            // Update the selection to match the position of the selection inside
 4875            // the rename editor.
 4876            let snapshot = self.buffer.read(cx).read(cx);
 4877            let rename_range = rename.range.to_offset(&snapshot);
 4878            let cursor_in_editor = snapshot
 4879                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4880                .min(rename_range.end);
 4881            drop(snapshot);
 4882
 4883            self.update_selections(
 4884                vec![Selection {
 4885                    id: self.newest_anchor_selection().id,
 4886                    start: cursor_in_editor,
 4887                    end: cursor_in_editor,
 4888                    reversed: false,
 4889                    goal: SelectionGoal::None,
 4890                }],
 4891                None,
 4892                cx,
 4893            );
 4894        }
 4895
 4896        Some(rename)
 4897    }
 4898
 4899    #[cfg(any(test, feature = "test-support"))]
 4900    pub fn pending_rename(&self) -> Option<&RenameState> {
 4901        self.pending_rename.as_ref()
 4902    }
 4903
 4904    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4905        if let Some(project) = self.project.clone() {
 4906            self.buffer.update(cx, |multi_buffer, cx| {
 4907                project.update(cx, |project, cx| {
 4908                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4909                });
 4910            })
 4911        }
 4912    }
 4913
 4914    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4915        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4916            let buffer = self.buffer.read(cx).snapshot(cx);
 4917            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4918            let is_valid = buffer
 4919                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4920                .any(|entry| {
 4921                    entry.diagnostic.is_primary
 4922                        && !entry.range.is_empty()
 4923                        && entry.range.start == primary_range_start
 4924                        && entry.diagnostic.message == active_diagnostics.primary_message
 4925                });
 4926
 4927            if is_valid != active_diagnostics.is_valid {
 4928                active_diagnostics.is_valid = is_valid;
 4929                let mut new_styles = HashMap::default();
 4930                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4931                    new_styles.insert(
 4932                        *block_id,
 4933                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4934                    );
 4935                }
 4936                self.display_map
 4937                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4938            }
 4939        }
 4940    }
 4941
 4942    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4943        self.dismiss_diagnostics(cx);
 4944        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4945            let buffer = self.buffer.read(cx).snapshot(cx);
 4946
 4947            let mut primary_range = None;
 4948            let mut primary_message = None;
 4949            let mut group_end = Point::zero();
 4950            let diagnostic_group = buffer
 4951                .diagnostic_group::<Point>(group_id)
 4952                .map(|entry| {
 4953                    if entry.range.end > group_end {
 4954                        group_end = entry.range.end;
 4955                    }
 4956                    if entry.diagnostic.is_primary {
 4957                        primary_range = Some(entry.range.clone());
 4958                        primary_message = Some(entry.diagnostic.message.clone());
 4959                    }
 4960                    entry
 4961                })
 4962                .collect::<Vec<_>>();
 4963            let primary_range = primary_range.unwrap();
 4964            let primary_message = primary_message.unwrap();
 4965            let primary_range =
 4966                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 4967
 4968            let blocks = display_map
 4969                .insert_blocks(
 4970                    diagnostic_group.iter().map(|entry| {
 4971                        let diagnostic = entry.diagnostic.clone();
 4972                        let message_height = diagnostic.message.lines().count() as u8;
 4973                        BlockProperties {
 4974                            position: buffer.anchor_after(entry.range.start),
 4975                            height: message_height,
 4976                            render: diagnostic_block_renderer(diagnostic, true),
 4977                            disposition: BlockDisposition::Below,
 4978                        }
 4979                    }),
 4980                    cx,
 4981                )
 4982                .into_iter()
 4983                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 4984                .collect();
 4985
 4986            Some(ActiveDiagnosticGroup {
 4987                primary_range,
 4988                primary_message,
 4989                blocks,
 4990                is_valid: true,
 4991            })
 4992        });
 4993    }
 4994
 4995    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 4996        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 4997            self.display_map.update(cx, |display_map, cx| {
 4998                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 4999            });
 5000            cx.notify();
 5001        }
 5002    }
 5003
 5004    fn build_columnar_selection(
 5005        &mut self,
 5006        display_map: &DisplaySnapshot,
 5007        row: u32,
 5008        columns: &Range<u32>,
 5009        reversed: bool,
 5010    ) -> Option<Selection<Point>> {
 5011        let is_empty = columns.start == columns.end;
 5012        let line_len = display_map.line_len(row);
 5013        if columns.start < line_len || (is_empty && columns.start == line_len) {
 5014            let start = DisplayPoint::new(row, columns.start);
 5015            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
 5016            Some(Selection {
 5017                id: post_inc(&mut self.next_selection_id),
 5018                start: start.to_point(display_map),
 5019                end: end.to_point(display_map),
 5020                reversed,
 5021                goal: SelectionGoal::ColumnRange {
 5022                    start: columns.start,
 5023                    end: columns.end,
 5024                },
 5025            })
 5026        } else {
 5027            None
 5028        }
 5029    }
 5030
 5031    pub fn local_selections_in_range(
 5032        &self,
 5033        range: Range<Anchor>,
 5034        display_map: &DisplaySnapshot,
 5035    ) -> Vec<Selection<Point>> {
 5036        let buffer = &display_map.buffer_snapshot;
 5037
 5038        let start_ix = match self
 5039            .selections
 5040            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
 5041        {
 5042            Ok(ix) | Err(ix) => ix,
 5043        };
 5044        let end_ix = match self
 5045            .selections
 5046            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
 5047        {
 5048            Ok(ix) => ix + 1,
 5049            Err(ix) => ix,
 5050        };
 5051
 5052        fn point_selection(
 5053            selection: &Selection<Anchor>,
 5054            buffer: &MultiBufferSnapshot,
 5055        ) -> Selection<Point> {
 5056            let start = selection.start.to_point(&buffer);
 5057            let end = selection.end.to_point(&buffer);
 5058            Selection {
 5059                id: selection.id,
 5060                start,
 5061                end,
 5062                reversed: selection.reversed,
 5063                goal: selection.goal,
 5064            }
 5065        }
 5066
 5067        self.selections[start_ix..end_ix]
 5068            .iter()
 5069            .chain(
 5070                self.pending_selection
 5071                    .as_ref()
 5072                    .map(|pending| &pending.selection),
 5073            )
 5074            .map(|s| point_selection(s, &buffer))
 5075            .collect()
 5076    }
 5077
 5078    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
 5079    where
 5080        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
 5081    {
 5082        let buffer = self.buffer.read(cx).snapshot(cx);
 5083        let mut selections = self
 5084            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
 5085            .peekable();
 5086
 5087        let mut pending_selection = self.pending_selection::<D>(&buffer);
 5088
 5089        iter::from_fn(move || {
 5090            if let Some(pending) = pending_selection.as_mut() {
 5091                while let Some(next_selection) = selections.peek() {
 5092                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 5093                        let next_selection = selections.next().unwrap();
 5094                        if next_selection.start < pending.start {
 5095                            pending.start = next_selection.start;
 5096                        }
 5097                        if next_selection.end > pending.end {
 5098                            pending.end = next_selection.end;
 5099                        }
 5100                    } else if next_selection.end < pending.start {
 5101                        return selections.next();
 5102                    } else {
 5103                        break;
 5104                    }
 5105                }
 5106
 5107                pending_selection.take()
 5108            } else {
 5109                selections.next()
 5110            }
 5111        })
 5112        .collect()
 5113    }
 5114
 5115    fn resolve_selections<'a, D, I>(
 5116        &self,
 5117        selections: I,
 5118        snapshot: &MultiBufferSnapshot,
 5119    ) -> impl 'a + Iterator<Item = Selection<D>>
 5120    where
 5121        D: TextDimension + Ord + Sub<D, Output = D>,
 5122        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 5123    {
 5124        let (to_summarize, selections) = selections.into_iter().tee();
 5125        let mut summaries = snapshot
 5126            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
 5127            .into_iter();
 5128        selections.map(move |s| Selection {
 5129            id: s.id,
 5130            start: summaries.next().unwrap(),
 5131            end: summaries.next().unwrap(),
 5132            reversed: s.reversed,
 5133            goal: s.goal,
 5134        })
 5135    }
 5136
 5137    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5138        &self,
 5139        snapshot: &MultiBufferSnapshot,
 5140    ) -> Option<Selection<D>> {
 5141        self.pending_selection
 5142            .as_ref()
 5143            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
 5144    }
 5145
 5146    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5147        &self,
 5148        selection: &Selection<Anchor>,
 5149        buffer: &MultiBufferSnapshot,
 5150    ) -> Selection<D> {
 5151        Selection {
 5152            id: selection.id,
 5153            start: selection.start.summary::<D>(&buffer),
 5154            end: selection.end.summary::<D>(&buffer),
 5155            reversed: selection.reversed,
 5156            goal: selection.goal,
 5157        }
 5158    }
 5159
 5160    fn selection_count<'a>(&self) -> usize {
 5161        let mut count = self.selections.len();
 5162        if self.pending_selection.is_some() {
 5163            count += 1;
 5164        }
 5165        count
 5166    }
 5167
 5168    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5169        &self,
 5170        cx: &AppContext,
 5171    ) -> Selection<D> {
 5172        let snapshot = self.buffer.read(cx).read(cx);
 5173        self.selections
 5174            .iter()
 5175            .min_by_key(|s| s.id)
 5176            .map(|selection| self.resolve_selection(selection, &snapshot))
 5177            .or_else(|| self.pending_selection(&snapshot))
 5178            .unwrap()
 5179    }
 5180
 5181    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5182        &self,
 5183        cx: &AppContext,
 5184    ) -> Selection<D> {
 5185        self.resolve_selection(
 5186            self.newest_anchor_selection(),
 5187            &self.buffer.read(cx).read(cx),
 5188        )
 5189    }
 5190
 5191    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
 5192        &self,
 5193        snapshot: &MultiBufferSnapshot,
 5194    ) -> Selection<D> {
 5195        self.resolve_selection(self.newest_anchor_selection(), snapshot)
 5196    }
 5197
 5198    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
 5199        self.pending_selection
 5200            .as_ref()
 5201            .map(|s| &s.selection)
 5202            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
 5203            .unwrap()
 5204    }
 5205
 5206    pub fn update_selections<T>(
 5207        &mut self,
 5208        mut selections: Vec<Selection<T>>,
 5209        autoscroll: Option<Autoscroll>,
 5210        cx: &mut ViewContext<Self>,
 5211    ) where
 5212        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
 5213    {
 5214        let buffer = self.buffer.read(cx).snapshot(cx);
 5215        selections.sort_unstable_by_key(|s| s.start);
 5216
 5217        // Merge overlapping selections.
 5218        let mut i = 1;
 5219        while i < selections.len() {
 5220            if selections[i - 1].end >= selections[i].start {
 5221                let removed = selections.remove(i);
 5222                if removed.start < selections[i - 1].start {
 5223                    selections[i - 1].start = removed.start;
 5224                }
 5225                if removed.end > selections[i - 1].end {
 5226                    selections[i - 1].end = removed.end;
 5227                }
 5228            } else {
 5229                i += 1;
 5230            }
 5231        }
 5232
 5233        if let Some(autoscroll) = autoscroll {
 5234            self.request_autoscroll(autoscroll, cx);
 5235        }
 5236
 5237        self.set_selections(
 5238            Arc::from_iter(selections.into_iter().map(|selection| {
 5239                let end_bias = if selection.end > selection.start {
 5240                    Bias::Left
 5241                } else {
 5242                    Bias::Right
 5243                };
 5244                Selection {
 5245                    id: selection.id,
 5246                    start: buffer.anchor_after(selection.start),
 5247                    end: buffer.anchor_at(selection.end, end_bias),
 5248                    reversed: selection.reversed,
 5249                    goal: selection.goal,
 5250                }
 5251            })),
 5252            None,
 5253            true,
 5254            cx,
 5255        );
 5256    }
 5257
 5258    pub fn set_selections_from_remote(
 5259        &mut self,
 5260        mut selections: Vec<Selection<Anchor>>,
 5261        cx: &mut ViewContext<Self>,
 5262    ) {
 5263        let buffer = self.buffer.read(cx);
 5264        let buffer = buffer.read(cx);
 5265        selections.sort_by(|a, b| {
 5266            a.start
 5267                .cmp(&b.start, &*buffer)
 5268                .then_with(|| b.end.cmp(&a.end, &*buffer))
 5269        });
 5270
 5271        // Merge overlapping selections
 5272        let mut i = 1;
 5273        while i < selections.len() {
 5274            if selections[i - 1]
 5275                .end
 5276                .cmp(&selections[i].start, &*buffer)
 5277                .is_ge()
 5278            {
 5279                let removed = selections.remove(i);
 5280                if removed
 5281                    .start
 5282                    .cmp(&selections[i - 1].start, &*buffer)
 5283                    .is_lt()
 5284                {
 5285                    selections[i - 1].start = removed.start;
 5286                }
 5287                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
 5288                    selections[i - 1].end = removed.end;
 5289                }
 5290            } else {
 5291                i += 1;
 5292            }
 5293        }
 5294
 5295        drop(buffer);
 5296        self.set_selections(selections.into(), None, false, cx);
 5297    }
 5298
 5299    /// Compute new ranges for any selections that were located in excerpts that have
 5300    /// since been removed.
 5301    ///
 5302    /// Returns a `HashMap` indicating which selections whose former head position
 5303    /// was no longer present. The keys of the map are selection ids. The values are
 5304    /// the id of the new excerpt where the head of the selection has been moved.
 5305    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
 5306        let snapshot = self.buffer.read(cx).read(cx);
 5307        let mut selections_with_lost_position = HashMap::default();
 5308
 5309        let mut pending_selection = self.pending_selection.take();
 5310        if let Some(pending) = pending_selection.as_mut() {
 5311            let anchors =
 5312                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
 5313            let (_, start, kept_start) = anchors[0].clone();
 5314            let (_, end, kept_end) = anchors[1].clone();
 5315            let kept_head = if pending.selection.reversed {
 5316                kept_start
 5317            } else {
 5318                kept_end
 5319            };
 5320            if !kept_head {
 5321                selections_with_lost_position.insert(
 5322                    pending.selection.id,
 5323                    pending.selection.head().excerpt_id.clone(),
 5324                );
 5325            }
 5326
 5327            pending.selection.start = start;
 5328            pending.selection.end = end;
 5329        }
 5330
 5331        let anchors_with_status = snapshot.refresh_anchors(
 5332            self.selections
 5333                .iter()
 5334                .flat_map(|selection| [&selection.start, &selection.end]),
 5335        );
 5336        self.selections = anchors_with_status
 5337            .chunks(2)
 5338            .map(|selection_anchors| {
 5339                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
 5340                let (_, end, kept_end) = selection_anchors[1].clone();
 5341                let selection = &self.selections[anchor_ix / 2];
 5342                let kept_head = if selection.reversed {
 5343                    kept_start
 5344                } else {
 5345                    kept_end
 5346                };
 5347                if !kept_head {
 5348                    selections_with_lost_position
 5349                        .insert(selection.id, selection.head().excerpt_id.clone());
 5350                }
 5351
 5352                Selection {
 5353                    id: selection.id,
 5354                    start,
 5355                    end,
 5356                    reversed: selection.reversed,
 5357                    goal: selection.goal,
 5358                }
 5359            })
 5360            .collect();
 5361        drop(snapshot);
 5362
 5363        let new_selections = self.local_selections::<usize>(cx);
 5364        if !new_selections.is_empty() {
 5365            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 5366        }
 5367        self.pending_selection = pending_selection;
 5368
 5369        selections_with_lost_position
 5370    }
 5371
 5372    fn set_selections(
 5373        &mut self,
 5374        selections: Arc<[Selection<Anchor>]>,
 5375        pending_selection: Option<PendingSelection>,
 5376        local: bool,
 5377        cx: &mut ViewContext<Self>,
 5378    ) {
 5379        assert!(
 5380            !selections.is_empty() || pending_selection.is_some(),
 5381            "must have at least one selection"
 5382        );
 5383
 5384        let old_cursor_position = self.newest_anchor_selection().head();
 5385
 5386        self.push_to_selection_history();
 5387        self.selections = selections;
 5388        self.pending_selection = pending_selection;
 5389        if self.focused && self.leader_replica_id.is_none() {
 5390            self.buffer.update(cx, |buffer, cx| {
 5391                buffer.set_active_selections(&self.selections, cx)
 5392            });
 5393        }
 5394
 5395        let display_map = self
 5396            .display_map
 5397            .update(cx, |display_map, cx| display_map.snapshot(cx));
 5398        let buffer = &display_map.buffer_snapshot;
 5399        self.add_selections_state = None;
 5400        self.select_next_state = None;
 5401        self.select_larger_syntax_node_stack.clear();
 5402        self.autoclose_stack.invalidate(&self.selections, &buffer);
 5403        self.snippet_stack.invalidate(&self.selections, &buffer);
 5404        self.take_rename(false, cx);
 5405
 5406        let new_cursor_position = self.newest_anchor_selection().head();
 5407
 5408        self.push_to_nav_history(
 5409            old_cursor_position.clone(),
 5410            Some(new_cursor_position.to_point(&buffer)),
 5411            cx,
 5412        );
 5413
 5414        if local {
 5415            let completion_menu = match self.context_menu.as_mut() {
 5416                Some(ContextMenu::Completions(menu)) => Some(menu),
 5417                _ => {
 5418                    self.context_menu.take();
 5419                    None
 5420                }
 5421            };
 5422
 5423            if let Some(completion_menu) = completion_menu {
 5424                let cursor_position = new_cursor_position.to_offset(&buffer);
 5425                let (word_range, kind) =
 5426                    buffer.surrounding_word(completion_menu.initial_position.clone());
 5427                if kind == Some(CharKind::Word)
 5428                    && word_range.to_inclusive().contains(&cursor_position)
 5429                {
 5430                    let query = Self::completion_query(&buffer, cursor_position);
 5431                    cx.background()
 5432                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 5433                    self.show_completions(&ShowCompletions, cx);
 5434                } else {
 5435                    self.hide_context_menu(cx);
 5436                }
 5437            }
 5438
 5439            if old_cursor_position.to_display_point(&display_map).row()
 5440                != new_cursor_position.to_display_point(&display_map).row()
 5441            {
 5442                self.available_code_actions.take();
 5443            }
 5444            self.refresh_code_actions(cx);
 5445            self.refresh_document_highlights(cx);
 5446        }
 5447
 5448        self.pause_cursor_blinking(cx);
 5449        cx.emit(Event::SelectionsChanged { local });
 5450    }
 5451
 5452    fn push_to_selection_history(&mut self) {
 5453        self.selection_history.push(SelectionHistoryEntry {
 5454            selections: self.selections.clone(),
 5455            select_next_state: self.select_next_state.clone(),
 5456            add_selections_state: self.add_selections_state.clone(),
 5457        });
 5458    }
 5459
 5460    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5461        self.autoscroll_request = Some((autoscroll, true));
 5462        cx.notify();
 5463    }
 5464
 5465    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5466        self.autoscroll_request = Some((autoscroll, false));
 5467        cx.notify();
 5468    }
 5469
 5470    pub fn transact(
 5471        &mut self,
 5472        cx: &mut ViewContext<Self>,
 5473        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5474    ) {
 5475        self.start_transaction_at(Instant::now(), cx);
 5476        update(self, cx);
 5477        self.end_transaction_at(Instant::now(), cx);
 5478    }
 5479
 5480    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5481        self.end_selection(cx);
 5482        if let Some(tx_id) = self
 5483            .buffer
 5484            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5485        {
 5486            self.selection_history
 5487                .insert_transaction(tx_id, self.selections.clone());
 5488        }
 5489    }
 5490
 5491    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5492        if let Some(tx_id) = self
 5493            .buffer
 5494            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5495        {
 5496            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5497                *end_selections = Some(self.selections.clone());
 5498            } else {
 5499                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5500            }
 5501
 5502            cx.emit(Event::Edited);
 5503        }
 5504    }
 5505
 5506    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5507        log::info!("Editor::page_up");
 5508    }
 5509
 5510    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5511        log::info!("Editor::page_down");
 5512    }
 5513
 5514    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5515        let mut fold_ranges = Vec::new();
 5516
 5517        let selections = self.local_selections::<Point>(cx);
 5518        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5519        for selection in selections {
 5520            let range = selection.display_range(&display_map).sorted();
 5521            let buffer_start_row = range.start.to_point(&display_map).row;
 5522
 5523            for row in (0..=range.end.row()).rev() {
 5524                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5525                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5526                    if fold_range.end.row >= buffer_start_row {
 5527                        fold_ranges.push(fold_range);
 5528                        if row <= range.start.row() {
 5529                            break;
 5530                        }
 5531                    }
 5532                }
 5533            }
 5534        }
 5535
 5536        self.fold_ranges(fold_ranges, cx);
 5537    }
 5538
 5539    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5540        let selections = self.local_selections::<Point>(cx);
 5541        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5542        let buffer = &display_map.buffer_snapshot;
 5543        let ranges = selections
 5544            .iter()
 5545            .map(|s| {
 5546                let range = s.display_range(&display_map).sorted();
 5547                let mut start = range.start.to_point(&display_map);
 5548                let mut end = range.end.to_point(&display_map);
 5549                start.column = 0;
 5550                end.column = buffer.line_len(end.row);
 5551                start..end
 5552            })
 5553            .collect::<Vec<_>>();
 5554        self.unfold_ranges(ranges, true, cx);
 5555    }
 5556
 5557    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5558        let max_point = display_map.max_point();
 5559        if display_row >= max_point.row() {
 5560            false
 5561        } else {
 5562            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5563            if is_blank {
 5564                false
 5565            } else {
 5566                for display_row in display_row + 1..=max_point.row() {
 5567                    let (indent, is_blank) = display_map.line_indent(display_row);
 5568                    if !is_blank {
 5569                        return indent > start_indent;
 5570                    }
 5571                }
 5572                false
 5573            }
 5574        }
 5575    }
 5576
 5577    fn foldable_range_for_line(
 5578        &self,
 5579        display_map: &DisplaySnapshot,
 5580        start_row: u32,
 5581    ) -> Range<Point> {
 5582        let max_point = display_map.max_point();
 5583
 5584        let (start_indent, _) = display_map.line_indent(start_row);
 5585        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5586        let mut end = None;
 5587        for row in start_row + 1..=max_point.row() {
 5588            let (indent, is_blank) = display_map.line_indent(row);
 5589            if !is_blank && indent <= start_indent {
 5590                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5591                break;
 5592            }
 5593        }
 5594
 5595        let end = end.unwrap_or(max_point);
 5596        return start.to_point(display_map)..end.to_point(display_map);
 5597    }
 5598
 5599    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5600        let selections = self.local_selections::<Point>(cx);
 5601        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5602        self.fold_ranges(ranges, cx);
 5603    }
 5604
 5605    pub fn fold_ranges<T: ToOffset>(
 5606        &mut self,
 5607        ranges: impl IntoIterator<Item = Range<T>>,
 5608        cx: &mut ViewContext<Self>,
 5609    ) {
 5610        let mut ranges = ranges.into_iter().peekable();
 5611        if ranges.peek().is_some() {
 5612            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5613            self.request_autoscroll(Autoscroll::Fit, cx);
 5614            cx.notify();
 5615        }
 5616    }
 5617
 5618    pub fn unfold_ranges<T: ToOffset>(
 5619        &mut self,
 5620        ranges: impl IntoIterator<Item = Range<T>>,
 5621        inclusive: bool,
 5622        cx: &mut ViewContext<Self>,
 5623    ) {
 5624        let mut ranges = ranges.into_iter().peekable();
 5625        if ranges.peek().is_some() {
 5626            self.display_map
 5627                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5628            self.request_autoscroll(Autoscroll::Fit, cx);
 5629            cx.notify();
 5630        }
 5631    }
 5632
 5633    pub fn insert_blocks(
 5634        &mut self,
 5635        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5636        cx: &mut ViewContext<Self>,
 5637    ) -> Vec<BlockId> {
 5638        let blocks = self
 5639            .display_map
 5640            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5641        self.request_autoscroll(Autoscroll::Fit, cx);
 5642        blocks
 5643    }
 5644
 5645    pub fn replace_blocks(
 5646        &mut self,
 5647        blocks: HashMap<BlockId, RenderBlock>,
 5648        cx: &mut ViewContext<Self>,
 5649    ) {
 5650        self.display_map
 5651            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5652        self.request_autoscroll(Autoscroll::Fit, cx);
 5653    }
 5654
 5655    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5656        self.display_map.update(cx, |display_map, cx| {
 5657            display_map.remove_blocks(block_ids, cx)
 5658        });
 5659    }
 5660
 5661    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5662        self.display_map
 5663            .update(cx, |map, cx| map.snapshot(cx))
 5664            .longest_row()
 5665    }
 5666
 5667    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5668        self.display_map
 5669            .update(cx, |map, cx| map.snapshot(cx))
 5670            .max_point()
 5671    }
 5672
 5673    pub fn text(&self, cx: &AppContext) -> String {
 5674        self.buffer.read(cx).read(cx).text()
 5675    }
 5676
 5677    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5678        self.transact(cx, |this, cx| {
 5679            this.buffer
 5680                .read(cx)
 5681                .as_singleton()
 5682                .expect("you can only call set_text on editors for singleton buffers")
 5683                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5684        });
 5685    }
 5686
 5687    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5688        self.display_map
 5689            .update(cx, |map, cx| map.snapshot(cx))
 5690            .text()
 5691    }
 5692
 5693    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5694        let language_name = self
 5695            .buffer
 5696            .read(cx)
 5697            .as_singleton()
 5698            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5699            .map(|l| l.name());
 5700
 5701        let settings = cx.global::<Settings>();
 5702        let mode = self
 5703            .soft_wrap_mode_override
 5704            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5705        match mode {
 5706            settings::SoftWrap::None => SoftWrap::None,
 5707            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5708            settings::SoftWrap::PreferredLineLength => {
 5709                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5710            }
 5711        }
 5712    }
 5713
 5714    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5715        self.soft_wrap_mode_override = Some(mode);
 5716        cx.notify();
 5717    }
 5718
 5719    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5720        self.display_map
 5721            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5722    }
 5723
 5724    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5725        self.highlighted_rows = rows;
 5726    }
 5727
 5728    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5729        self.highlighted_rows.clone()
 5730    }
 5731
 5732    pub fn highlight_background<T: 'static>(
 5733        &mut self,
 5734        ranges: Vec<Range<Anchor>>,
 5735        color_fetcher: fn(&Theme) -> Color,
 5736        cx: &mut ViewContext<Self>,
 5737    ) {
 5738        self.background_highlights
 5739            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5740        cx.notify();
 5741    }
 5742
 5743    pub fn clear_background_highlights<T: 'static>(
 5744        &mut self,
 5745        cx: &mut ViewContext<Self>,
 5746    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5747        cx.notify();
 5748        self.background_highlights.remove(&TypeId::of::<T>())
 5749    }
 5750
 5751    #[cfg(feature = "test-support")]
 5752    pub fn all_background_highlights(
 5753        &mut self,
 5754        cx: &mut ViewContext<Self>,
 5755    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5756        let snapshot = self.snapshot(cx);
 5757        let buffer = &snapshot.buffer_snapshot;
 5758        let start = buffer.anchor_before(0);
 5759        let end = buffer.anchor_after(buffer.len());
 5760        let theme = cx.global::<Settings>().theme.as_ref();
 5761        self.background_highlights_in_range(start..end, &snapshot, theme)
 5762    }
 5763
 5764    fn document_highlights_for_position<'a>(
 5765        &'a self,
 5766        position: Anchor,
 5767        buffer: &'a MultiBufferSnapshot,
 5768    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5769        let read_highlights = self
 5770            .background_highlights
 5771            .get(&TypeId::of::<DocumentHighlightRead>())
 5772            .map(|h| &h.1);
 5773        let write_highlights = self
 5774            .background_highlights
 5775            .get(&TypeId::of::<DocumentHighlightRead>())
 5776            .map(|h| &h.1);
 5777        let left_position = position.bias_left(buffer);
 5778        let right_position = position.bias_right(buffer);
 5779        read_highlights
 5780            .into_iter()
 5781            .chain(write_highlights)
 5782            .flat_map(move |ranges| {
 5783                let start_ix = match ranges.binary_search_by(|probe| {
 5784                    let cmp = probe.end.cmp(&left_position, &buffer);
 5785                    if cmp.is_ge() {
 5786                        Ordering::Greater
 5787                    } else {
 5788                        Ordering::Less
 5789                    }
 5790                }) {
 5791                    Ok(i) | Err(i) => i,
 5792                };
 5793
 5794                let right_position = right_position.clone();
 5795                ranges[start_ix..]
 5796                    .iter()
 5797                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5798            })
 5799    }
 5800
 5801    pub fn background_highlights_in_range(
 5802        &self,
 5803        search_range: Range<Anchor>,
 5804        display_snapshot: &DisplaySnapshot,
 5805        theme: &Theme,
 5806    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5807        let mut results = Vec::new();
 5808        let buffer = &display_snapshot.buffer_snapshot;
 5809        for (color_fetcher, ranges) in self.background_highlights.values() {
 5810            let color = color_fetcher(theme);
 5811            let start_ix = match ranges.binary_search_by(|probe| {
 5812                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5813                if cmp.is_gt() {
 5814                    Ordering::Greater
 5815                } else {
 5816                    Ordering::Less
 5817                }
 5818            }) {
 5819                Ok(i) | Err(i) => i,
 5820            };
 5821            for range in &ranges[start_ix..] {
 5822                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5823                    break;
 5824                }
 5825                let start = range
 5826                    .start
 5827                    .to_point(buffer)
 5828                    .to_display_point(display_snapshot);
 5829                let end = range
 5830                    .end
 5831                    .to_point(buffer)
 5832                    .to_display_point(display_snapshot);
 5833                results.push((start..end, color))
 5834            }
 5835        }
 5836        results
 5837    }
 5838
 5839    pub fn highlight_text<T: 'static>(
 5840        &mut self,
 5841        ranges: Vec<Range<Anchor>>,
 5842        style: HighlightStyle,
 5843        cx: &mut ViewContext<Self>,
 5844    ) {
 5845        self.display_map.update(cx, |map, _| {
 5846            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5847        });
 5848        cx.notify();
 5849    }
 5850
 5851    pub fn clear_text_highlights<T: 'static>(
 5852        &mut self,
 5853        cx: &mut ViewContext<Self>,
 5854    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5855        cx.notify();
 5856        self.display_map
 5857            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5858    }
 5859
 5860    fn next_blink_epoch(&mut self) -> usize {
 5861        self.blink_epoch += 1;
 5862        self.blink_epoch
 5863    }
 5864
 5865    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5866        if !self.focused {
 5867            return;
 5868        }
 5869
 5870        self.show_local_cursors = true;
 5871        cx.notify();
 5872
 5873        let epoch = self.next_blink_epoch();
 5874        cx.spawn(|this, mut cx| {
 5875            let this = this.downgrade();
 5876            async move {
 5877                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5878                if let Some(this) = this.upgrade(&cx) {
 5879                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5880                }
 5881            }
 5882        })
 5883        .detach();
 5884    }
 5885
 5886    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5887        if epoch == self.blink_epoch {
 5888            self.blinking_paused = false;
 5889            self.blink_cursors(epoch, cx);
 5890        }
 5891    }
 5892
 5893    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5894        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5895            self.show_local_cursors = !self.show_local_cursors;
 5896            cx.notify();
 5897
 5898            let epoch = self.next_blink_epoch();
 5899            cx.spawn(|this, mut cx| {
 5900                let this = this.downgrade();
 5901                async move {
 5902                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5903                    if let Some(this) = this.upgrade(&cx) {
 5904                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5905                    }
 5906                }
 5907            })
 5908            .detach();
 5909        }
 5910    }
 5911
 5912    pub fn show_local_cursors(&self) -> bool {
 5913        self.show_local_cursors && self.focused
 5914    }
 5915
 5916    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5917        cx.notify();
 5918    }
 5919
 5920    fn on_buffer_event(
 5921        &mut self,
 5922        _: ModelHandle<MultiBuffer>,
 5923        event: &language::Event,
 5924        cx: &mut ViewContext<Self>,
 5925    ) {
 5926        match event {
 5927            language::Event::Edited => {
 5928                self.refresh_active_diagnostics(cx);
 5929                self.refresh_code_actions(cx);
 5930                cx.emit(Event::BufferEdited);
 5931            }
 5932            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5933            language::Event::Dirtied => cx.emit(Event::Dirtied),
 5934            language::Event::Saved => cx.emit(Event::Saved),
 5935            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5936            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5937            language::Event::Closed => cx.emit(Event::Closed),
 5938            language::Event::DiagnosticsUpdated => {
 5939                self.refresh_active_diagnostics(cx);
 5940            }
 5941            _ => {}
 5942        }
 5943    }
 5944
 5945    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5946        cx.notify();
 5947    }
 5948
 5949    pub fn set_searchable(&mut self, searchable: bool) {
 5950        self.searchable = searchable;
 5951    }
 5952
 5953    pub fn searchable(&self) -> bool {
 5954        self.searchable
 5955    }
 5956
 5957    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5958        let active_item = workspace.active_item(cx);
 5959        let editor_handle = if let Some(editor) = active_item
 5960            .as_ref()
 5961            .and_then(|item| item.act_as::<Self>(cx))
 5962        {
 5963            editor
 5964        } else {
 5965            cx.propagate_action();
 5966            return;
 5967        };
 5968
 5969        let editor = editor_handle.read(cx);
 5970        let buffer = editor.buffer.read(cx);
 5971        if buffer.is_singleton() {
 5972            cx.propagate_action();
 5973            return;
 5974        }
 5975
 5976        let mut new_selections_by_buffer = HashMap::default();
 5977        for selection in editor.local_selections::<usize>(cx) {
 5978            for (buffer, mut range) in
 5979                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5980            {
 5981                if selection.reversed {
 5982                    mem::swap(&mut range.start, &mut range.end);
 5983                }
 5984                new_selections_by_buffer
 5985                    .entry(buffer)
 5986                    .or_insert(Vec::new())
 5987                    .push(range)
 5988            }
 5989        }
 5990
 5991        editor_handle.update(cx, |editor, cx| {
 5992            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
 5993        });
 5994        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 5995        nav_history.borrow_mut().disable();
 5996
 5997        // We defer the pane interaction because we ourselves are a workspace item
 5998        // and activating a new item causes the pane to call a method on us reentrantly,
 5999        // which panics if we're on the stack.
 6000        cx.defer(move |workspace, cx| {
 6001            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 6002                let editor = workspace.open_project_item::<Self>(buffer, cx);
 6003                editor.update(cx, |editor, cx| {
 6004                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
 6005                });
 6006            }
 6007
 6008            nav_history.borrow_mut().enable();
 6009        });
 6010    }
 6011}
 6012
 6013impl EditorSnapshot {
 6014    pub fn is_focused(&self) -> bool {
 6015        self.is_focused
 6016    }
 6017
 6018    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 6019        self.placeholder_text.as_ref()
 6020    }
 6021
 6022    pub fn scroll_position(&self) -> Vector2F {
 6023        compute_scroll_position(
 6024            &self.display_snapshot,
 6025            self.scroll_position,
 6026            &self.scroll_top_anchor,
 6027        )
 6028    }
 6029}
 6030
 6031impl Deref for EditorSnapshot {
 6032    type Target = DisplaySnapshot;
 6033
 6034    fn deref(&self) -> &Self::Target {
 6035        &self.display_snapshot
 6036    }
 6037}
 6038
 6039fn compute_scroll_position(
 6040    snapshot: &DisplaySnapshot,
 6041    mut scroll_position: Vector2F,
 6042    scroll_top_anchor: &Anchor,
 6043) -> Vector2F {
 6044    if *scroll_top_anchor != Anchor::min() {
 6045        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 6046        scroll_position.set_y(scroll_top + scroll_position.y());
 6047    } else {
 6048        scroll_position.set_y(0.);
 6049    }
 6050    scroll_position
 6051}
 6052
 6053#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 6054pub enum Event {
 6055    Activate,
 6056    BufferEdited,
 6057    Edited,
 6058    Reparsed,
 6059    Blurred,
 6060    Dirtied,
 6061    Saved,
 6062    TitleChanged,
 6063    SelectionsChanged { local: bool },
 6064    ScrollPositionChanged { local: bool },
 6065    Closed,
 6066}
 6067
 6068pub struct EditorFocused(pub ViewHandle<Editor>);
 6069pub struct EditorBlurred(pub ViewHandle<Editor>);
 6070pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6071
 6072impl Entity for Editor {
 6073    type Event = Event;
 6074
 6075    fn release(&mut self, cx: &mut MutableAppContext) {
 6076        cx.emit_global(EditorReleased(self.handle.clone()));
 6077    }
 6078}
 6079
 6080impl View for Editor {
 6081    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6082        let style = self.style(cx);
 6083        self.display_map.update(cx, |map, cx| {
 6084            map.set_font(style.text.font_id, style.text.font_size, cx)
 6085        });
 6086        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 6087    }
 6088
 6089    fn ui_name() -> &'static str {
 6090        "Editor"
 6091    }
 6092
 6093    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 6094        let focused_event = EditorFocused(cx.handle());
 6095        cx.emit_global(focused_event);
 6096        if let Some(rename) = self.pending_rename.as_ref() {
 6097            cx.focus(&rename.editor);
 6098        } else {
 6099            self.focused = true;
 6100            self.blink_cursors(self.blink_epoch, cx);
 6101            self.buffer.update(cx, |buffer, cx| {
 6102                buffer.finalize_last_transaction(cx);
 6103                if self.leader_replica_id.is_none() {
 6104                    buffer.set_active_selections(&self.selections, cx);
 6105                }
 6106            });
 6107        }
 6108    }
 6109
 6110    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6111        let blurred_event = EditorBlurred(cx.handle());
 6112        cx.emit_global(blurred_event);
 6113        self.focused = false;
 6114        self.buffer
 6115            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6116        self.hide_context_menu(cx);
 6117        cx.emit(Event::Blurred);
 6118        cx.notify();
 6119    }
 6120
 6121    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6122        let mut context = Self::default_keymap_context();
 6123        let mode = match self.mode {
 6124            EditorMode::SingleLine => "single_line",
 6125            EditorMode::AutoHeight { .. } => "auto_height",
 6126            EditorMode::Full => "full",
 6127        };
 6128        context.map.insert("mode".into(), mode.into());
 6129        if self.pending_rename.is_some() {
 6130            context.set.insert("renaming".into());
 6131        }
 6132        match self.context_menu.as_ref() {
 6133            Some(ContextMenu::Completions(_)) => {
 6134                context.set.insert("showing_completions".into());
 6135            }
 6136            Some(ContextMenu::CodeActions(_)) => {
 6137                context.set.insert("showing_code_actions".into());
 6138            }
 6139            None => {}
 6140        }
 6141
 6142        for layer in self.keymap_context_layers.values() {
 6143            context.extend(layer);
 6144        }
 6145
 6146        context
 6147    }
 6148}
 6149
 6150fn build_style(
 6151    settings: &Settings,
 6152    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6153    override_text_style: Option<&OverrideTextStyle>,
 6154    cx: &AppContext,
 6155) -> EditorStyle {
 6156    let font_cache = cx.font_cache();
 6157
 6158    let mut theme = settings.theme.editor.clone();
 6159    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6160        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6161        theme.text_color = field_editor_theme.text.color;
 6162        theme.selection = field_editor_theme.selection;
 6163        theme.background = field_editor_theme
 6164            .container
 6165            .background_color
 6166            .unwrap_or_default();
 6167        EditorStyle {
 6168            text: field_editor_theme.text,
 6169            placeholder_text: field_editor_theme.placeholder_text,
 6170            theme,
 6171        }
 6172    } else {
 6173        let font_family_id = settings.buffer_font_family;
 6174        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6175        let font_properties = Default::default();
 6176        let font_id = font_cache
 6177            .select_font(font_family_id, &font_properties)
 6178            .unwrap();
 6179        let font_size = settings.buffer_font_size;
 6180        EditorStyle {
 6181            text: TextStyle {
 6182                color: settings.theme.editor.text_color,
 6183                font_family_name,
 6184                font_family_id,
 6185                font_id,
 6186                font_size,
 6187                font_properties,
 6188                underline: Default::default(),
 6189            },
 6190            placeholder_text: None,
 6191            theme,
 6192        }
 6193    };
 6194
 6195    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6196        if let Some(highlighted) = style
 6197            .text
 6198            .clone()
 6199            .highlight(highlight_style, font_cache)
 6200            .log_err()
 6201        {
 6202            style.text = highlighted;
 6203        }
 6204    }
 6205
 6206    style
 6207}
 6208
 6209trait SelectionExt {
 6210    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6211    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6212    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6213    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6214        -> Range<u32>;
 6215}
 6216
 6217impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6218    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6219        let start = self.start.to_point(buffer);
 6220        let end = self.end.to_point(buffer);
 6221        if self.reversed {
 6222            end..start
 6223        } else {
 6224            start..end
 6225        }
 6226    }
 6227
 6228    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6229        let start = self.start.to_offset(buffer);
 6230        let end = self.end.to_offset(buffer);
 6231        if self.reversed {
 6232            end..start
 6233        } else {
 6234            start..end
 6235        }
 6236    }
 6237
 6238    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6239        let start = self
 6240            .start
 6241            .to_point(&map.buffer_snapshot)
 6242            .to_display_point(map);
 6243        let end = self
 6244            .end
 6245            .to_point(&map.buffer_snapshot)
 6246            .to_display_point(map);
 6247        if self.reversed {
 6248            end..start
 6249        } else {
 6250            start..end
 6251        }
 6252    }
 6253
 6254    fn spanned_rows(
 6255        &self,
 6256        include_end_if_at_line_start: bool,
 6257        map: &DisplaySnapshot,
 6258    ) -> Range<u32> {
 6259        let start = self.start.to_point(&map.buffer_snapshot);
 6260        let mut end = self.end.to_point(&map.buffer_snapshot);
 6261        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6262            end.row -= 1;
 6263        }
 6264
 6265        let buffer_start = map.prev_line_boundary(start).0;
 6266        let buffer_end = map.next_line_boundary(end).0;
 6267        buffer_start.row..buffer_end.row + 1
 6268    }
 6269}
 6270
 6271impl<T: InvalidationRegion> InvalidationStack<T> {
 6272    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6273    where
 6274        S: Clone + ToOffset,
 6275    {
 6276        while let Some(region) = self.last() {
 6277            let all_selections_inside_invalidation_ranges =
 6278                if selections.len() == region.ranges().len() {
 6279                    selections
 6280                        .iter()
 6281                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6282                        .all(|(selection, invalidation_range)| {
 6283                            let head = selection.head().to_offset(&buffer);
 6284                            invalidation_range.start <= head && invalidation_range.end >= head
 6285                        })
 6286                } else {
 6287                    false
 6288                };
 6289
 6290            if all_selections_inside_invalidation_ranges {
 6291                break;
 6292            } else {
 6293                self.pop();
 6294            }
 6295        }
 6296    }
 6297}
 6298
 6299impl<T> Default for InvalidationStack<T> {
 6300    fn default() -> Self {
 6301        Self(Default::default())
 6302    }
 6303}
 6304
 6305impl<T> Deref for InvalidationStack<T> {
 6306    type Target = Vec<T>;
 6307
 6308    fn deref(&self) -> &Self::Target {
 6309        &self.0
 6310    }
 6311}
 6312
 6313impl<T> DerefMut for InvalidationStack<T> {
 6314    fn deref_mut(&mut self) -> &mut Self::Target {
 6315        &mut self.0
 6316    }
 6317}
 6318
 6319impl InvalidationRegion for BracketPairState {
 6320    fn ranges(&self) -> &[Range<Anchor>] {
 6321        &self.ranges
 6322    }
 6323}
 6324
 6325impl InvalidationRegion for SnippetState {
 6326    fn ranges(&self) -> &[Range<Anchor>] {
 6327        &self.ranges[self.active_index]
 6328    }
 6329}
 6330
 6331impl Deref for EditorStyle {
 6332    type Target = theme::Editor;
 6333
 6334    fn deref(&self) -> &Self::Target {
 6335        &self.theme
 6336    }
 6337}
 6338
 6339pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6340    let mut highlighted_lines = Vec::new();
 6341    for line in diagnostic.message.lines() {
 6342        highlighted_lines.push(highlight_diagnostic_message(line));
 6343    }
 6344
 6345    Arc::new(move |cx: &BlockContext| {
 6346        let settings = cx.global::<Settings>();
 6347        let theme = &settings.theme.editor;
 6348        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6349        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6350        Flex::column()
 6351            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6352                Label::new(
 6353                    line.clone(),
 6354                    style.message.clone().with_font_size(font_size),
 6355                )
 6356                .with_highlights(highlights.clone())
 6357                .contained()
 6358                .with_margin_left(cx.anchor_x)
 6359                .boxed()
 6360            }))
 6361            .aligned()
 6362            .left()
 6363            .boxed()
 6364    })
 6365}
 6366
 6367pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6368    let mut message_without_backticks = String::new();
 6369    let mut prev_offset = 0;
 6370    let mut inside_block = false;
 6371    let mut highlights = Vec::new();
 6372    for (match_ix, (offset, _)) in message
 6373        .match_indices('`')
 6374        .chain([(message.len(), "")])
 6375        .enumerate()
 6376    {
 6377        message_without_backticks.push_str(&message[prev_offset..offset]);
 6378        if inside_block {
 6379            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6380        }
 6381
 6382        inside_block = !inside_block;
 6383        prev_offset = offset + 1;
 6384    }
 6385
 6386    (message_without_backticks, highlights)
 6387}
 6388
 6389pub fn diagnostic_style(
 6390    severity: DiagnosticSeverity,
 6391    valid: bool,
 6392    theme: &theme::Editor,
 6393) -> DiagnosticStyle {
 6394    match (severity, valid) {
 6395        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6396        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6397        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6398        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6399        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6400        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6401        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6402        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6403        _ => theme.invalid_hint_diagnostic.clone(),
 6404    }
 6405}
 6406
 6407pub fn combine_syntax_and_fuzzy_match_highlights(
 6408    text: &str,
 6409    default_style: HighlightStyle,
 6410    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6411    match_indices: &[usize],
 6412) -> Vec<(Range<usize>, HighlightStyle)> {
 6413    let mut result = Vec::new();
 6414    let mut match_indices = match_indices.iter().copied().peekable();
 6415
 6416    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6417    {
 6418        syntax_highlight.weight = None;
 6419
 6420        // Add highlights for any fuzzy match characters before the next
 6421        // syntax highlight range.
 6422        while let Some(&match_index) = match_indices.peek() {
 6423            if match_index >= range.start {
 6424                break;
 6425            }
 6426            match_indices.next();
 6427            let end_index = char_ix_after(match_index, text);
 6428            let mut match_style = default_style;
 6429            match_style.weight = Some(fonts::Weight::BOLD);
 6430            result.push((match_index..end_index, match_style));
 6431        }
 6432
 6433        if range.start == usize::MAX {
 6434            break;
 6435        }
 6436
 6437        // Add highlights for any fuzzy match characters within the
 6438        // syntax highlight range.
 6439        let mut offset = range.start;
 6440        while let Some(&match_index) = match_indices.peek() {
 6441            if match_index >= range.end {
 6442                break;
 6443            }
 6444
 6445            match_indices.next();
 6446            if match_index > offset {
 6447                result.push((offset..match_index, syntax_highlight));
 6448            }
 6449
 6450            let mut end_index = char_ix_after(match_index, text);
 6451            while let Some(&next_match_index) = match_indices.peek() {
 6452                if next_match_index == end_index && next_match_index < range.end {
 6453                    end_index = char_ix_after(next_match_index, text);
 6454                    match_indices.next();
 6455                } else {
 6456                    break;
 6457                }
 6458            }
 6459
 6460            let mut match_style = syntax_highlight;
 6461            match_style.weight = Some(fonts::Weight::BOLD);
 6462            result.push((match_index..end_index, match_style));
 6463            offset = end_index;
 6464        }
 6465
 6466        if offset < range.end {
 6467            result.push((offset..range.end, syntax_highlight));
 6468        }
 6469    }
 6470
 6471    fn char_ix_after(ix: usize, text: &str) -> usize {
 6472        ix + text[ix..].chars().next().unwrap().len_utf8()
 6473    }
 6474
 6475    result
 6476}
 6477
 6478pub fn styled_runs_for_code_label<'a>(
 6479    label: &'a CodeLabel,
 6480    syntax_theme: &'a theme::SyntaxTheme,
 6481) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6482    let fade_out = HighlightStyle {
 6483        fade_out: Some(0.35),
 6484        ..Default::default()
 6485    };
 6486
 6487    let mut prev_end = label.filter_range.end;
 6488    label
 6489        .runs
 6490        .iter()
 6491        .enumerate()
 6492        .flat_map(move |(ix, (range, highlight_id))| {
 6493            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6494                style
 6495            } else {
 6496                return Default::default();
 6497            };
 6498            let mut muted_style = style.clone();
 6499            muted_style.highlight(fade_out);
 6500
 6501            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6502            if range.start >= label.filter_range.end {
 6503                if range.start > prev_end {
 6504                    runs.push((prev_end..range.start, fade_out));
 6505                }
 6506                runs.push((range.clone(), muted_style));
 6507            } else if range.end <= label.filter_range.end {
 6508                runs.push((range.clone(), style));
 6509            } else {
 6510                runs.push((range.start..label.filter_range.end, style));
 6511                runs.push((label.filter_range.end..range.end, muted_style));
 6512            }
 6513            prev_end = cmp::max(prev_end, range.end);
 6514
 6515            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6516                runs.push((prev_end..label.text.len(), fade_out));
 6517            }
 6518
 6519            runs
 6520        })
 6521}
 6522
 6523#[cfg(test)]
 6524mod tests {
 6525    use crate::test::{assert_text_with_selections, select_ranges};
 6526
 6527    use super::*;
 6528    use gpui::{
 6529        geometry::rect::RectF,
 6530        platform::{WindowBounds, WindowOptions},
 6531    };
 6532    use indoc::indoc;
 6533    use language::{FakeLspAdapter, LanguageConfig};
 6534    use lsp::FakeLanguageServer;
 6535    use project::FakeFs;
 6536    use settings::LanguageOverride;
 6537    use smol::stream::StreamExt;
 6538    use std::{cell::RefCell, rc::Rc, time::Instant};
 6539    use text::Point;
 6540    use unindent::Unindent;
 6541    use util::test::{marked_text_by, marked_text_ranges, sample_text};
 6542    use workspace::{FollowableItem, ItemHandle};
 6543
 6544    #[gpui::test]
 6545    fn test_edit_events(cx: &mut MutableAppContext) {
 6546        cx.set_global(Settings::test(cx));
 6547        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6548
 6549        let events = Rc::new(RefCell::new(Vec::new()));
 6550        let (_, editor1) = cx.add_window(Default::default(), {
 6551            let events = events.clone();
 6552            |cx| {
 6553                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6554                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6555                        events.borrow_mut().push(("editor1", *event));
 6556                    }
 6557                })
 6558                .detach();
 6559                Editor::for_buffer(buffer.clone(), None, cx)
 6560            }
 6561        });
 6562        let (_, editor2) = cx.add_window(Default::default(), {
 6563            let events = events.clone();
 6564            |cx| {
 6565                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6566                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6567                        events.borrow_mut().push(("editor2", *event));
 6568                    }
 6569                })
 6570                .detach();
 6571                Editor::for_buffer(buffer.clone(), None, cx)
 6572            }
 6573        });
 6574        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6575
 6576        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6577        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6578        assert_eq!(
 6579            mem::take(&mut *events.borrow_mut()),
 6580            [
 6581                ("editor1", Event::Edited),
 6582                ("editor1", Event::BufferEdited),
 6583                ("editor2", Event::BufferEdited),
 6584                ("editor1", Event::Dirtied),
 6585                ("editor2", Event::Dirtied)
 6586            ]
 6587        );
 6588
 6589        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6590        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6591        assert_eq!(
 6592            mem::take(&mut *events.borrow_mut()),
 6593            [
 6594                ("editor2", Event::Edited),
 6595                ("editor1", Event::BufferEdited),
 6596                ("editor2", Event::BufferEdited),
 6597            ]
 6598        );
 6599
 6600        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6601        editor1.update(cx, |editor, cx| editor.undo(&Undo, 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        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6612        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6613        assert_eq!(
 6614            mem::take(&mut *events.borrow_mut()),
 6615            [
 6616                ("editor1", Event::Edited),
 6617                ("editor1", Event::BufferEdited),
 6618                ("editor2", Event::BufferEdited),
 6619            ]
 6620        );
 6621
 6622        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6623        editor2.update(cx, |editor, cx| editor.undo(&Undo, 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        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6634        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6635        assert_eq!(
 6636            mem::take(&mut *events.borrow_mut()),
 6637            [
 6638                ("editor2", Event::Edited),
 6639                ("editor1", Event::BufferEdited),
 6640                ("editor2", Event::BufferEdited),
 6641            ]
 6642        );
 6643
 6644        // No event is emitted when the mutation is a no-op.
 6645        editor2.update(cx, |editor, cx| {
 6646            editor.select_ranges([0..0], None, cx);
 6647            editor.backspace(&Backspace, cx);
 6648        });
 6649        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6650    }
 6651
 6652    #[gpui::test]
 6653    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6654        cx.set_global(Settings::test(cx));
 6655        let mut now = Instant::now();
 6656        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6657        let group_interval = buffer.read(cx).transaction_group_interval();
 6658        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6659        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6660
 6661        editor.update(cx, |editor, cx| {
 6662            editor.start_transaction_at(now, cx);
 6663            editor.select_ranges([2..4], None, cx);
 6664            editor.insert("cd", cx);
 6665            editor.end_transaction_at(now, cx);
 6666            assert_eq!(editor.text(cx), "12cd56");
 6667            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 6668
 6669            editor.start_transaction_at(now, cx);
 6670            editor.select_ranges([4..5], None, cx);
 6671            editor.insert("e", cx);
 6672            editor.end_transaction_at(now, cx);
 6673            assert_eq!(editor.text(cx), "12cde6");
 6674            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6675
 6676            now += group_interval + Duration::from_millis(1);
 6677            editor.select_ranges([2..2], None, cx);
 6678
 6679            // Simulate an edit in another editor
 6680            buffer.update(cx, |buffer, cx| {
 6681                buffer.start_transaction_at(now, cx);
 6682                buffer.edit([(0..1, "a")], cx);
 6683                buffer.edit([(1..1, "b")], cx);
 6684                buffer.end_transaction_at(now, cx);
 6685            });
 6686
 6687            assert_eq!(editor.text(cx), "ab2cde6");
 6688            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
 6689
 6690            // Last transaction happened past the group interval in a different editor.
 6691            // Undo it individually and don't restore selections.
 6692            editor.undo(&Undo, cx);
 6693            assert_eq!(editor.text(cx), "12cde6");
 6694            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
 6695
 6696            // First two transactions happened within the group interval in this editor.
 6697            // Undo them together and restore selections.
 6698            editor.undo(&Undo, cx);
 6699            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6700            assert_eq!(editor.text(cx), "123456");
 6701            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
 6702
 6703            // Redo the first two transactions together.
 6704            editor.redo(&Redo, cx);
 6705            assert_eq!(editor.text(cx), "12cde6");
 6706            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6707
 6708            // Redo the last transaction on its own.
 6709            editor.redo(&Redo, cx);
 6710            assert_eq!(editor.text(cx), "ab2cde6");
 6711            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
 6712
 6713            // Test empty transactions.
 6714            editor.start_transaction_at(now, cx);
 6715            editor.end_transaction_at(now, cx);
 6716            editor.undo(&Undo, cx);
 6717            assert_eq!(editor.text(cx), "12cde6");
 6718        });
 6719    }
 6720
 6721    #[gpui::test]
 6722    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6723        cx.set_global(Settings::test(cx));
 6724
 6725        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6726        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6727        editor.update(cx, |view, cx| {
 6728            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6729        });
 6730        assert_eq!(
 6731            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6732            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6733        );
 6734
 6735        editor.update(cx, |view, cx| {
 6736            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6737        });
 6738
 6739        assert_eq!(
 6740            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6741            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6742        );
 6743
 6744        editor.update(cx, |view, cx| {
 6745            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6746        });
 6747
 6748        assert_eq!(
 6749            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6750            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6751        );
 6752
 6753        editor.update(cx, |view, cx| {
 6754            view.end_selection(cx);
 6755            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6756        });
 6757
 6758        assert_eq!(
 6759            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6760            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6761        );
 6762
 6763        editor.update(cx, |view, cx| {
 6764            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6765            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6766        });
 6767
 6768        assert_eq!(
 6769            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6770            [
 6771                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6772                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6773            ]
 6774        );
 6775
 6776        editor.update(cx, |view, cx| {
 6777            view.end_selection(cx);
 6778        });
 6779
 6780        assert_eq!(
 6781            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6782            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6783        );
 6784    }
 6785
 6786    #[gpui::test]
 6787    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6788        cx.set_global(Settings::test(cx));
 6789        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6790        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6791
 6792        view.update(cx, |view, cx| {
 6793            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6794            assert_eq!(
 6795                view.selected_display_ranges(cx),
 6796                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6797            );
 6798        });
 6799
 6800        view.update(cx, |view, cx| {
 6801            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6802            assert_eq!(
 6803                view.selected_display_ranges(cx),
 6804                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6805            );
 6806        });
 6807
 6808        view.update(cx, |view, cx| {
 6809            view.cancel(&Cancel, cx);
 6810            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6811            assert_eq!(
 6812                view.selected_display_ranges(cx),
 6813                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6814            );
 6815        });
 6816    }
 6817
 6818    #[gpui::test]
 6819    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6820        cx.set_global(Settings::test(cx));
 6821        use workspace::Item;
 6822        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6823        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6824
 6825        cx.add_window(Default::default(), |cx| {
 6826            let mut editor = build_editor(buffer.clone(), cx);
 6827            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6828
 6829            // Move the cursor a small distance.
 6830            // Nothing is added to the navigation history.
 6831            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
 6832            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
 6833            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6834
 6835            // Move the cursor a large distance.
 6836            // The history can jump back to the previous position.
 6837            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
 6838            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6839            editor.navigate(nav_entry.data.unwrap(), cx);
 6840            assert_eq!(nav_entry.item.id(), cx.view_id());
 6841            assert_eq!(
 6842                editor.selected_display_ranges(cx),
 6843                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6844            );
 6845            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6846
 6847            // Move the cursor a small distance via the mouse.
 6848            // Nothing is added to the navigation history.
 6849            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6850            editor.end_selection(cx);
 6851            assert_eq!(
 6852                editor.selected_display_ranges(cx),
 6853                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6854            );
 6855            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6856
 6857            // Move the cursor a large distance via the mouse.
 6858            // The history can jump back to the previous position.
 6859            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6860            editor.end_selection(cx);
 6861            assert_eq!(
 6862                editor.selected_display_ranges(cx),
 6863                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6864            );
 6865            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6866            editor.navigate(nav_entry.data.unwrap(), cx);
 6867            assert_eq!(nav_entry.item.id(), cx.view_id());
 6868            assert_eq!(
 6869                editor.selected_display_ranges(cx),
 6870                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6871            );
 6872            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6873
 6874            // Set scroll position to check later
 6875            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6876            let original_scroll_position = editor.scroll_position;
 6877            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6878
 6879            // Jump to the end of the document and adjust scroll
 6880            editor.move_to_end(&MoveToEnd, cx);
 6881            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6882            assert_ne!(editor.scroll_position, original_scroll_position);
 6883            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6884
 6885            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6886            editor.navigate(nav_entry.data.unwrap(), cx);
 6887            assert_eq!(editor.scroll_position, original_scroll_position);
 6888            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6889
 6890            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6891            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6892            invalid_anchor.text_anchor.buffer_id = Some(999);
 6893            let invalid_point = Point::new(9999, 0);
 6894            editor.navigate(
 6895                Box::new(NavigationData {
 6896                    cursor_anchor: invalid_anchor.clone(),
 6897                    cursor_position: invalid_point,
 6898                    scroll_top_anchor: invalid_anchor.clone(),
 6899                    scroll_top_row: invalid_point.row,
 6900                    scroll_position: Default::default(),
 6901                }),
 6902                cx,
 6903            );
 6904            assert_eq!(
 6905                editor.selected_display_ranges(cx),
 6906                &[editor.max_point(cx)..editor.max_point(cx)]
 6907            );
 6908            assert_eq!(
 6909                editor.scroll_position(cx),
 6910                vec2f(0., editor.max_point(cx).row() as f32)
 6911            );
 6912
 6913            editor
 6914        });
 6915    }
 6916
 6917    #[gpui::test]
 6918    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6919        cx.set_global(Settings::test(cx));
 6920        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6921        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6922
 6923        view.update(cx, |view, cx| {
 6924            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6925            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6926            view.end_selection(cx);
 6927
 6928            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6929            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6930            view.end_selection(cx);
 6931            assert_eq!(
 6932                view.selected_display_ranges(cx),
 6933                [
 6934                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6935                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6936                ]
 6937            );
 6938        });
 6939
 6940        view.update(cx, |view, cx| {
 6941            view.cancel(&Cancel, cx);
 6942            assert_eq!(
 6943                view.selected_display_ranges(cx),
 6944                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6945            );
 6946        });
 6947
 6948        view.update(cx, |view, cx| {
 6949            view.cancel(&Cancel, cx);
 6950            assert_eq!(
 6951                view.selected_display_ranges(cx),
 6952                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6953            );
 6954        });
 6955    }
 6956
 6957    #[gpui::test]
 6958    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6959        cx.set_global(Settings::test(cx));
 6960        let buffer = MultiBuffer::build_simple(
 6961            &"
 6962                impl Foo {
 6963                    // Hello!
 6964
 6965                    fn a() {
 6966                        1
 6967                    }
 6968
 6969                    fn b() {
 6970                        2
 6971                    }
 6972
 6973                    fn c() {
 6974                        3
 6975                    }
 6976                }
 6977            "
 6978            .unindent(),
 6979            cx,
 6980        );
 6981        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6982
 6983        view.update(cx, |view, cx| {
 6984            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 6985            view.fold(&Fold, cx);
 6986            assert_eq!(
 6987                view.display_text(cx),
 6988                "
 6989                    impl Foo {
 6990                        // Hello!
 6991
 6992                        fn a() {
 6993                            1
 6994                        }
 6995
 6996                        fn b() {…
 6997                        }
 6998
 6999                        fn c() {…
 7000                        }
 7001                    }
 7002                "
 7003                .unindent(),
 7004            );
 7005
 7006            view.fold(&Fold, cx);
 7007            assert_eq!(
 7008                view.display_text(cx),
 7009                "
 7010                    impl Foo {…
 7011                    }
 7012                "
 7013                .unindent(),
 7014            );
 7015
 7016            view.unfold_lines(&UnfoldLines, cx);
 7017            assert_eq!(
 7018                view.display_text(cx),
 7019                "
 7020                    impl Foo {
 7021                        // Hello!
 7022
 7023                        fn a() {
 7024                            1
 7025                        }
 7026
 7027                        fn b() {…
 7028                        }
 7029
 7030                        fn c() {…
 7031                        }
 7032                    }
 7033                "
 7034                .unindent(),
 7035            );
 7036
 7037            view.unfold_lines(&UnfoldLines, cx);
 7038            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7039        });
 7040    }
 7041
 7042    #[gpui::test]
 7043    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7044        cx.set_global(Settings::test(cx));
 7045        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7046        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7047
 7048        buffer.update(cx, |buffer, cx| {
 7049            buffer.edit(
 7050                vec![
 7051                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7052                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7053                ],
 7054                cx,
 7055            );
 7056        });
 7057
 7058        view.update(cx, |view, cx| {
 7059            assert_eq!(
 7060                view.selected_display_ranges(cx),
 7061                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7062            );
 7063
 7064            view.move_down(&MoveDown, cx);
 7065            assert_eq!(
 7066                view.selected_display_ranges(cx),
 7067                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7068            );
 7069
 7070            view.move_right(&MoveRight, cx);
 7071            assert_eq!(
 7072                view.selected_display_ranges(cx),
 7073                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7074            );
 7075
 7076            view.move_left(&MoveLeft, cx);
 7077            assert_eq!(
 7078                view.selected_display_ranges(cx),
 7079                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7080            );
 7081
 7082            view.move_up(&MoveUp, cx);
 7083            assert_eq!(
 7084                view.selected_display_ranges(cx),
 7085                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7086            );
 7087
 7088            view.move_to_end(&MoveToEnd, cx);
 7089            assert_eq!(
 7090                view.selected_display_ranges(cx),
 7091                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7092            );
 7093
 7094            view.move_to_beginning(&MoveToBeginning, cx);
 7095            assert_eq!(
 7096                view.selected_display_ranges(cx),
 7097                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7098            );
 7099
 7100            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7101            view.select_to_beginning(&SelectToBeginning, cx);
 7102            assert_eq!(
 7103                view.selected_display_ranges(cx),
 7104                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7105            );
 7106
 7107            view.select_to_end(&SelectToEnd, cx);
 7108            assert_eq!(
 7109                view.selected_display_ranges(cx),
 7110                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7111            );
 7112        });
 7113    }
 7114
 7115    #[gpui::test]
 7116    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7117        cx.set_global(Settings::test(cx));
 7118        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7119        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7120
 7121        assert_eq!('ⓐ'.len_utf8(), 3);
 7122        assert_eq!('α'.len_utf8(), 2);
 7123
 7124        view.update(cx, |view, cx| {
 7125            view.fold_ranges(
 7126                vec![
 7127                    Point::new(0, 6)..Point::new(0, 12),
 7128                    Point::new(1, 2)..Point::new(1, 4),
 7129                    Point::new(2, 4)..Point::new(2, 8),
 7130                ],
 7131                cx,
 7132            );
 7133            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7134
 7135            view.move_right(&MoveRight, cx);
 7136            assert_eq!(
 7137                view.selected_display_ranges(cx),
 7138                &[empty_range(0, "".len())]
 7139            );
 7140            view.move_right(&MoveRight, cx);
 7141            assert_eq!(
 7142                view.selected_display_ranges(cx),
 7143                &[empty_range(0, "ⓐⓑ".len())]
 7144            );
 7145            view.move_right(&MoveRight, cx);
 7146            assert_eq!(
 7147                view.selected_display_ranges(cx),
 7148                &[empty_range(0, "ⓐⓑ…".len())]
 7149            );
 7150
 7151            view.move_down(&MoveDown, cx);
 7152            assert_eq!(
 7153                view.selected_display_ranges(cx),
 7154                &[empty_range(1, "ab…".len())]
 7155            );
 7156            view.move_left(&MoveLeft, cx);
 7157            assert_eq!(
 7158                view.selected_display_ranges(cx),
 7159                &[empty_range(1, "ab".len())]
 7160            );
 7161            view.move_left(&MoveLeft, cx);
 7162            assert_eq!(
 7163                view.selected_display_ranges(cx),
 7164                &[empty_range(1, "a".len())]
 7165            );
 7166
 7167            view.move_down(&MoveDown, cx);
 7168            assert_eq!(
 7169                view.selected_display_ranges(cx),
 7170                &[empty_range(2, "α".len())]
 7171            );
 7172            view.move_right(&MoveRight, cx);
 7173            assert_eq!(
 7174                view.selected_display_ranges(cx),
 7175                &[empty_range(2, "αβ".len())]
 7176            );
 7177            view.move_right(&MoveRight, cx);
 7178            assert_eq!(
 7179                view.selected_display_ranges(cx),
 7180                &[empty_range(2, "αβ…".len())]
 7181            );
 7182            view.move_right(&MoveRight, cx);
 7183            assert_eq!(
 7184                view.selected_display_ranges(cx),
 7185                &[empty_range(2, "αβ…ε".len())]
 7186            );
 7187
 7188            view.move_up(&MoveUp, cx);
 7189            assert_eq!(
 7190                view.selected_display_ranges(cx),
 7191                &[empty_range(1, "ab…e".len())]
 7192            );
 7193            view.move_up(&MoveUp, cx);
 7194            assert_eq!(
 7195                view.selected_display_ranges(cx),
 7196                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7197            );
 7198            view.move_left(&MoveLeft, cx);
 7199            assert_eq!(
 7200                view.selected_display_ranges(cx),
 7201                &[empty_range(0, "ⓐⓑ…".len())]
 7202            );
 7203            view.move_left(&MoveLeft, cx);
 7204            assert_eq!(
 7205                view.selected_display_ranges(cx),
 7206                &[empty_range(0, "ⓐⓑ".len())]
 7207            );
 7208            view.move_left(&MoveLeft, cx);
 7209            assert_eq!(
 7210                view.selected_display_ranges(cx),
 7211                &[empty_range(0, "".len())]
 7212            );
 7213        });
 7214    }
 7215
 7216    #[gpui::test]
 7217    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7218        cx.set_global(Settings::test(cx));
 7219        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7220        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7221        view.update(cx, |view, cx| {
 7222            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7223            view.move_down(&MoveDown, cx);
 7224            assert_eq!(
 7225                view.selected_display_ranges(cx),
 7226                &[empty_range(1, "abcd".len())]
 7227            );
 7228
 7229            view.move_down(&MoveDown, cx);
 7230            assert_eq!(
 7231                view.selected_display_ranges(cx),
 7232                &[empty_range(2, "αβγ".len())]
 7233            );
 7234
 7235            view.move_down(&MoveDown, cx);
 7236            assert_eq!(
 7237                view.selected_display_ranges(cx),
 7238                &[empty_range(3, "abcd".len())]
 7239            );
 7240
 7241            view.move_down(&MoveDown, cx);
 7242            assert_eq!(
 7243                view.selected_display_ranges(cx),
 7244                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7245            );
 7246
 7247            view.move_up(&MoveUp, cx);
 7248            assert_eq!(
 7249                view.selected_display_ranges(cx),
 7250                &[empty_range(3, "abcd".len())]
 7251            );
 7252
 7253            view.move_up(&MoveUp, cx);
 7254            assert_eq!(
 7255                view.selected_display_ranges(cx),
 7256                &[empty_range(2, "αβγ".len())]
 7257            );
 7258        });
 7259    }
 7260
 7261    #[gpui::test]
 7262    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7263        cx.set_global(Settings::test(cx));
 7264        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7265        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7266        view.update(cx, |view, cx| {
 7267            view.select_display_ranges(
 7268                &[
 7269                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7270                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7271                ],
 7272                cx,
 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, 2)..DisplayPoint::new(1, 2),
 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, 0)..DisplayPoint::new(1, 0),
 7294                ]
 7295            );
 7296        });
 7297
 7298        view.update(cx, |view, cx| {
 7299            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7300            assert_eq!(
 7301                view.selected_display_ranges(cx),
 7302                &[
 7303                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7304                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7305                ]
 7306            );
 7307        });
 7308
 7309        view.update(cx, |view, cx| {
 7310            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7311            assert_eq!(
 7312                view.selected_display_ranges(cx),
 7313                &[
 7314                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7315                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7316                ]
 7317            );
 7318        });
 7319
 7320        // Moving to the end of line again is a no-op.
 7321        view.update(cx, |view, cx| {
 7322            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7323            assert_eq!(
 7324                view.selected_display_ranges(cx),
 7325                &[
 7326                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7327                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7328                ]
 7329            );
 7330        });
 7331
 7332        view.update(cx, |view, cx| {
 7333            view.move_left(&MoveLeft, cx);
 7334            view.select_to_beginning_of_line(
 7335                &SelectToBeginningOfLine {
 7336                    stop_at_soft_wraps: true,
 7337                },
 7338                cx,
 7339            );
 7340            assert_eq!(
 7341                view.selected_display_ranges(cx),
 7342                &[
 7343                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7344                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7345                ]
 7346            );
 7347        });
 7348
 7349        view.update(cx, |view, cx| {
 7350            view.select_to_beginning_of_line(
 7351                &SelectToBeginningOfLine {
 7352                    stop_at_soft_wraps: true,
 7353                },
 7354                cx,
 7355            );
 7356            assert_eq!(
 7357                view.selected_display_ranges(cx),
 7358                &[
 7359                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7360                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7361                ]
 7362            );
 7363        });
 7364
 7365        view.update(cx, |view, cx| {
 7366            view.select_to_beginning_of_line(
 7367                &SelectToBeginningOfLine {
 7368                    stop_at_soft_wraps: true,
 7369                },
 7370                cx,
 7371            );
 7372            assert_eq!(
 7373                view.selected_display_ranges(cx),
 7374                &[
 7375                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7376                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7377                ]
 7378            );
 7379        });
 7380
 7381        view.update(cx, |view, cx| {
 7382            view.select_to_end_of_line(
 7383                &SelectToEndOfLine {
 7384                    stop_at_soft_wraps: true,
 7385                },
 7386                cx,
 7387            );
 7388            assert_eq!(
 7389                view.selected_display_ranges(cx),
 7390                &[
 7391                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7392                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7393                ]
 7394            );
 7395        });
 7396
 7397        view.update(cx, |view, cx| {
 7398            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7399            assert_eq!(view.display_text(cx), "ab\n  de");
 7400            assert_eq!(
 7401                view.selected_display_ranges(cx),
 7402                &[
 7403                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7404                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7405                ]
 7406            );
 7407        });
 7408
 7409        view.update(cx, |view, cx| {
 7410            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7411            assert_eq!(view.display_text(cx), "\n");
 7412            assert_eq!(
 7413                view.selected_display_ranges(cx),
 7414                &[
 7415                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7416                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7417                ]
 7418            );
 7419        });
 7420    }
 7421
 7422    #[gpui::test]
 7423    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7424        cx.set_global(Settings::test(cx));
 7425        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7426        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7427        view.update(cx, |view, cx| {
 7428            view.select_display_ranges(
 7429                &[
 7430                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7431                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7432                ],
 7433                cx,
 7434            );
 7435
 7436            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7437            assert_selection_ranges(
 7438                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7439                vec![('<', '>'), ('[', ']')],
 7440                view,
 7441                cx,
 7442            );
 7443
 7444            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7445            assert_selection_ranges(
 7446                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7447                vec![('<', '>'), ('[', ']')],
 7448                view,
 7449                cx,
 7450            );
 7451
 7452            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7453            assert_selection_ranges(
 7454                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7455                vec![('<', '>'), ('[', ']')],
 7456                view,
 7457                cx,
 7458            );
 7459
 7460            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7461            assert_selection_ranges(
 7462                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7463                vec![('<', '>'), ('[', ']')],
 7464                view,
 7465                cx,
 7466            );
 7467
 7468            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7469            assert_selection_ranges(
 7470                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7471                vec![('<', '>'), ('[', ']')],
 7472                view,
 7473                cx,
 7474            );
 7475
 7476            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7477            assert_selection_ranges(
 7478                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7479                vec![('<', '>'), ('[', ']')],
 7480                view,
 7481                cx,
 7482            );
 7483
 7484            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7485            assert_selection_ranges(
 7486                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7487                vec![('<', '>'), ('[', ']')],
 7488                view,
 7489                cx,
 7490            );
 7491
 7492            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7493            assert_selection_ranges(
 7494                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7495                vec![('<', '>'), ('[', ']')],
 7496                view,
 7497                cx,
 7498            );
 7499
 7500            view.move_right(&MoveRight, cx);
 7501            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7502            assert_selection_ranges(
 7503                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7504                vec![('<', '>'), ('[', ']')],
 7505                view,
 7506                cx,
 7507            );
 7508
 7509            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7510            assert_selection_ranges(
 7511                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7512                vec![('<', '>'), ('[', ']')],
 7513                view,
 7514                cx,
 7515            );
 7516
 7517            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7518            assert_selection_ranges(
 7519                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7520                vec![('<', '>'), ('[', ']')],
 7521                view,
 7522                cx,
 7523            );
 7524        });
 7525    }
 7526
 7527    #[gpui::test]
 7528    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7529        cx.set_global(Settings::test(cx));
 7530        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7531        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7532
 7533        view.update(cx, |view, cx| {
 7534            view.set_wrap_width(Some(140.), cx);
 7535            assert_eq!(
 7536                view.display_text(cx),
 7537                "use one::{\n    two::three::\n    four::five\n};"
 7538            );
 7539
 7540            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7541
 7542            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7543            assert_eq!(
 7544                view.selected_display_ranges(cx),
 7545                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7546            );
 7547
 7548            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7549            assert_eq!(
 7550                view.selected_display_ranges(cx),
 7551                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7552            );
 7553
 7554            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7555            assert_eq!(
 7556                view.selected_display_ranges(cx),
 7557                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7558            );
 7559
 7560            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7561            assert_eq!(
 7562                view.selected_display_ranges(cx),
 7563                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7564            );
 7565
 7566            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7567            assert_eq!(
 7568                view.selected_display_ranges(cx),
 7569                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7570            );
 7571
 7572            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7573            assert_eq!(
 7574                view.selected_display_ranges(cx),
 7575                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7576            );
 7577        });
 7578    }
 7579
 7580    #[gpui::test]
 7581    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7582        cx.set_global(Settings::test(cx));
 7583        let (text, ranges) = marked_text_ranges("one [two three] four");
 7584        let buffer = MultiBuffer::build_simple(&text, cx);
 7585
 7586        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7587
 7588        editor.update(cx, |editor, cx| {
 7589            editor.select_ranges(ranges, None, cx);
 7590            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7591            assert_eq!(editor.text(cx), " four");
 7592        });
 7593    }
 7594
 7595    #[gpui::test]
 7596    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7597        cx.set_global(Settings::test(cx));
 7598        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7599        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7600
 7601        view.update(cx, |view, cx| {
 7602            view.select_display_ranges(
 7603                &[
 7604                    // an empty selection - the preceding word fragment is deleted
 7605                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7606                    // characters selected - they are deleted
 7607                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7608                ],
 7609                cx,
 7610            );
 7611            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7612        });
 7613
 7614        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7615
 7616        view.update(cx, |view, cx| {
 7617            view.select_display_ranges(
 7618                &[
 7619                    // an empty selection - the following word fragment is deleted
 7620                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7621                    // characters selected - they are deleted
 7622                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7623                ],
 7624                cx,
 7625            );
 7626            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7627        });
 7628
 7629        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7630    }
 7631
 7632    #[gpui::test]
 7633    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7634        cx.set_global(Settings::test(cx));
 7635        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7636        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7637
 7638        view.update(cx, |view, cx| {
 7639            view.select_display_ranges(
 7640                &[
 7641                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7642                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7643                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7644                ],
 7645                cx,
 7646            );
 7647
 7648            view.newline(&Newline, cx);
 7649            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7650        });
 7651    }
 7652
 7653    #[gpui::test]
 7654    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7655        cx.set_global(Settings::test(cx));
 7656        let buffer = MultiBuffer::build_simple(
 7657            "
 7658                a
 7659                b(
 7660                    X
 7661                )
 7662                c(
 7663                    X
 7664                )
 7665            "
 7666            .unindent()
 7667            .as_str(),
 7668            cx,
 7669        );
 7670
 7671        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7672            let mut editor = build_editor(buffer.clone(), cx);
 7673            editor.select_ranges(
 7674                [
 7675                    Point::new(2, 4)..Point::new(2, 5),
 7676                    Point::new(5, 4)..Point::new(5, 5),
 7677                ],
 7678                None,
 7679                cx,
 7680            );
 7681            editor
 7682        });
 7683
 7684        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7685        buffer.update(cx, |buffer, cx| {
 7686            buffer.edit(
 7687                [
 7688                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7689                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7690                ],
 7691                cx,
 7692            );
 7693            assert_eq!(
 7694                buffer.read(cx).text(),
 7695                "
 7696                    a
 7697                    b()
 7698                    c()
 7699                "
 7700                .unindent()
 7701            );
 7702        });
 7703
 7704        editor.update(cx, |editor, cx| {
 7705            assert_eq!(
 7706                editor.selected_ranges(cx),
 7707                &[
 7708                    Point::new(1, 2)..Point::new(1, 2),
 7709                    Point::new(2, 2)..Point::new(2, 2),
 7710                ],
 7711            );
 7712
 7713            editor.newline(&Newline, cx);
 7714            assert_eq!(
 7715                editor.text(cx),
 7716                "
 7717                    a
 7718                    b(
 7719                    )
 7720                    c(
 7721                    )
 7722                "
 7723                .unindent()
 7724            );
 7725
 7726            // The selections are moved after the inserted newlines
 7727            assert_eq!(
 7728                editor.selected_ranges(cx),
 7729                &[
 7730                    Point::new(2, 0)..Point::new(2, 0),
 7731                    Point::new(4, 0)..Point::new(4, 0),
 7732                ],
 7733            );
 7734        });
 7735    }
 7736
 7737    #[gpui::test]
 7738    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7739        cx.set_global(Settings::test(cx));
 7740        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7741        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7742            let mut editor = build_editor(buffer.clone(), cx);
 7743            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7744            editor
 7745        });
 7746
 7747        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7748        buffer.update(cx, |buffer, cx| {
 7749            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7750            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7751        });
 7752
 7753        editor.update(cx, |editor, cx| {
 7754            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7755
 7756            editor.insert("Z", cx);
 7757            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7758
 7759            // The selections are moved after the inserted characters
 7760            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7761        });
 7762    }
 7763
 7764    #[gpui::test]
 7765    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7766        cx.set_global(Settings::test(cx));
 7767        let buffer = MultiBuffer::build_simple(
 7768            indoc! {"
 7769                  one two
 7770                three
 7771                 four"},
 7772            cx,
 7773        );
 7774        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7775
 7776        view.update(cx, |view, cx| {
 7777            // two selections on the same line
 7778            select_ranges(
 7779                view,
 7780                indoc! {"
 7781                      [one] [two]
 7782                    three
 7783                     four"},
 7784                cx,
 7785            );
 7786
 7787            // indent from mid-tabstop to full tabstop
 7788            view.tab(&Tab, cx);
 7789            assert_text_with_selections(
 7790                view,
 7791                indoc! {"
 7792                        [one] [two]
 7793                    three
 7794                     four"},
 7795                cx,
 7796            );
 7797
 7798            // outdent from 1 tabstop to 0 tabstops
 7799            view.tab_prev(&TabPrev, cx);
 7800            assert_text_with_selections(
 7801                view,
 7802                indoc! {"
 7803                    [one] [two]
 7804                    three
 7805                     four"},
 7806                cx,
 7807            );
 7808
 7809            // select across line ending
 7810            select_ranges(
 7811                view,
 7812                indoc! {"
 7813                    one two
 7814                    t[hree
 7815                    ] four"},
 7816                cx,
 7817            );
 7818
 7819            // indent and outdent affect only the preceding line
 7820            view.tab(&Tab, cx);
 7821            assert_text_with_selections(
 7822                view,
 7823                indoc! {"
 7824                    one two
 7825                        t[hree
 7826                    ] four"},
 7827                cx,
 7828            );
 7829            view.tab_prev(&TabPrev, cx);
 7830            assert_text_with_selections(
 7831                view,
 7832                indoc! {"
 7833                    one two
 7834                    t[hree
 7835                    ] four"},
 7836                cx,
 7837            );
 7838
 7839            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7840            select_ranges(
 7841                view,
 7842                indoc! {"
 7843                    one two
 7844                    []three
 7845                     four"},
 7846                cx,
 7847            );
 7848            view.tab(&Tab, cx);
 7849            assert_text_with_selections(
 7850                view,
 7851                indoc! {"
 7852                    one two
 7853                        []three
 7854                     four"},
 7855                cx,
 7856            );
 7857
 7858            select_ranges(
 7859                view,
 7860                indoc! {"
 7861                    one two
 7862                    []    three
 7863                     four"},
 7864                cx,
 7865            );
 7866            view.tab_prev(&TabPrev, cx);
 7867            assert_text_with_selections(
 7868                view,
 7869                indoc! {"
 7870                    one two
 7871                    []three
 7872                     four"},
 7873                cx,
 7874            );
 7875        });
 7876    }
 7877
 7878    #[gpui::test]
 7879    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7880        cx.set_global(
 7881            Settings::test(cx)
 7882                .with_overrides(
 7883                    "TOML",
 7884                    LanguageOverride {
 7885                        tab_size: Some(2),
 7886                        ..Default::default()
 7887                    },
 7888                )
 7889                .with_overrides(
 7890                    "Rust",
 7891                    LanguageOverride {
 7892                        tab_size: Some(4),
 7893                        ..Default::default()
 7894                    },
 7895                ),
 7896        );
 7897        let toml_language = Arc::new(Language::new(
 7898            LanguageConfig {
 7899                name: "TOML".into(),
 7900                ..Default::default()
 7901            },
 7902            None,
 7903        ));
 7904        let rust_language = Arc::new(Language::new(
 7905            LanguageConfig {
 7906                name: "Rust".into(),
 7907                ..Default::default()
 7908            },
 7909            None,
 7910        ));
 7911
 7912        let toml_buffer = cx
 7913            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7914        let rust_buffer = cx.add_model(|cx| {
 7915            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7916        });
 7917        let multibuffer = cx.add_model(|cx| {
 7918            let mut multibuffer = MultiBuffer::new(0);
 7919            multibuffer.push_excerpts(
 7920                toml_buffer.clone(),
 7921                [Point::new(0, 0)..Point::new(2, 0)],
 7922                cx,
 7923            );
 7924            multibuffer.push_excerpts(
 7925                rust_buffer.clone(),
 7926                [Point::new(0, 0)..Point::new(1, 0)],
 7927                cx,
 7928            );
 7929            multibuffer
 7930        });
 7931
 7932        cx.add_window(Default::default(), |cx| {
 7933            let mut editor = build_editor(multibuffer, cx);
 7934
 7935            assert_eq!(
 7936                editor.text(cx),
 7937                indoc! {"
 7938                    a = 1
 7939                    b = 2
 7940
 7941                    const c: usize = 3;
 7942                "}
 7943            );
 7944
 7945            select_ranges(
 7946                &mut editor,
 7947                indoc! {"
 7948                    [a] = 1
 7949                    b = 2
 7950
 7951                    [const c:] usize = 3;
 7952                "},
 7953                cx,
 7954            );
 7955
 7956            editor.tab(&Tab, 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            editor.tab_prev(&TabPrev, cx);
 7968            assert_text_with_selections(
 7969                &mut editor,
 7970                indoc! {"
 7971                    [a] = 1
 7972                    b = 2
 7973
 7974                    [const c:] usize = 3;
 7975                "},
 7976                cx,
 7977            );
 7978
 7979            editor
 7980        });
 7981    }
 7982
 7983    #[gpui::test]
 7984    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 7985        cx.set_global(Settings::test(cx));
 7986        let (_, view) = cx.add_window(Default::default(), |cx| {
 7987            build_editor(MultiBuffer::build_simple("", cx), cx)
 7988        });
 7989
 7990        view.update(cx, |view, cx| {
 7991            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7992            view.select_display_ranges(
 7993                &[
 7994                    // an empty selection - the preceding character is deleted
 7995                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7996                    // one character selected - it is deleted
 7997                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7998                    // a line suffix selected - it is deleted
 7999                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 8000                ],
 8001                cx,
 8002            );
 8003            view.backspace(&Backspace, cx);
 8004            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 8005
 8006            view.set_text("    one\n        two\n        three\n   four", cx);
 8007            view.select_display_ranges(
 8008                &[
 8009                    // cursors at the the end of leading indent - last indent is deleted
 8010                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 8011                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 8012                    // cursors inside leading indent - overlapping indent deletions are coalesced
 8013                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 8014                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8015                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 8016                    // cursor at the beginning of a line - preceding newline is deleted
 8017                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8018                    // selection inside leading indent - only the selected character is deleted
 8019                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 8020                ],
 8021                cx,
 8022            );
 8023            view.backspace(&Backspace, cx);
 8024            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 8025        });
 8026    }
 8027
 8028    #[gpui::test]
 8029    fn test_delete(cx: &mut gpui::MutableAppContext) {
 8030        cx.set_global(Settings::test(cx));
 8031        let buffer =
 8032            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 8033        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 8034
 8035        view.update(cx, |view, cx| {
 8036            view.select_display_ranges(
 8037                &[
 8038                    // an empty selection - the following character is deleted
 8039                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8040                    // one character selected - it is deleted
 8041                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8042                    // a line suffix selected - it is deleted
 8043                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 8044                ],
 8045                cx,
 8046            );
 8047            view.delete(&Delete, cx);
 8048        });
 8049
 8050        assert_eq!(
 8051            buffer.read(cx).read(cx).text(),
 8052            "on two three\nfou five six\nseven ten\n"
 8053        );
 8054    }
 8055
 8056    #[gpui::test]
 8057    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8058        cx.set_global(Settings::test(cx));
 8059        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8060        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8061        view.update(cx, |view, cx| {
 8062            view.select_display_ranges(
 8063                &[
 8064                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8065                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8066                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8067                ],
 8068                cx,
 8069            );
 8070            view.delete_line(&DeleteLine, cx);
 8071            assert_eq!(view.display_text(cx), "ghi");
 8072            assert_eq!(
 8073                view.selected_display_ranges(cx),
 8074                vec![
 8075                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8076                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8077                ]
 8078            );
 8079        });
 8080
 8081        cx.set_global(Settings::test(cx));
 8082        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8083        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8084        view.update(cx, |view, cx| {
 8085            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 8086            view.delete_line(&DeleteLine, cx);
 8087            assert_eq!(view.display_text(cx), "ghi\n");
 8088            assert_eq!(
 8089                view.selected_display_ranges(cx),
 8090                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8091            );
 8092        });
 8093    }
 8094
 8095    #[gpui::test]
 8096    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8097        cx.set_global(Settings::test(cx));
 8098        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8099        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8100        view.update(cx, |view, cx| {
 8101            view.select_display_ranges(
 8102                &[
 8103                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8104                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8105                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8106                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8107                ],
 8108                cx,
 8109            );
 8110            view.duplicate_line(&DuplicateLine, cx);
 8111            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8112            assert_eq!(
 8113                view.selected_display_ranges(cx),
 8114                vec![
 8115                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8116                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8117                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8118                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8119                ]
 8120            );
 8121        });
 8122
 8123        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8124        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8125        view.update(cx, |view, cx| {
 8126            view.select_display_ranges(
 8127                &[
 8128                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8129                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8130                ],
 8131                cx,
 8132            );
 8133            view.duplicate_line(&DuplicateLine, cx);
 8134            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8135            assert_eq!(
 8136                view.selected_display_ranges(cx),
 8137                vec![
 8138                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8139                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8140                ]
 8141            );
 8142        });
 8143    }
 8144
 8145    #[gpui::test]
 8146    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8147        cx.set_global(Settings::test(cx));
 8148        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8149        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8150        view.update(cx, |view, cx| {
 8151            view.fold_ranges(
 8152                vec![
 8153                    Point::new(0, 2)..Point::new(1, 2),
 8154                    Point::new(2, 3)..Point::new(4, 1),
 8155                    Point::new(7, 0)..Point::new(8, 4),
 8156                ],
 8157                cx,
 8158            );
 8159            view.select_display_ranges(
 8160                &[
 8161                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8162                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8163                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8164                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8165                ],
 8166                cx,
 8167            );
 8168            assert_eq!(
 8169                view.display_text(cx),
 8170                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8171            );
 8172
 8173            view.move_line_up(&MoveLineUp, cx);
 8174            assert_eq!(
 8175                view.display_text(cx),
 8176                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8177            );
 8178            assert_eq!(
 8179                view.selected_display_ranges(cx),
 8180                vec![
 8181                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8182                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8183                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8184                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8185                ]
 8186            );
 8187        });
 8188
 8189        view.update(cx, |view, cx| {
 8190            view.move_line_down(&MoveLineDown, cx);
 8191            assert_eq!(
 8192                view.display_text(cx),
 8193                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8194            );
 8195            assert_eq!(
 8196                view.selected_display_ranges(cx),
 8197                vec![
 8198                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8199                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8200                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8201                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8202                ]
 8203            );
 8204        });
 8205
 8206        view.update(cx, |view, cx| {
 8207            view.move_line_down(&MoveLineDown, cx);
 8208            assert_eq!(
 8209                view.display_text(cx),
 8210                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8211            );
 8212            assert_eq!(
 8213                view.selected_display_ranges(cx),
 8214                vec![
 8215                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8216                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8217                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8218                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8219                ]
 8220            );
 8221        });
 8222
 8223        view.update(cx, |view, cx| {
 8224            view.move_line_up(&MoveLineUp, cx);
 8225            assert_eq!(
 8226                view.display_text(cx),
 8227                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8228            );
 8229            assert_eq!(
 8230                view.selected_display_ranges(cx),
 8231                vec![
 8232                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8233                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8234                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8235                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8236                ]
 8237            );
 8238        });
 8239    }
 8240
 8241    #[gpui::test]
 8242    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8243        cx.set_global(Settings::test(cx));
 8244        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8245        let snapshot = buffer.read(cx).snapshot(cx);
 8246        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8247        editor.update(cx, |editor, cx| {
 8248            editor.insert_blocks(
 8249                [BlockProperties {
 8250                    position: snapshot.anchor_after(Point::new(2, 0)),
 8251                    disposition: BlockDisposition::Below,
 8252                    height: 1,
 8253                    render: Arc::new(|_| Empty::new().boxed()),
 8254                }],
 8255                cx,
 8256            );
 8257            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8258            editor.move_line_down(&MoveLineDown, cx);
 8259        });
 8260    }
 8261
 8262    #[gpui::test]
 8263    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8264        cx.set_global(Settings::test(cx));
 8265
 8266        cx.add_window(Default::default(), |cx| {
 8267            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8268
 8269            editor.select_ranges([1..1], None, cx);
 8270            editor.transpose(&Default::default(), cx);
 8271            assert_eq!(editor.text(cx), "bac");
 8272            assert_eq!(editor.selected_ranges(cx), [2..2]);
 8273
 8274            editor.transpose(&Default::default(), cx);
 8275            assert_eq!(editor.text(cx), "bca");
 8276            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8277
 8278            editor.transpose(&Default::default(), cx);
 8279            assert_eq!(editor.text(cx), "bac");
 8280            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8281
 8282            editor
 8283        })
 8284        .1;
 8285
 8286        cx.add_window(Default::default(), |cx| {
 8287            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8288
 8289            editor.select_ranges([3..3], None, cx);
 8290            editor.transpose(&Default::default(), cx);
 8291            assert_eq!(editor.text(cx), "acb\nde");
 8292            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8293
 8294            editor.select_ranges([4..4], None, cx);
 8295            editor.transpose(&Default::default(), cx);
 8296            assert_eq!(editor.text(cx), "acbd\ne");
 8297            assert_eq!(editor.selected_ranges(cx), [5..5]);
 8298
 8299            editor.transpose(&Default::default(), cx);
 8300            assert_eq!(editor.text(cx), "acbde\n");
 8301            assert_eq!(editor.selected_ranges(cx), [6..6]);
 8302
 8303            editor.transpose(&Default::default(), cx);
 8304            assert_eq!(editor.text(cx), "acbd\ne");
 8305            assert_eq!(editor.selected_ranges(cx), [6..6]);
 8306
 8307            editor
 8308        })
 8309        .1;
 8310
 8311        cx.add_window(Default::default(), |cx| {
 8312            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8313
 8314            editor.select_ranges([1..1, 2..2, 4..4], None, cx);
 8315            editor.transpose(&Default::default(), cx);
 8316            assert_eq!(editor.text(cx), "bacd\ne");
 8317            assert_eq!(editor.selected_ranges(cx), [2..2, 3..3, 5..5]);
 8318
 8319            editor.transpose(&Default::default(), cx);
 8320            assert_eq!(editor.text(cx), "bcade\n");
 8321            assert_eq!(editor.selected_ranges(cx), [3..3, 4..4, 6..6]);
 8322
 8323            editor.transpose(&Default::default(), cx);
 8324            assert_eq!(editor.text(cx), "bcda\ne");
 8325            assert_eq!(editor.selected_ranges(cx), [4..4, 6..6]);
 8326
 8327            editor.transpose(&Default::default(), cx);
 8328            assert_eq!(editor.text(cx), "bcade\n");
 8329            assert_eq!(editor.selected_ranges(cx), [4..4, 6..6]);
 8330
 8331            editor.transpose(&Default::default(), cx);
 8332            assert_eq!(editor.text(cx), "bcaed\n");
 8333            assert_eq!(editor.selected_ranges(cx), [5..5, 6..6]);
 8334
 8335            editor
 8336        })
 8337        .1;
 8338
 8339        cx.add_window(Default::default(), |cx| {
 8340            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8341
 8342            editor.select_ranges([4..4], None, cx);
 8343            editor.transpose(&Default::default(), cx);
 8344            assert_eq!(editor.text(cx), "🏀🍐✋");
 8345            assert_eq!(editor.selected_ranges(cx), [8..8]);
 8346
 8347            editor.transpose(&Default::default(), cx);
 8348            assert_eq!(editor.text(cx), "🏀✋🍐");
 8349            assert_eq!(editor.selected_ranges(cx), [11..11]);
 8350
 8351            editor.transpose(&Default::default(), cx);
 8352            assert_eq!(editor.text(cx), "🏀🍐✋");
 8353            assert_eq!(editor.selected_ranges(cx), [11..11]);
 8354
 8355            editor
 8356        })
 8357        .1;
 8358    }
 8359
 8360    #[gpui::test]
 8361    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8362        cx.set_global(Settings::test(cx));
 8363        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8364        let view = cx
 8365            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8366            .1;
 8367
 8368        // Cut with three selections. Clipboard text is divided into three slices.
 8369        view.update(cx, |view, cx| {
 8370            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8371            view.cut(&Cut, cx);
 8372            assert_eq!(view.display_text(cx), "two four six ");
 8373        });
 8374
 8375        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8376        view.update(cx, |view, cx| {
 8377            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8378            view.paste(&Paste, cx);
 8379            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8380            assert_eq!(
 8381                view.selected_display_ranges(cx),
 8382                &[
 8383                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8384                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8385                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8386                ]
 8387            );
 8388        });
 8389
 8390        // Paste again but with only two cursors. Since the number of cursors doesn't
 8391        // match the number of slices in the clipboard, the entire clipboard text
 8392        // is pasted at each cursor.
 8393        view.update(cx, |view, cx| {
 8394            view.select_ranges(vec![0..0, 31..31], None, cx);
 8395            view.handle_input(&Input("( ".into()), cx);
 8396            view.paste(&Paste, cx);
 8397            view.handle_input(&Input(") ".into()), cx);
 8398            assert_eq!(
 8399                view.display_text(cx),
 8400                "( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8401            );
 8402        });
 8403
 8404        view.update(cx, |view, cx| {
 8405            view.select_ranges(vec![0..0], None, cx);
 8406            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8407            assert_eq!(
 8408                view.display_text(cx),
 8409                "123\n4567\n89\n( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8410            );
 8411        });
 8412
 8413        // Cut with three selections, one of which is full-line.
 8414        view.update(cx, |view, cx| {
 8415            view.select_display_ranges(
 8416                &[
 8417                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8418                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8419                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8420                ],
 8421                cx,
 8422            );
 8423            view.cut(&Cut, cx);
 8424            assert_eq!(
 8425                view.display_text(cx),
 8426                "13\n9\n( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8427            );
 8428        });
 8429
 8430        // Paste with three selections, noticing how the copied selection that was full-line
 8431        // gets inserted before the second cursor.
 8432        view.update(cx, |view, cx| {
 8433            view.select_display_ranges(
 8434                &[
 8435                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8436                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8437                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8438                ],
 8439                cx,
 8440            );
 8441            view.paste(&Paste, cx);
 8442            assert_eq!(
 8443                view.display_text(cx),
 8444                "123\n4567\n9\n( 8ne✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8445            );
 8446            assert_eq!(
 8447                view.selected_display_ranges(cx),
 8448                &[
 8449                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8450                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8451                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8452                ]
 8453            );
 8454        });
 8455
 8456        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8457        view.update(cx, |view, cx| {
 8458            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8459            view.copy(&Copy, cx);
 8460        });
 8461
 8462        // Paste with three selections, noticing how the copied full-line selection is inserted
 8463        // before the empty selections but replaces the selection that is non-empty.
 8464        view.update(cx, |view, cx| {
 8465            view.select_display_ranges(
 8466                &[
 8467                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8468                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8469                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8470                ],
 8471                cx,
 8472            );
 8473            view.paste(&Paste, cx);
 8474            assert_eq!(
 8475                view.display_text(cx),
 8476                "123\n123\n123\n67\n123\n9\n( 8ne✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8477            );
 8478            assert_eq!(
 8479                view.selected_display_ranges(cx),
 8480                &[
 8481                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8482                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8483                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8484                ]
 8485            );
 8486        });
 8487    }
 8488
 8489    #[gpui::test]
 8490    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8491        cx.set_global(Settings::test(cx));
 8492        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8493        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8494        view.update(cx, |view, cx| {
 8495            view.select_all(&SelectAll, cx);
 8496            assert_eq!(
 8497                view.selected_display_ranges(cx),
 8498                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8499            );
 8500        });
 8501    }
 8502
 8503    #[gpui::test]
 8504    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8505        cx.set_global(Settings::test(cx));
 8506        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8507        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8508        view.update(cx, |view, cx| {
 8509            view.select_display_ranges(
 8510                &[
 8511                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8512                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8513                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8514                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8515                ],
 8516                cx,
 8517            );
 8518            view.select_line(&SelectLine, cx);
 8519            assert_eq!(
 8520                view.selected_display_ranges(cx),
 8521                vec![
 8522                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8523                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8524                ]
 8525            );
 8526        });
 8527
 8528        view.update(cx, |view, cx| {
 8529            view.select_line(&SelectLine, cx);
 8530            assert_eq!(
 8531                view.selected_display_ranges(cx),
 8532                vec![
 8533                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8534                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8535                ]
 8536            );
 8537        });
 8538
 8539        view.update(cx, |view, cx| {
 8540            view.select_line(&SelectLine, cx);
 8541            assert_eq!(
 8542                view.selected_display_ranges(cx),
 8543                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8544            );
 8545        });
 8546    }
 8547
 8548    #[gpui::test]
 8549    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8550        cx.set_global(Settings::test(cx));
 8551        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8552        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8553        view.update(cx, |view, cx| {
 8554            view.fold_ranges(
 8555                vec![
 8556                    Point::new(0, 2)..Point::new(1, 2),
 8557                    Point::new(2, 3)..Point::new(4, 1),
 8558                    Point::new(7, 0)..Point::new(8, 4),
 8559                ],
 8560                cx,
 8561            );
 8562            view.select_display_ranges(
 8563                &[
 8564                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8565                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8566                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8567                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8568                ],
 8569                cx,
 8570            );
 8571            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8572        });
 8573
 8574        view.update(cx, |view, cx| {
 8575            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8576            assert_eq!(
 8577                view.display_text(cx),
 8578                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8579            );
 8580            assert_eq!(
 8581                view.selected_display_ranges(cx),
 8582                [
 8583                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8584                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8585                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8586                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8587                ]
 8588            );
 8589        });
 8590
 8591        view.update(cx, |view, cx| {
 8592            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8593            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8594            assert_eq!(
 8595                view.display_text(cx),
 8596                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8597            );
 8598            assert_eq!(
 8599                view.selected_display_ranges(cx),
 8600                [
 8601                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8602                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8603                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8604                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8605                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8606                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8607                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8608                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8609                ]
 8610            );
 8611        });
 8612    }
 8613
 8614    #[gpui::test]
 8615    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8616        cx.set_global(Settings::test(cx));
 8617        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8618        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8619
 8620        view.update(cx, |view, cx| {
 8621            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8622        });
 8623        view.update(cx, |view, cx| {
 8624            view.add_selection_above(&AddSelectionAbove, cx);
 8625            assert_eq!(
 8626                view.selected_display_ranges(cx),
 8627                vec![
 8628                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8629                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8630                ]
 8631            );
 8632        });
 8633
 8634        view.update(cx, |view, cx| {
 8635            view.add_selection_above(&AddSelectionAbove, cx);
 8636            assert_eq!(
 8637                view.selected_display_ranges(cx),
 8638                vec![
 8639                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8640                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8641                ]
 8642            );
 8643        });
 8644
 8645        view.update(cx, |view, cx| {
 8646            view.add_selection_below(&AddSelectionBelow, cx);
 8647            assert_eq!(
 8648                view.selected_display_ranges(cx),
 8649                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8650            );
 8651
 8652            view.undo_selection(&UndoSelection, cx);
 8653            assert_eq!(
 8654                view.selected_display_ranges(cx),
 8655                vec![
 8656                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8657                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8658                ]
 8659            );
 8660
 8661            view.redo_selection(&RedoSelection, cx);
 8662            assert_eq!(
 8663                view.selected_display_ranges(cx),
 8664                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8665            );
 8666        });
 8667
 8668        view.update(cx, |view, cx| {
 8669            view.add_selection_below(&AddSelectionBelow, cx);
 8670            assert_eq!(
 8671                view.selected_display_ranges(cx),
 8672                vec![
 8673                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8674                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8675                ]
 8676            );
 8677        });
 8678
 8679        view.update(cx, |view, cx| {
 8680            view.add_selection_below(&AddSelectionBelow, cx);
 8681            assert_eq!(
 8682                view.selected_display_ranges(cx),
 8683                vec![
 8684                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8685                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8686                ]
 8687            );
 8688        });
 8689
 8690        view.update(cx, |view, cx| {
 8691            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8692        });
 8693        view.update(cx, |view, cx| {
 8694            view.add_selection_below(&AddSelectionBelow, cx);
 8695            assert_eq!(
 8696                view.selected_display_ranges(cx),
 8697                vec![
 8698                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8699                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8700                ]
 8701            );
 8702        });
 8703
 8704        view.update(cx, |view, cx| {
 8705            view.add_selection_below(&AddSelectionBelow, cx);
 8706            assert_eq!(
 8707                view.selected_display_ranges(cx),
 8708                vec![
 8709                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8710                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8711                ]
 8712            );
 8713        });
 8714
 8715        view.update(cx, |view, cx| {
 8716            view.add_selection_above(&AddSelectionAbove, cx);
 8717            assert_eq!(
 8718                view.selected_display_ranges(cx),
 8719                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8720            );
 8721        });
 8722
 8723        view.update(cx, |view, cx| {
 8724            view.add_selection_above(&AddSelectionAbove, cx);
 8725            assert_eq!(
 8726                view.selected_display_ranges(cx),
 8727                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8728            );
 8729        });
 8730
 8731        view.update(cx, |view, cx| {
 8732            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8733            view.add_selection_below(&AddSelectionBelow, cx);
 8734            assert_eq!(
 8735                view.selected_display_ranges(cx),
 8736                vec![
 8737                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8738                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8739                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8740                ]
 8741            );
 8742        });
 8743
 8744        view.update(cx, |view, cx| {
 8745            view.add_selection_below(&AddSelectionBelow, cx);
 8746            assert_eq!(
 8747                view.selected_display_ranges(cx),
 8748                vec![
 8749                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8750                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8751                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8752                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8753                ]
 8754            );
 8755        });
 8756
 8757        view.update(cx, |view, cx| {
 8758            view.add_selection_above(&AddSelectionAbove, cx);
 8759            assert_eq!(
 8760                view.selected_display_ranges(cx),
 8761                vec![
 8762                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8763                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8764                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8765                ]
 8766            );
 8767        });
 8768
 8769        view.update(cx, |view, cx| {
 8770            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8771        });
 8772        view.update(cx, |view, cx| {
 8773            view.add_selection_above(&AddSelectionAbove, cx);
 8774            assert_eq!(
 8775                view.selected_display_ranges(cx),
 8776                vec![
 8777                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8778                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8779                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8780                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8781                ]
 8782            );
 8783        });
 8784
 8785        view.update(cx, |view, cx| {
 8786            view.add_selection_below(&AddSelectionBelow, cx);
 8787            assert_eq!(
 8788                view.selected_display_ranges(cx),
 8789                vec![
 8790                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8791                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8792                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8793                ]
 8794            );
 8795        });
 8796    }
 8797
 8798    #[gpui::test]
 8799    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8800        cx.set_global(Settings::test(cx));
 8801
 8802        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8803        let buffer = MultiBuffer::build_simple(&text, cx);
 8804        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8805
 8806        view.update(cx, |view, cx| {
 8807            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8808            view.select_next(
 8809                &SelectNext {
 8810                    replace_newest: false,
 8811                },
 8812                cx,
 8813            );
 8814            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8815
 8816            view.select_next(
 8817                &SelectNext {
 8818                    replace_newest: false,
 8819                },
 8820                cx,
 8821            );
 8822            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8823
 8824            view.undo_selection(&UndoSelection, cx);
 8825            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8826
 8827            view.redo_selection(&RedoSelection, cx);
 8828            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8829
 8830            view.select_next(
 8831                &SelectNext {
 8832                    replace_newest: false,
 8833                },
 8834                cx,
 8835            );
 8836            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8837
 8838            view.select_next(
 8839                &SelectNext {
 8840                    replace_newest: false,
 8841                },
 8842                cx,
 8843            );
 8844            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8845        });
 8846    }
 8847
 8848    #[gpui::test]
 8849    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8850        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8851        let language = Arc::new(Language::new(
 8852            LanguageConfig::default(),
 8853            Some(tree_sitter_rust::language()),
 8854        ));
 8855
 8856        let text = r#"
 8857            use mod1::mod2::{mod3, mod4};
 8858
 8859            fn fn_1(param1: bool, param2: &str) {
 8860                let var1 = "text";
 8861            }
 8862        "#
 8863        .unindent();
 8864
 8865        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8866        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8867        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8868        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8869            .await;
 8870
 8871        view.update(cx, |view, cx| {
 8872            view.select_display_ranges(
 8873                &[
 8874                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8875                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8876                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8877                ],
 8878                cx,
 8879            );
 8880            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8881        });
 8882        assert_eq!(
 8883            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8884            &[
 8885                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8886                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8887                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8888            ]
 8889        );
 8890
 8891        view.update(cx, |view, cx| {
 8892            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8893        });
 8894        assert_eq!(
 8895            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8896            &[
 8897                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8898                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8899            ]
 8900        );
 8901
 8902        view.update(cx, |view, cx| {
 8903            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8904        });
 8905        assert_eq!(
 8906            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8907            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8908        );
 8909
 8910        // Trying to expand the selected syntax node one more time has no effect.
 8911        view.update(cx, |view, cx| {
 8912            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8913        });
 8914        assert_eq!(
 8915            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8916            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8917        );
 8918
 8919        view.update(cx, |view, cx| {
 8920            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8921        });
 8922        assert_eq!(
 8923            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8924            &[
 8925                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8926                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8927            ]
 8928        );
 8929
 8930        view.update(cx, |view, cx| {
 8931            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8932        });
 8933        assert_eq!(
 8934            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8935            &[
 8936                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8937                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8938                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8939            ]
 8940        );
 8941
 8942        view.update(cx, |view, cx| {
 8943            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8944        });
 8945        assert_eq!(
 8946            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8947            &[
 8948                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8949                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8950                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8951            ]
 8952        );
 8953
 8954        // Trying to shrink the selected syntax node one more time has no effect.
 8955        view.update(cx, |view, cx| {
 8956            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8957        });
 8958        assert_eq!(
 8959            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8960            &[
 8961                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8962                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8963                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8964            ]
 8965        );
 8966
 8967        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8968        // a fold.
 8969        view.update(cx, |view, cx| {
 8970            view.fold_ranges(
 8971                vec![
 8972                    Point::new(0, 21)..Point::new(0, 24),
 8973                    Point::new(3, 20)..Point::new(3, 22),
 8974                ],
 8975                cx,
 8976            );
 8977            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8978        });
 8979        assert_eq!(
 8980            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8981            &[
 8982                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8983                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8984                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8985            ]
 8986        );
 8987    }
 8988
 8989    #[gpui::test]
 8990    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8991        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8992        let language = Arc::new(
 8993            Language::new(
 8994                LanguageConfig {
 8995                    brackets: vec![
 8996                        BracketPair {
 8997                            start: "{".to_string(),
 8998                            end: "}".to_string(),
 8999                            close: false,
 9000                            newline: true,
 9001                        },
 9002                        BracketPair {
 9003                            start: "(".to_string(),
 9004                            end: ")".to_string(),
 9005                            close: false,
 9006                            newline: true,
 9007                        },
 9008                    ],
 9009                    ..Default::default()
 9010                },
 9011                Some(tree_sitter_rust::language()),
 9012            )
 9013            .with_indents_query(
 9014                r#"
 9015                (_ "(" ")" @end) @indent
 9016                (_ "{" "}" @end) @indent
 9017                "#,
 9018            )
 9019            .unwrap(),
 9020        );
 9021
 9022        let text = "fn a() {}";
 9023
 9024        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9025        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9026        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9027        editor
 9028            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9029            .await;
 9030
 9031        editor.update(cx, |editor, cx| {
 9032            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 9033            editor.newline(&Newline, cx);
 9034            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9035            assert_eq!(
 9036                editor.selected_ranges(cx),
 9037                &[
 9038                    Point::new(1, 4)..Point::new(1, 4),
 9039                    Point::new(3, 4)..Point::new(3, 4),
 9040                    Point::new(5, 0)..Point::new(5, 0)
 9041                ]
 9042            );
 9043        });
 9044    }
 9045
 9046    #[gpui::test]
 9047    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9048        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9049        let language = Arc::new(Language::new(
 9050            LanguageConfig {
 9051                brackets: vec![
 9052                    BracketPair {
 9053                        start: "{".to_string(),
 9054                        end: "}".to_string(),
 9055                        close: true,
 9056                        newline: true,
 9057                    },
 9058                    BracketPair {
 9059                        start: "/*".to_string(),
 9060                        end: " */".to_string(),
 9061                        close: true,
 9062                        newline: true,
 9063                    },
 9064                ],
 9065                autoclose_before: "})]".to_string(),
 9066                ..Default::default()
 9067            },
 9068            Some(tree_sitter_rust::language()),
 9069        ));
 9070
 9071        let text = r#"
 9072            a
 9073
 9074            /
 9075
 9076        "#
 9077        .unindent();
 9078
 9079        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9080        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9081        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9082        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9083            .await;
 9084
 9085        view.update(cx, |view, cx| {
 9086            view.select_display_ranges(
 9087                &[
 9088                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9089                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9090                ],
 9091                cx,
 9092            );
 9093
 9094            view.handle_input(&Input("{".to_string()), cx);
 9095            view.handle_input(&Input("{".to_string()), cx);
 9096            view.handle_input(&Input("{".to_string()), cx);
 9097            assert_eq!(
 9098                view.text(cx),
 9099                "
 9100                {{{}}}
 9101                {{{}}}
 9102                /
 9103
 9104                "
 9105                .unindent()
 9106            );
 9107
 9108            view.move_right(&MoveRight, cx);
 9109            view.handle_input(&Input("}".to_string()), cx);
 9110            view.handle_input(&Input("}".to_string()), cx);
 9111            view.handle_input(&Input("}".to_string()), cx);
 9112            assert_eq!(
 9113                view.text(cx),
 9114                "
 9115                {{{}}}}
 9116                {{{}}}}
 9117                /
 9118
 9119                "
 9120                .unindent()
 9121            );
 9122
 9123            view.undo(&Undo, cx);
 9124            view.handle_input(&Input("/".to_string()), cx);
 9125            view.handle_input(&Input("*".to_string()), cx);
 9126            assert_eq!(
 9127                view.text(cx),
 9128                "
 9129                /* */
 9130                /* */
 9131                /
 9132
 9133                "
 9134                .unindent()
 9135            );
 9136
 9137            view.undo(&Undo, cx);
 9138            view.select_display_ranges(
 9139                &[
 9140                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9141                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9142                ],
 9143                cx,
 9144            );
 9145            view.handle_input(&Input("*".to_string()), cx);
 9146            assert_eq!(
 9147                view.text(cx),
 9148                "
 9149                a
 9150
 9151                /*
 9152                *
 9153                "
 9154                .unindent()
 9155            );
 9156
 9157            // Don't autoclose if the next character isn't whitespace and isn't
 9158            // listed in the language's "autoclose_before" section.
 9159            view.finalize_last_transaction(cx);
 9160            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 9161            view.handle_input(&Input("{".to_string()), cx);
 9162            assert_eq!(
 9163                view.text(cx),
 9164                "
 9165                {a
 9166
 9167                /*
 9168                *
 9169                "
 9170                .unindent()
 9171            );
 9172
 9173            view.undo(&Undo, cx);
 9174            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 9175            view.handle_input(&Input("{".to_string()), cx);
 9176            assert_eq!(
 9177                view.text(cx),
 9178                "
 9179                {a}
 9180
 9181                /*
 9182                *
 9183                "
 9184                .unindent()
 9185            );
 9186            assert_eq!(
 9187                view.selected_display_ranges(cx),
 9188                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9189            );
 9190        });
 9191    }
 9192
 9193    #[gpui::test]
 9194    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9195        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9196
 9197        let text = "
 9198            a. b
 9199            a. b
 9200            a. b
 9201        "
 9202        .unindent();
 9203        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9204        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9205
 9206        editor.update(cx, |editor, cx| {
 9207            let buffer = &editor.snapshot(cx).buffer_snapshot;
 9208            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9209            let insertion_ranges = [
 9210                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 9211                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 9212                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 9213            ];
 9214
 9215            editor
 9216                .insert_snippet(&insertion_ranges, snippet, cx)
 9217                .unwrap();
 9218            assert_eq!(
 9219                editor.text(cx),
 9220                "
 9221                    a.f(one, two, three) b
 9222                    a.f(one, two, three) b
 9223                    a.f(one, two, three) b
 9224                "
 9225                .unindent()
 9226            );
 9227            assert_eq!(
 9228                editor.selected_ranges::<Point>(cx),
 9229                &[
 9230                    Point::new(0, 4)..Point::new(0, 7),
 9231                    Point::new(0, 14)..Point::new(0, 19),
 9232                    Point::new(1, 4)..Point::new(1, 7),
 9233                    Point::new(1, 14)..Point::new(1, 19),
 9234                    Point::new(2, 4)..Point::new(2, 7),
 9235                    Point::new(2, 14)..Point::new(2, 19),
 9236                ]
 9237            );
 9238
 9239            // Can't move earlier than the first tab stop
 9240            editor.move_to_prev_snippet_tabstop(cx);
 9241            assert_eq!(
 9242                editor.selected_ranges::<Point>(cx),
 9243                &[
 9244                    Point::new(0, 4)..Point::new(0, 7),
 9245                    Point::new(0, 14)..Point::new(0, 19),
 9246                    Point::new(1, 4)..Point::new(1, 7),
 9247                    Point::new(1, 14)..Point::new(1, 19),
 9248                    Point::new(2, 4)..Point::new(2, 7),
 9249                    Point::new(2, 14)..Point::new(2, 19),
 9250                ]
 9251            );
 9252
 9253            assert!(editor.move_to_next_snippet_tabstop(cx));
 9254            assert_eq!(
 9255                editor.selected_ranges::<Point>(cx),
 9256                &[
 9257                    Point::new(0, 9)..Point::new(0, 12),
 9258                    Point::new(1, 9)..Point::new(1, 12),
 9259                    Point::new(2, 9)..Point::new(2, 12)
 9260                ]
 9261            );
 9262
 9263            editor.move_to_prev_snippet_tabstop(cx);
 9264            assert_eq!(
 9265                editor.selected_ranges::<Point>(cx),
 9266                &[
 9267                    Point::new(0, 4)..Point::new(0, 7),
 9268                    Point::new(0, 14)..Point::new(0, 19),
 9269                    Point::new(1, 4)..Point::new(1, 7),
 9270                    Point::new(1, 14)..Point::new(1, 19),
 9271                    Point::new(2, 4)..Point::new(2, 7),
 9272                    Point::new(2, 14)..Point::new(2, 19),
 9273                ]
 9274            );
 9275
 9276            assert!(editor.move_to_next_snippet_tabstop(cx));
 9277            assert!(editor.move_to_next_snippet_tabstop(cx));
 9278            assert_eq!(
 9279                editor.selected_ranges::<Point>(cx),
 9280                &[
 9281                    Point::new(0, 20)..Point::new(0, 20),
 9282                    Point::new(1, 20)..Point::new(1, 20),
 9283                    Point::new(2, 20)..Point::new(2, 20)
 9284                ]
 9285            );
 9286
 9287            // As soon as the last tab stop is reached, snippet state is gone
 9288            editor.move_to_prev_snippet_tabstop(cx);
 9289            assert_eq!(
 9290                editor.selected_ranges::<Point>(cx),
 9291                &[
 9292                    Point::new(0, 20)..Point::new(0, 20),
 9293                    Point::new(1, 20)..Point::new(1, 20),
 9294                    Point::new(2, 20)..Point::new(2, 20)
 9295                ]
 9296            );
 9297        });
 9298    }
 9299
 9300    #[gpui::test]
 9301    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9302        cx.foreground().forbid_parking();
 9303        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9304
 9305        let mut language = Language::new(
 9306            LanguageConfig {
 9307                name: "Rust".into(),
 9308                path_suffixes: vec!["rs".to_string()],
 9309                ..Default::default()
 9310            },
 9311            Some(tree_sitter_rust::language()),
 9312        );
 9313        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9314            capabilities: lsp::ServerCapabilities {
 9315                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9316                ..Default::default()
 9317            },
 9318            ..Default::default()
 9319        });
 9320
 9321        let fs = FakeFs::new(cx.background().clone());
 9322        fs.insert_file("/file.rs", Default::default()).await;
 9323
 9324        let project = Project::test(fs, cx);
 9325        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9326
 9327        let worktree_id = project
 9328            .update(cx, |project, cx| {
 9329                project.find_or_create_local_worktree("/file.rs", true, cx)
 9330            })
 9331            .await
 9332            .unwrap()
 9333            .0
 9334            .read_with(cx, |tree, _| tree.id());
 9335        let buffer = project
 9336            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9337            .await
 9338            .unwrap();
 9339
 9340        cx.foreground().start_waiting();
 9341        let fake_server = fake_servers.next().await.unwrap();
 9342
 9343        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9344        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9345        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9346        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9347
 9348        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9349        fake_server
 9350            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9351                assert_eq!(
 9352                    params.text_document.uri,
 9353                    lsp::Url::from_file_path("/file.rs").unwrap()
 9354                );
 9355                assert_eq!(params.options.tab_size, 4);
 9356                Ok(Some(vec![lsp::TextEdit::new(
 9357                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9358                    ", ".to_string(),
 9359                )]))
 9360            })
 9361            .next()
 9362            .await;
 9363        cx.foreground().start_waiting();
 9364        save.await.unwrap();
 9365        assert_eq!(
 9366            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9367            "one, two\nthree\n"
 9368        );
 9369        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9370
 9371        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9372        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9373
 9374        // Ensure we can still save even if formatting hangs.
 9375        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9376            assert_eq!(
 9377                params.text_document.uri,
 9378                lsp::Url::from_file_path("/file.rs").unwrap()
 9379            );
 9380            futures::future::pending::<()>().await;
 9381            unreachable!()
 9382        });
 9383        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9384        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9385        cx.foreground().start_waiting();
 9386        save.await.unwrap();
 9387        assert_eq!(
 9388            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9389            "one\ntwo\nthree\n"
 9390        );
 9391        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9392
 9393        // Set rust language override and assert overriden tabsize is sent to language server
 9394        cx.update(|cx| {
 9395            cx.update_global::<Settings, _, _>(|settings, _| {
 9396                settings.language_overrides.insert(
 9397                    "Rust".into(),
 9398                    LanguageOverride {
 9399                        tab_size: Some(8),
 9400                        ..Default::default()
 9401                    },
 9402                );
 9403            })
 9404        });
 9405
 9406        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9407        fake_server
 9408            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9409                assert_eq!(
 9410                    params.text_document.uri,
 9411                    lsp::Url::from_file_path("/file.rs").unwrap()
 9412                );
 9413                assert_eq!(params.options.tab_size, 8);
 9414                Ok(Some(vec![]))
 9415            })
 9416            .next()
 9417            .await;
 9418        cx.foreground().start_waiting();
 9419        save.await.unwrap();
 9420    }
 9421
 9422    #[gpui::test]
 9423    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9424        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9425
 9426        let mut language = Language::new(
 9427            LanguageConfig {
 9428                name: "Rust".into(),
 9429                path_suffixes: vec!["rs".to_string()],
 9430                ..Default::default()
 9431            },
 9432            Some(tree_sitter_rust::language()),
 9433        );
 9434        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9435            capabilities: lsp::ServerCapabilities {
 9436                completion_provider: Some(lsp::CompletionOptions {
 9437                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9438                    ..Default::default()
 9439                }),
 9440                ..Default::default()
 9441            },
 9442            ..Default::default()
 9443        });
 9444
 9445        let text = "
 9446            one
 9447            two
 9448            three
 9449        "
 9450        .unindent();
 9451
 9452        let fs = FakeFs::new(cx.background().clone());
 9453        fs.insert_file("/file.rs", text).await;
 9454
 9455        let project = Project::test(fs, cx);
 9456        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9457
 9458        let worktree_id = project
 9459            .update(cx, |project, cx| {
 9460                project.find_or_create_local_worktree("/file.rs", true, cx)
 9461            })
 9462            .await
 9463            .unwrap()
 9464            .0
 9465            .read_with(cx, |tree, _| tree.id());
 9466        let buffer = project
 9467            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9468            .await
 9469            .unwrap();
 9470        let mut fake_server = fake_servers.next().await.unwrap();
 9471
 9472        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9473        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9474
 9475        editor.update(cx, |editor, cx| {
 9476            editor.project = Some(project);
 9477            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9478            editor.handle_input(&Input(".".to_string()), cx);
 9479        });
 9480
 9481        handle_completion_request(
 9482            &mut fake_server,
 9483            "/file.rs",
 9484            Point::new(0, 4),
 9485            vec![
 9486                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9487                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9488            ],
 9489        )
 9490        .await;
 9491        editor
 9492            .condition(&cx, |editor, _| editor.context_menu_visible())
 9493            .await;
 9494
 9495        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9496            editor.move_down(&MoveDown, cx);
 9497            let apply_additional_edits = editor
 9498                .confirm_completion(&ConfirmCompletion::default(), cx)
 9499                .unwrap();
 9500            assert_eq!(
 9501                editor.text(cx),
 9502                "
 9503                    one.second_completion
 9504                    two
 9505                    three
 9506                "
 9507                .unindent()
 9508            );
 9509            apply_additional_edits
 9510        });
 9511
 9512        handle_resolve_completion_request(
 9513            &mut fake_server,
 9514            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9515        )
 9516        .await;
 9517        apply_additional_edits.await.unwrap();
 9518        assert_eq!(
 9519            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9520            "
 9521                one.second_completion
 9522                two
 9523                three
 9524                additional edit
 9525            "
 9526            .unindent()
 9527        );
 9528
 9529        editor.update(cx, |editor, cx| {
 9530            editor.select_ranges(
 9531                [
 9532                    Point::new(1, 3)..Point::new(1, 3),
 9533                    Point::new(2, 5)..Point::new(2, 5),
 9534                ],
 9535                None,
 9536                cx,
 9537            );
 9538
 9539            editor.handle_input(&Input(" ".to_string()), cx);
 9540            assert!(editor.context_menu.is_none());
 9541            editor.handle_input(&Input("s".to_string()), cx);
 9542            assert!(editor.context_menu.is_none());
 9543        });
 9544
 9545        handle_completion_request(
 9546            &mut fake_server,
 9547            "/file.rs",
 9548            Point::new(2, 7),
 9549            vec![
 9550                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9551                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9552                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9553            ],
 9554        )
 9555        .await;
 9556        editor
 9557            .condition(&cx, |editor, _| editor.context_menu_visible())
 9558            .await;
 9559
 9560        editor.update(cx, |editor, cx| {
 9561            editor.handle_input(&Input("i".to_string()), cx);
 9562        });
 9563
 9564        handle_completion_request(
 9565            &mut fake_server,
 9566            "/file.rs",
 9567            Point::new(2, 8),
 9568            vec![
 9569                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9570                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9571                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9572            ],
 9573        )
 9574        .await;
 9575        editor
 9576            .condition(&cx, |editor, _| editor.context_menu_visible())
 9577            .await;
 9578
 9579        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9580            let apply_additional_edits = editor
 9581                .confirm_completion(&ConfirmCompletion::default(), cx)
 9582                .unwrap();
 9583            assert_eq!(
 9584                editor.text(cx),
 9585                "
 9586                    one.second_completion
 9587                    two sixth_completion
 9588                    three sixth_completion
 9589                    additional edit
 9590                "
 9591                .unindent()
 9592            );
 9593            apply_additional_edits
 9594        });
 9595        handle_resolve_completion_request(&mut fake_server, None).await;
 9596        apply_additional_edits.await.unwrap();
 9597
 9598        async fn handle_completion_request(
 9599            fake: &mut FakeLanguageServer,
 9600            path: &'static str,
 9601            position: Point,
 9602            completions: Vec<(Range<Point>, &'static str)>,
 9603        ) {
 9604            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9605                let completions = completions.clone();
 9606                async move {
 9607                    assert_eq!(
 9608                        params.text_document_position.text_document.uri,
 9609                        lsp::Url::from_file_path(path).unwrap()
 9610                    );
 9611                    assert_eq!(
 9612                        params.text_document_position.position,
 9613                        lsp::Position::new(position.row, position.column)
 9614                    );
 9615                    Ok(Some(lsp::CompletionResponse::Array(
 9616                        completions
 9617                            .iter()
 9618                            .map(|(range, new_text)| lsp::CompletionItem {
 9619                                label: new_text.to_string(),
 9620                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9621                                    range: lsp::Range::new(
 9622                                        lsp::Position::new(range.start.row, range.start.column),
 9623                                        lsp::Position::new(range.start.row, range.start.column),
 9624                                    ),
 9625                                    new_text: new_text.to_string(),
 9626                                })),
 9627                                ..Default::default()
 9628                            })
 9629                            .collect(),
 9630                    )))
 9631                }
 9632            })
 9633            .next()
 9634            .await;
 9635        }
 9636
 9637        async fn handle_resolve_completion_request(
 9638            fake: &mut FakeLanguageServer,
 9639            edit: Option<(Range<Point>, &'static str)>,
 9640        ) {
 9641            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9642                let edit = edit.clone();
 9643                async move {
 9644                    Ok(lsp::CompletionItem {
 9645                        additional_text_edits: edit.map(|(range, new_text)| {
 9646                            vec![lsp::TextEdit::new(
 9647                                lsp::Range::new(
 9648                                    lsp::Position::new(range.start.row, range.start.column),
 9649                                    lsp::Position::new(range.end.row, range.end.column),
 9650                                ),
 9651                                new_text.to_string(),
 9652                            )]
 9653                        }),
 9654                        ..Default::default()
 9655                    })
 9656                }
 9657            })
 9658            .next()
 9659            .await;
 9660        }
 9661    }
 9662
 9663    #[gpui::test]
 9664    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9665        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9666        let language = Arc::new(Language::new(
 9667            LanguageConfig {
 9668                line_comment: Some("// ".to_string()),
 9669                ..Default::default()
 9670            },
 9671            Some(tree_sitter_rust::language()),
 9672        ));
 9673
 9674        let text = "
 9675            fn a() {
 9676                //b();
 9677                // c();
 9678                //  d();
 9679            }
 9680        "
 9681        .unindent();
 9682
 9683        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9684        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9685        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9686
 9687        view.update(cx, |editor, cx| {
 9688            // If multiple selections intersect a line, the line is only
 9689            // toggled once.
 9690            editor.select_display_ranges(
 9691                &[
 9692                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9693                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9694                ],
 9695                cx,
 9696            );
 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            // The comment prefix is inserted at the same column for every line
 9711            // in a selection.
 9712            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9713            editor.toggle_comments(&ToggleComments, cx);
 9714            assert_eq!(
 9715                editor.text(cx),
 9716                "
 9717                    fn a() {
 9718                        // b();
 9719                        // c();
 9720                        //  d();
 9721                    }
 9722                "
 9723                .unindent()
 9724            );
 9725
 9726            // If a selection ends at the beginning of a line, that line is not toggled.
 9727            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9728            editor.toggle_comments(&ToggleComments, cx);
 9729            assert_eq!(
 9730                editor.text(cx),
 9731                "
 9732                        fn a() {
 9733                            // b();
 9734                            c();
 9735                            //  d();
 9736                        }
 9737                    "
 9738                .unindent()
 9739            );
 9740        });
 9741    }
 9742
 9743    #[gpui::test]
 9744    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9745        cx.set_global(Settings::test(cx));
 9746        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9747        let multibuffer = cx.add_model(|cx| {
 9748            let mut multibuffer = MultiBuffer::new(0);
 9749            multibuffer.push_excerpts(
 9750                buffer.clone(),
 9751                [
 9752                    Point::new(0, 0)..Point::new(0, 4),
 9753                    Point::new(1, 0)..Point::new(1, 4),
 9754                ],
 9755                cx,
 9756            );
 9757            multibuffer
 9758        });
 9759
 9760        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9761
 9762        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9763        view.update(cx, |view, cx| {
 9764            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9765            view.select_ranges(
 9766                [
 9767                    Point::new(0, 0)..Point::new(0, 0),
 9768                    Point::new(1, 0)..Point::new(1, 0),
 9769                ],
 9770                None,
 9771                cx,
 9772            );
 9773
 9774            view.handle_input(&Input("X".to_string()), cx);
 9775            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9776            assert_eq!(
 9777                view.selected_ranges(cx),
 9778                [
 9779                    Point::new(0, 1)..Point::new(0, 1),
 9780                    Point::new(1, 1)..Point::new(1, 1),
 9781                ]
 9782            )
 9783        });
 9784    }
 9785
 9786    #[gpui::test]
 9787    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9788        cx.set_global(Settings::test(cx));
 9789        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9790        let multibuffer = cx.add_model(|cx| {
 9791            let mut multibuffer = MultiBuffer::new(0);
 9792            multibuffer.push_excerpts(
 9793                buffer,
 9794                [
 9795                    Point::new(0, 0)..Point::new(1, 4),
 9796                    Point::new(1, 0)..Point::new(2, 4),
 9797                ],
 9798                cx,
 9799            );
 9800            multibuffer
 9801        });
 9802
 9803        assert_eq!(
 9804            multibuffer.read(cx).read(cx).text(),
 9805            "aaaa\nbbbb\nbbbb\ncccc"
 9806        );
 9807
 9808        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9809        view.update(cx, |view, cx| {
 9810            view.select_ranges(
 9811                [
 9812                    Point::new(1, 1)..Point::new(1, 1),
 9813                    Point::new(2, 3)..Point::new(2, 3),
 9814                ],
 9815                None,
 9816                cx,
 9817            );
 9818
 9819            view.handle_input(&Input("X".to_string()), cx);
 9820            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9821            assert_eq!(
 9822                view.selected_ranges(cx),
 9823                [
 9824                    Point::new(1, 2)..Point::new(1, 2),
 9825                    Point::new(2, 5)..Point::new(2, 5),
 9826                ]
 9827            );
 9828
 9829            view.newline(&Newline, cx);
 9830            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9831            assert_eq!(
 9832                view.selected_ranges(cx),
 9833                [
 9834                    Point::new(2, 0)..Point::new(2, 0),
 9835                    Point::new(6, 0)..Point::new(6, 0),
 9836                ]
 9837            );
 9838        });
 9839    }
 9840
 9841    #[gpui::test]
 9842    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9843        cx.set_global(Settings::test(cx));
 9844        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9845        let mut excerpt1_id = None;
 9846        let multibuffer = cx.add_model(|cx| {
 9847            let mut multibuffer = MultiBuffer::new(0);
 9848            excerpt1_id = multibuffer
 9849                .push_excerpts(
 9850                    buffer.clone(),
 9851                    [
 9852                        Point::new(0, 0)..Point::new(1, 4),
 9853                        Point::new(1, 0)..Point::new(2, 4),
 9854                    ],
 9855                    cx,
 9856                )
 9857                .into_iter()
 9858                .next();
 9859            multibuffer
 9860        });
 9861        assert_eq!(
 9862            multibuffer.read(cx).read(cx).text(),
 9863            "aaaa\nbbbb\nbbbb\ncccc"
 9864        );
 9865        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9866            let mut editor = build_editor(multibuffer.clone(), cx);
 9867            let snapshot = editor.snapshot(cx);
 9868            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9869            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9870            assert_eq!(
 9871                editor.selected_ranges(cx),
 9872                [
 9873                    Point::new(1, 3)..Point::new(1, 3),
 9874                    Point::new(2, 1)..Point::new(2, 1),
 9875                ]
 9876            );
 9877            editor
 9878        });
 9879
 9880        // Refreshing selections is a no-op when excerpts haven't changed.
 9881        editor.update(cx, |editor, cx| {
 9882            editor.refresh_selections(cx);
 9883            assert_eq!(
 9884                editor.selected_ranges(cx),
 9885                [
 9886                    Point::new(1, 3)..Point::new(1, 3),
 9887                    Point::new(2, 1)..Point::new(2, 1),
 9888                ]
 9889            );
 9890        });
 9891
 9892        multibuffer.update(cx, |multibuffer, cx| {
 9893            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9894        });
 9895        editor.update(cx, |editor, cx| {
 9896            // Removing an excerpt causes the first selection to become degenerate.
 9897            assert_eq!(
 9898                editor.selected_ranges(cx),
 9899                [
 9900                    Point::new(0, 0)..Point::new(0, 0),
 9901                    Point::new(0, 1)..Point::new(0, 1)
 9902                ]
 9903            );
 9904
 9905            // Refreshing selections will relocate the first selection to the original buffer
 9906            // location.
 9907            editor.refresh_selections(cx);
 9908            assert_eq!(
 9909                editor.selected_ranges(cx),
 9910                [
 9911                    Point::new(0, 1)..Point::new(0, 1),
 9912                    Point::new(0, 3)..Point::new(0, 3)
 9913                ]
 9914            );
 9915            assert!(editor.pending_selection.is_some());
 9916        });
 9917    }
 9918
 9919    #[gpui::test]
 9920    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9921        cx.set_global(Settings::test(cx));
 9922        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9923        let mut excerpt1_id = None;
 9924        let multibuffer = cx.add_model(|cx| {
 9925            let mut multibuffer = MultiBuffer::new(0);
 9926            excerpt1_id = multibuffer
 9927                .push_excerpts(
 9928                    buffer.clone(),
 9929                    [
 9930                        Point::new(0, 0)..Point::new(1, 4),
 9931                        Point::new(1, 0)..Point::new(2, 4),
 9932                    ],
 9933                    cx,
 9934                )
 9935                .into_iter()
 9936                .next();
 9937            multibuffer
 9938        });
 9939        assert_eq!(
 9940            multibuffer.read(cx).read(cx).text(),
 9941            "aaaa\nbbbb\nbbbb\ncccc"
 9942        );
 9943        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9944            let mut editor = build_editor(multibuffer.clone(), cx);
 9945            let snapshot = editor.snapshot(cx);
 9946            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9947            assert_eq!(
 9948                editor.selected_ranges(cx),
 9949                [Point::new(1, 3)..Point::new(1, 3)]
 9950            );
 9951            editor
 9952        });
 9953
 9954        multibuffer.update(cx, |multibuffer, cx| {
 9955            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9956        });
 9957        editor.update(cx, |editor, cx| {
 9958            assert_eq!(
 9959                editor.selected_ranges(cx),
 9960                [Point::new(0, 0)..Point::new(0, 0)]
 9961            );
 9962
 9963            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9964            editor.refresh_selections(cx);
 9965            assert_eq!(
 9966                editor.selected_ranges(cx),
 9967                [Point::new(0, 3)..Point::new(0, 3)]
 9968            );
 9969            assert!(editor.pending_selection.is_some());
 9970        });
 9971    }
 9972
 9973    #[gpui::test]
 9974    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9975        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9976        let language = Arc::new(Language::new(
 9977            LanguageConfig {
 9978                brackets: vec![
 9979                    BracketPair {
 9980                        start: "{".to_string(),
 9981                        end: "}".to_string(),
 9982                        close: true,
 9983                        newline: true,
 9984                    },
 9985                    BracketPair {
 9986                        start: "/* ".to_string(),
 9987                        end: " */".to_string(),
 9988                        close: true,
 9989                        newline: true,
 9990                    },
 9991                ],
 9992                ..Default::default()
 9993            },
 9994            Some(tree_sitter_rust::language()),
 9995        ));
 9996
 9997        let text = concat!(
 9998            "{   }\n",     // Suppress rustfmt
 9999            "  x\n",       //
10000            "  /*   */\n", //
10001            "x\n",         //
10002            "{{} }\n",     //
10003        );
10004
10005        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10006        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10007        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10008        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10009            .await;
10010
10011        view.update(cx, |view, cx| {
10012            view.select_display_ranges(
10013                &[
10014                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10015                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10016                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10017                ],
10018                cx,
10019            );
10020            view.newline(&Newline, cx);
10021
10022            assert_eq!(
10023                view.buffer().read(cx).read(cx).text(),
10024                concat!(
10025                    "{ \n",    // Suppress rustfmt
10026                    "\n",      //
10027                    "}\n",     //
10028                    "  x\n",   //
10029                    "  /* \n", //
10030                    "  \n",    //
10031                    "  */\n",  //
10032                    "x\n",     //
10033                    "{{} \n",  //
10034                    "}\n",     //
10035                )
10036            );
10037        });
10038    }
10039
10040    #[gpui::test]
10041    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10042        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10043
10044        cx.set_global(Settings::test(cx));
10045        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10046
10047        editor.update(cx, |editor, cx| {
10048            struct Type1;
10049            struct Type2;
10050
10051            let buffer = buffer.read(cx).snapshot(cx);
10052
10053            let anchor_range = |range: Range<Point>| {
10054                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10055            };
10056
10057            editor.highlight_background::<Type1>(
10058                vec![
10059                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10060                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10061                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10062                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10063                ],
10064                |_| Color::red(),
10065                cx,
10066            );
10067            editor.highlight_background::<Type2>(
10068                vec![
10069                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10070                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10071                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10072                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10073                ],
10074                |_| Color::green(),
10075                cx,
10076            );
10077
10078            let snapshot = editor.snapshot(cx);
10079            let mut highlighted_ranges = editor.background_highlights_in_range(
10080                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10081                &snapshot,
10082                cx.global::<Settings>().theme.as_ref(),
10083            );
10084            // Enforce a consistent ordering based on color without relying on the ordering of the
10085            // highlight's `TypeId` which is non-deterministic.
10086            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10087            assert_eq!(
10088                highlighted_ranges,
10089                &[
10090                    (
10091                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10092                        Color::green(),
10093                    ),
10094                    (
10095                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10096                        Color::green(),
10097                    ),
10098                    (
10099                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10100                        Color::red(),
10101                    ),
10102                    (
10103                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10104                        Color::red(),
10105                    ),
10106                ]
10107            );
10108            assert_eq!(
10109                editor.background_highlights_in_range(
10110                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10111                    &snapshot,
10112                    cx.global::<Settings>().theme.as_ref(),
10113                ),
10114                &[(
10115                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10116                    Color::red(),
10117                )]
10118            );
10119        });
10120    }
10121
10122    #[gpui::test]
10123    fn test_following(cx: &mut gpui::MutableAppContext) {
10124        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10125
10126        cx.set_global(Settings::test(cx));
10127
10128        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10129        let (_, follower) = cx.add_window(
10130            WindowOptions {
10131                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10132                ..Default::default()
10133            },
10134            |cx| build_editor(buffer.clone(), cx),
10135        );
10136
10137        let pending_update = Rc::new(RefCell::new(None));
10138        follower.update(cx, {
10139            let update = pending_update.clone();
10140            |_, cx| {
10141                cx.subscribe(&leader, move |_, leader, event, cx| {
10142                    leader
10143                        .read(cx)
10144                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10145                })
10146                .detach();
10147            }
10148        });
10149
10150        // Update the selections only
10151        leader.update(cx, |leader, cx| {
10152            leader.select_ranges([1..1], None, cx);
10153        });
10154        follower.update(cx, |follower, cx| {
10155            follower
10156                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10157                .unwrap();
10158        });
10159        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
10160
10161        // Update the scroll position only
10162        leader.update(cx, |leader, cx| {
10163            leader.set_scroll_position(vec2f(1.5, 3.5), 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!(
10171            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10172            vec2f(1.5, 3.5)
10173        );
10174
10175        // Update the selections and scroll position
10176        leader.update(cx, |leader, cx| {
10177            leader.select_ranges([0..0], None, cx);
10178            leader.request_autoscroll(Autoscroll::Newest, cx);
10179            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10180        });
10181        follower.update(cx, |follower, cx| {
10182            let initial_scroll_position = follower.scroll_position(cx);
10183            follower
10184                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10185                .unwrap();
10186            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10187            assert!(follower.autoscroll_request.is_some());
10188        });
10189        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
10190
10191        // Creating a pending selection that precedes another selection
10192        leader.update(cx, |leader, cx| {
10193            leader.select_ranges([1..1], None, cx);
10194            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10195        });
10196        follower.update(cx, |follower, cx| {
10197            follower
10198                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10199                .unwrap();
10200        });
10201        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
10202
10203        // Extend the pending selection so that it surrounds another selection
10204        leader.update(cx, |leader, cx| {
10205            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10206        });
10207        follower.update(cx, |follower, cx| {
10208            follower
10209                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10210                .unwrap();
10211        });
10212        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
10213    }
10214
10215    #[test]
10216    fn test_combine_syntax_and_fuzzy_match_highlights() {
10217        let string = "abcdefghijklmnop";
10218        let syntax_ranges = [
10219            (
10220                0..3,
10221                HighlightStyle {
10222                    color: Some(Color::red()),
10223                    ..Default::default()
10224                },
10225            ),
10226            (
10227                4..8,
10228                HighlightStyle {
10229                    color: Some(Color::green()),
10230                    ..Default::default()
10231                },
10232            ),
10233        ];
10234        let match_indices = [4, 6, 7, 8];
10235        assert_eq!(
10236            combine_syntax_and_fuzzy_match_highlights(
10237                &string,
10238                Default::default(),
10239                syntax_ranges.into_iter(),
10240                &match_indices,
10241            ),
10242            &[
10243                (
10244                    0..3,
10245                    HighlightStyle {
10246                        color: Some(Color::red()),
10247                        ..Default::default()
10248                    },
10249                ),
10250                (
10251                    4..5,
10252                    HighlightStyle {
10253                        color: Some(Color::green()),
10254                        weight: Some(fonts::Weight::BOLD),
10255                        ..Default::default()
10256                    },
10257                ),
10258                (
10259                    5..6,
10260                    HighlightStyle {
10261                        color: Some(Color::green()),
10262                        ..Default::default()
10263                    },
10264                ),
10265                (
10266                    6..8,
10267                    HighlightStyle {
10268                        color: Some(Color::green()),
10269                        weight: Some(fonts::Weight::BOLD),
10270                        ..Default::default()
10271                    },
10272                ),
10273                (
10274                    8..9,
10275                    HighlightStyle {
10276                        weight: Some(fonts::Weight::BOLD),
10277                        ..Default::default()
10278                    },
10279                ),
10280            ]
10281        );
10282    }
10283
10284    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10285        let point = DisplayPoint::new(row as u32, column as u32);
10286        point..point
10287    }
10288
10289    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10290        Editor::new(EditorMode::Full, buffer, None, None, cx)
10291    }
10292
10293    fn assert_selection_ranges(
10294        marked_text: &str,
10295        selection_marker_pairs: Vec<(char, char)>,
10296        view: &mut Editor,
10297        cx: &mut ViewContext<Editor>,
10298    ) {
10299        let snapshot = view.snapshot(cx).display_snapshot;
10300        let mut marker_chars = Vec::new();
10301        for (start, end) in selection_marker_pairs.iter() {
10302            marker_chars.push(*start);
10303            marker_chars.push(*end);
10304        }
10305        let (_, markers) = marked_text_by(marked_text, marker_chars);
10306        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10307            .iter()
10308            .map(|(start, end)| {
10309                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10310                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10311                start..end
10312            })
10313            .collect();
10314        assert_eq!(
10315            view.selected_display_ranges(cx),
10316            &asserted_ranges[..],
10317            "Assert selections are {}",
10318            marked_text
10319        );
10320    }
10321}
10322
10323trait RangeExt<T> {
10324    fn sorted(&self) -> Range<T>;
10325    fn to_inclusive(&self) -> RangeInclusive<T>;
10326}
10327
10328impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10329    fn sorted(&self) -> Self {
10330        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10331    }
10332
10333    fn to_inclusive(&self) -> RangeInclusive<T> {
10334        self.start.clone()..=self.end.clone()
10335    }
10336}