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