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