editor.rs

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