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