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        }
 4983
 4984        Some(rename)
 4985    }
 4986
 4987    #[cfg(any(test, feature = "test-support"))]
 4988    pub fn pending_rename(&self) -> Option<&RenameState> {
 4989        self.pending_rename.as_ref()
 4990    }
 4991
 4992    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4993        if let Some(project) = self.project.clone() {
 4994            self.buffer.update(cx, |multi_buffer, cx| {
 4995                project.update(cx, |project, cx| {
 4996                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4997                });
 4998            })
 4999        }
 5000    }
 5001
 5002    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 5003        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 5004            let buffer = self.buffer.read(cx).snapshot(cx);
 5005            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 5006            let is_valid = buffer
 5007                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 5008                .any(|entry| {
 5009                    entry.diagnostic.is_primary
 5010                        && !entry.range.is_empty()
 5011                        && entry.range.start == primary_range_start
 5012                        && entry.diagnostic.message == active_diagnostics.primary_message
 5013                });
 5014
 5015            if is_valid != active_diagnostics.is_valid {
 5016                active_diagnostics.is_valid = is_valid;
 5017                let mut new_styles = HashMap::default();
 5018                for (block_id, diagnostic) in &active_diagnostics.blocks {
 5019                    new_styles.insert(
 5020                        *block_id,
 5021                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 5022                    );
 5023                }
 5024                self.display_map
 5025                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 5026            }
 5027        }
 5028    }
 5029
 5030    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 5031        self.dismiss_diagnostics(cx);
 5032        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 5033            let buffer = self.buffer.read(cx).snapshot(cx);
 5034
 5035            let mut primary_range = None;
 5036            let mut primary_message = None;
 5037            let mut group_end = Point::zero();
 5038            let diagnostic_group = buffer
 5039                .diagnostic_group::<Point>(group_id)
 5040                .map(|entry| {
 5041                    if entry.range.end > group_end {
 5042                        group_end = entry.range.end;
 5043                    }
 5044                    if entry.diagnostic.is_primary {
 5045                        primary_range = Some(entry.range.clone());
 5046                        primary_message = Some(entry.diagnostic.message.clone());
 5047                    }
 5048                    entry
 5049                })
 5050                .collect::<Vec<_>>();
 5051            let primary_range = primary_range.unwrap();
 5052            let primary_message = primary_message.unwrap();
 5053            let primary_range =
 5054                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5055
 5056            let blocks = display_map
 5057                .insert_blocks(
 5058                    diagnostic_group.iter().map(|entry| {
 5059                        let diagnostic = entry.diagnostic.clone();
 5060                        let message_height = diagnostic.message.lines().count() as u8;
 5061                        BlockProperties {
 5062                            style: BlockStyle::Fixed,
 5063                            position: buffer.anchor_after(entry.range.start),
 5064                            height: message_height,
 5065                            render: diagnostic_block_renderer(diagnostic, true),
 5066                            disposition: BlockDisposition::Below,
 5067                        }
 5068                    }),
 5069                    cx,
 5070                )
 5071                .into_iter()
 5072                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5073                .collect();
 5074
 5075            Some(ActiveDiagnosticGroup {
 5076                primary_range,
 5077                primary_message,
 5078                blocks,
 5079                is_valid: true,
 5080            })
 5081        });
 5082    }
 5083
 5084    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5085        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5086            self.display_map.update(cx, |display_map, cx| {
 5087                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5088            });
 5089            cx.notify();
 5090        }
 5091    }
 5092
 5093    pub fn set_selections_from_remote(
 5094        &mut self,
 5095        selections: Vec<Selection<Anchor>>,
 5096        cx: &mut ViewContext<Self>,
 5097    ) {
 5098        let old_cursor_position = self.selections.newest_anchor().head();
 5099        self.selections.change_with(cx, |s| {
 5100            s.select_anchors(selections);
 5101        });
 5102        self.selections_did_change(false, &old_cursor_position, cx);
 5103    }
 5104
 5105    fn push_to_selection_history(&mut self) {
 5106        self.selection_history.push(SelectionHistoryEntry {
 5107            selections: self.selections.disjoint_anchors().clone(),
 5108            select_next_state: self.select_next_state.clone(),
 5109            add_selections_state: self.add_selections_state.clone(),
 5110        });
 5111    }
 5112
 5113    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5114        self.autoscroll_request = Some((autoscroll, true));
 5115        cx.notify();
 5116    }
 5117
 5118    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5119        self.autoscroll_request = Some((autoscroll, false));
 5120        cx.notify();
 5121    }
 5122
 5123    pub fn transact(
 5124        &mut self,
 5125        cx: &mut ViewContext<Self>,
 5126        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5127    ) {
 5128        self.start_transaction_at(Instant::now(), cx);
 5129        update(self, cx);
 5130        self.end_transaction_at(Instant::now(), cx);
 5131    }
 5132
 5133    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5134        self.end_selection(cx);
 5135        if let Some(tx_id) = self
 5136            .buffer
 5137            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5138        {
 5139            self.selection_history
 5140                .insert_transaction(tx_id, self.selections.disjoint_anchors().clone());
 5141        }
 5142    }
 5143
 5144    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5145        if let Some(tx_id) = self
 5146            .buffer
 5147            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5148        {
 5149            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5150                *end_selections = Some(self.selections.disjoint_anchors().clone());
 5151            } else {
 5152                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5153            }
 5154
 5155            cx.emit(Event::Edited);
 5156        }
 5157    }
 5158
 5159    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5160        log::info!("Editor::page_up");
 5161    }
 5162
 5163    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5164        log::info!("Editor::page_down");
 5165    }
 5166
 5167    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5168        let mut fold_ranges = Vec::new();
 5169
 5170        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5171        let selections = self.selections.all::<Point>(cx);
 5172        for selection in selections {
 5173            let range = selection.display_range(&display_map).sorted();
 5174            let buffer_start_row = range.start.to_point(&display_map).row;
 5175
 5176            for row in (0..=range.end.row()).rev() {
 5177                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5178                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5179                    if fold_range.end.row >= buffer_start_row {
 5180                        fold_ranges.push(fold_range);
 5181                        if row <= range.start.row() {
 5182                            break;
 5183                        }
 5184                    }
 5185                }
 5186            }
 5187        }
 5188
 5189        self.fold_ranges(fold_ranges, cx);
 5190    }
 5191
 5192    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5193        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5194        let buffer = &display_map.buffer_snapshot;
 5195        let selections = self.selections.all::<Point>(cx);
 5196        let ranges = selections
 5197            .iter()
 5198            .map(|s| {
 5199                let range = s.display_range(&display_map).sorted();
 5200                let mut start = range.start.to_point(&display_map);
 5201                let mut end = range.end.to_point(&display_map);
 5202                start.column = 0;
 5203                end.column = buffer.line_len(end.row);
 5204                start..end
 5205            })
 5206            .collect::<Vec<_>>();
 5207        self.unfold_ranges(ranges, true, cx);
 5208    }
 5209
 5210    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5211        let max_point = display_map.max_point();
 5212        if display_row >= max_point.row() {
 5213            false
 5214        } else {
 5215            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5216            if is_blank {
 5217                false
 5218            } else {
 5219                for display_row in display_row + 1..=max_point.row() {
 5220                    let (indent, is_blank) = display_map.line_indent(display_row);
 5221                    if !is_blank {
 5222                        return indent > start_indent;
 5223                    }
 5224                }
 5225                false
 5226            }
 5227        }
 5228    }
 5229
 5230    fn foldable_range_for_line(
 5231        &self,
 5232        display_map: &DisplaySnapshot,
 5233        start_row: u32,
 5234    ) -> Range<Point> {
 5235        let max_point = display_map.max_point();
 5236
 5237        let (start_indent, _) = display_map.line_indent(start_row);
 5238        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5239        let mut end = None;
 5240        for row in start_row + 1..=max_point.row() {
 5241            let (indent, is_blank) = display_map.line_indent(row);
 5242            if !is_blank && indent <= start_indent {
 5243                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5244                break;
 5245            }
 5246        }
 5247
 5248        let end = end.unwrap_or(max_point);
 5249        return start.to_point(display_map)..end.to_point(display_map);
 5250    }
 5251
 5252    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5253        let selections = self.selections.all::<Point>(cx);
 5254        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5255        self.fold_ranges(ranges, cx);
 5256    }
 5257
 5258    pub fn fold_ranges<T: ToOffset>(
 5259        &mut self,
 5260        ranges: impl IntoIterator<Item = Range<T>>,
 5261        cx: &mut ViewContext<Self>,
 5262    ) {
 5263        let mut ranges = ranges.into_iter().peekable();
 5264        if ranges.peek().is_some() {
 5265            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5266            self.request_autoscroll(Autoscroll::Fit, cx);
 5267            cx.notify();
 5268        }
 5269    }
 5270
 5271    pub fn unfold_ranges<T: ToOffset>(
 5272        &mut self,
 5273        ranges: impl IntoIterator<Item = Range<T>>,
 5274        inclusive: bool,
 5275        cx: &mut ViewContext<Self>,
 5276    ) {
 5277        let mut ranges = ranges.into_iter().peekable();
 5278        if ranges.peek().is_some() {
 5279            self.display_map
 5280                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5281            self.request_autoscroll(Autoscroll::Fit, cx);
 5282            cx.notify();
 5283        }
 5284    }
 5285
 5286    pub fn insert_blocks(
 5287        &mut self,
 5288        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5289        cx: &mut ViewContext<Self>,
 5290    ) -> Vec<BlockId> {
 5291        let blocks = self
 5292            .display_map
 5293            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5294        self.request_autoscroll(Autoscroll::Fit, cx);
 5295        blocks
 5296    }
 5297
 5298    pub fn replace_blocks(
 5299        &mut self,
 5300        blocks: HashMap<BlockId, RenderBlock>,
 5301        cx: &mut ViewContext<Self>,
 5302    ) {
 5303        self.display_map
 5304            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5305        self.request_autoscroll(Autoscroll::Fit, cx);
 5306    }
 5307
 5308    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5309        self.display_map.update(cx, |display_map, cx| {
 5310            display_map.remove_blocks(block_ids, cx)
 5311        });
 5312    }
 5313
 5314    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5315        self.display_map
 5316            .update(cx, |map, cx| map.snapshot(cx))
 5317            .longest_row()
 5318    }
 5319
 5320    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5321        self.display_map
 5322            .update(cx, |map, cx| map.snapshot(cx))
 5323            .max_point()
 5324    }
 5325
 5326    pub fn text(&self, cx: &AppContext) -> String {
 5327        self.buffer.read(cx).read(cx).text()
 5328    }
 5329
 5330    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5331        self.transact(cx, |this, cx| {
 5332            this.buffer
 5333                .read(cx)
 5334                .as_singleton()
 5335                .expect("you can only call set_text on editors for singleton buffers")
 5336                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5337        });
 5338    }
 5339
 5340    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5341        self.display_map
 5342            .update(cx, |map, cx| map.snapshot(cx))
 5343            .text()
 5344    }
 5345
 5346    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5347        let language_name = self
 5348            .buffer
 5349            .read(cx)
 5350            .as_singleton()
 5351            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5352            .map(|l| l.name());
 5353
 5354        let settings = cx.global::<Settings>();
 5355        let mode = self
 5356            .soft_wrap_mode_override
 5357            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5358        match mode {
 5359            settings::SoftWrap::None => SoftWrap::None,
 5360            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5361            settings::SoftWrap::PreferredLineLength => {
 5362                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5363            }
 5364        }
 5365    }
 5366
 5367    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5368        self.soft_wrap_mode_override = Some(mode);
 5369        cx.notify();
 5370    }
 5371
 5372    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5373        self.display_map
 5374            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5375    }
 5376
 5377    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5378        self.highlighted_rows = rows;
 5379    }
 5380
 5381    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5382        self.highlighted_rows.clone()
 5383    }
 5384
 5385    pub fn highlight_background<T: 'static>(
 5386        &mut self,
 5387        ranges: Vec<Range<Anchor>>,
 5388        color_fetcher: fn(&Theme) -> Color,
 5389        cx: &mut ViewContext<Self>,
 5390    ) {
 5391        self.background_highlights
 5392            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5393        cx.notify();
 5394    }
 5395
 5396    pub fn clear_background_highlights<T: 'static>(
 5397        &mut self,
 5398        cx: &mut ViewContext<Self>,
 5399    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5400        cx.notify();
 5401        self.background_highlights.remove(&TypeId::of::<T>())
 5402    }
 5403
 5404    #[cfg(feature = "test-support")]
 5405    pub fn all_background_highlights(
 5406        &mut self,
 5407        cx: &mut ViewContext<Self>,
 5408    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5409        let snapshot = self.snapshot(cx);
 5410        let buffer = &snapshot.buffer_snapshot;
 5411        let start = buffer.anchor_before(0);
 5412        let end = buffer.anchor_after(buffer.len());
 5413        let theme = cx.global::<Settings>().theme.as_ref();
 5414        self.background_highlights_in_range(start..end, &snapshot, theme)
 5415    }
 5416
 5417    fn document_highlights_for_position<'a>(
 5418        &'a self,
 5419        position: Anchor,
 5420        buffer: &'a MultiBufferSnapshot,
 5421    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5422        let read_highlights = self
 5423            .background_highlights
 5424            .get(&TypeId::of::<DocumentHighlightRead>())
 5425            .map(|h| &h.1);
 5426        let write_highlights = self
 5427            .background_highlights
 5428            .get(&TypeId::of::<DocumentHighlightWrite>())
 5429            .map(|h| &h.1);
 5430        let left_position = position.bias_left(buffer);
 5431        let right_position = position.bias_right(buffer);
 5432        read_highlights
 5433            .into_iter()
 5434            .chain(write_highlights)
 5435            .flat_map(move |ranges| {
 5436                let start_ix = match ranges.binary_search_by(|probe| {
 5437                    let cmp = probe.end.cmp(&left_position, &buffer);
 5438                    if cmp.is_ge() {
 5439                        Ordering::Greater
 5440                    } else {
 5441                        Ordering::Less
 5442                    }
 5443                }) {
 5444                    Ok(i) | Err(i) => i,
 5445                };
 5446
 5447                let right_position = right_position.clone();
 5448                ranges[start_ix..]
 5449                    .iter()
 5450                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5451            })
 5452    }
 5453
 5454    pub fn background_highlights_in_range(
 5455        &self,
 5456        search_range: Range<Anchor>,
 5457        display_snapshot: &DisplaySnapshot,
 5458        theme: &Theme,
 5459    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5460        let mut results = Vec::new();
 5461        let buffer = &display_snapshot.buffer_snapshot;
 5462        for (color_fetcher, ranges) in self.background_highlights.values() {
 5463            let color = color_fetcher(theme);
 5464            let start_ix = match ranges.binary_search_by(|probe| {
 5465                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5466                if cmp.is_gt() {
 5467                    Ordering::Greater
 5468                } else {
 5469                    Ordering::Less
 5470                }
 5471            }) {
 5472                Ok(i) | Err(i) => i,
 5473            };
 5474            for range in &ranges[start_ix..] {
 5475                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5476                    break;
 5477                }
 5478                let start = range
 5479                    .start
 5480                    .to_point(buffer)
 5481                    .to_display_point(display_snapshot);
 5482                let end = range
 5483                    .end
 5484                    .to_point(buffer)
 5485                    .to_display_point(display_snapshot);
 5486                results.push((start..end, color))
 5487            }
 5488        }
 5489        results
 5490    }
 5491
 5492    pub fn highlight_text<T: 'static>(
 5493        &mut self,
 5494        ranges: Vec<Range<Anchor>>,
 5495        style: HighlightStyle,
 5496        cx: &mut ViewContext<Self>,
 5497    ) {
 5498        self.display_map.update(cx, |map, _| {
 5499            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5500        });
 5501        cx.notify();
 5502    }
 5503
 5504    pub fn clear_text_highlights<T: 'static>(
 5505        &mut self,
 5506        cx: &mut ViewContext<Self>,
 5507    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5508        cx.notify();
 5509        self.display_map
 5510            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5511    }
 5512
 5513    fn next_blink_epoch(&mut self) -> usize {
 5514        self.blink_epoch += 1;
 5515        self.blink_epoch
 5516    }
 5517
 5518    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5519        if !self.focused {
 5520            return;
 5521        }
 5522
 5523        self.show_local_cursors = true;
 5524        cx.notify();
 5525
 5526        let epoch = self.next_blink_epoch();
 5527        cx.spawn(|this, mut cx| {
 5528            let this = this.downgrade();
 5529            async move {
 5530                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5531                if let Some(this) = this.upgrade(&cx) {
 5532                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5533                }
 5534            }
 5535        })
 5536        .detach();
 5537    }
 5538
 5539    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5540        if epoch == self.blink_epoch {
 5541            self.blinking_paused = false;
 5542            self.blink_cursors(epoch, cx);
 5543        }
 5544    }
 5545
 5546    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5547        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5548            self.show_local_cursors = !self.show_local_cursors;
 5549            cx.notify();
 5550
 5551            let epoch = self.next_blink_epoch();
 5552            cx.spawn(|this, mut cx| {
 5553                let this = this.downgrade();
 5554                async move {
 5555                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5556                    if let Some(this) = this.upgrade(&cx) {
 5557                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5558                    }
 5559                }
 5560            })
 5561            .detach();
 5562        }
 5563    }
 5564
 5565    pub fn show_local_cursors(&self) -> bool {
 5566        self.show_local_cursors && self.focused
 5567    }
 5568
 5569    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5570        cx.notify();
 5571    }
 5572
 5573    fn on_buffer_event(
 5574        &mut self,
 5575        _: ModelHandle<MultiBuffer>,
 5576        event: &language::Event,
 5577        cx: &mut ViewContext<Self>,
 5578    ) {
 5579        match event {
 5580            language::Event::Edited => {
 5581                self.refresh_active_diagnostics(cx);
 5582                self.refresh_code_actions(cx);
 5583                cx.emit(Event::BufferEdited);
 5584            }
 5585            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5586            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 5587            language::Event::Saved => cx.emit(Event::Saved),
 5588            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5589            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5590            language::Event::Closed => cx.emit(Event::Closed),
 5591            language::Event::DiagnosticsUpdated => {
 5592                self.refresh_active_diagnostics(cx);
 5593            }
 5594            _ => {}
 5595        }
 5596    }
 5597
 5598    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5599        cx.notify();
 5600    }
 5601
 5602    pub fn set_searchable(&mut self, searchable: bool) {
 5603        self.searchable = searchable;
 5604    }
 5605
 5606    pub fn searchable(&self) -> bool {
 5607        self.searchable
 5608    }
 5609
 5610    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5611        let active_item = workspace.active_item(cx);
 5612        let editor_handle = if let Some(editor) = active_item
 5613            .as_ref()
 5614            .and_then(|item| item.act_as::<Self>(cx))
 5615        {
 5616            editor
 5617        } else {
 5618            cx.propagate_action();
 5619            return;
 5620        };
 5621
 5622        let editor = editor_handle.read(cx);
 5623        let buffer = editor.buffer.read(cx);
 5624        if buffer.is_singleton() {
 5625            cx.propagate_action();
 5626            return;
 5627        }
 5628
 5629        let mut new_selections_by_buffer = HashMap::default();
 5630        for selection in editor.selections.all::<usize>(cx) {
 5631            for (buffer, mut range) in
 5632                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5633            {
 5634                if selection.reversed {
 5635                    mem::swap(&mut range.start, &mut range.end);
 5636                }
 5637                new_selections_by_buffer
 5638                    .entry(buffer)
 5639                    .or_insert(Vec::new())
 5640                    .push(range)
 5641            }
 5642        }
 5643
 5644        editor_handle.update(cx, |editor, cx| {
 5645            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 5646        });
 5647        let pane = workspace.active_pane().clone();
 5648        pane.update(cx, |pane, _| pane.disable_history());
 5649
 5650        // We defer the pane interaction because we ourselves are a workspace item
 5651        // and activating a new item causes the pane to call a method on us reentrantly,
 5652        // which panics if we're on the stack.
 5653        cx.defer(move |workspace, cx| {
 5654            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5655                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5656                editor.update(cx, |editor, cx| {
 5657                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5658                        s.select_ranges(ranges);
 5659                    });
 5660                });
 5661            }
 5662
 5663            pane.update(cx, |pane, _| pane.enable_history());
 5664        });
 5665    }
 5666
 5667    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 5668        let editor = workspace.open_path(action.path.clone(), true, cx);
 5669        let position = action.position;
 5670        let anchor = action.anchor;
 5671        cx.spawn_weak(|_, mut cx| async move {
 5672            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 5673            editor.update(&mut cx, |editor, cx| {
 5674                let buffer = editor.buffer().read(cx).as_singleton()?;
 5675                let buffer = buffer.read(cx);
 5676                let cursor = if buffer.can_resolve(&anchor) {
 5677                    language::ToPoint::to_point(&anchor, buffer)
 5678                } else {
 5679                    buffer.clip_point(position, Bias::Left)
 5680                };
 5681
 5682                let nav_history = editor.nav_history.take();
 5683                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5684                    s.select_ranges([cursor..cursor]);
 5685                });
 5686                editor.nav_history = nav_history;
 5687
 5688                Some(())
 5689            })?;
 5690            Some(())
 5691        })
 5692        .detach()
 5693    }
 5694}
 5695
 5696impl EditorSnapshot {
 5697    pub fn is_focused(&self) -> bool {
 5698        self.is_focused
 5699    }
 5700
 5701    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5702        self.placeholder_text.as_ref()
 5703    }
 5704
 5705    pub fn scroll_position(&self) -> Vector2F {
 5706        compute_scroll_position(
 5707            &self.display_snapshot,
 5708            self.scroll_position,
 5709            &self.scroll_top_anchor,
 5710        )
 5711    }
 5712}
 5713
 5714impl Deref for EditorSnapshot {
 5715    type Target = DisplaySnapshot;
 5716
 5717    fn deref(&self) -> &Self::Target {
 5718        &self.display_snapshot
 5719    }
 5720}
 5721
 5722fn compute_scroll_position(
 5723    snapshot: &DisplaySnapshot,
 5724    mut scroll_position: Vector2F,
 5725    scroll_top_anchor: &Anchor,
 5726) -> Vector2F {
 5727    if *scroll_top_anchor != Anchor::min() {
 5728        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5729        scroll_position.set_y(scroll_top + scroll_position.y());
 5730    } else {
 5731        scroll_position.set_y(0.);
 5732    }
 5733    scroll_position
 5734}
 5735
 5736#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5737pub enum Event {
 5738    Activate,
 5739    BufferEdited,
 5740    Edited,
 5741    Reparsed,
 5742    Blurred,
 5743    DirtyChanged,
 5744    Saved,
 5745    TitleChanged,
 5746    SelectionsChanged { local: bool },
 5747    ScrollPositionChanged { local: bool },
 5748    Closed,
 5749}
 5750
 5751pub struct EditorFocused(pub ViewHandle<Editor>);
 5752pub struct EditorBlurred(pub ViewHandle<Editor>);
 5753pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5754
 5755impl Entity for Editor {
 5756    type Event = Event;
 5757
 5758    fn release(&mut self, cx: &mut MutableAppContext) {
 5759        cx.emit_global(EditorReleased(self.handle.clone()));
 5760    }
 5761}
 5762
 5763impl View for Editor {
 5764    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5765        let style = self.style(cx);
 5766        let font_changed = self.display_map.update(cx, |map, cx| {
 5767            map.set_font(style.text.font_id, style.text.font_size, cx)
 5768        });
 5769
 5770        if font_changed {
 5771            let handle = self.handle.clone();
 5772            cx.defer(move |cx| {
 5773                if let Some(editor) = handle.upgrade(cx) {
 5774                    editor.update(cx, |editor, cx| {
 5775                        hide_hover(editor, cx);
 5776                    })
 5777                }
 5778            });
 5779        }
 5780
 5781        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 5782    }
 5783
 5784    fn ui_name() -> &'static str {
 5785        "Editor"
 5786    }
 5787
 5788    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5789        let focused_event = EditorFocused(cx.handle());
 5790        cx.emit_global(focused_event);
 5791        if let Some(rename) = self.pending_rename.as_ref() {
 5792            cx.focus(&rename.editor);
 5793        } else {
 5794            self.focused = true;
 5795            self.blink_cursors(self.blink_epoch, cx);
 5796            self.buffer.update(cx, |buffer, cx| {
 5797                buffer.finalize_last_transaction(cx);
 5798                if self.leader_replica_id.is_none() {
 5799                    buffer.set_active_selections(
 5800                        &self.selections.disjoint_anchors(),
 5801                        self.selections.line_mode,
 5802                        cx,
 5803                    );
 5804                }
 5805            });
 5806        }
 5807    }
 5808
 5809    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 5810        let blurred_event = EditorBlurred(cx.handle());
 5811        cx.emit_global(blurred_event);
 5812        self.focused = false;
 5813        self.buffer
 5814            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 5815        self.hide_context_menu(cx);
 5816        hide_hover(self, cx);
 5817        cx.emit(Event::Blurred);
 5818        cx.notify();
 5819    }
 5820
 5821    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 5822        let mut context = Self::default_keymap_context();
 5823        let mode = match self.mode {
 5824            EditorMode::SingleLine => "single_line",
 5825            EditorMode::AutoHeight { .. } => "auto_height",
 5826            EditorMode::Full => "full",
 5827        };
 5828        context.map.insert("mode".into(), mode.into());
 5829        if self.pending_rename.is_some() {
 5830            context.set.insert("renaming".into());
 5831        }
 5832        match self.context_menu.as_ref() {
 5833            Some(ContextMenu::Completions(_)) => {
 5834                context.set.insert("showing_completions".into());
 5835            }
 5836            Some(ContextMenu::CodeActions(_)) => {
 5837                context.set.insert("showing_code_actions".into());
 5838            }
 5839            None => {}
 5840        }
 5841
 5842        for layer in self.keymap_context_layers.values() {
 5843            context.extend(layer);
 5844        }
 5845
 5846        context
 5847    }
 5848}
 5849
 5850fn build_style(
 5851    settings: &Settings,
 5852    get_field_editor_theme: Option<GetFieldEditorTheme>,
 5853    override_text_style: Option<&OverrideTextStyle>,
 5854    cx: &AppContext,
 5855) -> EditorStyle {
 5856    let font_cache = cx.font_cache();
 5857
 5858    let mut theme = settings.theme.editor.clone();
 5859    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 5860        let field_editor_theme = get_field_editor_theme(&settings.theme);
 5861        theme.text_color = field_editor_theme.text.color;
 5862        theme.selection = field_editor_theme.selection;
 5863        theme.background = field_editor_theme
 5864            .container
 5865            .background_color
 5866            .unwrap_or_default();
 5867        EditorStyle {
 5868            text: field_editor_theme.text,
 5869            placeholder_text: field_editor_theme.placeholder_text,
 5870            theme,
 5871        }
 5872    } else {
 5873        let font_family_id = settings.buffer_font_family;
 5874        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 5875        let font_properties = Default::default();
 5876        let font_id = font_cache
 5877            .select_font(font_family_id, &font_properties)
 5878            .unwrap();
 5879        let font_size = settings.buffer_font_size;
 5880        EditorStyle {
 5881            text: TextStyle {
 5882                color: settings.theme.editor.text_color,
 5883                font_family_name,
 5884                font_family_id,
 5885                font_id,
 5886                font_size,
 5887                font_properties,
 5888                underline: Default::default(),
 5889            },
 5890            placeholder_text: None,
 5891            theme,
 5892        }
 5893    };
 5894
 5895    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 5896        if let Some(highlighted) = style
 5897            .text
 5898            .clone()
 5899            .highlight(highlight_style, font_cache)
 5900            .log_err()
 5901        {
 5902            style.text = highlighted;
 5903        }
 5904    }
 5905
 5906    style
 5907}
 5908
 5909trait SelectionExt {
 5910    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 5911    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 5912    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 5913    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 5914        -> Range<u32>;
 5915}
 5916
 5917impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 5918    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 5919        let start = self.start.to_point(buffer);
 5920        let end = self.end.to_point(buffer);
 5921        if self.reversed {
 5922            end..start
 5923        } else {
 5924            start..end
 5925        }
 5926    }
 5927
 5928    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 5929        let start = self.start.to_offset(buffer);
 5930        let end = self.end.to_offset(buffer);
 5931        if self.reversed {
 5932            end..start
 5933        } else {
 5934            start..end
 5935        }
 5936    }
 5937
 5938    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 5939        let start = self
 5940            .start
 5941            .to_point(&map.buffer_snapshot)
 5942            .to_display_point(map);
 5943        let end = self
 5944            .end
 5945            .to_point(&map.buffer_snapshot)
 5946            .to_display_point(map);
 5947        if self.reversed {
 5948            end..start
 5949        } else {
 5950            start..end
 5951        }
 5952    }
 5953
 5954    fn spanned_rows(
 5955        &self,
 5956        include_end_if_at_line_start: bool,
 5957        map: &DisplaySnapshot,
 5958    ) -> Range<u32> {
 5959        let start = self.start.to_point(&map.buffer_snapshot);
 5960        let mut end = self.end.to_point(&map.buffer_snapshot);
 5961        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 5962            end.row -= 1;
 5963        }
 5964
 5965        let buffer_start = map.prev_line_boundary(start).0;
 5966        let buffer_end = map.next_line_boundary(end).0;
 5967        buffer_start.row..buffer_end.row + 1
 5968    }
 5969}
 5970
 5971impl<T: InvalidationRegion> InvalidationStack<T> {
 5972    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 5973    where
 5974        S: Clone + ToOffset,
 5975    {
 5976        while let Some(region) = self.last() {
 5977            let all_selections_inside_invalidation_ranges =
 5978                if selections.len() == region.ranges().len() {
 5979                    selections
 5980                        .iter()
 5981                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 5982                        .all(|(selection, invalidation_range)| {
 5983                            let head = selection.head().to_offset(&buffer);
 5984                            invalidation_range.start <= head && invalidation_range.end >= head
 5985                        })
 5986                } else {
 5987                    false
 5988                };
 5989
 5990            if all_selections_inside_invalidation_ranges {
 5991                break;
 5992            } else {
 5993                self.pop();
 5994            }
 5995        }
 5996    }
 5997}
 5998
 5999impl<T> Default for InvalidationStack<T> {
 6000    fn default() -> Self {
 6001        Self(Default::default())
 6002    }
 6003}
 6004
 6005impl<T> Deref for InvalidationStack<T> {
 6006    type Target = Vec<T>;
 6007
 6008    fn deref(&self) -> &Self::Target {
 6009        &self.0
 6010    }
 6011}
 6012
 6013impl<T> DerefMut for InvalidationStack<T> {
 6014    fn deref_mut(&mut self) -> &mut Self::Target {
 6015        &mut self.0
 6016    }
 6017}
 6018
 6019impl InvalidationRegion for BracketPairState {
 6020    fn ranges(&self) -> &[Range<Anchor>] {
 6021        &self.ranges
 6022    }
 6023}
 6024
 6025impl InvalidationRegion for SnippetState {
 6026    fn ranges(&self) -> &[Range<Anchor>] {
 6027        &self.ranges[self.active_index]
 6028    }
 6029}
 6030
 6031impl Deref for EditorStyle {
 6032    type Target = theme::Editor;
 6033
 6034    fn deref(&self) -> &Self::Target {
 6035        &self.theme
 6036    }
 6037}
 6038
 6039pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6040    let mut highlighted_lines = Vec::new();
 6041    for line in diagnostic.message.lines() {
 6042        highlighted_lines.push(highlight_diagnostic_message(line));
 6043    }
 6044
 6045    Arc::new(move |cx: &mut BlockContext| {
 6046        let settings = cx.global::<Settings>();
 6047        let theme = &settings.theme.editor;
 6048        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6049        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6050        Flex::column()
 6051            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6052                Label::new(
 6053                    line.clone(),
 6054                    style.message.clone().with_font_size(font_size),
 6055                )
 6056                .with_highlights(highlights.clone())
 6057                .contained()
 6058                .with_margin_left(cx.anchor_x)
 6059                .boxed()
 6060            }))
 6061            .aligned()
 6062            .left()
 6063            .boxed()
 6064    })
 6065}
 6066
 6067pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6068    let mut message_without_backticks = String::new();
 6069    let mut prev_offset = 0;
 6070    let mut inside_block = false;
 6071    let mut highlights = Vec::new();
 6072    for (match_ix, (offset, _)) in message
 6073        .match_indices('`')
 6074        .chain([(message.len(), "")])
 6075        .enumerate()
 6076    {
 6077        message_without_backticks.push_str(&message[prev_offset..offset]);
 6078        if inside_block {
 6079            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6080        }
 6081
 6082        inside_block = !inside_block;
 6083        prev_offset = offset + 1;
 6084    }
 6085
 6086    (message_without_backticks, highlights)
 6087}
 6088
 6089pub fn diagnostic_style(
 6090    severity: DiagnosticSeverity,
 6091    valid: bool,
 6092    theme: &theme::Editor,
 6093) -> DiagnosticStyle {
 6094    match (severity, valid) {
 6095        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6096        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6097        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6098        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6099        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6100        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6101        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6102        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6103        _ => theme.invalid_hint_diagnostic.clone(),
 6104    }
 6105}
 6106
 6107pub fn combine_syntax_and_fuzzy_match_highlights(
 6108    text: &str,
 6109    default_style: HighlightStyle,
 6110    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6111    match_indices: &[usize],
 6112) -> Vec<(Range<usize>, HighlightStyle)> {
 6113    let mut result = Vec::new();
 6114    let mut match_indices = match_indices.iter().copied().peekable();
 6115
 6116    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6117    {
 6118        syntax_highlight.weight = None;
 6119
 6120        // Add highlights for any fuzzy match characters before the next
 6121        // syntax highlight range.
 6122        while let Some(&match_index) = match_indices.peek() {
 6123            if match_index >= range.start {
 6124                break;
 6125            }
 6126            match_indices.next();
 6127            let end_index = char_ix_after(match_index, text);
 6128            let mut match_style = default_style;
 6129            match_style.weight = Some(fonts::Weight::BOLD);
 6130            result.push((match_index..end_index, match_style));
 6131        }
 6132
 6133        if range.start == usize::MAX {
 6134            break;
 6135        }
 6136
 6137        // Add highlights for any fuzzy match characters within the
 6138        // syntax highlight range.
 6139        let mut offset = range.start;
 6140        while let Some(&match_index) = match_indices.peek() {
 6141            if match_index >= range.end {
 6142                break;
 6143            }
 6144
 6145            match_indices.next();
 6146            if match_index > offset {
 6147                result.push((offset..match_index, syntax_highlight));
 6148            }
 6149
 6150            let mut end_index = char_ix_after(match_index, text);
 6151            while let Some(&next_match_index) = match_indices.peek() {
 6152                if next_match_index == end_index && next_match_index < range.end {
 6153                    end_index = char_ix_after(next_match_index, text);
 6154                    match_indices.next();
 6155                } else {
 6156                    break;
 6157                }
 6158            }
 6159
 6160            let mut match_style = syntax_highlight;
 6161            match_style.weight = Some(fonts::Weight::BOLD);
 6162            result.push((match_index..end_index, match_style));
 6163            offset = end_index;
 6164        }
 6165
 6166        if offset < range.end {
 6167            result.push((offset..range.end, syntax_highlight));
 6168        }
 6169    }
 6170
 6171    fn char_ix_after(ix: usize, text: &str) -> usize {
 6172        ix + text[ix..].chars().next().unwrap().len_utf8()
 6173    }
 6174
 6175    result
 6176}
 6177
 6178pub fn styled_runs_for_code_label<'a>(
 6179    label: &'a CodeLabel,
 6180    syntax_theme: &'a theme::SyntaxTheme,
 6181) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6182    let fade_out = HighlightStyle {
 6183        fade_out: Some(0.35),
 6184        ..Default::default()
 6185    };
 6186
 6187    let mut prev_end = label.filter_range.end;
 6188    label
 6189        .runs
 6190        .iter()
 6191        .enumerate()
 6192        .flat_map(move |(ix, (range, highlight_id))| {
 6193            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6194                style
 6195            } else {
 6196                return Default::default();
 6197            };
 6198            let mut muted_style = style.clone();
 6199            muted_style.highlight(fade_out);
 6200
 6201            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6202            if range.start >= label.filter_range.end {
 6203                if range.start > prev_end {
 6204                    runs.push((prev_end..range.start, fade_out));
 6205                }
 6206                runs.push((range.clone(), muted_style));
 6207            } else if range.end <= label.filter_range.end {
 6208                runs.push((range.clone(), style));
 6209            } else {
 6210                runs.push((range.start..label.filter_range.end, style));
 6211                runs.push((label.filter_range.end..range.end, muted_style));
 6212            }
 6213            prev_end = cmp::max(prev_end, range.end);
 6214
 6215            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6216                runs.push((prev_end..label.text.len(), fade_out));
 6217            }
 6218
 6219            runs
 6220        })
 6221}
 6222
 6223#[cfg(test)]
 6224mod tests {
 6225    use crate::test::{
 6226        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
 6227    };
 6228
 6229    use super::*;
 6230    use futures::StreamExt;
 6231    use gpui::{
 6232        geometry::rect::RectF,
 6233        platform::{WindowBounds, WindowOptions},
 6234    };
 6235    use indoc::indoc;
 6236    use language::{FakeLspAdapter, LanguageConfig};
 6237    use lsp::FakeLanguageServer;
 6238    use project::FakeFs;
 6239    use settings::EditorSettings;
 6240    use std::{cell::RefCell, rc::Rc, time::Instant};
 6241    use text::Point;
 6242    use unindent::Unindent;
 6243    use util::{
 6244        assert_set_eq,
 6245        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
 6246    };
 6247    use workspace::{FollowableItem, ItemHandle, NavigationEntry, Pane};
 6248
 6249    #[gpui::test]
 6250    fn test_edit_events(cx: &mut MutableAppContext) {
 6251        cx.set_global(Settings::test(cx));
 6252        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6253
 6254        let events = Rc::new(RefCell::new(Vec::new()));
 6255        let (_, editor1) = cx.add_window(Default::default(), {
 6256            let events = events.clone();
 6257            |cx| {
 6258                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6259                    if matches!(
 6260                        event,
 6261                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6262                    ) {
 6263                        events.borrow_mut().push(("editor1", *event));
 6264                    }
 6265                })
 6266                .detach();
 6267                Editor::for_buffer(buffer.clone(), None, cx)
 6268            }
 6269        });
 6270        let (_, editor2) = cx.add_window(Default::default(), {
 6271            let events = events.clone();
 6272            |cx| {
 6273                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6274                    if matches!(
 6275                        event,
 6276                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6277                    ) {
 6278                        events.borrow_mut().push(("editor2", *event));
 6279                    }
 6280                })
 6281                .detach();
 6282                Editor::for_buffer(buffer.clone(), None, cx)
 6283            }
 6284        });
 6285        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6286
 6287        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6288        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6289        assert_eq!(
 6290            mem::take(&mut *events.borrow_mut()),
 6291            [
 6292                ("editor1", Event::Edited),
 6293                ("editor1", Event::BufferEdited),
 6294                ("editor2", Event::BufferEdited),
 6295                ("editor1", Event::DirtyChanged),
 6296                ("editor2", Event::DirtyChanged)
 6297            ]
 6298        );
 6299
 6300        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6301        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6302        assert_eq!(
 6303            mem::take(&mut *events.borrow_mut()),
 6304            [
 6305                ("editor2", Event::Edited),
 6306                ("editor1", Event::BufferEdited),
 6307                ("editor2", Event::BufferEdited),
 6308            ]
 6309        );
 6310
 6311        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6312        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6313        assert_eq!(
 6314            mem::take(&mut *events.borrow_mut()),
 6315            [
 6316                ("editor1", Event::Edited),
 6317                ("editor1", Event::BufferEdited),
 6318                ("editor2", Event::BufferEdited),
 6319                ("editor1", Event::DirtyChanged),
 6320                ("editor2", Event::DirtyChanged),
 6321            ]
 6322        );
 6323
 6324        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6325        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6326        assert_eq!(
 6327            mem::take(&mut *events.borrow_mut()),
 6328            [
 6329                ("editor1", Event::Edited),
 6330                ("editor1", Event::BufferEdited),
 6331                ("editor2", Event::BufferEdited),
 6332                ("editor1", Event::DirtyChanged),
 6333                ("editor2", Event::DirtyChanged),
 6334            ]
 6335        );
 6336
 6337        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6338        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6339        assert_eq!(
 6340            mem::take(&mut *events.borrow_mut()),
 6341            [
 6342                ("editor2", Event::Edited),
 6343                ("editor1", Event::BufferEdited),
 6344                ("editor2", Event::BufferEdited),
 6345                ("editor1", Event::DirtyChanged),
 6346                ("editor2", Event::DirtyChanged),
 6347            ]
 6348        );
 6349
 6350        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6351        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6352        assert_eq!(
 6353            mem::take(&mut *events.borrow_mut()),
 6354            [
 6355                ("editor2", Event::Edited),
 6356                ("editor1", Event::BufferEdited),
 6357                ("editor2", Event::BufferEdited),
 6358                ("editor1", Event::DirtyChanged),
 6359                ("editor2", Event::DirtyChanged),
 6360            ]
 6361        );
 6362
 6363        // No event is emitted when the mutation is a no-op.
 6364        editor2.update(cx, |editor, cx| {
 6365            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6366
 6367            editor.backspace(&Backspace, cx);
 6368        });
 6369        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6370    }
 6371
 6372    #[gpui::test]
 6373    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6374        cx.set_global(Settings::test(cx));
 6375        let mut now = Instant::now();
 6376        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6377        let group_interval = buffer.read(cx).transaction_group_interval();
 6378        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6379        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6380
 6381        editor.update(cx, |editor, cx| {
 6382            editor.start_transaction_at(now, cx);
 6383            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6384
 6385            editor.insert("cd", cx);
 6386            editor.end_transaction_at(now, cx);
 6387            assert_eq!(editor.text(cx), "12cd56");
 6388            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6389
 6390            editor.start_transaction_at(now, cx);
 6391            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6392            editor.insert("e", cx);
 6393            editor.end_transaction_at(now, cx);
 6394            assert_eq!(editor.text(cx), "12cde6");
 6395            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6396
 6397            now += group_interval + Duration::from_millis(1);
 6398            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6399
 6400            // Simulate an edit in another editor
 6401            buffer.update(cx, |buffer, cx| {
 6402                buffer.start_transaction_at(now, cx);
 6403                buffer.edit([(0..1, "a")], cx);
 6404                buffer.edit([(1..1, "b")], cx);
 6405                buffer.end_transaction_at(now, cx);
 6406            });
 6407
 6408            assert_eq!(editor.text(cx), "ab2cde6");
 6409            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6410
 6411            // Last transaction happened past the group interval in a different editor.
 6412            // Undo it individually and don't restore selections.
 6413            editor.undo(&Undo, cx);
 6414            assert_eq!(editor.text(cx), "12cde6");
 6415            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6416
 6417            // First two transactions happened within the group interval in this editor.
 6418            // Undo them together and restore selections.
 6419            editor.undo(&Undo, cx);
 6420            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6421            assert_eq!(editor.text(cx), "123456");
 6422            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6423
 6424            // Redo the first two transactions together.
 6425            editor.redo(&Redo, cx);
 6426            assert_eq!(editor.text(cx), "12cde6");
 6427            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6428
 6429            // Redo the last transaction on its own.
 6430            editor.redo(&Redo, cx);
 6431            assert_eq!(editor.text(cx), "ab2cde6");
 6432            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6433
 6434            // Test empty transactions.
 6435            editor.start_transaction_at(now, cx);
 6436            editor.end_transaction_at(now, cx);
 6437            editor.undo(&Undo, cx);
 6438            assert_eq!(editor.text(cx), "12cde6");
 6439        });
 6440    }
 6441
 6442    #[gpui::test]
 6443    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6444        cx.set_global(Settings::test(cx));
 6445
 6446        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6447        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6448        editor.update(cx, |view, cx| {
 6449            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6450        });
 6451        assert_eq!(
 6452            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6453            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6454        );
 6455
 6456        editor.update(cx, |view, cx| {
 6457            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6458        });
 6459
 6460        assert_eq!(
 6461            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6462            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6463        );
 6464
 6465        editor.update(cx, |view, cx| {
 6466            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6467        });
 6468
 6469        assert_eq!(
 6470            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6471            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6472        );
 6473
 6474        editor.update(cx, |view, cx| {
 6475            view.end_selection(cx);
 6476            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6477        });
 6478
 6479        assert_eq!(
 6480            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6481            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6482        );
 6483
 6484        editor.update(cx, |view, cx| {
 6485            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6486            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6487        });
 6488
 6489        assert_eq!(
 6490            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6491            [
 6492                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6493                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6494            ]
 6495        );
 6496
 6497        editor.update(cx, |view, cx| {
 6498            view.end_selection(cx);
 6499        });
 6500
 6501        assert_eq!(
 6502            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6503            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6504        );
 6505    }
 6506
 6507    #[gpui::test]
 6508    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6509        cx.set_global(Settings::test(cx));
 6510        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6511        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6512
 6513        view.update(cx, |view, cx| {
 6514            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6515            assert_eq!(
 6516                view.selections.display_ranges(cx),
 6517                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6518            );
 6519        });
 6520
 6521        view.update(cx, |view, cx| {
 6522            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6523            assert_eq!(
 6524                view.selections.display_ranges(cx),
 6525                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6526            );
 6527        });
 6528
 6529        view.update(cx, |view, cx| {
 6530            view.cancel(&Cancel, cx);
 6531            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6532            assert_eq!(
 6533                view.selections.display_ranges(cx),
 6534                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6535            );
 6536        });
 6537    }
 6538
 6539    #[gpui::test]
 6540    fn test_clone(cx: &mut gpui::MutableAppContext) {
 6541        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6542            one
 6543            two
 6544            three[]
 6545            four
 6546            five[]
 6547        "});
 6548        cx.set_global(Settings::test(cx));
 6549        let buffer = MultiBuffer::build_simple(&text, cx);
 6550
 6551        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6552
 6553        editor.update(cx, |editor, cx| {
 6554            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6555            editor.fold_ranges(
 6556                [
 6557                    Point::new(1, 0)..Point::new(2, 0),
 6558                    Point::new(3, 0)..Point::new(4, 0),
 6559                ],
 6560                cx,
 6561            );
 6562        });
 6563
 6564        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 6565            cx.add_window(Default::default(), |cx| editor.clone(cx))
 6566        });
 6567
 6568        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 6569        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 6570
 6571        assert_eq!(
 6572            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 6573            editor.update(cx, |e, cx| e.display_text(cx))
 6574        );
 6575        assert_eq!(
 6576            cloned_snapshot
 6577                .folds_in_range(0..text.len())
 6578                .collect::<Vec<_>>(),
 6579            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 6580        );
 6581        assert_set_eq!(
 6582            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 6583            editor.read(cx).selections.ranges(cx)
 6584        );
 6585        assert_set_eq!(
 6586            cloned_editor.update(cx, |e, cx| e.selections.display_ranges(cx)),
 6587            editor.update(cx, |e, cx| e.selections.display_ranges(cx))
 6588        );
 6589    }
 6590
 6591    #[gpui::test]
 6592    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6593        cx.set_global(Settings::test(cx));
 6594        use workspace::Item;
 6595        let pane = cx.add_view(Default::default(), |cx| Pane::new(cx));
 6596        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6597
 6598        cx.add_window(Default::default(), |cx| {
 6599            let mut editor = build_editor(buffer.clone(), cx);
 6600            let handle = cx.handle();
 6601            editor.set_nav_history(Some(pane.read(cx).nav_history_for_item(&handle)));
 6602
 6603            fn pop_history(
 6604                editor: &mut Editor,
 6605                cx: &mut MutableAppContext,
 6606            ) -> Option<NavigationEntry> {
 6607                editor.nav_history.as_mut().unwrap().pop_backward(cx)
 6608            }
 6609
 6610            // Move the cursor a small distance.
 6611            // Nothing is added to the navigation history.
 6612            editor.change_selections(None, cx, |s| {
 6613                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6614            });
 6615            editor.change_selections(None, cx, |s| {
 6616                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6617            });
 6618            assert!(pop_history(&mut editor, cx).is_none());
 6619
 6620            // Move the cursor a large distance.
 6621            // The history can jump back to the previous position.
 6622            editor.change_selections(None, cx, |s| {
 6623                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6624            });
 6625            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6626            editor.navigate(nav_entry.data.unwrap(), cx);
 6627            assert_eq!(nav_entry.item.id(), cx.view_id());
 6628            assert_eq!(
 6629                editor.selections.display_ranges(cx),
 6630                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6631            );
 6632            assert!(pop_history(&mut editor, cx).is_none());
 6633
 6634            // Move the cursor a small distance via the mouse.
 6635            // Nothing is added to the navigation history.
 6636            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6637            editor.end_selection(cx);
 6638            assert_eq!(
 6639                editor.selections.display_ranges(cx),
 6640                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6641            );
 6642            assert!(pop_history(&mut editor, cx).is_none());
 6643
 6644            // Move the cursor a large distance via the mouse.
 6645            // The history can jump back to the previous position.
 6646            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6647            editor.end_selection(cx);
 6648            assert_eq!(
 6649                editor.selections.display_ranges(cx),
 6650                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6651            );
 6652            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6653            editor.navigate(nav_entry.data.unwrap(), cx);
 6654            assert_eq!(nav_entry.item.id(), cx.view_id());
 6655            assert_eq!(
 6656                editor.selections.display_ranges(cx),
 6657                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6658            );
 6659            assert!(pop_history(&mut editor, cx).is_none());
 6660
 6661            // Set scroll position to check later
 6662            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6663            let original_scroll_position = editor.scroll_position;
 6664            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6665
 6666            // Jump to the end of the document and adjust scroll
 6667            editor.move_to_end(&MoveToEnd, cx);
 6668            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6669            assert_ne!(editor.scroll_position, original_scroll_position);
 6670            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6671
 6672            let nav_entry = pop_history(&mut editor, cx).unwrap();
 6673            editor.navigate(nav_entry.data.unwrap(), cx);
 6674            assert_eq!(editor.scroll_position, original_scroll_position);
 6675            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6676
 6677            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6678            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6679            invalid_anchor.text_anchor.buffer_id = Some(999);
 6680            let invalid_point = Point::new(9999, 0);
 6681            editor.navigate(
 6682                Box::new(NavigationData {
 6683                    cursor_anchor: invalid_anchor.clone(),
 6684                    cursor_position: invalid_point,
 6685                    scroll_top_anchor: invalid_anchor.clone(),
 6686                    scroll_top_row: invalid_point.row,
 6687                    scroll_position: Default::default(),
 6688                }),
 6689                cx,
 6690            );
 6691            assert_eq!(
 6692                editor.selections.display_ranges(cx),
 6693                &[editor.max_point(cx)..editor.max_point(cx)]
 6694            );
 6695            assert_eq!(
 6696                editor.scroll_position(cx),
 6697                vec2f(0., editor.max_point(cx).row() as f32)
 6698            );
 6699
 6700            editor
 6701        });
 6702    }
 6703
 6704    #[gpui::test]
 6705    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6706        cx.set_global(Settings::test(cx));
 6707        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6708        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6709
 6710        view.update(cx, |view, cx| {
 6711            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6712            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6713            view.end_selection(cx);
 6714
 6715            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6716            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6717            view.end_selection(cx);
 6718            assert_eq!(
 6719                view.selections.display_ranges(cx),
 6720                [
 6721                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6722                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6723                ]
 6724            );
 6725        });
 6726
 6727        view.update(cx, |view, cx| {
 6728            view.cancel(&Cancel, cx);
 6729            assert_eq!(
 6730                view.selections.display_ranges(cx),
 6731                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6732            );
 6733        });
 6734
 6735        view.update(cx, |view, cx| {
 6736            view.cancel(&Cancel, cx);
 6737            assert_eq!(
 6738                view.selections.display_ranges(cx),
 6739                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6740            );
 6741        });
 6742    }
 6743
 6744    #[gpui::test]
 6745    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6746        cx.set_global(Settings::test(cx));
 6747        let buffer = MultiBuffer::build_simple(
 6748            &"
 6749                impl Foo {
 6750                    // Hello!
 6751
 6752                    fn a() {
 6753                        1
 6754                    }
 6755
 6756                    fn b() {
 6757                        2
 6758                    }
 6759
 6760                    fn c() {
 6761                        3
 6762                    }
 6763                }
 6764            "
 6765            .unindent(),
 6766            cx,
 6767        );
 6768        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6769
 6770        view.update(cx, |view, cx| {
 6771            view.change_selections(None, cx, |s| {
 6772                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 6773            });
 6774            view.fold(&Fold, cx);
 6775            assert_eq!(
 6776                view.display_text(cx),
 6777                "
 6778                    impl Foo {
 6779                        // Hello!
 6780
 6781                        fn a() {
 6782                            1
 6783                        }
 6784
 6785                        fn b() {…
 6786                        }
 6787
 6788                        fn c() {…
 6789                        }
 6790                    }
 6791                "
 6792                .unindent(),
 6793            );
 6794
 6795            view.fold(&Fold, cx);
 6796            assert_eq!(
 6797                view.display_text(cx),
 6798                "
 6799                    impl Foo {…
 6800                    }
 6801                "
 6802                .unindent(),
 6803            );
 6804
 6805            view.unfold_lines(&UnfoldLines, cx);
 6806            assert_eq!(
 6807                view.display_text(cx),
 6808                "
 6809                    impl Foo {
 6810                        // Hello!
 6811
 6812                        fn a() {
 6813                            1
 6814                        }
 6815
 6816                        fn b() {…
 6817                        }
 6818
 6819                        fn c() {…
 6820                        }
 6821                    }
 6822                "
 6823                .unindent(),
 6824            );
 6825
 6826            view.unfold_lines(&UnfoldLines, cx);
 6827            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6828        });
 6829    }
 6830
 6831    #[gpui::test]
 6832    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6833        cx.set_global(Settings::test(cx));
 6834        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6835        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6836
 6837        buffer.update(cx, |buffer, cx| {
 6838            buffer.edit(
 6839                vec![
 6840                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 6841                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 6842                ],
 6843                cx,
 6844            );
 6845        });
 6846
 6847        view.update(cx, |view, cx| {
 6848            assert_eq!(
 6849                view.selections.display_ranges(cx),
 6850                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6851            );
 6852
 6853            view.move_down(&MoveDown, cx);
 6854            assert_eq!(
 6855                view.selections.display_ranges(cx),
 6856                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6857            );
 6858
 6859            view.move_right(&MoveRight, cx);
 6860            assert_eq!(
 6861                view.selections.display_ranges(cx),
 6862                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6863            );
 6864
 6865            view.move_left(&MoveLeft, cx);
 6866            assert_eq!(
 6867                view.selections.display_ranges(cx),
 6868                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6869            );
 6870
 6871            view.move_up(&MoveUp, cx);
 6872            assert_eq!(
 6873                view.selections.display_ranges(cx),
 6874                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6875            );
 6876
 6877            view.move_to_end(&MoveToEnd, cx);
 6878            assert_eq!(
 6879                view.selections.display_ranges(cx),
 6880                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 6881            );
 6882
 6883            view.move_to_beginning(&MoveToBeginning, cx);
 6884            assert_eq!(
 6885                view.selections.display_ranges(cx),
 6886                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6887            );
 6888
 6889            view.change_selections(None, cx, |s| {
 6890                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 6891            });
 6892            view.select_to_beginning(&SelectToBeginning, cx);
 6893            assert_eq!(
 6894                view.selections.display_ranges(cx),
 6895                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 6896            );
 6897
 6898            view.select_to_end(&SelectToEnd, cx);
 6899            assert_eq!(
 6900                view.selections.display_ranges(cx),
 6901                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 6902            );
 6903        });
 6904    }
 6905
 6906    #[gpui::test]
 6907    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 6908        cx.set_global(Settings::test(cx));
 6909        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 6910        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6911
 6912        assert_eq!('ⓐ'.len_utf8(), 3);
 6913        assert_eq!('α'.len_utf8(), 2);
 6914
 6915        view.update(cx, |view, cx| {
 6916            view.fold_ranges(
 6917                vec![
 6918                    Point::new(0, 6)..Point::new(0, 12),
 6919                    Point::new(1, 2)..Point::new(1, 4),
 6920                    Point::new(2, 4)..Point::new(2, 8),
 6921                ],
 6922                cx,
 6923            );
 6924            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 6925
 6926            view.move_right(&MoveRight, cx);
 6927            assert_eq!(
 6928                view.selections.display_ranges(cx),
 6929                &[empty_range(0, "".len())]
 6930            );
 6931            view.move_right(&MoveRight, cx);
 6932            assert_eq!(
 6933                view.selections.display_ranges(cx),
 6934                &[empty_range(0, "ⓐⓑ".len())]
 6935            );
 6936            view.move_right(&MoveRight, cx);
 6937            assert_eq!(
 6938                view.selections.display_ranges(cx),
 6939                &[empty_range(0, "ⓐⓑ…".len())]
 6940            );
 6941
 6942            view.move_down(&MoveDown, cx);
 6943            assert_eq!(
 6944                view.selections.display_ranges(cx),
 6945                &[empty_range(1, "ab…".len())]
 6946            );
 6947            view.move_left(&MoveLeft, cx);
 6948            assert_eq!(
 6949                view.selections.display_ranges(cx),
 6950                &[empty_range(1, "ab".len())]
 6951            );
 6952            view.move_left(&MoveLeft, cx);
 6953            assert_eq!(
 6954                view.selections.display_ranges(cx),
 6955                &[empty_range(1, "a".len())]
 6956            );
 6957
 6958            view.move_down(&MoveDown, cx);
 6959            assert_eq!(
 6960                view.selections.display_ranges(cx),
 6961                &[empty_range(2, "α".len())]
 6962            );
 6963            view.move_right(&MoveRight, cx);
 6964            assert_eq!(
 6965                view.selections.display_ranges(cx),
 6966                &[empty_range(2, "αβ".len())]
 6967            );
 6968            view.move_right(&MoveRight, cx);
 6969            assert_eq!(
 6970                view.selections.display_ranges(cx),
 6971                &[empty_range(2, "αβ…".len())]
 6972            );
 6973            view.move_right(&MoveRight, cx);
 6974            assert_eq!(
 6975                view.selections.display_ranges(cx),
 6976                &[empty_range(2, "αβ…ε".len())]
 6977            );
 6978
 6979            view.move_up(&MoveUp, cx);
 6980            assert_eq!(
 6981                view.selections.display_ranges(cx),
 6982                &[empty_range(1, "ab…e".len())]
 6983            );
 6984            view.move_up(&MoveUp, cx);
 6985            assert_eq!(
 6986                view.selections.display_ranges(cx),
 6987                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 6988            );
 6989            view.move_left(&MoveLeft, cx);
 6990            assert_eq!(
 6991                view.selections.display_ranges(cx),
 6992                &[empty_range(0, "ⓐⓑ…".len())]
 6993            );
 6994            view.move_left(&MoveLeft, cx);
 6995            assert_eq!(
 6996                view.selections.display_ranges(cx),
 6997                &[empty_range(0, "ⓐⓑ".len())]
 6998            );
 6999            view.move_left(&MoveLeft, cx);
 7000            assert_eq!(
 7001                view.selections.display_ranges(cx),
 7002                &[empty_range(0, "".len())]
 7003            );
 7004        });
 7005    }
 7006
 7007    #[gpui::test]
 7008    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7009        cx.set_global(Settings::test(cx));
 7010        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7011        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7012        view.update(cx, |view, cx| {
 7013            view.change_selections(None, cx, |s| {
 7014                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 7015            });
 7016            view.move_down(&MoveDown, cx);
 7017            assert_eq!(
 7018                view.selections.display_ranges(cx),
 7019                &[empty_range(1, "abcd".len())]
 7020            );
 7021
 7022            view.move_down(&MoveDown, cx);
 7023            assert_eq!(
 7024                view.selections.display_ranges(cx),
 7025                &[empty_range(2, "αβγ".len())]
 7026            );
 7027
 7028            view.move_down(&MoveDown, cx);
 7029            assert_eq!(
 7030                view.selections.display_ranges(cx),
 7031                &[empty_range(3, "abcd".len())]
 7032            );
 7033
 7034            view.move_down(&MoveDown, cx);
 7035            assert_eq!(
 7036                view.selections.display_ranges(cx),
 7037                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7038            );
 7039
 7040            view.move_up(&MoveUp, cx);
 7041            assert_eq!(
 7042                view.selections.display_ranges(cx),
 7043                &[empty_range(3, "abcd".len())]
 7044            );
 7045
 7046            view.move_up(&MoveUp, cx);
 7047            assert_eq!(
 7048                view.selections.display_ranges(cx),
 7049                &[empty_range(2, "αβγ".len())]
 7050            );
 7051        });
 7052    }
 7053
 7054    #[gpui::test]
 7055    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7056        cx.set_global(Settings::test(cx));
 7057        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7058        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7059        view.update(cx, |view, cx| {
 7060            view.change_selections(None, cx, |s| {
 7061                s.select_display_ranges([
 7062                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7063                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7064                ]);
 7065            });
 7066        });
 7067
 7068        view.update(cx, |view, cx| {
 7069            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7070            assert_eq!(
 7071                view.selections.display_ranges(cx),
 7072                &[
 7073                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7074                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7075                ]
 7076            );
 7077        });
 7078
 7079        view.update(cx, |view, cx| {
 7080            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7081            assert_eq!(
 7082                view.selections.display_ranges(cx),
 7083                &[
 7084                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7085                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7086                ]
 7087            );
 7088        });
 7089
 7090        view.update(cx, |view, cx| {
 7091            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7092            assert_eq!(
 7093                view.selections.display_ranges(cx),
 7094                &[
 7095                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7096                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7097                ]
 7098            );
 7099        });
 7100
 7101        view.update(cx, |view, cx| {
 7102            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7103            assert_eq!(
 7104                view.selections.display_ranges(cx),
 7105                &[
 7106                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7107                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7108                ]
 7109            );
 7110        });
 7111
 7112        // Moving to the end of line again is a no-op.
 7113        view.update(cx, |view, cx| {
 7114            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7115            assert_eq!(
 7116                view.selections.display_ranges(cx),
 7117                &[
 7118                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7119                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7120                ]
 7121            );
 7122        });
 7123
 7124        view.update(cx, |view, cx| {
 7125            view.move_left(&MoveLeft, cx);
 7126            view.select_to_beginning_of_line(
 7127                &SelectToBeginningOfLine {
 7128                    stop_at_soft_wraps: true,
 7129                },
 7130                cx,
 7131            );
 7132            assert_eq!(
 7133                view.selections.display_ranges(cx),
 7134                &[
 7135                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7136                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7137                ]
 7138            );
 7139        });
 7140
 7141        view.update(cx, |view, cx| {
 7142            view.select_to_beginning_of_line(
 7143                &SelectToBeginningOfLine {
 7144                    stop_at_soft_wraps: true,
 7145                },
 7146                cx,
 7147            );
 7148            assert_eq!(
 7149                view.selections.display_ranges(cx),
 7150                &[
 7151                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7152                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7153                ]
 7154            );
 7155        });
 7156
 7157        view.update(cx, |view, cx| {
 7158            view.select_to_beginning_of_line(
 7159                &SelectToBeginningOfLine {
 7160                    stop_at_soft_wraps: true,
 7161                },
 7162                cx,
 7163            );
 7164            assert_eq!(
 7165                view.selections.display_ranges(cx),
 7166                &[
 7167                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7168                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7169                ]
 7170            );
 7171        });
 7172
 7173        view.update(cx, |view, cx| {
 7174            view.select_to_end_of_line(
 7175                &SelectToEndOfLine {
 7176                    stop_at_soft_wraps: true,
 7177                },
 7178                cx,
 7179            );
 7180            assert_eq!(
 7181                view.selections.display_ranges(cx),
 7182                &[
 7183                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7184                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7185                ]
 7186            );
 7187        });
 7188
 7189        view.update(cx, |view, cx| {
 7190            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7191            assert_eq!(view.display_text(cx), "ab\n  de");
 7192            assert_eq!(
 7193                view.selections.display_ranges(cx),
 7194                &[
 7195                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7196                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7197                ]
 7198            );
 7199        });
 7200
 7201        view.update(cx, |view, cx| {
 7202            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7203            assert_eq!(view.display_text(cx), "\n");
 7204            assert_eq!(
 7205                view.selections.display_ranges(cx),
 7206                &[
 7207                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7208                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7209                ]
 7210            );
 7211        });
 7212    }
 7213
 7214    #[gpui::test]
 7215    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7216        cx.set_global(Settings::test(cx));
 7217        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7218        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7219        view.update(cx, |view, cx| {
 7220            view.change_selections(None, cx, |s| {
 7221                s.select_display_ranges([
 7222                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7223                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7224                ])
 7225            });
 7226
 7227            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7228            assert_selection_ranges(
 7229                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7230                vec![('<', '>'), ('[', ']')],
 7231                view,
 7232                cx,
 7233            );
 7234
 7235            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7236            assert_selection_ranges(
 7237                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7238                vec![('<', '>'), ('[', ']')],
 7239                view,
 7240                cx,
 7241            );
 7242
 7243            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7244            assert_selection_ranges(
 7245                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7246                vec![('<', '>'), ('[', ']')],
 7247                view,
 7248                cx,
 7249            );
 7250
 7251            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7252            assert_selection_ranges(
 7253                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7254                vec![('<', '>'), ('[', ']')],
 7255                view,
 7256                cx,
 7257            );
 7258
 7259            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7260            assert_selection_ranges(
 7261                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7262                vec![('<', '>'), ('[', ']')],
 7263                view,
 7264                cx,
 7265            );
 7266
 7267            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7268            assert_selection_ranges(
 7269                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7270                vec![('<', '>'), ('[', ']')],
 7271                view,
 7272                cx,
 7273            );
 7274
 7275            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7276            assert_selection_ranges(
 7277                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7278                vec![('<', '>'), ('[', ']')],
 7279                view,
 7280                cx,
 7281            );
 7282
 7283            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7284            assert_selection_ranges(
 7285                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7286                vec![('<', '>'), ('[', ']')],
 7287                view,
 7288                cx,
 7289            );
 7290
 7291            view.move_right(&MoveRight, cx);
 7292            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7293            assert_selection_ranges(
 7294                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7295                vec![('<', '>'), ('[', ']')],
 7296                view,
 7297                cx,
 7298            );
 7299
 7300            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7301            assert_selection_ranges(
 7302                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7303                vec![('<', '>'), ('[', ']')],
 7304                view,
 7305                cx,
 7306            );
 7307
 7308            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7309            assert_selection_ranges(
 7310                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7311                vec![('<', '>'), ('[', ']')],
 7312                view,
 7313                cx,
 7314            );
 7315        });
 7316    }
 7317
 7318    #[gpui::test]
 7319    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7320        cx.set_global(Settings::test(cx));
 7321        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7322        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7323
 7324        view.update(cx, |view, cx| {
 7325            view.set_wrap_width(Some(140.), cx);
 7326            assert_eq!(
 7327                view.display_text(cx),
 7328                "use one::{\n    two::three::\n    four::five\n};"
 7329            );
 7330
 7331            view.change_selections(None, cx, |s| {
 7332                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7333            });
 7334
 7335            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7336            assert_eq!(
 7337                view.selections.display_ranges(cx),
 7338                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7339            );
 7340
 7341            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7342            assert_eq!(
 7343                view.selections.display_ranges(cx),
 7344                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7345            );
 7346
 7347            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7348            assert_eq!(
 7349                view.selections.display_ranges(cx),
 7350                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7351            );
 7352
 7353            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7354            assert_eq!(
 7355                view.selections.display_ranges(cx),
 7356                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7357            );
 7358
 7359            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7360            assert_eq!(
 7361                view.selections.display_ranges(cx),
 7362                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7363            );
 7364
 7365            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7366            assert_eq!(
 7367                view.selections.display_ranges(cx),
 7368                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7369            );
 7370        });
 7371    }
 7372
 7373    #[gpui::test]
 7374    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7375        cx.set_global(Settings::test(cx));
 7376        let (text, ranges) = marked_text_ranges("one [two three] four");
 7377        let buffer = MultiBuffer::build_simple(&text, cx);
 7378
 7379        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7380
 7381        editor.update(cx, |editor, cx| {
 7382            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7383            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7384            assert_eq!(editor.text(cx), " four");
 7385        });
 7386    }
 7387
 7388    #[gpui::test]
 7389    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7390        cx.set_global(Settings::test(cx));
 7391        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7392        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7393
 7394        view.update(cx, |view, cx| {
 7395            view.change_selections(None, cx, |s| {
 7396                s.select_display_ranges([
 7397                    // an empty selection - the preceding word fragment is deleted
 7398                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7399                    // characters selected - they are deleted
 7400                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7401                ])
 7402            });
 7403            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7404        });
 7405
 7406        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7407
 7408        view.update(cx, |view, cx| {
 7409            view.change_selections(None, cx, |s| {
 7410                s.select_display_ranges([
 7411                    // an empty selection - the following word fragment is deleted
 7412                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7413                    // characters selected - they are deleted
 7414                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7415                ])
 7416            });
 7417            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7418        });
 7419
 7420        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7421    }
 7422
 7423    #[gpui::test]
 7424    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7425        cx.set_global(Settings::test(cx));
 7426        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7427        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7428
 7429        view.update(cx, |view, cx| {
 7430            view.change_selections(None, cx, |s| {
 7431                s.select_display_ranges([
 7432                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7433                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7434                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7435                ])
 7436            });
 7437
 7438            view.newline(&Newline, cx);
 7439            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7440        });
 7441    }
 7442
 7443    #[gpui::test]
 7444    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7445        cx.set_global(Settings::test(cx));
 7446        let buffer = MultiBuffer::build_simple(
 7447            "
 7448                a
 7449                b(
 7450                    X
 7451                )
 7452                c(
 7453                    X
 7454                )
 7455            "
 7456            .unindent()
 7457            .as_str(),
 7458            cx,
 7459        );
 7460
 7461        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7462            let mut editor = build_editor(buffer.clone(), cx);
 7463            editor.change_selections(None, cx, |s| {
 7464                s.select_ranges([
 7465                    Point::new(2, 4)..Point::new(2, 5),
 7466                    Point::new(5, 4)..Point::new(5, 5),
 7467                ])
 7468            });
 7469            editor
 7470        });
 7471
 7472        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7473        buffer.update(cx, |buffer, cx| {
 7474            buffer.edit(
 7475                [
 7476                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7477                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7478                ],
 7479                cx,
 7480            );
 7481            assert_eq!(
 7482                buffer.read(cx).text(),
 7483                "
 7484                    a
 7485                    b()
 7486                    c()
 7487                "
 7488                .unindent()
 7489            );
 7490        });
 7491
 7492        editor.update(cx, |editor, cx| {
 7493            assert_eq!(
 7494                editor.selections.ranges(cx),
 7495                &[
 7496                    Point::new(1, 2)..Point::new(1, 2),
 7497                    Point::new(2, 2)..Point::new(2, 2),
 7498                ],
 7499            );
 7500
 7501            editor.newline(&Newline, cx);
 7502            assert_eq!(
 7503                editor.text(cx),
 7504                "
 7505                    a
 7506                    b(
 7507                    )
 7508                    c(
 7509                    )
 7510                "
 7511                .unindent()
 7512            );
 7513
 7514            // The selections are moved after the inserted newlines
 7515            assert_eq!(
 7516                editor.selections.ranges(cx),
 7517                &[
 7518                    Point::new(2, 0)..Point::new(2, 0),
 7519                    Point::new(4, 0)..Point::new(4, 0),
 7520                ],
 7521            );
 7522        });
 7523    }
 7524
 7525    #[gpui::test]
 7526    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7527        cx.set_global(Settings::test(cx));
 7528        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7529        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7530            let mut editor = build_editor(buffer.clone(), cx);
 7531            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7532            editor
 7533        });
 7534
 7535        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7536        buffer.update(cx, |buffer, cx| {
 7537            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7538            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7539        });
 7540
 7541        editor.update(cx, |editor, cx| {
 7542            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7543
 7544            editor.insert("Z", cx);
 7545            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7546
 7547            // The selections are moved after the inserted characters
 7548            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7549        });
 7550    }
 7551
 7552    #[gpui::test]
 7553    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7554        let mut cx = EditorTestContext::new(cx).await;
 7555
 7556        cx.set_state(indoc! {"
 7557              [one} [two}
 7558            three
 7559             four"});
 7560        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7561        cx.assert_editor_state(indoc! {"
 7562                [one} [two}
 7563            three
 7564             four"});
 7565
 7566        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7567        cx.assert_editor_state(indoc! {"
 7568            [one} [two}
 7569            three
 7570             four"});
 7571
 7572        // select across line ending
 7573        cx.set_state(indoc! {"
 7574            one two
 7575            t[hree
 7576            } four"});
 7577        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7578        cx.assert_editor_state(indoc! {"
 7579            one two
 7580                t[hree
 7581            } four"});
 7582
 7583        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7584        cx.assert_editor_state(indoc! {"
 7585            one two
 7586            t[hree
 7587            } four"});
 7588
 7589        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7590        cx.set_state(indoc! {"
 7591            one two
 7592            |three
 7593                four"});
 7594        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7595        cx.assert_editor_state(indoc! {"
 7596            one two
 7597                |three
 7598                four"});
 7599
 7600        cx.set_state(indoc! {"
 7601            one two
 7602            |    three
 7603             four"});
 7604        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7605        cx.assert_editor_state(indoc! {"
 7606            one two
 7607            |three
 7608             four"});
 7609    }
 7610
 7611    #[gpui::test]
 7612    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 7613        let mut cx = EditorTestContext::new(cx).await;
 7614        cx.update(|cx| {
 7615            cx.update_global::<Settings, _, _>(|settings, _| {
 7616                settings.editor_overrides.hard_tabs = Some(true);
 7617            });
 7618        });
 7619
 7620        // select two ranges on one line
 7621        cx.set_state(indoc! {"
 7622            [one} [two}
 7623            three
 7624            four"});
 7625        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7626        cx.assert_editor_state(indoc! {"
 7627            \t[one} [two}
 7628            three
 7629            four"});
 7630        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7631        cx.assert_editor_state(indoc! {"
 7632            \t\t[one} [two}
 7633            three
 7634            four"});
 7635        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7636        cx.assert_editor_state(indoc! {"
 7637            \t[one} [two}
 7638            three
 7639            four"});
 7640        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7641        cx.assert_editor_state(indoc! {"
 7642            [one} [two}
 7643            three
 7644            four"});
 7645
 7646        // select across a line ending
 7647        cx.set_state(indoc! {"
 7648            one two
 7649            t[hree
 7650            }four"});
 7651        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7652        cx.assert_editor_state(indoc! {"
 7653            one two
 7654            \tt[hree
 7655            }four"});
 7656        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7657        cx.assert_editor_state(indoc! {"
 7658            one two
 7659            \t\tt[hree
 7660            }four"});
 7661        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7662        cx.assert_editor_state(indoc! {"
 7663            one two
 7664            \tt[hree
 7665            }four"});
 7666        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7667        cx.assert_editor_state(indoc! {"
 7668            one two
 7669            t[hree
 7670            }four"});
 7671
 7672        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7673        cx.set_state(indoc! {"
 7674            one two
 7675            |three
 7676            four"});
 7677        cx.assert_editor_state(indoc! {"
 7678            one two
 7679            |three
 7680            four"});
 7681        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7682        cx.assert_editor_state(indoc! {"
 7683            one two
 7684            \t|three
 7685            four"});
 7686        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7687        cx.assert_editor_state(indoc! {"
 7688            one two
 7689            |three
 7690            four"});
 7691    }
 7692
 7693    #[gpui::test]
 7694    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7695        cx.set_global(
 7696            Settings::test(cx)
 7697                .with_language_defaults(
 7698                    "TOML",
 7699                    EditorSettings {
 7700                        tab_size: Some(2.try_into().unwrap()),
 7701                        ..Default::default()
 7702                    },
 7703                )
 7704                .with_language_defaults(
 7705                    "Rust",
 7706                    EditorSettings {
 7707                        tab_size: Some(4.try_into().unwrap()),
 7708                        ..Default::default()
 7709                    },
 7710                ),
 7711        );
 7712        let toml_language = Arc::new(Language::new(
 7713            LanguageConfig {
 7714                name: "TOML".into(),
 7715                ..Default::default()
 7716            },
 7717            None,
 7718        ));
 7719        let rust_language = Arc::new(Language::new(
 7720            LanguageConfig {
 7721                name: "Rust".into(),
 7722                ..Default::default()
 7723            },
 7724            None,
 7725        ));
 7726
 7727        let toml_buffer = cx
 7728            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7729        let rust_buffer = cx.add_model(|cx| {
 7730            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7731        });
 7732        let multibuffer = cx.add_model(|cx| {
 7733            let mut multibuffer = MultiBuffer::new(0);
 7734            multibuffer.push_excerpts(
 7735                toml_buffer.clone(),
 7736                [ExcerptRange {
 7737                    context: Point::new(0, 0)..Point::new(2, 0),
 7738                    primary: None,
 7739                }],
 7740                cx,
 7741            );
 7742            multibuffer.push_excerpts(
 7743                rust_buffer.clone(),
 7744                [ExcerptRange {
 7745                    context: Point::new(0, 0)..Point::new(1, 0),
 7746                    primary: None,
 7747                }],
 7748                cx,
 7749            );
 7750            multibuffer
 7751        });
 7752
 7753        cx.add_window(Default::default(), |cx| {
 7754            let mut editor = build_editor(multibuffer, cx);
 7755
 7756            assert_eq!(
 7757                editor.text(cx),
 7758                indoc! {"
 7759                    a = 1
 7760                    b = 2
 7761
 7762                    const c: usize = 3;
 7763                "}
 7764            );
 7765
 7766            select_ranges(
 7767                &mut editor,
 7768                indoc! {"
 7769                    [a] = 1
 7770                    b = 2
 7771
 7772                    [const c:] usize = 3;
 7773                "},
 7774                cx,
 7775            );
 7776
 7777            editor.tab(&Tab, cx);
 7778            assert_text_with_selections(
 7779                &mut editor,
 7780                indoc! {"
 7781                      [a] = 1
 7782                    b = 2
 7783
 7784                        [const c:] usize = 3;
 7785                "},
 7786                cx,
 7787            );
 7788            editor.tab_prev(&TabPrev, cx);
 7789            assert_text_with_selections(
 7790                &mut editor,
 7791                indoc! {"
 7792                    [a] = 1
 7793                    b = 2
 7794
 7795                    [const c:] usize = 3;
 7796                "},
 7797                cx,
 7798            );
 7799
 7800            editor
 7801        });
 7802    }
 7803
 7804    #[gpui::test]
 7805    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7806        let mut cx = EditorTestContext::new(cx).await;
 7807        // Basic backspace
 7808        cx.set_state(indoc! {"
 7809            on|e two three
 7810            fou[r} five six
 7811            seven {eight nine
 7812            ]ten"});
 7813        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7814        cx.assert_editor_state(indoc! {"
 7815            o|e two three
 7816            fou| five six
 7817            seven |ten"});
 7818
 7819        // Test backspace inside and around indents
 7820        cx.set_state(indoc! {"
 7821            zero
 7822                |one
 7823                    |two
 7824                | | |  three
 7825            |  |  four"});
 7826        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7827        cx.assert_editor_state(indoc! {"
 7828            zero
 7829            |one
 7830                |two
 7831            |  three|  four"});
 7832
 7833        // Test backspace with line_mode set to true
 7834        cx.update_editor(|e, _| e.selections.line_mode = true);
 7835        cx.set_state(indoc! {"
 7836            The |quick |brown
 7837            fox jumps over
 7838            the lazy dog
 7839            |The qu[ick b}rown"});
 7840        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7841        cx.assert_editor_state(indoc! {"
 7842            |fox jumps over
 7843            the lazy dog|"});
 7844    }
 7845
 7846    #[gpui::test]
 7847    async fn test_delete(cx: &mut gpui::TestAppContext) {
 7848        let mut cx = EditorTestContext::new(cx).await;
 7849
 7850        cx.set_state(indoc! {"
 7851            on|e two three
 7852            fou[r} five six
 7853            seven {eight nine
 7854            ]ten"});
 7855        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 7856        cx.assert_editor_state(indoc! {"
 7857            on| two three
 7858            fou| five six
 7859            seven |ten"});
 7860
 7861        // Test backspace with line_mode set to true
 7862        cx.update_editor(|e, _| e.selections.line_mode = true);
 7863        cx.set_state(indoc! {"
 7864            The |quick |brown
 7865            fox {jum]ps over
 7866            the lazy dog
 7867            |The qu[ick b}rown"});
 7868        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7869        cx.assert_editor_state("|the lazy dog|");
 7870    }
 7871
 7872    #[gpui::test]
 7873    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7874        cx.set_global(Settings::test(cx));
 7875        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7876        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7877        view.update(cx, |view, cx| {
 7878            view.change_selections(None, cx, |s| {
 7879                s.select_display_ranges([
 7880                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7881                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7882                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7883                ])
 7884            });
 7885            view.delete_line(&DeleteLine, cx);
 7886            assert_eq!(view.display_text(cx), "ghi");
 7887            assert_eq!(
 7888                view.selections.display_ranges(cx),
 7889                vec![
 7890                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7891                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7892                ]
 7893            );
 7894        });
 7895
 7896        cx.set_global(Settings::test(cx));
 7897        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7898        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7899        view.update(cx, |view, cx| {
 7900            view.change_selections(None, cx, |s| {
 7901                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 7902            });
 7903            view.delete_line(&DeleteLine, cx);
 7904            assert_eq!(view.display_text(cx), "ghi\n");
 7905            assert_eq!(
 7906                view.selections.display_ranges(cx),
 7907                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7908            );
 7909        });
 7910    }
 7911
 7912    #[gpui::test]
 7913    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7914        cx.set_global(Settings::test(cx));
 7915        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7916        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7917        view.update(cx, |view, cx| {
 7918            view.change_selections(None, cx, |s| {
 7919                s.select_display_ranges([
 7920                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7921                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7922                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7923                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7924                ])
 7925            });
 7926            view.duplicate_line(&DuplicateLine, cx);
 7927            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 7928            assert_eq!(
 7929                view.selections.display_ranges(cx),
 7930                vec![
 7931                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7932                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7933                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7934                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 7935                ]
 7936            );
 7937        });
 7938
 7939        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7940        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7941        view.update(cx, |view, cx| {
 7942            view.change_selections(None, cx, |s| {
 7943                s.select_display_ranges([
 7944                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 7945                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 7946                ])
 7947            });
 7948            view.duplicate_line(&DuplicateLine, cx);
 7949            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 7950            assert_eq!(
 7951                view.selections.display_ranges(cx),
 7952                vec![
 7953                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 7954                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 7955                ]
 7956            );
 7957        });
 7958    }
 7959
 7960    #[gpui::test]
 7961    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 7962        cx.set_global(Settings::test(cx));
 7963        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 7964        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7965        view.update(cx, |view, cx| {
 7966            view.fold_ranges(
 7967                vec![
 7968                    Point::new(0, 2)..Point::new(1, 2),
 7969                    Point::new(2, 3)..Point::new(4, 1),
 7970                    Point::new(7, 0)..Point::new(8, 4),
 7971                ],
 7972                cx,
 7973            );
 7974            view.change_selections(None, cx, |s| {
 7975                s.select_display_ranges([
 7976                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7977                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7978                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7979                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 7980                ])
 7981            });
 7982            assert_eq!(
 7983                view.display_text(cx),
 7984                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 7985            );
 7986
 7987            view.move_line_up(&MoveLineUp, cx);
 7988            assert_eq!(
 7989                view.display_text(cx),
 7990                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 7991            );
 7992            assert_eq!(
 7993                view.selections.display_ranges(cx),
 7994                vec![
 7995                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7996                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 7997                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 7998                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 7999                ]
 8000            );
 8001        });
 8002
 8003        view.update(cx, |view, cx| {
 8004            view.move_line_down(&MoveLineDown, cx);
 8005            assert_eq!(
 8006                view.display_text(cx),
 8007                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8008            );
 8009            assert_eq!(
 8010                view.selections.display_ranges(cx),
 8011                vec![
 8012                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8013                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8014                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8015                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8016                ]
 8017            );
 8018        });
 8019
 8020        view.update(cx, |view, cx| {
 8021            view.move_line_down(&MoveLineDown, cx);
 8022            assert_eq!(
 8023                view.display_text(cx),
 8024                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8025            );
 8026            assert_eq!(
 8027                view.selections.display_ranges(cx),
 8028                vec![
 8029                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8030                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8031                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8032                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8033                ]
 8034            );
 8035        });
 8036
 8037        view.update(cx, |view, cx| {
 8038            view.move_line_up(&MoveLineUp, cx);
 8039            assert_eq!(
 8040                view.display_text(cx),
 8041                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8042            );
 8043            assert_eq!(
 8044                view.selections.display_ranges(cx),
 8045                vec![
 8046                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8047                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8048                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8049                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8050                ]
 8051            );
 8052        });
 8053    }
 8054
 8055    #[gpui::test]
 8056    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8057        cx.set_global(Settings::test(cx));
 8058        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8059        let snapshot = buffer.read(cx).snapshot(cx);
 8060        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8061        editor.update(cx, |editor, cx| {
 8062            editor.insert_blocks(
 8063                [BlockProperties {
 8064                    style: BlockStyle::Fixed,
 8065                    position: snapshot.anchor_after(Point::new(2, 0)),
 8066                    disposition: BlockDisposition::Below,
 8067                    height: 1,
 8068                    render: Arc::new(|_| Empty::new().boxed()),
 8069                }],
 8070                cx,
 8071            );
 8072            editor.change_selections(None, cx, |s| {
 8073                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8074            });
 8075            editor.move_line_down(&MoveLineDown, cx);
 8076        });
 8077    }
 8078
 8079    #[gpui::test]
 8080    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8081        cx.set_global(Settings::test(cx));
 8082
 8083        cx.add_window(Default::default(), |cx| {
 8084            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8085
 8086            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8087            editor.transpose(&Default::default(), cx);
 8088            assert_eq!(editor.text(cx), "bac");
 8089            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8090
 8091            editor.transpose(&Default::default(), cx);
 8092            assert_eq!(editor.text(cx), "bca");
 8093            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8094
 8095            editor.transpose(&Default::default(), cx);
 8096            assert_eq!(editor.text(cx), "bac");
 8097            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8098
 8099            editor
 8100        })
 8101        .1;
 8102
 8103        cx.add_window(Default::default(), |cx| {
 8104            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8105
 8106            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8107            editor.transpose(&Default::default(), cx);
 8108            assert_eq!(editor.text(cx), "acb\nde");
 8109            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8110
 8111            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8112            editor.transpose(&Default::default(), cx);
 8113            assert_eq!(editor.text(cx), "acbd\ne");
 8114            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8115
 8116            editor.transpose(&Default::default(), cx);
 8117            assert_eq!(editor.text(cx), "acbde\n");
 8118            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8119
 8120            editor.transpose(&Default::default(), cx);
 8121            assert_eq!(editor.text(cx), "acbd\ne");
 8122            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8123
 8124            editor
 8125        })
 8126        .1;
 8127
 8128        cx.add_window(Default::default(), |cx| {
 8129            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8130
 8131            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8132            editor.transpose(&Default::default(), cx);
 8133            assert_eq!(editor.text(cx), "bacd\ne");
 8134            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8135
 8136            editor.transpose(&Default::default(), cx);
 8137            assert_eq!(editor.text(cx), "bcade\n");
 8138            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8139
 8140            editor.transpose(&Default::default(), cx);
 8141            assert_eq!(editor.text(cx), "bcda\ne");
 8142            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8143
 8144            editor.transpose(&Default::default(), cx);
 8145            assert_eq!(editor.text(cx), "bcade\n");
 8146            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8147
 8148            editor.transpose(&Default::default(), cx);
 8149            assert_eq!(editor.text(cx), "bcaed\n");
 8150            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8151
 8152            editor
 8153        })
 8154        .1;
 8155
 8156        cx.add_window(Default::default(), |cx| {
 8157            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8158
 8159            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8160            editor.transpose(&Default::default(), cx);
 8161            assert_eq!(editor.text(cx), "🏀🍐✋");
 8162            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8163
 8164            editor.transpose(&Default::default(), cx);
 8165            assert_eq!(editor.text(cx), "🏀✋🍐");
 8166            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8167
 8168            editor.transpose(&Default::default(), cx);
 8169            assert_eq!(editor.text(cx), "🏀🍐✋");
 8170            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8171
 8172            editor
 8173        })
 8174        .1;
 8175    }
 8176
 8177    #[gpui::test]
 8178    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8179        let mut cx = EditorTestContext::new(cx).await;
 8180
 8181        cx.set_state("[one✅ }two [three }four [five }six ");
 8182        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8183        cx.assert_editor_state("|two |four |six ");
 8184
 8185        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8186        cx.set_state("two |four |six |");
 8187        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8188        cx.assert_editor_state("two one✅ |four three |six five |");
 8189
 8190        // Paste again but with only two cursors. Since the number of cursors doesn't
 8191        // match the number of slices in the clipboard, the entire clipboard text
 8192        // is pasted at each cursor.
 8193        cx.set_state("|two one✅ four three six five |");
 8194        cx.update_editor(|e, cx| {
 8195            e.handle_input(&Input("( ".into()), cx);
 8196            e.paste(&Paste, cx);
 8197            e.handle_input(&Input(") ".into()), cx);
 8198        });
 8199        cx.assert_editor_state(indoc! {"
 8200            ( one✅ 
 8201            three 
 8202            five ) |two one✅ four three six five ( one✅ 
 8203            three 
 8204            five ) |"});
 8205
 8206        // Cut with three selections, one of which is full-line.
 8207        cx.set_state(indoc! {"
 8208            1[2}3
 8209            4|567
 8210            [8}9"});
 8211        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8212        cx.assert_editor_state(indoc! {"
 8213            1|3
 8214            |9"});
 8215
 8216        // Paste with three selections, noticing how the copied selection that was full-line
 8217        // gets inserted before the second cursor.
 8218        cx.set_state(indoc! {"
 8219            1|3
 8220            9|
 8221            [o}ne"});
 8222        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8223        cx.assert_editor_state(indoc! {"
 8224            12|3
 8225            4567
 8226            9|
 8227            8|ne"});
 8228
 8229        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8230        cx.set_state(indoc! {"
 8231            The quick brown
 8232            fox ju|mps over
 8233            the lazy dog"});
 8234        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8235        cx.cx.assert_clipboard_content(Some("fox jumps over\n"));
 8236
 8237        // Paste with three selections, noticing how the copied full-line selection is inserted
 8238        // before the empty selections but replaces the selection that is non-empty.
 8239        cx.set_state(indoc! {"
 8240            T|he quick brown
 8241            [fo}x jumps over
 8242            t|he lazy dog"});
 8243        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8244        cx.assert_editor_state(indoc! {"
 8245            fox jumps over
 8246            T|he quick brown
 8247            fox jumps over
 8248            |x jumps over
 8249            fox jumps over
 8250            t|he lazy dog"});
 8251    }
 8252
 8253    #[gpui::test]
 8254    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8255        cx.set_global(Settings::test(cx));
 8256        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8257        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8258        view.update(cx, |view, cx| {
 8259            view.select_all(&SelectAll, cx);
 8260            assert_eq!(
 8261                view.selections.display_ranges(cx),
 8262                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8263            );
 8264        });
 8265    }
 8266
 8267    #[gpui::test]
 8268    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8269        cx.set_global(Settings::test(cx));
 8270        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8271        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8272        view.update(cx, |view, cx| {
 8273            view.change_selections(None, cx, |s| {
 8274                s.select_display_ranges([
 8275                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8276                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8277                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8278                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8279                ])
 8280            });
 8281            view.select_line(&SelectLine, cx);
 8282            assert_eq!(
 8283                view.selections.display_ranges(cx),
 8284                vec![
 8285                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8286                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8287                ]
 8288            );
 8289        });
 8290
 8291        view.update(cx, |view, cx| {
 8292            view.select_line(&SelectLine, cx);
 8293            assert_eq!(
 8294                view.selections.display_ranges(cx),
 8295                vec![
 8296                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8297                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8298                ]
 8299            );
 8300        });
 8301
 8302        view.update(cx, |view, cx| {
 8303            view.select_line(&SelectLine, cx);
 8304            assert_eq!(
 8305                view.selections.display_ranges(cx),
 8306                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8307            );
 8308        });
 8309    }
 8310
 8311    #[gpui::test]
 8312    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8313        cx.set_global(Settings::test(cx));
 8314        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8315        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8316        view.update(cx, |view, cx| {
 8317            view.fold_ranges(
 8318                vec![
 8319                    Point::new(0, 2)..Point::new(1, 2),
 8320                    Point::new(2, 3)..Point::new(4, 1),
 8321                    Point::new(7, 0)..Point::new(8, 4),
 8322                ],
 8323                cx,
 8324            );
 8325            view.change_selections(None, cx, |s| {
 8326                s.select_display_ranges([
 8327                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8328                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8329                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8330                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8331                ])
 8332            });
 8333            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8334        });
 8335
 8336        view.update(cx, |view, cx| {
 8337            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8338            assert_eq!(
 8339                view.display_text(cx),
 8340                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8341            );
 8342            assert_eq!(
 8343                view.selections.display_ranges(cx),
 8344                [
 8345                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8346                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8347                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8348                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8349                ]
 8350            );
 8351        });
 8352
 8353        view.update(cx, |view, cx| {
 8354            view.change_selections(None, cx, |s| {
 8355                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8356            });
 8357            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8358            assert_eq!(
 8359                view.display_text(cx),
 8360                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8361            );
 8362            assert_eq!(
 8363                view.selections.display_ranges(cx),
 8364                [
 8365                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8366                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8367                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8368                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8369                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8370                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8371                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8372                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8373                ]
 8374            );
 8375        });
 8376    }
 8377
 8378    #[gpui::test]
 8379    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8380        cx.set_global(Settings::test(cx));
 8381        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8382        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8383
 8384        view.update(cx, |view, cx| {
 8385            view.change_selections(None, cx, |s| {
 8386                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8387            });
 8388        });
 8389        view.update(cx, |view, cx| {
 8390            view.add_selection_above(&AddSelectionAbove, cx);
 8391            assert_eq!(
 8392                view.selections.display_ranges(cx),
 8393                vec![
 8394                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8395                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8396                ]
 8397            );
 8398        });
 8399
 8400        view.update(cx, |view, cx| {
 8401            view.add_selection_above(&AddSelectionAbove, cx);
 8402            assert_eq!(
 8403                view.selections.display_ranges(cx),
 8404                vec![
 8405                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8406                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8407                ]
 8408            );
 8409        });
 8410
 8411        view.update(cx, |view, cx| {
 8412            view.add_selection_below(&AddSelectionBelow, cx);
 8413            assert_eq!(
 8414                view.selections.display_ranges(cx),
 8415                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8416            );
 8417
 8418            view.undo_selection(&UndoSelection, cx);
 8419            assert_eq!(
 8420                view.selections.display_ranges(cx),
 8421                vec![
 8422                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8423                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8424                ]
 8425            );
 8426
 8427            view.redo_selection(&RedoSelection, cx);
 8428            assert_eq!(
 8429                view.selections.display_ranges(cx),
 8430                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8431            );
 8432        });
 8433
 8434        view.update(cx, |view, cx| {
 8435            view.add_selection_below(&AddSelectionBelow, cx);
 8436            assert_eq!(
 8437                view.selections.display_ranges(cx),
 8438                vec![
 8439                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8440                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8441                ]
 8442            );
 8443        });
 8444
 8445        view.update(cx, |view, cx| {
 8446            view.add_selection_below(&AddSelectionBelow, cx);
 8447            assert_eq!(
 8448                view.selections.display_ranges(cx),
 8449                vec![
 8450                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8451                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8452                ]
 8453            );
 8454        });
 8455
 8456        view.update(cx, |view, cx| {
 8457            view.change_selections(None, cx, |s| {
 8458                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8459            });
 8460        });
 8461        view.update(cx, |view, cx| {
 8462            view.add_selection_below(&AddSelectionBelow, cx);
 8463            assert_eq!(
 8464                view.selections.display_ranges(cx),
 8465                vec![
 8466                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8467                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8468                ]
 8469            );
 8470        });
 8471
 8472        view.update(cx, |view, cx| {
 8473            view.add_selection_below(&AddSelectionBelow, cx);
 8474            assert_eq!(
 8475                view.selections.display_ranges(cx),
 8476                vec![
 8477                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8478                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8479                ]
 8480            );
 8481        });
 8482
 8483        view.update(cx, |view, cx| {
 8484            view.add_selection_above(&AddSelectionAbove, cx);
 8485            assert_eq!(
 8486                view.selections.display_ranges(cx),
 8487                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8488            );
 8489        });
 8490
 8491        view.update(cx, |view, cx| {
 8492            view.add_selection_above(&AddSelectionAbove, cx);
 8493            assert_eq!(
 8494                view.selections.display_ranges(cx),
 8495                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8496            );
 8497        });
 8498
 8499        view.update(cx, |view, cx| {
 8500            view.change_selections(None, cx, |s| {
 8501                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8502            });
 8503            view.add_selection_below(&AddSelectionBelow, cx);
 8504            assert_eq!(
 8505                view.selections.display_ranges(cx),
 8506                vec![
 8507                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8508                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8509                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8510                ]
 8511            );
 8512        });
 8513
 8514        view.update(cx, |view, cx| {
 8515            view.add_selection_below(&AddSelectionBelow, cx);
 8516            assert_eq!(
 8517                view.selections.display_ranges(cx),
 8518                vec![
 8519                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8520                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8521                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8522                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8523                ]
 8524            );
 8525        });
 8526
 8527        view.update(cx, |view, cx| {
 8528            view.add_selection_above(&AddSelectionAbove, cx);
 8529            assert_eq!(
 8530                view.selections.display_ranges(cx),
 8531                vec![
 8532                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8533                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8534                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8535                ]
 8536            );
 8537        });
 8538
 8539        view.update(cx, |view, cx| {
 8540            view.change_selections(None, cx, |s| {
 8541                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8542            });
 8543        });
 8544        view.update(cx, |view, cx| {
 8545            view.add_selection_above(&AddSelectionAbove, cx);
 8546            assert_eq!(
 8547                view.selections.display_ranges(cx),
 8548                vec![
 8549                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8550                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8551                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8552                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8553                ]
 8554            );
 8555        });
 8556
 8557        view.update(cx, |view, cx| {
 8558            view.add_selection_below(&AddSelectionBelow, cx);
 8559            assert_eq!(
 8560                view.selections.display_ranges(cx),
 8561                vec![
 8562                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8563                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8564                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8565                ]
 8566            );
 8567        });
 8568    }
 8569
 8570    #[gpui::test]
 8571    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8572        cx.set_global(Settings::test(cx));
 8573
 8574        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8575        let buffer = MultiBuffer::build_simple(&text, cx);
 8576        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8577
 8578        view.update(cx, |view, cx| {
 8579            view.change_selections(None, cx, |s| {
 8580                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8581            });
 8582            view.select_next(
 8583                &SelectNext {
 8584                    replace_newest: false,
 8585                },
 8586                cx,
 8587            );
 8588            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8589
 8590            view.select_next(
 8591                &SelectNext {
 8592                    replace_newest: false,
 8593                },
 8594                cx,
 8595            );
 8596            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8597
 8598            view.undo_selection(&UndoSelection, cx);
 8599            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8600
 8601            view.redo_selection(&RedoSelection, cx);
 8602            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8603
 8604            view.select_next(
 8605                &SelectNext {
 8606                    replace_newest: false,
 8607                },
 8608                cx,
 8609            );
 8610            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8611
 8612            view.select_next(
 8613                &SelectNext {
 8614                    replace_newest: false,
 8615                },
 8616                cx,
 8617            );
 8618            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8619        });
 8620    }
 8621
 8622    #[gpui::test]
 8623    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8624        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8625        let language = Arc::new(Language::new(
 8626            LanguageConfig::default(),
 8627            Some(tree_sitter_rust::language()),
 8628        ));
 8629
 8630        let text = r#"
 8631            use mod1::mod2::{mod3, mod4};
 8632
 8633            fn fn_1(param1: bool, param2: &str) {
 8634                let var1 = "text";
 8635            }
 8636        "#
 8637        .unindent();
 8638
 8639        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8640        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8641        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8642        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8643            .await;
 8644
 8645        view.update(cx, |view, cx| {
 8646            view.change_selections(None, cx, |s| {
 8647                s.select_display_ranges([
 8648                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8649                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8650                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8651                ]);
 8652            });
 8653            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8654        });
 8655        assert_eq!(
 8656            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8657            &[
 8658                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8659                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8660                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8661            ]
 8662        );
 8663
 8664        view.update(cx, |view, cx| {
 8665            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8666        });
 8667        assert_eq!(
 8668            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8669            &[
 8670                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8671                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8672            ]
 8673        );
 8674
 8675        view.update(cx, |view, cx| {
 8676            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8677        });
 8678        assert_eq!(
 8679            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8680            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8681        );
 8682
 8683        // Trying to expand the selected syntax node one more time has no effect.
 8684        view.update(cx, |view, cx| {
 8685            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8686        });
 8687        assert_eq!(
 8688            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8689            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8690        );
 8691
 8692        view.update(cx, |view, cx| {
 8693            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8694        });
 8695        assert_eq!(
 8696            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8697            &[
 8698                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8699                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8700            ]
 8701        );
 8702
 8703        view.update(cx, |view, cx| {
 8704            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8705        });
 8706        assert_eq!(
 8707            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8708            &[
 8709                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8710                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8711                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8712            ]
 8713        );
 8714
 8715        view.update(cx, |view, cx| {
 8716            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8717        });
 8718        assert_eq!(
 8719            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8720            &[
 8721                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8722                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8723                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8724            ]
 8725        );
 8726
 8727        // Trying to shrink the selected syntax node one more time has no effect.
 8728        view.update(cx, |view, cx| {
 8729            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8730        });
 8731        assert_eq!(
 8732            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8733            &[
 8734                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8735                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8736                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8737            ]
 8738        );
 8739
 8740        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8741        // a fold.
 8742        view.update(cx, |view, cx| {
 8743            view.fold_ranges(
 8744                vec![
 8745                    Point::new(0, 21)..Point::new(0, 24),
 8746                    Point::new(3, 20)..Point::new(3, 22),
 8747                ],
 8748                cx,
 8749            );
 8750            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8751        });
 8752        assert_eq!(
 8753            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8754            &[
 8755                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8756                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8757                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8758            ]
 8759        );
 8760    }
 8761
 8762    #[gpui::test]
 8763    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8764        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8765        let language = Arc::new(
 8766            Language::new(
 8767                LanguageConfig {
 8768                    brackets: vec![
 8769                        BracketPair {
 8770                            start: "{".to_string(),
 8771                            end: "}".to_string(),
 8772                            close: false,
 8773                            newline: true,
 8774                        },
 8775                        BracketPair {
 8776                            start: "(".to_string(),
 8777                            end: ")".to_string(),
 8778                            close: false,
 8779                            newline: true,
 8780                        },
 8781                    ],
 8782                    ..Default::default()
 8783                },
 8784                Some(tree_sitter_rust::language()),
 8785            )
 8786            .with_indents_query(
 8787                r#"
 8788                (_ "(" ")" @end) @indent
 8789                (_ "{" "}" @end) @indent
 8790                "#,
 8791            )
 8792            .unwrap(),
 8793        );
 8794
 8795        let text = "fn a() {}";
 8796
 8797        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8798        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8799        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8800        editor
 8801            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8802            .await;
 8803
 8804        editor.update(cx, |editor, cx| {
 8805            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8806            editor.newline(&Newline, cx);
 8807            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8808            assert_eq!(
 8809                editor.selections.ranges(cx),
 8810                &[
 8811                    Point::new(1, 4)..Point::new(1, 4),
 8812                    Point::new(3, 4)..Point::new(3, 4),
 8813                    Point::new(5, 0)..Point::new(5, 0)
 8814                ]
 8815            );
 8816        });
 8817    }
 8818
 8819    #[gpui::test]
 8820    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8821        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8822        let language = Arc::new(Language::new(
 8823            LanguageConfig {
 8824                brackets: vec![
 8825                    BracketPair {
 8826                        start: "{".to_string(),
 8827                        end: "}".to_string(),
 8828                        close: true,
 8829                        newline: true,
 8830                    },
 8831                    BracketPair {
 8832                        start: "/*".to_string(),
 8833                        end: " */".to_string(),
 8834                        close: true,
 8835                        newline: true,
 8836                    },
 8837                    BracketPair {
 8838                        start: "[".to_string(),
 8839                        end: "]".to_string(),
 8840                        close: false,
 8841                        newline: true,
 8842                    },
 8843                ],
 8844                autoclose_before: "})]".to_string(),
 8845                ..Default::default()
 8846            },
 8847            Some(tree_sitter_rust::language()),
 8848        ));
 8849
 8850        let text = r#"
 8851            a
 8852
 8853            /
 8854
 8855        "#
 8856        .unindent();
 8857
 8858        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8859        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8860        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8861        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8862            .await;
 8863
 8864        view.update(cx, |view, cx| {
 8865            view.change_selections(None, cx, |s| {
 8866                s.select_display_ranges([
 8867                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8868                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8869                ])
 8870            });
 8871
 8872            view.handle_input(&Input("{".to_string()), cx);
 8873            view.handle_input(&Input("{".to_string()), cx);
 8874            view.handle_input(&Input("{".to_string()), cx);
 8875            assert_eq!(
 8876                view.text(cx),
 8877                "
 8878                {{{}}}
 8879                {{{}}}
 8880                /
 8881
 8882                "
 8883                .unindent()
 8884            );
 8885
 8886            view.move_right(&MoveRight, cx);
 8887            view.handle_input(&Input("}".to_string()), cx);
 8888            view.handle_input(&Input("}".to_string()), cx);
 8889            view.handle_input(&Input("}".to_string()), cx);
 8890            assert_eq!(
 8891                view.text(cx),
 8892                "
 8893                {{{}}}}
 8894                {{{}}}}
 8895                /
 8896
 8897                "
 8898                .unindent()
 8899            );
 8900
 8901            view.undo(&Undo, cx);
 8902            view.handle_input(&Input("/".to_string()), cx);
 8903            view.handle_input(&Input("*".to_string()), cx);
 8904            assert_eq!(
 8905                view.text(cx),
 8906                "
 8907                /* */
 8908                /* */
 8909                /
 8910
 8911                "
 8912                .unindent()
 8913            );
 8914
 8915            view.undo(&Undo, cx);
 8916            view.change_selections(None, cx, |s| {
 8917                s.select_display_ranges([
 8918                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8919                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8920                ])
 8921            });
 8922            view.handle_input(&Input("*".to_string()), cx);
 8923            assert_eq!(
 8924                view.text(cx),
 8925                "
 8926                a
 8927
 8928                /*
 8929                *
 8930                "
 8931                .unindent()
 8932            );
 8933
 8934            // Don't autoclose if the next character isn't whitespace and isn't
 8935            // listed in the language's "autoclose_before" section.
 8936            view.finalize_last_transaction(cx);
 8937            view.change_selections(None, cx, |s| {
 8938                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 8939            });
 8940            view.handle_input(&Input("{".to_string()), cx);
 8941            assert_eq!(
 8942                view.text(cx),
 8943                "
 8944                {a
 8945
 8946                /*
 8947                *
 8948                "
 8949                .unindent()
 8950            );
 8951
 8952            view.undo(&Undo, cx);
 8953            view.change_selections(None, cx, |s| {
 8954                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 8955            });
 8956            view.handle_input(&Input("{".to_string()), cx);
 8957            assert_eq!(
 8958                view.text(cx),
 8959                "
 8960                {a}
 8961
 8962                /*
 8963                *
 8964                "
 8965                .unindent()
 8966            );
 8967            assert_eq!(
 8968                view.selections.display_ranges(cx),
 8969                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8970            );
 8971
 8972            view.undo(&Undo, cx);
 8973            view.handle_input(&Input("[".to_string()), cx);
 8974            assert_eq!(
 8975                view.text(cx),
 8976                "
 8977                [a]
 8978                
 8979                /*
 8980                *
 8981                "
 8982                .unindent()
 8983            );
 8984            assert_eq!(
 8985                view.selections.display_ranges(cx),
 8986                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8987            );
 8988
 8989            view.undo(&Undo, cx);
 8990            view.change_selections(None, cx, |s| {
 8991                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 8992            });
 8993            view.handle_input(&Input("[".to_string()), cx);
 8994            assert_eq!(
 8995                view.text(cx),
 8996                "
 8997                a[
 8998                
 8999                /*
 9000                *
 9001                "
 9002                .unindent()
 9003            );
 9004            assert_eq!(
 9005                view.selections.display_ranges(cx),
 9006                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 9007            );
 9008        });
 9009    }
 9010
 9011    #[gpui::test]
 9012    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 9013        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9014        let language = Arc::new(Language::new(
 9015            LanguageConfig {
 9016                brackets: vec![BracketPair {
 9017                    start: "{".to_string(),
 9018                    end: "}".to_string(),
 9019                    close: true,
 9020                    newline: true,
 9021                }],
 9022                ..Default::default()
 9023            },
 9024            Some(tree_sitter_rust::language()),
 9025        ));
 9026
 9027        let text = r#"
 9028            a
 9029            b
 9030            c
 9031        "#
 9032        .unindent();
 9033
 9034        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9035        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9036        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9037        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9038            .await;
 9039
 9040        view.update(cx, |view, cx| {
 9041            view.change_selections(None, cx, |s| {
 9042                s.select_display_ranges([
 9043                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9044                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9045                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 9046                ])
 9047            });
 9048
 9049            view.handle_input(&Input("{".to_string()), cx);
 9050            view.handle_input(&Input("{".to_string()), cx);
 9051            view.handle_input(&Input("{".to_string()), cx);
 9052            assert_eq!(
 9053                view.text(cx),
 9054                "
 9055                {{{a}}}
 9056                {{{b}}}
 9057                {{{c}}}
 9058                "
 9059                .unindent()
 9060            );
 9061            assert_eq!(
 9062                view.selections.display_ranges(cx),
 9063                [
 9064                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 9065                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 9066                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 9067                ]
 9068            );
 9069
 9070            view.undo(&Undo, cx);
 9071            assert_eq!(
 9072                view.text(cx),
 9073                "
 9074                a
 9075                b
 9076                c
 9077                "
 9078                .unindent()
 9079            );
 9080            assert_eq!(
 9081                view.selections.display_ranges(cx),
 9082                [
 9083                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9084                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9085                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9086                ]
 9087            );
 9088        });
 9089    }
 9090
 9091    #[gpui::test]
 9092    async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
 9093        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9094        let language = Arc::new(Language::new(
 9095            LanguageConfig {
 9096                brackets: vec![BracketPair {
 9097                    start: "{".to_string(),
 9098                    end: "}".to_string(),
 9099                    close: true,
 9100                    newline: true,
 9101                }],
 9102                autoclose_before: "}".to_string(),
 9103                ..Default::default()
 9104            },
 9105            Some(tree_sitter_rust::language()),
 9106        ));
 9107
 9108        let text = r#"
 9109            a
 9110            b
 9111            c
 9112        "#
 9113        .unindent();
 9114
 9115        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9116        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9117        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9118        editor
 9119            .condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9120            .await;
 9121
 9122        editor.update(cx, |editor, cx| {
 9123            editor.change_selections(None, cx, |s| {
 9124                s.select_ranges([
 9125                    Point::new(0, 1)..Point::new(0, 1),
 9126                    Point::new(1, 1)..Point::new(1, 1),
 9127                    Point::new(2, 1)..Point::new(2, 1),
 9128                ])
 9129            });
 9130
 9131            editor.handle_input(&Input("{".to_string()), cx);
 9132            editor.handle_input(&Input("{".to_string()), cx);
 9133            editor.handle_input(&Input("_".to_string()), cx);
 9134            assert_eq!(
 9135                editor.text(cx),
 9136                "
 9137                a{{_}}
 9138                b{{_}}
 9139                c{{_}}
 9140                "
 9141                .unindent()
 9142            );
 9143            assert_eq!(
 9144                editor.selections.ranges::<Point>(cx),
 9145                [
 9146                    Point::new(0, 4)..Point::new(0, 4),
 9147                    Point::new(1, 4)..Point::new(1, 4),
 9148                    Point::new(2, 4)..Point::new(2, 4)
 9149                ]
 9150            );
 9151
 9152            editor.backspace(&Default::default(), cx);
 9153            editor.backspace(&Default::default(), cx);
 9154            assert_eq!(
 9155                editor.text(cx),
 9156                "
 9157                a{}
 9158                b{}
 9159                c{}
 9160                "
 9161                .unindent()
 9162            );
 9163            assert_eq!(
 9164                editor.selections.ranges::<Point>(cx),
 9165                [
 9166                    Point::new(0, 2)..Point::new(0, 2),
 9167                    Point::new(1, 2)..Point::new(1, 2),
 9168                    Point::new(2, 2)..Point::new(2, 2)
 9169                ]
 9170            );
 9171
 9172            editor.delete_to_previous_word_start(&Default::default(), cx);
 9173            assert_eq!(
 9174                editor.text(cx),
 9175                "
 9176                a
 9177                b
 9178                c
 9179                "
 9180                .unindent()
 9181            );
 9182            assert_eq!(
 9183                editor.selections.ranges::<Point>(cx),
 9184                [
 9185                    Point::new(0, 1)..Point::new(0, 1),
 9186                    Point::new(1, 1)..Point::new(1, 1),
 9187                    Point::new(2, 1)..Point::new(2, 1)
 9188                ]
 9189            );
 9190        });
 9191    }
 9192
 9193    #[gpui::test]
 9194    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9195        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9196
 9197        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9198            a.| b
 9199            a.| b
 9200            a.| b"});
 9201        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9202        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9203
 9204        editor.update(cx, |editor, cx| {
 9205            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9206
 9207            editor
 9208                .insert_snippet(&insertion_ranges, snippet, cx)
 9209                .unwrap();
 9210
 9211            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9212                let range_markers = ('<', '>');
 9213                let (expected_text, mut selection_ranges_lookup) =
 9214                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9215                let selection_ranges = selection_ranges_lookup
 9216                    .remove(&range_markers.into())
 9217                    .unwrap();
 9218                assert_eq!(editor.text(cx), expected_text);
 9219                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9220            }
 9221            assert(
 9222                editor,
 9223                cx,
 9224                indoc! {"
 9225                    a.f(<one>, two, <three>) b
 9226                    a.f(<one>, two, <three>) b
 9227                    a.f(<one>, two, <three>) b"},
 9228            );
 9229
 9230            // Can't move earlier than the first tab stop
 9231            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9232            assert(
 9233                editor,
 9234                cx,
 9235                indoc! {"
 9236                    a.f(<one>, two, <three>) b
 9237                    a.f(<one>, two, <three>) b
 9238                    a.f(<one>, two, <three>) b"},
 9239            );
 9240
 9241            assert!(editor.move_to_next_snippet_tabstop(cx));
 9242            assert(
 9243                editor,
 9244                cx,
 9245                indoc! {"
 9246                    a.f(one, <two>, three) b
 9247                    a.f(one, <two>, three) b
 9248                    a.f(one, <two>, three) b"},
 9249            );
 9250
 9251            editor.move_to_prev_snippet_tabstop(cx);
 9252            assert(
 9253                editor,
 9254                cx,
 9255                indoc! {"
 9256                    a.f(<one>, two, <three>) b
 9257                    a.f(<one>, two, <three>) b
 9258                    a.f(<one>, two, <three>) b"},
 9259            );
 9260
 9261            assert!(editor.move_to_next_snippet_tabstop(cx));
 9262            assert(
 9263                editor,
 9264                cx,
 9265                indoc! {"
 9266                    a.f(one, <two>, three) b
 9267                    a.f(one, <two>, three) b
 9268                    a.f(one, <two>, three) b"},
 9269            );
 9270            assert!(editor.move_to_next_snippet_tabstop(cx));
 9271            assert(
 9272                editor,
 9273                cx,
 9274                indoc! {"
 9275                    a.f(one, two, three)<> b
 9276                    a.f(one, two, three)<> b
 9277                    a.f(one, two, three)<> b"},
 9278            );
 9279
 9280            // As soon as the last tab stop is reached, snippet state is gone
 9281            editor.move_to_prev_snippet_tabstop(cx);
 9282            assert(
 9283                editor,
 9284                cx,
 9285                indoc! {"
 9286                    a.f(one, two, three)<> b
 9287                    a.f(one, two, three)<> b
 9288                    a.f(one, two, three)<> b"},
 9289            );
 9290        });
 9291    }
 9292
 9293    #[gpui::test]
 9294    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9295        cx.foreground().forbid_parking();
 9296
 9297        let mut language = Language::new(
 9298            LanguageConfig {
 9299                name: "Rust".into(),
 9300                path_suffixes: vec!["rs".to_string()],
 9301                ..Default::default()
 9302            },
 9303            Some(tree_sitter_rust::language()),
 9304        );
 9305        let mut fake_servers = language
 9306            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9307                capabilities: lsp::ServerCapabilities {
 9308                    document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9309                    ..Default::default()
 9310                },
 9311                ..Default::default()
 9312            }))
 9313            .await;
 9314
 9315        let fs = FakeFs::new(cx.background().clone());
 9316        fs.insert_file("/file.rs", Default::default()).await;
 9317
 9318        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9319        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9320        let buffer = project
 9321            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9322            .await
 9323            .unwrap();
 9324
 9325        cx.foreground().start_waiting();
 9326        let fake_server = fake_servers.next().await.unwrap();
 9327
 9328        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9329        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9330        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9331        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9332
 9333        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9334        fake_server
 9335            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9336                assert_eq!(
 9337                    params.text_document.uri,
 9338                    lsp::Url::from_file_path("/file.rs").unwrap()
 9339                );
 9340                assert_eq!(params.options.tab_size, 4);
 9341                Ok(Some(vec![lsp::TextEdit::new(
 9342                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9343                    ", ".to_string(),
 9344                )]))
 9345            })
 9346            .next()
 9347            .await;
 9348        cx.foreground().start_waiting();
 9349        save.await.unwrap();
 9350        assert_eq!(
 9351            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9352            "one, two\nthree\n"
 9353        );
 9354        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9355
 9356        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9357        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9358
 9359        // Ensure we can still save even if formatting hangs.
 9360        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9361            assert_eq!(
 9362                params.text_document.uri,
 9363                lsp::Url::from_file_path("/file.rs").unwrap()
 9364            );
 9365            futures::future::pending::<()>().await;
 9366            unreachable!()
 9367        });
 9368        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9369        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9370        cx.foreground().start_waiting();
 9371        save.await.unwrap();
 9372        assert_eq!(
 9373            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9374            "one\ntwo\nthree\n"
 9375        );
 9376        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9377
 9378        // Set rust language override and assert overriden tabsize is sent to language server
 9379        cx.update(|cx| {
 9380            cx.update_global::<Settings, _, _>(|settings, _| {
 9381                settings.language_overrides.insert(
 9382                    "Rust".into(),
 9383                    EditorSettings {
 9384                        tab_size: Some(8.try_into().unwrap()),
 9385                        ..Default::default()
 9386                    },
 9387                );
 9388            })
 9389        });
 9390
 9391        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9392        fake_server
 9393            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9394                assert_eq!(
 9395                    params.text_document.uri,
 9396                    lsp::Url::from_file_path("/file.rs").unwrap()
 9397                );
 9398                assert_eq!(params.options.tab_size, 8);
 9399                Ok(Some(vec![]))
 9400            })
 9401            .next()
 9402            .await;
 9403        cx.foreground().start_waiting();
 9404        save.await.unwrap();
 9405    }
 9406
 9407    #[gpui::test]
 9408    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9409        cx.foreground().forbid_parking();
 9410
 9411        let mut language = Language::new(
 9412            LanguageConfig {
 9413                name: "Rust".into(),
 9414                path_suffixes: vec!["rs".to_string()],
 9415                ..Default::default()
 9416            },
 9417            Some(tree_sitter_rust::language()),
 9418        );
 9419        let mut fake_servers = language
 9420            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9421                capabilities: lsp::ServerCapabilities {
 9422                    document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9423                    ..Default::default()
 9424                },
 9425                ..Default::default()
 9426            }))
 9427            .await;
 9428
 9429        let fs = FakeFs::new(cx.background().clone());
 9430        fs.insert_file("/file.rs", Default::default()).await;
 9431
 9432        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9433        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9434        let buffer = project
 9435            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9436            .await
 9437            .unwrap();
 9438
 9439        cx.foreground().start_waiting();
 9440        let fake_server = fake_servers.next().await.unwrap();
 9441
 9442        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9443        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9444        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9445        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9446
 9447        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9448        fake_server
 9449            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9450                assert_eq!(
 9451                    params.text_document.uri,
 9452                    lsp::Url::from_file_path("/file.rs").unwrap()
 9453                );
 9454                assert_eq!(params.options.tab_size, 4);
 9455                Ok(Some(vec![lsp::TextEdit::new(
 9456                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9457                    ", ".to_string(),
 9458                )]))
 9459            })
 9460            .next()
 9461            .await;
 9462        cx.foreground().start_waiting();
 9463        save.await.unwrap();
 9464        assert_eq!(
 9465            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9466            "one, two\nthree\n"
 9467        );
 9468        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9469
 9470        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9471        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9472
 9473        // Ensure we can still save even if formatting hangs.
 9474        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9475            move |params, _| async move {
 9476                assert_eq!(
 9477                    params.text_document.uri,
 9478                    lsp::Url::from_file_path("/file.rs").unwrap()
 9479                );
 9480                futures::future::pending::<()>().await;
 9481                unreachable!()
 9482            },
 9483        );
 9484        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9485        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9486        cx.foreground().start_waiting();
 9487        save.await.unwrap();
 9488        assert_eq!(
 9489            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9490            "one\ntwo\nthree\n"
 9491        );
 9492        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9493
 9494        // Set rust language override and assert overriden tabsize is sent to language server
 9495        cx.update(|cx| {
 9496            cx.update_global::<Settings, _, _>(|settings, _| {
 9497                settings.language_overrides.insert(
 9498                    "Rust".into(),
 9499                    EditorSettings {
 9500                        tab_size: Some(8.try_into().unwrap()),
 9501                        ..Default::default()
 9502                    },
 9503                );
 9504            })
 9505        });
 9506
 9507        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9508        fake_server
 9509            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9510                assert_eq!(
 9511                    params.text_document.uri,
 9512                    lsp::Url::from_file_path("/file.rs").unwrap()
 9513                );
 9514                assert_eq!(params.options.tab_size, 8);
 9515                Ok(Some(vec![]))
 9516            })
 9517            .next()
 9518            .await;
 9519        cx.foreground().start_waiting();
 9520        save.await.unwrap();
 9521    }
 9522
 9523    #[gpui::test]
 9524    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9525        let mut language = Language::new(
 9526            LanguageConfig {
 9527                name: "Rust".into(),
 9528                path_suffixes: vec!["rs".to_string()],
 9529                ..Default::default()
 9530            },
 9531            Some(tree_sitter_rust::language()),
 9532        );
 9533        let mut fake_servers = language
 9534            .set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
 9535                capabilities: lsp::ServerCapabilities {
 9536                    completion_provider: Some(lsp::CompletionOptions {
 9537                        trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9538                        ..Default::default()
 9539                    }),
 9540                    ..Default::default()
 9541                },
 9542                ..Default::default()
 9543            }))
 9544            .await;
 9545
 9546        let text = "
 9547            one
 9548            two
 9549            three
 9550        "
 9551        .unindent();
 9552
 9553        let fs = FakeFs::new(cx.background().clone());
 9554        fs.insert_file("/file.rs", text).await;
 9555
 9556        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9557        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9558        let buffer = project
 9559            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9560            .await
 9561            .unwrap();
 9562        let mut fake_server = fake_servers.next().await.unwrap();
 9563
 9564        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9565        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9566
 9567        editor.update(cx, |editor, cx| {
 9568            editor.project = Some(project);
 9569            editor.change_selections(None, cx, |s| {
 9570                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
 9571            });
 9572            editor.handle_input(&Input(".".to_string()), cx);
 9573        });
 9574
 9575        handle_completion_request(
 9576            &mut fake_server,
 9577            "/file.rs",
 9578            Point::new(0, 4),
 9579            vec![
 9580                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9581                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9582            ],
 9583        )
 9584        .await;
 9585        editor
 9586            .condition(&cx, |editor, _| editor.context_menu_visible())
 9587            .await;
 9588
 9589        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9590            editor.move_down(&MoveDown, cx);
 9591            let apply_additional_edits = editor
 9592                .confirm_completion(&ConfirmCompletion::default(), cx)
 9593                .unwrap();
 9594            assert_eq!(
 9595                editor.text(cx),
 9596                "
 9597                    one.second_completion
 9598                    two
 9599                    three
 9600                "
 9601                .unindent()
 9602            );
 9603            apply_additional_edits
 9604        });
 9605
 9606        handle_resolve_completion_request(
 9607            &mut fake_server,
 9608            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9609        )
 9610        .await;
 9611        apply_additional_edits.await.unwrap();
 9612        assert_eq!(
 9613            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9614            "
 9615                one.second_completion
 9616                two
 9617                three
 9618                additional edit
 9619            "
 9620            .unindent()
 9621        );
 9622
 9623        editor.update(cx, |editor, cx| {
 9624            editor.change_selections(None, cx, |s| {
 9625                s.select_ranges([
 9626                    Point::new(1, 3)..Point::new(1, 3),
 9627                    Point::new(2, 5)..Point::new(2, 5),
 9628                ])
 9629            });
 9630
 9631            editor.handle_input(&Input(" ".to_string()), cx);
 9632            assert!(editor.context_menu.is_none());
 9633            editor.handle_input(&Input("s".to_string()), cx);
 9634            assert!(editor.context_menu.is_none());
 9635        });
 9636
 9637        handle_completion_request(
 9638            &mut fake_server,
 9639            "/file.rs",
 9640            Point::new(2, 7),
 9641            vec![
 9642                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9643                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9644                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9645            ],
 9646        )
 9647        .await;
 9648        editor
 9649            .condition(&cx, |editor, _| editor.context_menu_visible())
 9650            .await;
 9651
 9652        editor.update(cx, |editor, cx| {
 9653            editor.handle_input(&Input("i".to_string()), cx);
 9654        });
 9655
 9656        handle_completion_request(
 9657            &mut fake_server,
 9658            "/file.rs",
 9659            Point::new(2, 8),
 9660            vec![
 9661                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9662                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9663                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9664            ],
 9665        )
 9666        .await;
 9667        editor
 9668            .condition(&cx, |editor, _| editor.context_menu_visible())
 9669            .await;
 9670
 9671        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9672            let apply_additional_edits = editor
 9673                .confirm_completion(&ConfirmCompletion::default(), cx)
 9674                .unwrap();
 9675            assert_eq!(
 9676                editor.text(cx),
 9677                "
 9678                    one.second_completion
 9679                    two sixth_completion
 9680                    three sixth_completion
 9681                    additional edit
 9682                "
 9683                .unindent()
 9684            );
 9685            apply_additional_edits
 9686        });
 9687        handle_resolve_completion_request(&mut fake_server, None).await;
 9688        apply_additional_edits.await.unwrap();
 9689
 9690        async fn handle_completion_request(
 9691            fake: &mut FakeLanguageServer,
 9692            path: &'static str,
 9693            position: Point,
 9694            completions: Vec<(Range<Point>, &'static str)>,
 9695        ) {
 9696            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9697                let completions = completions.clone();
 9698                async move {
 9699                    assert_eq!(
 9700                        params.text_document_position.text_document.uri,
 9701                        lsp::Url::from_file_path(path).unwrap()
 9702                    );
 9703                    assert_eq!(
 9704                        params.text_document_position.position,
 9705                        lsp::Position::new(position.row, position.column)
 9706                    );
 9707                    Ok(Some(lsp::CompletionResponse::Array(
 9708                        completions
 9709                            .iter()
 9710                            .map(|(range, new_text)| lsp::CompletionItem {
 9711                                label: new_text.to_string(),
 9712                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9713                                    range: lsp::Range::new(
 9714                                        lsp::Position::new(range.start.row, range.start.column),
 9715                                        lsp::Position::new(range.start.row, range.start.column),
 9716                                    ),
 9717                                    new_text: new_text.to_string(),
 9718                                })),
 9719                                ..Default::default()
 9720                            })
 9721                            .collect(),
 9722                    )))
 9723                }
 9724            })
 9725            .next()
 9726            .await;
 9727        }
 9728
 9729        async fn handle_resolve_completion_request(
 9730            fake: &mut FakeLanguageServer,
 9731            edit: Option<(Range<Point>, &'static str)>,
 9732        ) {
 9733            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9734                let edit = edit.clone();
 9735                async move {
 9736                    Ok(lsp::CompletionItem {
 9737                        additional_text_edits: edit.map(|(range, new_text)| {
 9738                            vec![lsp::TextEdit::new(
 9739                                lsp::Range::new(
 9740                                    lsp::Position::new(range.start.row, range.start.column),
 9741                                    lsp::Position::new(range.end.row, range.end.column),
 9742                                ),
 9743                                new_text.to_string(),
 9744                            )]
 9745                        }),
 9746                        ..Default::default()
 9747                    })
 9748                }
 9749            })
 9750            .next()
 9751            .await;
 9752        }
 9753    }
 9754
 9755    #[gpui::test]
 9756    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9757        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9758        let language = Arc::new(Language::new(
 9759            LanguageConfig {
 9760                line_comment: Some("// ".to_string()),
 9761                ..Default::default()
 9762            },
 9763            Some(tree_sitter_rust::language()),
 9764        ));
 9765
 9766        let text = "
 9767            fn a() {
 9768                //b();
 9769                // c();
 9770                //  d();
 9771            }
 9772        "
 9773        .unindent();
 9774
 9775        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9776        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9777        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9778
 9779        view.update(cx, |editor, cx| {
 9780            // If multiple selections intersect a line, the line is only
 9781            // toggled once.
 9782            editor.change_selections(None, cx, |s| {
 9783                s.select_display_ranges([
 9784                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9785                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9786                ])
 9787            });
 9788            editor.toggle_comments(&ToggleComments, cx);
 9789            assert_eq!(
 9790                editor.text(cx),
 9791                "
 9792                    fn a() {
 9793                        b();
 9794                        c();
 9795                         d();
 9796                    }
 9797                "
 9798                .unindent()
 9799            );
 9800
 9801            // The comment prefix is inserted at the same column for every line
 9802            // in a selection.
 9803            editor.change_selections(None, cx, |s| {
 9804                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
 9805            });
 9806            editor.toggle_comments(&ToggleComments, cx);
 9807            assert_eq!(
 9808                editor.text(cx),
 9809                "
 9810                    fn a() {
 9811                        // b();
 9812                        // c();
 9813                        //  d();
 9814                    }
 9815                "
 9816                .unindent()
 9817            );
 9818
 9819            // If a selection ends at the beginning of a line, that line is not toggled.
 9820            editor.change_selections(None, cx, |s| {
 9821                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
 9822            });
 9823            editor.toggle_comments(&ToggleComments, cx);
 9824            assert_eq!(
 9825                editor.text(cx),
 9826                "
 9827                        fn a() {
 9828                            // b();
 9829                            c();
 9830                            //  d();
 9831                        }
 9832                    "
 9833                .unindent()
 9834            );
 9835        });
 9836    }
 9837
 9838    #[gpui::test]
 9839    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9840        cx.set_global(Settings::test(cx));
 9841        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9842        let multibuffer = cx.add_model(|cx| {
 9843            let mut multibuffer = MultiBuffer::new(0);
 9844            multibuffer.push_excerpts(
 9845                buffer.clone(),
 9846                [
 9847                    ExcerptRange {
 9848                        context: Point::new(0, 0)..Point::new(0, 4),
 9849                        primary: None,
 9850                    },
 9851                    ExcerptRange {
 9852                        context: Point::new(1, 0)..Point::new(1, 4),
 9853                        primary: None,
 9854                    },
 9855                ],
 9856                cx,
 9857            );
 9858            multibuffer
 9859        });
 9860
 9861        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9862
 9863        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9864        view.update(cx, |view, cx| {
 9865            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9866            view.change_selections(None, cx, |s| {
 9867                s.select_ranges([
 9868                    Point::new(0, 0)..Point::new(0, 0),
 9869                    Point::new(1, 0)..Point::new(1, 0),
 9870                ])
 9871            });
 9872
 9873            view.handle_input(&Input("X".to_string()), cx);
 9874            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9875            assert_eq!(
 9876                view.selections.ranges(cx),
 9877                [
 9878                    Point::new(0, 1)..Point::new(0, 1),
 9879                    Point::new(1, 1)..Point::new(1, 1),
 9880                ]
 9881            )
 9882        });
 9883    }
 9884
 9885    #[gpui::test]
 9886    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9887        cx.set_global(Settings::test(cx));
 9888        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
 9889                [aaaa
 9890                (bbbb]
 9891                cccc)"});
 9892        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
 9893            context,
 9894            primary: None,
 9895        });
 9896        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
 9897        let multibuffer = cx.add_model(|cx| {
 9898            let mut multibuffer = MultiBuffer::new(0);
 9899            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
 9900            multibuffer
 9901        });
 9902
 9903        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9904        view.update(cx, |view, cx| {
 9905            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
 9906                aaaa
 9907                b|bbb
 9908                b|bb|b
 9909                cccc"});
 9910            assert_eq!(view.text(cx), expected_text);
 9911            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
 9912
 9913            view.handle_input(&Input("X".to_string()), cx);
 9914
 9915            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9916                aaaa
 9917                bX|bbXb
 9918                bX|bbX|b
 9919                cccc"});
 9920            assert_eq!(view.text(cx), expected_text);
 9921            assert_eq!(view.selections.ranges(cx), expected_selections);
 9922
 9923            view.newline(&Newline, cx);
 9924            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9925                aaaa
 9926                bX
 9927                |bbX
 9928                b
 9929                bX
 9930                |bbX
 9931                |b
 9932                cccc"});
 9933            assert_eq!(view.text(cx), expected_text);
 9934            assert_eq!(view.selections.ranges(cx), expected_selections);
 9935        });
 9936    }
 9937
 9938    #[gpui::test]
 9939    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9940        cx.set_global(Settings::test(cx));
 9941        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9942        let mut excerpt1_id = None;
 9943        let multibuffer = cx.add_model(|cx| {
 9944            let mut multibuffer = MultiBuffer::new(0);
 9945            excerpt1_id = multibuffer
 9946                .push_excerpts(
 9947                    buffer.clone(),
 9948                    [
 9949                        ExcerptRange {
 9950                            context: Point::new(0, 0)..Point::new(1, 4),
 9951                            primary: None,
 9952                        },
 9953                        ExcerptRange {
 9954                            context: Point::new(1, 0)..Point::new(2, 4),
 9955                            primary: None,
 9956                        },
 9957                    ],
 9958                    cx,
 9959                )
 9960                .into_iter()
 9961                .next();
 9962            multibuffer
 9963        });
 9964        assert_eq!(
 9965            multibuffer.read(cx).read(cx).text(),
 9966            "aaaa\nbbbb\nbbbb\ncccc"
 9967        );
 9968        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9969            let mut editor = build_editor(multibuffer.clone(), cx);
 9970            let snapshot = editor.snapshot(cx);
 9971            editor.change_selections(None, cx, |s| {
 9972                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
 9973            });
 9974            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9975            assert_eq!(
 9976                editor.selections.ranges(cx),
 9977                [
 9978                    Point::new(1, 3)..Point::new(1, 3),
 9979                    Point::new(2, 1)..Point::new(2, 1),
 9980                ]
 9981            );
 9982            editor
 9983        });
 9984
 9985        // Refreshing selections is a no-op when excerpts haven't changed.
 9986        editor.update(cx, |editor, cx| {
 9987            editor.change_selections(None, cx, |s| {
 9988                s.refresh();
 9989            });
 9990            assert_eq!(
 9991                editor.selections.ranges(cx),
 9992                [
 9993                    Point::new(1, 3)..Point::new(1, 3),
 9994                    Point::new(2, 1)..Point::new(2, 1),
 9995                ]
 9996            );
 9997        });
 9998
 9999        multibuffer.update(cx, |multibuffer, cx| {
10000            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10001        });
10002        editor.update(cx, |editor, cx| {
10003            // Removing an excerpt causes the first selection to become degenerate.
10004            assert_eq!(
10005                editor.selections.ranges(cx),
10006                [
10007                    Point::new(0, 0)..Point::new(0, 0),
10008                    Point::new(0, 1)..Point::new(0, 1)
10009                ]
10010            );
10011
10012            // Refreshing selections will relocate the first selection to the original buffer
10013            // location.
10014            editor.change_selections(None, cx, |s| {
10015                s.refresh();
10016            });
10017            assert_eq!(
10018                editor.selections.ranges(cx),
10019                [
10020                    Point::new(0, 1)..Point::new(0, 1),
10021                    Point::new(0, 3)..Point::new(0, 3)
10022                ]
10023            );
10024            assert!(editor.selections.pending_anchor().is_some());
10025        });
10026    }
10027
10028    #[gpui::test]
10029    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
10030        cx.set_global(Settings::test(cx));
10031        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
10032        let mut excerpt1_id = None;
10033        let multibuffer = cx.add_model(|cx| {
10034            let mut multibuffer = MultiBuffer::new(0);
10035            excerpt1_id = multibuffer
10036                .push_excerpts(
10037                    buffer.clone(),
10038                    [
10039                        ExcerptRange {
10040                            context: Point::new(0, 0)..Point::new(1, 4),
10041                            primary: None,
10042                        },
10043                        ExcerptRange {
10044                            context: Point::new(1, 0)..Point::new(2, 4),
10045                            primary: None,
10046                        },
10047                    ],
10048                    cx,
10049                )
10050                .into_iter()
10051                .next();
10052            multibuffer
10053        });
10054        assert_eq!(
10055            multibuffer.read(cx).read(cx).text(),
10056            "aaaa\nbbbb\nbbbb\ncccc"
10057        );
10058        let (_, editor) = cx.add_window(Default::default(), |cx| {
10059            let mut editor = build_editor(multibuffer.clone(), cx);
10060            let snapshot = editor.snapshot(cx);
10061            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
10062            assert_eq!(
10063                editor.selections.ranges(cx),
10064                [Point::new(1, 3)..Point::new(1, 3)]
10065            );
10066            editor
10067        });
10068
10069        multibuffer.update(cx, |multibuffer, cx| {
10070            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
10071        });
10072        editor.update(cx, |editor, cx| {
10073            assert_eq!(
10074                editor.selections.ranges(cx),
10075                [Point::new(0, 0)..Point::new(0, 0)]
10076            );
10077
10078            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
10079            editor.change_selections(None, cx, |s| {
10080                s.refresh();
10081            });
10082            assert_eq!(
10083                editor.selections.ranges(cx),
10084                [Point::new(0, 3)..Point::new(0, 3)]
10085            );
10086            assert!(editor.selections.pending_anchor().is_some());
10087        });
10088    }
10089
10090    #[gpui::test]
10091    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10092        cx.update(|cx| cx.set_global(Settings::test(cx)));
10093        let language = Arc::new(
10094            Language::new(
10095                LanguageConfig {
10096                    brackets: vec![
10097                        BracketPair {
10098                            start: "{".to_string(),
10099                            end: "}".to_string(),
10100                            close: true,
10101                            newline: true,
10102                        },
10103                        BracketPair {
10104                            start: "/* ".to_string(),
10105                            end: " */".to_string(),
10106                            close: true,
10107                            newline: true,
10108                        },
10109                    ],
10110                    ..Default::default()
10111                },
10112                Some(tree_sitter_rust::language()),
10113            )
10114            .with_indents_query("")
10115            .unwrap(),
10116        );
10117
10118        let text = concat!(
10119            "{   }\n",     // Suppress rustfmt
10120            "  x\n",       //
10121            "  /*   */\n", //
10122            "x\n",         //
10123            "{{} }\n",     //
10124        );
10125
10126        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10127        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10128        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10129        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10130            .await;
10131
10132        view.update(cx, |view, cx| {
10133            view.change_selections(None, cx, |s| {
10134                s.select_display_ranges([
10135                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10136                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10137                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10138                ])
10139            });
10140            view.newline(&Newline, cx);
10141
10142            assert_eq!(
10143                view.buffer().read(cx).read(cx).text(),
10144                concat!(
10145                    "{ \n",    // Suppress rustfmt
10146                    "\n",      //
10147                    "}\n",     //
10148                    "  x\n",   //
10149                    "  /* \n", //
10150                    "  \n",    //
10151                    "  */\n",  //
10152                    "x\n",     //
10153                    "{{} \n",  //
10154                    "}\n",     //
10155                )
10156            );
10157        });
10158    }
10159
10160    #[gpui::test]
10161    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10162        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10163
10164        cx.set_global(Settings::test(cx));
10165        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10166
10167        editor.update(cx, |editor, cx| {
10168            struct Type1;
10169            struct Type2;
10170
10171            let buffer = buffer.read(cx).snapshot(cx);
10172
10173            let anchor_range = |range: Range<Point>| {
10174                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10175            };
10176
10177            editor.highlight_background::<Type1>(
10178                vec![
10179                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10180                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10181                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10182                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10183                ],
10184                |_| Color::red(),
10185                cx,
10186            );
10187            editor.highlight_background::<Type2>(
10188                vec![
10189                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10190                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10191                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10192                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10193                ],
10194                |_| Color::green(),
10195                cx,
10196            );
10197
10198            let snapshot = editor.snapshot(cx);
10199            let mut highlighted_ranges = editor.background_highlights_in_range(
10200                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10201                &snapshot,
10202                cx.global::<Settings>().theme.as_ref(),
10203            );
10204            // Enforce a consistent ordering based on color without relying on the ordering of the
10205            // highlight's `TypeId` which is non-deterministic.
10206            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10207            assert_eq!(
10208                highlighted_ranges,
10209                &[
10210                    (
10211                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10212                        Color::green(),
10213                    ),
10214                    (
10215                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10216                        Color::green(),
10217                    ),
10218                    (
10219                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10220                        Color::red(),
10221                    ),
10222                    (
10223                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10224                        Color::red(),
10225                    ),
10226                ]
10227            );
10228            assert_eq!(
10229                editor.background_highlights_in_range(
10230                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10231                    &snapshot,
10232                    cx.global::<Settings>().theme.as_ref(),
10233                ),
10234                &[(
10235                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10236                    Color::red(),
10237                )]
10238            );
10239        });
10240    }
10241
10242    #[gpui::test]
10243    fn test_following(cx: &mut gpui::MutableAppContext) {
10244        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10245
10246        cx.set_global(Settings::test(cx));
10247
10248        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10249        let (_, follower) = cx.add_window(
10250            WindowOptions {
10251                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10252                ..Default::default()
10253            },
10254            |cx| build_editor(buffer.clone(), cx),
10255        );
10256
10257        let pending_update = Rc::new(RefCell::new(None));
10258        follower.update(cx, {
10259            let update = pending_update.clone();
10260            |_, cx| {
10261                cx.subscribe(&leader, move |_, leader, event, cx| {
10262                    leader
10263                        .read(cx)
10264                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10265                })
10266                .detach();
10267            }
10268        });
10269
10270        // Update the selections only
10271        leader.update(cx, |leader, cx| {
10272            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10273        });
10274        follower.update(cx, |follower, cx| {
10275            follower
10276                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10277                .unwrap();
10278        });
10279        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10280
10281        // Update the scroll position only
10282        leader.update(cx, |leader, cx| {
10283            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10284        });
10285        follower.update(cx, |follower, cx| {
10286            follower
10287                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10288                .unwrap();
10289        });
10290        assert_eq!(
10291            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10292            vec2f(1.5, 3.5)
10293        );
10294
10295        // Update the selections and scroll position
10296        leader.update(cx, |leader, cx| {
10297            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10298            leader.request_autoscroll(Autoscroll::Newest, cx);
10299            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10300        });
10301        follower.update(cx, |follower, cx| {
10302            let initial_scroll_position = follower.scroll_position(cx);
10303            follower
10304                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10305                .unwrap();
10306            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10307            assert!(follower.autoscroll_request.is_some());
10308        });
10309        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10310
10311        // Creating a pending selection that precedes another selection
10312        leader.update(cx, |leader, cx| {
10313            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10314            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10315        });
10316        follower.update(cx, |follower, cx| {
10317            follower
10318                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10319                .unwrap();
10320        });
10321        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10322
10323        // Extend the pending selection so that it surrounds another selection
10324        leader.update(cx, |leader, cx| {
10325            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10326        });
10327        follower.update(cx, |follower, cx| {
10328            follower
10329                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10330                .unwrap();
10331        });
10332        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10333    }
10334
10335    #[test]
10336    fn test_combine_syntax_and_fuzzy_match_highlights() {
10337        let string = "abcdefghijklmnop";
10338        let syntax_ranges = [
10339            (
10340                0..3,
10341                HighlightStyle {
10342                    color: Some(Color::red()),
10343                    ..Default::default()
10344                },
10345            ),
10346            (
10347                4..8,
10348                HighlightStyle {
10349                    color: Some(Color::green()),
10350                    ..Default::default()
10351                },
10352            ),
10353        ];
10354        let match_indices = [4, 6, 7, 8];
10355        assert_eq!(
10356            combine_syntax_and_fuzzy_match_highlights(
10357                &string,
10358                Default::default(),
10359                syntax_ranges.into_iter(),
10360                &match_indices,
10361            ),
10362            &[
10363                (
10364                    0..3,
10365                    HighlightStyle {
10366                        color: Some(Color::red()),
10367                        ..Default::default()
10368                    },
10369                ),
10370                (
10371                    4..5,
10372                    HighlightStyle {
10373                        color: Some(Color::green()),
10374                        weight: Some(fonts::Weight::BOLD),
10375                        ..Default::default()
10376                    },
10377                ),
10378                (
10379                    5..6,
10380                    HighlightStyle {
10381                        color: Some(Color::green()),
10382                        ..Default::default()
10383                    },
10384                ),
10385                (
10386                    6..8,
10387                    HighlightStyle {
10388                        color: Some(Color::green()),
10389                        weight: Some(fonts::Weight::BOLD),
10390                        ..Default::default()
10391                    },
10392                ),
10393                (
10394                    8..9,
10395                    HighlightStyle {
10396                        weight: Some(fonts::Weight::BOLD),
10397                        ..Default::default()
10398                    },
10399                ),
10400            ]
10401        );
10402    }
10403
10404    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10405        let point = DisplayPoint::new(row as u32, column as u32);
10406        point..point
10407    }
10408
10409    fn assert_selection_ranges(
10410        marked_text: &str,
10411        selection_marker_pairs: Vec<(char, char)>,
10412        view: &mut Editor,
10413        cx: &mut ViewContext<Editor>,
10414    ) {
10415        let snapshot = view.snapshot(cx).display_snapshot;
10416        let mut marker_chars = Vec::new();
10417        for (start, end) in selection_marker_pairs.iter() {
10418            marker_chars.push(*start);
10419            marker_chars.push(*end);
10420        }
10421        let (_, markers) = marked_text_by(marked_text, marker_chars);
10422        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10423            .iter()
10424            .map(|(start, end)| {
10425                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10426                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10427                start..end
10428            })
10429            .collect();
10430        assert_eq!(
10431            view.selections.display_ranges(cx),
10432            &asserted_ranges[..],
10433            "Assert selections are {}",
10434            marked_text
10435        );
10436    }
10437}
10438
10439trait RangeExt<T> {
10440    fn sorted(&self) -> Range<T>;
10441    fn to_inclusive(&self) -> RangeInclusive<T>;
10442}
10443
10444impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10445    fn sorted(&self) -> Self {
10446        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10447    }
10448
10449    fn to_inclusive(&self) -> RangeInclusive<T> {
10450        self.start.clone()..=self.end.clone()
10451    }
10452}
10453
10454trait RangeToAnchorExt {
10455    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10456}
10457
10458impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10459    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10460        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10461    }
10462}