editor.rs

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