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