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