editor.rs

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