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