editor.rs

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