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