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            workspace.activate_next_pane(cx);
 5960
 5961            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5962                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5963                editor.update(cx, |editor, cx| {
 5964                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
 5965                });
 5966            }
 5967
 5968            nav_history.borrow_mut().enable();
 5969        });
 5970    }
 5971}
 5972
 5973impl EditorSnapshot {
 5974    pub fn is_focused(&self) -> bool {
 5975        self.is_focused
 5976    }
 5977
 5978    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5979        self.placeholder_text.as_ref()
 5980    }
 5981
 5982    pub fn scroll_position(&self) -> Vector2F {
 5983        compute_scroll_position(
 5984            &self.display_snapshot,
 5985            self.scroll_position,
 5986            &self.scroll_top_anchor,
 5987        )
 5988    }
 5989}
 5990
 5991impl Deref for EditorSnapshot {
 5992    type Target = DisplaySnapshot;
 5993
 5994    fn deref(&self) -> &Self::Target {
 5995        &self.display_snapshot
 5996    }
 5997}
 5998
 5999fn compute_scroll_position(
 6000    snapshot: &DisplaySnapshot,
 6001    mut scroll_position: Vector2F,
 6002    scroll_top_anchor: &Anchor,
 6003) -> Vector2F {
 6004    if *scroll_top_anchor != Anchor::min() {
 6005        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 6006        scroll_position.set_y(scroll_top + scroll_position.y());
 6007    } else {
 6008        scroll_position.set_y(0.);
 6009    }
 6010    scroll_position
 6011}
 6012
 6013#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 6014pub enum Event {
 6015    Activate,
 6016    BufferEdited,
 6017    Edited,
 6018    Reparsed,
 6019    Blurred,
 6020    Dirtied,
 6021    Saved,
 6022    TitleChanged,
 6023    SelectionsChanged { local: bool },
 6024    ScrollPositionChanged { local: bool },
 6025    Closed,
 6026}
 6027
 6028pub struct EditorFocused(pub ViewHandle<Editor>);
 6029pub struct EditorBlurred(pub ViewHandle<Editor>);
 6030pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6031
 6032impl Entity for Editor {
 6033    type Event = Event;
 6034
 6035    fn release(&mut self, cx: &mut MutableAppContext) {
 6036        cx.emit_global(EditorReleased(self.handle.clone()));
 6037    }
 6038}
 6039
 6040impl View for Editor {
 6041    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6042        let style = self.style(cx);
 6043        self.display_map.update(cx, |map, cx| {
 6044            map.set_font(style.text.font_id, style.text.font_size, cx)
 6045        });
 6046        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 6047    }
 6048
 6049    fn ui_name() -> &'static str {
 6050        "Editor"
 6051    }
 6052
 6053    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 6054        let focused_event = EditorFocused(cx.handle());
 6055        cx.emit_global(focused_event);
 6056        if let Some(rename) = self.pending_rename.as_ref() {
 6057            cx.focus(&rename.editor);
 6058        } else {
 6059            self.focused = true;
 6060            self.blink_cursors(self.blink_epoch, cx);
 6061            self.buffer.update(cx, |buffer, cx| {
 6062                buffer.finalize_last_transaction(cx);
 6063                if self.leader_replica_id.is_none() {
 6064                    buffer.set_active_selections(&self.selections, cx);
 6065                }
 6066            });
 6067        }
 6068    }
 6069
 6070    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6071        let blurred_event = EditorBlurred(cx.handle());
 6072        cx.emit_global(blurred_event);
 6073        self.focused = false;
 6074        self.buffer
 6075            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6076        self.hide_context_menu(cx);
 6077        cx.emit(Event::Blurred);
 6078        cx.notify();
 6079    }
 6080
 6081    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6082        let mut context = Self::default_keymap_context();
 6083        let mode = match self.mode {
 6084            EditorMode::SingleLine => "single_line",
 6085            EditorMode::AutoHeight { .. } => "auto_height",
 6086            EditorMode::Full => "full",
 6087        };
 6088        context.map.insert("mode".into(), mode.into());
 6089        if self.pending_rename.is_some() {
 6090            context.set.insert("renaming".into());
 6091        }
 6092        match self.context_menu.as_ref() {
 6093            Some(ContextMenu::Completions(_)) => {
 6094                context.set.insert("showing_completions".into());
 6095            }
 6096            Some(ContextMenu::CodeActions(_)) => {
 6097                context.set.insert("showing_code_actions".into());
 6098            }
 6099            None => {}
 6100        }
 6101
 6102        for layer in self.keymap_context_layers.values() {
 6103            context.extend(layer);
 6104        }
 6105
 6106        context
 6107    }
 6108}
 6109
 6110fn build_style(
 6111    settings: &Settings,
 6112    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6113    override_text_style: Option<&OverrideTextStyle>,
 6114    cx: &AppContext,
 6115) -> EditorStyle {
 6116    let font_cache = cx.font_cache();
 6117
 6118    let mut theme = settings.theme.editor.clone();
 6119    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6120        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6121        theme.text_color = field_editor_theme.text.color;
 6122        theme.selection = field_editor_theme.selection;
 6123        theme.background = field_editor_theme
 6124            .container
 6125            .background_color
 6126            .unwrap_or_default();
 6127        EditorStyle {
 6128            text: field_editor_theme.text,
 6129            placeholder_text: field_editor_theme.placeholder_text,
 6130            theme,
 6131        }
 6132    } else {
 6133        let font_family_id = settings.buffer_font_family;
 6134        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6135        let font_properties = Default::default();
 6136        let font_id = font_cache
 6137            .select_font(font_family_id, &font_properties)
 6138            .unwrap();
 6139        let font_size = settings.buffer_font_size;
 6140        EditorStyle {
 6141            text: TextStyle {
 6142                color: settings.theme.editor.text_color,
 6143                font_family_name,
 6144                font_family_id,
 6145                font_id,
 6146                font_size,
 6147                font_properties,
 6148                underline: Default::default(),
 6149            },
 6150            placeholder_text: None,
 6151            theme,
 6152        }
 6153    };
 6154
 6155    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6156        if let Some(highlighted) = style
 6157            .text
 6158            .clone()
 6159            .highlight(highlight_style, font_cache)
 6160            .log_err()
 6161        {
 6162            style.text = highlighted;
 6163        }
 6164    }
 6165
 6166    style
 6167}
 6168
 6169trait SelectionExt {
 6170    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6171    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6172    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6173    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6174        -> Range<u32>;
 6175}
 6176
 6177impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6178    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6179        let start = self.start.to_point(buffer);
 6180        let end = self.end.to_point(buffer);
 6181        if self.reversed {
 6182            end..start
 6183        } else {
 6184            start..end
 6185        }
 6186    }
 6187
 6188    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6189        let start = self.start.to_offset(buffer);
 6190        let end = self.end.to_offset(buffer);
 6191        if self.reversed {
 6192            end..start
 6193        } else {
 6194            start..end
 6195        }
 6196    }
 6197
 6198    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6199        let start = self
 6200            .start
 6201            .to_point(&map.buffer_snapshot)
 6202            .to_display_point(map);
 6203        let end = self
 6204            .end
 6205            .to_point(&map.buffer_snapshot)
 6206            .to_display_point(map);
 6207        if self.reversed {
 6208            end..start
 6209        } else {
 6210            start..end
 6211        }
 6212    }
 6213
 6214    fn spanned_rows(
 6215        &self,
 6216        include_end_if_at_line_start: bool,
 6217        map: &DisplaySnapshot,
 6218    ) -> Range<u32> {
 6219        let start = self.start.to_point(&map.buffer_snapshot);
 6220        let mut end = self.end.to_point(&map.buffer_snapshot);
 6221        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6222            end.row -= 1;
 6223        }
 6224
 6225        let buffer_start = map.prev_line_boundary(start).0;
 6226        let buffer_end = map.next_line_boundary(end).0;
 6227        buffer_start.row..buffer_end.row + 1
 6228    }
 6229}
 6230
 6231impl<T: InvalidationRegion> InvalidationStack<T> {
 6232    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6233    where
 6234        S: Clone + ToOffset,
 6235    {
 6236        while let Some(region) = self.last() {
 6237            let all_selections_inside_invalidation_ranges =
 6238                if selections.len() == region.ranges().len() {
 6239                    selections
 6240                        .iter()
 6241                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6242                        .all(|(selection, invalidation_range)| {
 6243                            let head = selection.head().to_offset(&buffer);
 6244                            invalidation_range.start <= head && invalidation_range.end >= head
 6245                        })
 6246                } else {
 6247                    false
 6248                };
 6249
 6250            if all_selections_inside_invalidation_ranges {
 6251                break;
 6252            } else {
 6253                self.pop();
 6254            }
 6255        }
 6256    }
 6257}
 6258
 6259impl<T> Default for InvalidationStack<T> {
 6260    fn default() -> Self {
 6261        Self(Default::default())
 6262    }
 6263}
 6264
 6265impl<T> Deref for InvalidationStack<T> {
 6266    type Target = Vec<T>;
 6267
 6268    fn deref(&self) -> &Self::Target {
 6269        &self.0
 6270    }
 6271}
 6272
 6273impl<T> DerefMut for InvalidationStack<T> {
 6274    fn deref_mut(&mut self) -> &mut Self::Target {
 6275        &mut self.0
 6276    }
 6277}
 6278
 6279impl InvalidationRegion for BracketPairState {
 6280    fn ranges(&self) -> &[Range<Anchor>] {
 6281        &self.ranges
 6282    }
 6283}
 6284
 6285impl InvalidationRegion for SnippetState {
 6286    fn ranges(&self) -> &[Range<Anchor>] {
 6287        &self.ranges[self.active_index]
 6288    }
 6289}
 6290
 6291impl Deref for EditorStyle {
 6292    type Target = theme::Editor;
 6293
 6294    fn deref(&self) -> &Self::Target {
 6295        &self.theme
 6296    }
 6297}
 6298
 6299pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6300    let mut highlighted_lines = Vec::new();
 6301    for line in diagnostic.message.lines() {
 6302        highlighted_lines.push(highlight_diagnostic_message(line));
 6303    }
 6304
 6305    Arc::new(move |cx: &BlockContext| {
 6306        let settings = cx.global::<Settings>();
 6307        let theme = &settings.theme.editor;
 6308        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6309        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6310        Flex::column()
 6311            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6312                Label::new(
 6313                    line.clone(),
 6314                    style.message.clone().with_font_size(font_size),
 6315                )
 6316                .with_highlights(highlights.clone())
 6317                .contained()
 6318                .with_margin_left(cx.anchor_x)
 6319                .boxed()
 6320            }))
 6321            .aligned()
 6322            .left()
 6323            .boxed()
 6324    })
 6325}
 6326
 6327pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6328    let mut message_without_backticks = String::new();
 6329    let mut prev_offset = 0;
 6330    let mut inside_block = false;
 6331    let mut highlights = Vec::new();
 6332    for (match_ix, (offset, _)) in message
 6333        .match_indices('`')
 6334        .chain([(message.len(), "")])
 6335        .enumerate()
 6336    {
 6337        message_without_backticks.push_str(&message[prev_offset..offset]);
 6338        if inside_block {
 6339            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6340        }
 6341
 6342        inside_block = !inside_block;
 6343        prev_offset = offset + 1;
 6344    }
 6345
 6346    (message_without_backticks, highlights)
 6347}
 6348
 6349pub fn diagnostic_style(
 6350    severity: DiagnosticSeverity,
 6351    valid: bool,
 6352    theme: &theme::Editor,
 6353) -> DiagnosticStyle {
 6354    match (severity, valid) {
 6355        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6356        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6357        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6358        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6359        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6360        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6361        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6362        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6363        _ => theme.invalid_hint_diagnostic.clone(),
 6364    }
 6365}
 6366
 6367pub fn combine_syntax_and_fuzzy_match_highlights(
 6368    text: &str,
 6369    default_style: HighlightStyle,
 6370    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6371    match_indices: &[usize],
 6372) -> Vec<(Range<usize>, HighlightStyle)> {
 6373    let mut result = Vec::new();
 6374    let mut match_indices = match_indices.iter().copied().peekable();
 6375
 6376    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6377    {
 6378        syntax_highlight.weight = None;
 6379
 6380        // Add highlights for any fuzzy match characters before the next
 6381        // syntax highlight range.
 6382        while let Some(&match_index) = match_indices.peek() {
 6383            if match_index >= range.start {
 6384                break;
 6385            }
 6386            match_indices.next();
 6387            let end_index = char_ix_after(match_index, text);
 6388            let mut match_style = default_style;
 6389            match_style.weight = Some(fonts::Weight::BOLD);
 6390            result.push((match_index..end_index, match_style));
 6391        }
 6392
 6393        if range.start == usize::MAX {
 6394            break;
 6395        }
 6396
 6397        // Add highlights for any fuzzy match characters within the
 6398        // syntax highlight range.
 6399        let mut offset = range.start;
 6400        while let Some(&match_index) = match_indices.peek() {
 6401            if match_index >= range.end {
 6402                break;
 6403            }
 6404
 6405            match_indices.next();
 6406            if match_index > offset {
 6407                result.push((offset..match_index, syntax_highlight));
 6408            }
 6409
 6410            let mut end_index = char_ix_after(match_index, text);
 6411            while let Some(&next_match_index) = match_indices.peek() {
 6412                if next_match_index == end_index && next_match_index < range.end {
 6413                    end_index = char_ix_after(next_match_index, text);
 6414                    match_indices.next();
 6415                } else {
 6416                    break;
 6417                }
 6418            }
 6419
 6420            let mut match_style = syntax_highlight;
 6421            match_style.weight = Some(fonts::Weight::BOLD);
 6422            result.push((match_index..end_index, match_style));
 6423            offset = end_index;
 6424        }
 6425
 6426        if offset < range.end {
 6427            result.push((offset..range.end, syntax_highlight));
 6428        }
 6429    }
 6430
 6431    fn char_ix_after(ix: usize, text: &str) -> usize {
 6432        ix + text[ix..].chars().next().unwrap().len_utf8()
 6433    }
 6434
 6435    result
 6436}
 6437
 6438pub fn styled_runs_for_code_label<'a>(
 6439    label: &'a CodeLabel,
 6440    syntax_theme: &'a theme::SyntaxTheme,
 6441) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6442    let fade_out = HighlightStyle {
 6443        fade_out: Some(0.35),
 6444        ..Default::default()
 6445    };
 6446
 6447    let mut prev_end = label.filter_range.end;
 6448    label
 6449        .runs
 6450        .iter()
 6451        .enumerate()
 6452        .flat_map(move |(ix, (range, highlight_id))| {
 6453            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6454                style
 6455            } else {
 6456                return Default::default();
 6457            };
 6458            let mut muted_style = style.clone();
 6459            muted_style.highlight(fade_out);
 6460
 6461            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6462            if range.start >= label.filter_range.end {
 6463                if range.start > prev_end {
 6464                    runs.push((prev_end..range.start, fade_out));
 6465                }
 6466                runs.push((range.clone(), muted_style));
 6467            } else if range.end <= label.filter_range.end {
 6468                runs.push((range.clone(), style));
 6469            } else {
 6470                runs.push((range.start..label.filter_range.end, style));
 6471                runs.push((label.filter_range.end..range.end, muted_style));
 6472            }
 6473            prev_end = cmp::max(prev_end, range.end);
 6474
 6475            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6476                runs.push((prev_end..label.text.len(), fade_out));
 6477            }
 6478
 6479            runs
 6480        })
 6481}
 6482
 6483#[cfg(test)]
 6484mod tests {
 6485    use crate::test::{assert_text_with_selections, select_ranges};
 6486
 6487    use super::*;
 6488    use gpui::{
 6489        geometry::rect::RectF,
 6490        platform::{WindowBounds, WindowOptions},
 6491    };
 6492    use indoc::indoc;
 6493    use language::{FakeLspAdapter, LanguageConfig};
 6494    use lsp::FakeLanguageServer;
 6495    use project::FakeFs;
 6496    use settings::LanguageOverride;
 6497    use smol::stream::StreamExt;
 6498    use std::{cell::RefCell, rc::Rc, time::Instant};
 6499    use text::Point;
 6500    use unindent::Unindent;
 6501    use util::test::{marked_text_by, marked_text_ranges, sample_text};
 6502    use workspace::{FollowableItem, ItemHandle};
 6503
 6504    #[gpui::test]
 6505    fn test_edit_events(cx: &mut MutableAppContext) {
 6506        cx.set_global(Settings::test(cx));
 6507        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6508
 6509        let events = Rc::new(RefCell::new(Vec::new()));
 6510        let (_, editor1) = cx.add_window(Default::default(), {
 6511            let events = events.clone();
 6512            |cx| {
 6513                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6514                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6515                        events.borrow_mut().push(("editor1", *event));
 6516                    }
 6517                })
 6518                .detach();
 6519                Editor::for_buffer(buffer.clone(), None, cx)
 6520            }
 6521        });
 6522        let (_, editor2) = cx.add_window(Default::default(), {
 6523            let events = events.clone();
 6524            |cx| {
 6525                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6526                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6527                        events.borrow_mut().push(("editor2", *event));
 6528                    }
 6529                })
 6530                .detach();
 6531                Editor::for_buffer(buffer.clone(), None, cx)
 6532            }
 6533        });
 6534        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6535
 6536        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6537        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6538        assert_eq!(
 6539            mem::take(&mut *events.borrow_mut()),
 6540            [
 6541                ("editor1", Event::Edited),
 6542                ("editor1", Event::BufferEdited),
 6543                ("editor2", Event::BufferEdited),
 6544                ("editor1", Event::Dirtied),
 6545                ("editor2", Event::Dirtied)
 6546            ]
 6547        );
 6548
 6549        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6550        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6551        assert_eq!(
 6552            mem::take(&mut *events.borrow_mut()),
 6553            [
 6554                ("editor2", Event::Edited),
 6555                ("editor1", Event::BufferEdited),
 6556                ("editor2", Event::BufferEdited),
 6557            ]
 6558        );
 6559
 6560        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6561        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6562        assert_eq!(
 6563            mem::take(&mut *events.borrow_mut()),
 6564            [
 6565                ("editor1", Event::Edited),
 6566                ("editor1", Event::BufferEdited),
 6567                ("editor2", Event::BufferEdited),
 6568            ]
 6569        );
 6570
 6571        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6572        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6573        assert_eq!(
 6574            mem::take(&mut *events.borrow_mut()),
 6575            [
 6576                ("editor1", Event::Edited),
 6577                ("editor1", Event::BufferEdited),
 6578                ("editor2", Event::BufferEdited),
 6579            ]
 6580        );
 6581
 6582        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6583        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6584        assert_eq!(
 6585            mem::take(&mut *events.borrow_mut()),
 6586            [
 6587                ("editor2", Event::Edited),
 6588                ("editor1", Event::BufferEdited),
 6589                ("editor2", Event::BufferEdited),
 6590            ]
 6591        );
 6592
 6593        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6594        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6595        assert_eq!(
 6596            mem::take(&mut *events.borrow_mut()),
 6597            [
 6598                ("editor2", Event::Edited),
 6599                ("editor1", Event::BufferEdited),
 6600                ("editor2", Event::BufferEdited),
 6601            ]
 6602        );
 6603
 6604        // No event is emitted when the mutation is a no-op.
 6605        editor2.update(cx, |editor, cx| {
 6606            editor.select_ranges([0..0], None, cx);
 6607            editor.backspace(&Backspace, cx);
 6608        });
 6609        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6610    }
 6611
 6612    #[gpui::test]
 6613    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6614        cx.set_global(Settings::test(cx));
 6615        let mut now = Instant::now();
 6616        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6617        let group_interval = buffer.read(cx).transaction_group_interval();
 6618        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6619        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6620
 6621        editor.update(cx, |editor, cx| {
 6622            editor.start_transaction_at(now, cx);
 6623            editor.select_ranges([2..4], None, cx);
 6624            editor.insert("cd", cx);
 6625            editor.end_transaction_at(now, cx);
 6626            assert_eq!(editor.text(cx), "12cd56");
 6627            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 6628
 6629            editor.start_transaction_at(now, cx);
 6630            editor.select_ranges([4..5], None, cx);
 6631            editor.insert("e", cx);
 6632            editor.end_transaction_at(now, cx);
 6633            assert_eq!(editor.text(cx), "12cde6");
 6634            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6635
 6636            now += group_interval + Duration::from_millis(1);
 6637            editor.select_ranges([2..2], None, cx);
 6638
 6639            // Simulate an edit in another editor
 6640            buffer.update(cx, |buffer, cx| {
 6641                buffer.start_transaction_at(now, cx);
 6642                buffer.edit([0..1], "a", cx);
 6643                buffer.edit([1..1], "b", cx);
 6644                buffer.end_transaction_at(now, cx);
 6645            });
 6646
 6647            assert_eq!(editor.text(cx), "ab2cde6");
 6648            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
 6649
 6650            // Last transaction happened past the group interval in a different editor.
 6651            // Undo it individually and don't restore selections.
 6652            editor.undo(&Undo, cx);
 6653            assert_eq!(editor.text(cx), "12cde6");
 6654            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
 6655
 6656            // First two transactions happened within the group interval in this editor.
 6657            // Undo them together and restore selections.
 6658            editor.undo(&Undo, cx);
 6659            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6660            assert_eq!(editor.text(cx), "123456");
 6661            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
 6662
 6663            // Redo the first two transactions together.
 6664            editor.redo(&Redo, cx);
 6665            assert_eq!(editor.text(cx), "12cde6");
 6666            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6667
 6668            // Redo the last transaction on its own.
 6669            editor.redo(&Redo, cx);
 6670            assert_eq!(editor.text(cx), "ab2cde6");
 6671            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
 6672
 6673            // Test empty transactions.
 6674            editor.start_transaction_at(now, cx);
 6675            editor.end_transaction_at(now, cx);
 6676            editor.undo(&Undo, cx);
 6677            assert_eq!(editor.text(cx), "12cde6");
 6678        });
 6679    }
 6680
 6681    #[gpui::test]
 6682    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6683        cx.set_global(Settings::test(cx));
 6684
 6685        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6686        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6687        editor.update(cx, |view, cx| {
 6688            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6689        });
 6690        assert_eq!(
 6691            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6692            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6693        );
 6694
 6695        editor.update(cx, |view, cx| {
 6696            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6697        });
 6698
 6699        assert_eq!(
 6700            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6701            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6702        );
 6703
 6704        editor.update(cx, |view, cx| {
 6705            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6706        });
 6707
 6708        assert_eq!(
 6709            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6710            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6711        );
 6712
 6713        editor.update(cx, |view, cx| {
 6714            view.end_selection(cx);
 6715            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6716        });
 6717
 6718        assert_eq!(
 6719            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6720            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6721        );
 6722
 6723        editor.update(cx, |view, cx| {
 6724            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6725            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6726        });
 6727
 6728        assert_eq!(
 6729            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6730            [
 6731                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6732                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6733            ]
 6734        );
 6735
 6736        editor.update(cx, |view, cx| {
 6737            view.end_selection(cx);
 6738        });
 6739
 6740        assert_eq!(
 6741            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6742            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6743        );
 6744    }
 6745
 6746    #[gpui::test]
 6747    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6748        cx.set_global(Settings::test(cx));
 6749        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6750        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6751
 6752        view.update(cx, |view, cx| {
 6753            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6754            assert_eq!(
 6755                view.selected_display_ranges(cx),
 6756                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6757            );
 6758        });
 6759
 6760        view.update(cx, |view, cx| {
 6761            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6762            assert_eq!(
 6763                view.selected_display_ranges(cx),
 6764                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6765            );
 6766        });
 6767
 6768        view.update(cx, |view, cx| {
 6769            view.cancel(&Cancel, cx);
 6770            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6771            assert_eq!(
 6772                view.selected_display_ranges(cx),
 6773                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6774            );
 6775        });
 6776    }
 6777
 6778    #[gpui::test]
 6779    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6780        cx.set_global(Settings::test(cx));
 6781        use workspace::Item;
 6782        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6783        let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx);
 6784
 6785        cx.add_window(Default::default(), |cx| {
 6786            let mut editor = build_editor(buffer.clone(), cx);
 6787            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6788
 6789            // Move the cursor a small distance.
 6790            // Nothing is added to the navigation history.
 6791            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
 6792            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
 6793            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6794
 6795            // Move the cursor a large distance.
 6796            // The history can jump back to the previous position.
 6797            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
 6798            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6799            editor.navigate(nav_entry.data.unwrap(), cx);
 6800            assert_eq!(nav_entry.item.id(), cx.view_id());
 6801            assert_eq!(
 6802                editor.selected_display_ranges(cx),
 6803                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6804            );
 6805            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6806
 6807            // Move the cursor a small distance via the mouse.
 6808            // Nothing is added to the navigation history.
 6809            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6810            editor.end_selection(cx);
 6811            assert_eq!(
 6812                editor.selected_display_ranges(cx),
 6813                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6814            );
 6815            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6816
 6817            // Move the cursor a large distance via the mouse.
 6818            // The history can jump back to the previous position.
 6819            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6820            editor.end_selection(cx);
 6821            assert_eq!(
 6822                editor.selected_display_ranges(cx),
 6823                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6824            );
 6825            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6826            editor.navigate(nav_entry.data.unwrap(), cx);
 6827            assert_eq!(nav_entry.item.id(), cx.view_id());
 6828            assert_eq!(
 6829                editor.selected_display_ranges(cx),
 6830                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6831            );
 6832            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6833
 6834            editor
 6835        });
 6836    }
 6837
 6838    #[gpui::test]
 6839    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6840        cx.set_global(Settings::test(cx));
 6841        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6842        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6843
 6844        view.update(cx, |view, cx| {
 6845            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6846            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6847            view.end_selection(cx);
 6848
 6849            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6850            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6851            view.end_selection(cx);
 6852            assert_eq!(
 6853                view.selected_display_ranges(cx),
 6854                [
 6855                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6856                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6857                ]
 6858            );
 6859        });
 6860
 6861        view.update(cx, |view, cx| {
 6862            view.cancel(&Cancel, cx);
 6863            assert_eq!(
 6864                view.selected_display_ranges(cx),
 6865                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6866            );
 6867        });
 6868
 6869        view.update(cx, |view, cx| {
 6870            view.cancel(&Cancel, cx);
 6871            assert_eq!(
 6872                view.selected_display_ranges(cx),
 6873                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6874            );
 6875        });
 6876    }
 6877
 6878    #[gpui::test]
 6879    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6880        cx.set_global(Settings::test(cx));
 6881        let buffer = MultiBuffer::build_simple(
 6882            &"
 6883                impl Foo {
 6884                    // Hello!
 6885
 6886                    fn a() {
 6887                        1
 6888                    }
 6889
 6890                    fn b() {
 6891                        2
 6892                    }
 6893
 6894                    fn c() {
 6895                        3
 6896                    }
 6897                }
 6898            "
 6899            .unindent(),
 6900            cx,
 6901        );
 6902        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6903
 6904        view.update(cx, |view, cx| {
 6905            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 6906            view.fold(&Fold, cx);
 6907            assert_eq!(
 6908                view.display_text(cx),
 6909                "
 6910                    impl Foo {
 6911                        // Hello!
 6912
 6913                        fn a() {
 6914                            1
 6915                        }
 6916
 6917                        fn b() {…
 6918                        }
 6919
 6920                        fn c() {…
 6921                        }
 6922                    }
 6923                "
 6924                .unindent(),
 6925            );
 6926
 6927            view.fold(&Fold, cx);
 6928            assert_eq!(
 6929                view.display_text(cx),
 6930                "
 6931                    impl Foo {…
 6932                    }
 6933                "
 6934                .unindent(),
 6935            );
 6936
 6937            view.unfold_lines(&UnfoldLines, cx);
 6938            assert_eq!(
 6939                view.display_text(cx),
 6940                "
 6941                    impl Foo {
 6942                        // Hello!
 6943
 6944                        fn a() {
 6945                            1
 6946                        }
 6947
 6948                        fn b() {…
 6949                        }
 6950
 6951                        fn c() {…
 6952                        }
 6953                    }
 6954                "
 6955                .unindent(),
 6956            );
 6957
 6958            view.unfold_lines(&UnfoldLines, cx);
 6959            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6960        });
 6961    }
 6962
 6963    #[gpui::test]
 6964    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6965        cx.set_global(Settings::test(cx));
 6966        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6967        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6968
 6969        buffer.update(cx, |buffer, cx| {
 6970            buffer.edit(
 6971                vec![
 6972                    Point::new(1, 0)..Point::new(1, 0),
 6973                    Point::new(1, 1)..Point::new(1, 1),
 6974                ],
 6975                "\t",
 6976                cx,
 6977            );
 6978        });
 6979
 6980        view.update(cx, |view, cx| {
 6981            assert_eq!(
 6982                view.selected_display_ranges(cx),
 6983                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6984            );
 6985
 6986            view.move_down(&MoveDown, cx);
 6987            assert_eq!(
 6988                view.selected_display_ranges(cx),
 6989                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6990            );
 6991
 6992            view.move_right(&MoveRight, cx);
 6993            assert_eq!(
 6994                view.selected_display_ranges(cx),
 6995                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6996            );
 6997
 6998            view.move_left(&MoveLeft, cx);
 6999            assert_eq!(
 7000                view.selected_display_ranges(cx),
 7001                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7002            );
 7003
 7004            view.move_up(&MoveUp, cx);
 7005            assert_eq!(
 7006                view.selected_display_ranges(cx),
 7007                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7008            );
 7009
 7010            view.move_to_end(&MoveToEnd, cx);
 7011            assert_eq!(
 7012                view.selected_display_ranges(cx),
 7013                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7014            );
 7015
 7016            view.move_to_beginning(&MoveToBeginning, cx);
 7017            assert_eq!(
 7018                view.selected_display_ranges(cx),
 7019                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7020            );
 7021
 7022            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7023            view.select_to_beginning(&SelectToBeginning, cx);
 7024            assert_eq!(
 7025                view.selected_display_ranges(cx),
 7026                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7027            );
 7028
 7029            view.select_to_end(&SelectToEnd, cx);
 7030            assert_eq!(
 7031                view.selected_display_ranges(cx),
 7032                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7033            );
 7034        });
 7035    }
 7036
 7037    #[gpui::test]
 7038    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7039        cx.set_global(Settings::test(cx));
 7040        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7041        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7042
 7043        assert_eq!('ⓐ'.len_utf8(), 3);
 7044        assert_eq!('α'.len_utf8(), 2);
 7045
 7046        view.update(cx, |view, cx| {
 7047            view.fold_ranges(
 7048                vec![
 7049                    Point::new(0, 6)..Point::new(0, 12),
 7050                    Point::new(1, 2)..Point::new(1, 4),
 7051                    Point::new(2, 4)..Point::new(2, 8),
 7052                ],
 7053                cx,
 7054            );
 7055            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7056
 7057            view.move_right(&MoveRight, cx);
 7058            assert_eq!(
 7059                view.selected_display_ranges(cx),
 7060                &[empty_range(0, "".len())]
 7061            );
 7062            view.move_right(&MoveRight, cx);
 7063            assert_eq!(
 7064                view.selected_display_ranges(cx),
 7065                &[empty_range(0, "ⓐⓑ".len())]
 7066            );
 7067            view.move_right(&MoveRight, cx);
 7068            assert_eq!(
 7069                view.selected_display_ranges(cx),
 7070                &[empty_range(0, "ⓐⓑ…".len())]
 7071            );
 7072
 7073            view.move_down(&MoveDown, cx);
 7074            assert_eq!(
 7075                view.selected_display_ranges(cx),
 7076                &[empty_range(1, "ab…".len())]
 7077            );
 7078            view.move_left(&MoveLeft, cx);
 7079            assert_eq!(
 7080                view.selected_display_ranges(cx),
 7081                &[empty_range(1, "ab".len())]
 7082            );
 7083            view.move_left(&MoveLeft, cx);
 7084            assert_eq!(
 7085                view.selected_display_ranges(cx),
 7086                &[empty_range(1, "a".len())]
 7087            );
 7088
 7089            view.move_down(&MoveDown, cx);
 7090            assert_eq!(
 7091                view.selected_display_ranges(cx),
 7092                &[empty_range(2, "α".len())]
 7093            );
 7094            view.move_right(&MoveRight, cx);
 7095            assert_eq!(
 7096                view.selected_display_ranges(cx),
 7097                &[empty_range(2, "αβ".len())]
 7098            );
 7099            view.move_right(&MoveRight, cx);
 7100            assert_eq!(
 7101                view.selected_display_ranges(cx),
 7102                &[empty_range(2, "αβ…".len())]
 7103            );
 7104            view.move_right(&MoveRight, cx);
 7105            assert_eq!(
 7106                view.selected_display_ranges(cx),
 7107                &[empty_range(2, "αβ…ε".len())]
 7108            );
 7109
 7110            view.move_up(&MoveUp, cx);
 7111            assert_eq!(
 7112                view.selected_display_ranges(cx),
 7113                &[empty_range(1, "ab…e".len())]
 7114            );
 7115            view.move_up(&MoveUp, cx);
 7116            assert_eq!(
 7117                view.selected_display_ranges(cx),
 7118                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7119            );
 7120            view.move_left(&MoveLeft, cx);
 7121            assert_eq!(
 7122                view.selected_display_ranges(cx),
 7123                &[empty_range(0, "ⓐⓑ…".len())]
 7124            );
 7125            view.move_left(&MoveLeft, cx);
 7126            assert_eq!(
 7127                view.selected_display_ranges(cx),
 7128                &[empty_range(0, "ⓐⓑ".len())]
 7129            );
 7130            view.move_left(&MoveLeft, cx);
 7131            assert_eq!(
 7132                view.selected_display_ranges(cx),
 7133                &[empty_range(0, "".len())]
 7134            );
 7135        });
 7136    }
 7137
 7138    #[gpui::test]
 7139    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7140        cx.set_global(Settings::test(cx));
 7141        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7142        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7143        view.update(cx, |view, cx| {
 7144            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7145            view.move_down(&MoveDown, cx);
 7146            assert_eq!(
 7147                view.selected_display_ranges(cx),
 7148                &[empty_range(1, "abcd".len())]
 7149            );
 7150
 7151            view.move_down(&MoveDown, cx);
 7152            assert_eq!(
 7153                view.selected_display_ranges(cx),
 7154                &[empty_range(2, "αβγ".len())]
 7155            );
 7156
 7157            view.move_down(&MoveDown, cx);
 7158            assert_eq!(
 7159                view.selected_display_ranges(cx),
 7160                &[empty_range(3, "abcd".len())]
 7161            );
 7162
 7163            view.move_down(&MoveDown, cx);
 7164            assert_eq!(
 7165                view.selected_display_ranges(cx),
 7166                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7167            );
 7168
 7169            view.move_up(&MoveUp, cx);
 7170            assert_eq!(
 7171                view.selected_display_ranges(cx),
 7172                &[empty_range(3, "abcd".len())]
 7173            );
 7174
 7175            view.move_up(&MoveUp, cx);
 7176            assert_eq!(
 7177                view.selected_display_ranges(cx),
 7178                &[empty_range(2, "αβγ".len())]
 7179            );
 7180        });
 7181    }
 7182
 7183    #[gpui::test]
 7184    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7185        cx.set_global(Settings::test(cx));
 7186        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7187        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7188        view.update(cx, |view, cx| {
 7189            view.select_display_ranges(
 7190                &[
 7191                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7192                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7193                ],
 7194                cx,
 7195            );
 7196        });
 7197
 7198        view.update(cx, |view, cx| {
 7199            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7200            assert_eq!(
 7201                view.selected_display_ranges(cx),
 7202                &[
 7203                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7204                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7205                ]
 7206            );
 7207        });
 7208
 7209        view.update(cx, |view, cx| {
 7210            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7211            assert_eq!(
 7212                view.selected_display_ranges(cx),
 7213                &[
 7214                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7215                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7216                ]
 7217            );
 7218        });
 7219
 7220        view.update(cx, |view, cx| {
 7221            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7222            assert_eq!(
 7223                view.selected_display_ranges(cx),
 7224                &[
 7225                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7226                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7227                ]
 7228            );
 7229        });
 7230
 7231        view.update(cx, |view, cx| {
 7232            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7233            assert_eq!(
 7234                view.selected_display_ranges(cx),
 7235                &[
 7236                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7237                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7238                ]
 7239            );
 7240        });
 7241
 7242        // Moving to the end of line again is a no-op.
 7243        view.update(cx, |view, cx| {
 7244            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7245            assert_eq!(
 7246                view.selected_display_ranges(cx),
 7247                &[
 7248                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7249                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7250                ]
 7251            );
 7252        });
 7253
 7254        view.update(cx, |view, cx| {
 7255            view.move_left(&MoveLeft, cx);
 7256            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
 7257            assert_eq!(
 7258                view.selected_display_ranges(cx),
 7259                &[
 7260                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7261                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7262                ]
 7263            );
 7264        });
 7265
 7266        view.update(cx, |view, cx| {
 7267            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
 7268            assert_eq!(
 7269                view.selected_display_ranges(cx),
 7270                &[
 7271                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7272                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7273                ]
 7274            );
 7275        });
 7276
 7277        view.update(cx, |view, cx| {
 7278            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
 7279            assert_eq!(
 7280                view.selected_display_ranges(cx),
 7281                &[
 7282                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7283                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7284                ]
 7285            );
 7286        });
 7287
 7288        view.update(cx, |view, cx| {
 7289            view.select_to_end_of_line(&SelectToEndOfLine(true), cx);
 7290            assert_eq!(
 7291                view.selected_display_ranges(cx),
 7292                &[
 7293                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7294                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7295                ]
 7296            );
 7297        });
 7298
 7299        view.update(cx, |view, cx| {
 7300            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7301            assert_eq!(view.display_text(cx), "ab\n  de");
 7302            assert_eq!(
 7303                view.selected_display_ranges(cx),
 7304                &[
 7305                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7306                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7307                ]
 7308            );
 7309        });
 7310
 7311        view.update(cx, |view, cx| {
 7312            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7313            assert_eq!(view.display_text(cx), "\n");
 7314            assert_eq!(
 7315                view.selected_display_ranges(cx),
 7316                &[
 7317                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7318                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7319                ]
 7320            );
 7321        });
 7322    }
 7323
 7324    #[gpui::test]
 7325    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7326        cx.set_global(Settings::test(cx));
 7327        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7328        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7329        view.update(cx, |view, cx| {
 7330            view.select_display_ranges(
 7331                &[
 7332                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7333                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7334                ],
 7335                cx,
 7336            );
 7337
 7338            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7339            assert_selection_ranges(
 7340                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7341                vec![('<', '>'), ('[', ']')],
 7342                view,
 7343                cx,
 7344            );
 7345
 7346            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7347            assert_selection_ranges(
 7348                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7349                vec![('<', '>'), ('[', ']')],
 7350                view,
 7351                cx,
 7352            );
 7353
 7354            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7355            assert_selection_ranges(
 7356                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7357                vec![('<', '>'), ('[', ']')],
 7358                view,
 7359                cx,
 7360            );
 7361
 7362            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7363            assert_selection_ranges(
 7364                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7365                vec![('<', '>'), ('[', ']')],
 7366                view,
 7367                cx,
 7368            );
 7369
 7370            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7371            assert_selection_ranges(
 7372                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7373                vec![('<', '>'), ('[', ']')],
 7374                view,
 7375                cx,
 7376            );
 7377
 7378            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7379            assert_selection_ranges(
 7380                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7381                vec![('<', '>'), ('[', ']')],
 7382                view,
 7383                cx,
 7384            );
 7385
 7386            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7387            assert_selection_ranges(
 7388                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7389                vec![('<', '>'), ('[', ']')],
 7390                view,
 7391                cx,
 7392            );
 7393
 7394            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7395            assert_selection_ranges(
 7396                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7397                vec![('<', '>'), ('[', ']')],
 7398                view,
 7399                cx,
 7400            );
 7401
 7402            view.move_right(&MoveRight, cx);
 7403            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7404            assert_selection_ranges(
 7405                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7406                vec![('<', '>'), ('[', ']')],
 7407                view,
 7408                cx,
 7409            );
 7410
 7411            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7412            assert_selection_ranges(
 7413                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7414                vec![('<', '>'), ('[', ']')],
 7415                view,
 7416                cx,
 7417            );
 7418
 7419            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7420            assert_selection_ranges(
 7421                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7422                vec![('<', '>'), ('[', ']')],
 7423                view,
 7424                cx,
 7425            );
 7426        });
 7427    }
 7428
 7429    #[gpui::test]
 7430    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7431        cx.set_global(Settings::test(cx));
 7432        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7433        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7434
 7435        view.update(cx, |view, cx| {
 7436            view.set_wrap_width(Some(140.), cx);
 7437            assert_eq!(
 7438                view.display_text(cx),
 7439                "use one::{\n    two::three::\n    four::five\n};"
 7440            );
 7441
 7442            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7443
 7444            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7445            assert_eq!(
 7446                view.selected_display_ranges(cx),
 7447                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7448            );
 7449
 7450            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7451            assert_eq!(
 7452                view.selected_display_ranges(cx),
 7453                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7454            );
 7455
 7456            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7457            assert_eq!(
 7458                view.selected_display_ranges(cx),
 7459                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7460            );
 7461
 7462            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7463            assert_eq!(
 7464                view.selected_display_ranges(cx),
 7465                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7466            );
 7467
 7468            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7469            assert_eq!(
 7470                view.selected_display_ranges(cx),
 7471                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7472            );
 7473
 7474            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7475            assert_eq!(
 7476                view.selected_display_ranges(cx),
 7477                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7478            );
 7479        });
 7480    }
 7481
 7482    #[gpui::test]
 7483    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7484        cx.set_global(Settings::test(cx));
 7485        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7486        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7487
 7488        view.update(cx, |view, cx| {
 7489            view.select_display_ranges(
 7490                &[
 7491                    // an empty selection - the preceding word fragment is deleted
 7492                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7493                    // characters selected - they are deleted
 7494                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7495                ],
 7496                cx,
 7497            );
 7498            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7499        });
 7500
 7501        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7502
 7503        view.update(cx, |view, cx| {
 7504            view.select_display_ranges(
 7505                &[
 7506                    // an empty selection - the following word fragment is deleted
 7507                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7508                    // characters selected - they are deleted
 7509                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7510                ],
 7511                cx,
 7512            );
 7513            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7514        });
 7515
 7516        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7517    }
 7518
 7519    #[gpui::test]
 7520    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7521        cx.set_global(Settings::test(cx));
 7522        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7523        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7524
 7525        view.update(cx, |view, cx| {
 7526            view.select_display_ranges(
 7527                &[
 7528                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7529                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7530                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7531                ],
 7532                cx,
 7533            );
 7534
 7535            view.newline(&Newline, cx);
 7536            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7537        });
 7538    }
 7539
 7540    #[gpui::test]
 7541    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7542        cx.set_global(Settings::test(cx));
 7543        let buffer = MultiBuffer::build_simple(
 7544            "
 7545                a
 7546                b(
 7547                    X
 7548                )
 7549                c(
 7550                    X
 7551                )
 7552            "
 7553            .unindent()
 7554            .as_str(),
 7555            cx,
 7556        );
 7557
 7558        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7559            let mut editor = build_editor(buffer.clone(), cx);
 7560            editor.select_ranges(
 7561                [
 7562                    Point::new(2, 4)..Point::new(2, 5),
 7563                    Point::new(5, 4)..Point::new(5, 5),
 7564                ],
 7565                None,
 7566                cx,
 7567            );
 7568            editor
 7569        });
 7570
 7571        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7572        buffer.update(cx, |buffer, cx| {
 7573            buffer.edit(
 7574                [
 7575                    Point::new(1, 2)..Point::new(3, 0),
 7576                    Point::new(4, 2)..Point::new(6, 0),
 7577                ],
 7578                "",
 7579                cx,
 7580            );
 7581            assert_eq!(
 7582                buffer.read(cx).text(),
 7583                "
 7584                    a
 7585                    b()
 7586                    c()
 7587                "
 7588                .unindent()
 7589            );
 7590        });
 7591
 7592        editor.update(cx, |editor, cx| {
 7593            assert_eq!(
 7594                editor.selected_ranges(cx),
 7595                &[
 7596                    Point::new(1, 2)..Point::new(1, 2),
 7597                    Point::new(2, 2)..Point::new(2, 2),
 7598                ],
 7599            );
 7600
 7601            editor.newline(&Newline, cx);
 7602            assert_eq!(
 7603                editor.text(cx),
 7604                "
 7605                    a
 7606                    b(
 7607                    )
 7608                    c(
 7609                    )
 7610                "
 7611                .unindent()
 7612            );
 7613
 7614            // The selections are moved after the inserted newlines
 7615            assert_eq!(
 7616                editor.selected_ranges(cx),
 7617                &[
 7618                    Point::new(2, 0)..Point::new(2, 0),
 7619                    Point::new(4, 0)..Point::new(4, 0),
 7620                ],
 7621            );
 7622        });
 7623    }
 7624
 7625    #[gpui::test]
 7626    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7627        cx.set_global(Settings::test(cx));
 7628        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7629        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7630            let mut editor = build_editor(buffer.clone(), cx);
 7631            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7632            editor
 7633        });
 7634
 7635        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7636        buffer.update(cx, |buffer, cx| {
 7637            buffer.edit([2..5, 10..13, 18..21], "", cx);
 7638            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7639        });
 7640
 7641        editor.update(cx, |editor, cx| {
 7642            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7643
 7644            editor.insert("Z", cx);
 7645            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7646
 7647            // The selections are moved after the inserted characters
 7648            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7649        });
 7650    }
 7651
 7652    #[gpui::test]
 7653    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7654        cx.set_global(Settings::test(cx));
 7655        let buffer = MultiBuffer::build_simple(
 7656            indoc! {"
 7657                  one two
 7658                three
 7659                 four"},
 7660            cx,
 7661        );
 7662        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7663
 7664        view.update(cx, |view, cx| {
 7665            // two selections on the same line
 7666            select_ranges(
 7667                view,
 7668                indoc! {"
 7669                      [one] [two]
 7670                    three
 7671                     four"},
 7672                cx,
 7673            );
 7674
 7675            // indent from mid-tabstop to full tabstop
 7676            view.tab(&Tab(Direction::Next), cx);
 7677            assert_text_with_selections(
 7678                view,
 7679                indoc! {"
 7680                        [one] [two]
 7681                    three
 7682                     four"},
 7683                cx,
 7684            );
 7685
 7686            // outdent from 1 tabstop to 0 tabstops
 7687            view.tab(&Tab(Direction::Prev), cx);
 7688            assert_text_with_selections(
 7689                view,
 7690                indoc! {"
 7691                    [one] [two]
 7692                    three
 7693                     four"},
 7694                cx,
 7695            );
 7696
 7697            // select across line ending
 7698            select_ranges(
 7699                view,
 7700                indoc! {"
 7701                    one two
 7702                    t[hree
 7703                    ] four"},
 7704                cx,
 7705            );
 7706
 7707            // indent and outdent affect only the preceding line
 7708            view.tab(&Tab(Direction::Next), cx);
 7709            assert_text_with_selections(
 7710                view,
 7711                indoc! {"
 7712                    one two
 7713                        t[hree
 7714                    ] four"},
 7715                cx,
 7716            );
 7717            view.tab(&Tab(Direction::Prev), cx);
 7718            assert_text_with_selections(
 7719                view,
 7720                indoc! {"
 7721                    one two
 7722                    t[hree
 7723                    ] four"},
 7724                cx,
 7725            );
 7726
 7727            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7728            select_ranges(
 7729                view,
 7730                indoc! {"
 7731                    one two
 7732                    []three
 7733                     four"},
 7734                cx,
 7735            );
 7736            view.tab(&Tab(Direction::Next), cx);
 7737            assert_text_with_selections(
 7738                view,
 7739                indoc! {"
 7740                    one two
 7741                        []three
 7742                     four"},
 7743                cx,
 7744            );
 7745
 7746            select_ranges(
 7747                view,
 7748                indoc! {"
 7749                    one two
 7750                    []    three
 7751                     four"},
 7752                cx,
 7753            );
 7754            view.tab(&Tab(Direction::Prev), cx);
 7755            assert_text_with_selections(
 7756                view,
 7757                indoc! {"
 7758                    one two
 7759                    []three
 7760                     four"},
 7761                cx,
 7762            );
 7763        });
 7764    }
 7765
 7766    #[gpui::test]
 7767    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7768        cx.set_global(
 7769            Settings::test(cx)
 7770                .with_overrides(
 7771                    "TOML",
 7772                    LanguageOverride {
 7773                        tab_size: Some(2),
 7774                        ..Default::default()
 7775                    },
 7776                )
 7777                .with_overrides(
 7778                    "Rust",
 7779                    LanguageOverride {
 7780                        tab_size: Some(4),
 7781                        ..Default::default()
 7782                    },
 7783                ),
 7784        );
 7785        let toml_language = Arc::new(Language::new(
 7786            LanguageConfig {
 7787                name: "TOML".into(),
 7788                ..Default::default()
 7789            },
 7790            None,
 7791        ));
 7792        let rust_language = Arc::new(Language::new(
 7793            LanguageConfig {
 7794                name: "Rust".into(),
 7795                ..Default::default()
 7796            },
 7797            None,
 7798        ));
 7799
 7800        let toml_buffer = cx
 7801            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7802        let rust_buffer = cx.add_model(|cx| {
 7803            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7804        });
 7805        let multibuffer = cx.add_model(|cx| {
 7806            let mut multibuffer = MultiBuffer::new(0);
 7807            multibuffer.push_excerpts(
 7808                toml_buffer.clone(),
 7809                [Point::new(0, 0)..Point::new(2, 0)],
 7810                cx,
 7811            );
 7812            multibuffer.push_excerpts(
 7813                rust_buffer.clone(),
 7814                [Point::new(0, 0)..Point::new(1, 0)],
 7815                cx,
 7816            );
 7817            multibuffer
 7818        });
 7819
 7820        cx.add_window(Default::default(), |cx| {
 7821            let mut editor = build_editor(multibuffer, cx);
 7822
 7823            assert_eq!(
 7824                editor.text(cx),
 7825                indoc! {"
 7826                    a = 1
 7827                    b = 2
 7828
 7829                    const c: usize = 3;
 7830                "}
 7831            );
 7832
 7833            select_ranges(
 7834                &mut editor,
 7835                indoc! {"
 7836                    [a] = 1
 7837                    b = 2
 7838
 7839                    [const c:] usize = 3;
 7840                "},
 7841                cx,
 7842            );
 7843
 7844            editor.tab(&Tab(Direction::Next), cx);
 7845            assert_text_with_selections(
 7846                &mut editor,
 7847                indoc! {"
 7848                      [a] = 1
 7849                    b = 2
 7850
 7851                        [const c:] usize = 3;
 7852                "},
 7853                cx,
 7854            );
 7855            editor.tab(&Tab(Direction::Prev), cx);
 7856            assert_text_with_selections(
 7857                &mut editor,
 7858                indoc! {"
 7859                    [a] = 1
 7860                    b = 2
 7861
 7862                    [const c:] usize = 3;
 7863                "},
 7864                cx,
 7865            );
 7866
 7867            editor
 7868        });
 7869    }
 7870
 7871    #[gpui::test]
 7872    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 7873        cx.set_global(Settings::test(cx));
 7874        let (_, view) = cx.add_window(Default::default(), |cx| {
 7875            build_editor(MultiBuffer::build_simple("", cx), cx)
 7876        });
 7877
 7878        view.update(cx, |view, cx| {
 7879            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7880            view.select_display_ranges(
 7881                &[
 7882                    // an empty selection - the preceding character is deleted
 7883                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7884                    // one character selected - it is deleted
 7885                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7886                    // a line suffix selected - it is deleted
 7887                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7888                ],
 7889                cx,
 7890            );
 7891            view.backspace(&Backspace, cx);
 7892            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 7893
 7894            view.set_text("    one\n        two\n        three\n   four", cx);
 7895            view.select_display_ranges(
 7896                &[
 7897                    // cursors at the the end of leading indent - last indent is deleted
 7898                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 7899                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 7900                    // cursors inside leading indent - overlapping indent deletions are coalesced
 7901                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7902                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 7903                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 7904                    // cursor at the beginning of a line - preceding newline is deleted
 7905                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7906                    // selection inside leading indent - only the selected character is deleted
 7907                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 7908                ],
 7909                cx,
 7910            );
 7911            view.backspace(&Backspace, cx);
 7912            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 7913        });
 7914    }
 7915
 7916    #[gpui::test]
 7917    fn test_delete(cx: &mut gpui::MutableAppContext) {
 7918        cx.set_global(Settings::test(cx));
 7919        let buffer =
 7920            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 7921        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7922
 7923        view.update(cx, |view, cx| {
 7924            view.select_display_ranges(
 7925                &[
 7926                    // an empty selection - the following character is deleted
 7927                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7928                    // one character selected - it is deleted
 7929                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 7930                    // a line suffix selected - it is deleted
 7931                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 7932                ],
 7933                cx,
 7934            );
 7935            view.delete(&Delete, cx);
 7936        });
 7937
 7938        assert_eq!(
 7939            buffer.read(cx).read(cx).text(),
 7940            "on two three\nfou five six\nseven ten\n"
 7941        );
 7942    }
 7943
 7944    #[gpui::test]
 7945    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7946        cx.set_global(Settings::test(cx));
 7947        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7948        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7949        view.update(cx, |view, cx| {
 7950            view.select_display_ranges(
 7951                &[
 7952                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7953                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7954                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7955                ],
 7956                cx,
 7957            );
 7958            view.delete_line(&DeleteLine, cx);
 7959            assert_eq!(view.display_text(cx), "ghi");
 7960            assert_eq!(
 7961                view.selected_display_ranges(cx),
 7962                vec![
 7963                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7964                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7965                ]
 7966            );
 7967        });
 7968
 7969        cx.set_global(Settings::test(cx));
 7970        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7971        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7972        view.update(cx, |view, cx| {
 7973            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 7974            view.delete_line(&DeleteLine, cx);
 7975            assert_eq!(view.display_text(cx), "ghi\n");
 7976            assert_eq!(
 7977                view.selected_display_ranges(cx),
 7978                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7979            );
 7980        });
 7981    }
 7982
 7983    #[gpui::test]
 7984    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7985        cx.set_global(Settings::test(cx));
 7986        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7987        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7988        view.update(cx, |view, cx| {
 7989            view.select_display_ranges(
 7990                &[
 7991                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7992                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7993                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7994                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7995                ],
 7996                cx,
 7997            );
 7998            view.duplicate_line(&DuplicateLine, cx);
 7999            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8000            assert_eq!(
 8001                view.selected_display_ranges(cx),
 8002                vec![
 8003                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8004                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8005                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8006                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8007                ]
 8008            );
 8009        });
 8010
 8011        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8012        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8013        view.update(cx, |view, cx| {
 8014            view.select_display_ranges(
 8015                &[
 8016                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8017                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8018                ],
 8019                cx,
 8020            );
 8021            view.duplicate_line(&DuplicateLine, cx);
 8022            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8023            assert_eq!(
 8024                view.selected_display_ranges(cx),
 8025                vec![
 8026                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8027                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8028                ]
 8029            );
 8030        });
 8031    }
 8032
 8033    #[gpui::test]
 8034    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8035        cx.set_global(Settings::test(cx));
 8036        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8037        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8038        view.update(cx, |view, cx| {
 8039            view.fold_ranges(
 8040                vec![
 8041                    Point::new(0, 2)..Point::new(1, 2),
 8042                    Point::new(2, 3)..Point::new(4, 1),
 8043                    Point::new(7, 0)..Point::new(8, 4),
 8044                ],
 8045                cx,
 8046            );
 8047            view.select_display_ranges(
 8048                &[
 8049                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8050                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8051                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8052                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8053                ],
 8054                cx,
 8055            );
 8056            assert_eq!(
 8057                view.display_text(cx),
 8058                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8059            );
 8060
 8061            view.move_line_up(&MoveLineUp, cx);
 8062            assert_eq!(
 8063                view.display_text(cx),
 8064                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8065            );
 8066            assert_eq!(
 8067                view.selected_display_ranges(cx),
 8068                vec![
 8069                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8070                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8071                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8072                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8073                ]
 8074            );
 8075        });
 8076
 8077        view.update(cx, |view, cx| {
 8078            view.move_line_down(&MoveLineDown, cx);
 8079            assert_eq!(
 8080                view.display_text(cx),
 8081                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8082            );
 8083            assert_eq!(
 8084                view.selected_display_ranges(cx),
 8085                vec![
 8086                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8087                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8088                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8089                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8090                ]
 8091            );
 8092        });
 8093
 8094        view.update(cx, |view, cx| {
 8095            view.move_line_down(&MoveLineDown, cx);
 8096            assert_eq!(
 8097                view.display_text(cx),
 8098                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8099            );
 8100            assert_eq!(
 8101                view.selected_display_ranges(cx),
 8102                vec![
 8103                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8104                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8105                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8106                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8107                ]
 8108            );
 8109        });
 8110
 8111        view.update(cx, |view, cx| {
 8112            view.move_line_up(&MoveLineUp, cx);
 8113            assert_eq!(
 8114                view.display_text(cx),
 8115                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8116            );
 8117            assert_eq!(
 8118                view.selected_display_ranges(cx),
 8119                vec![
 8120                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8121                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8122                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8123                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8124                ]
 8125            );
 8126        });
 8127    }
 8128
 8129    #[gpui::test]
 8130    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8131        cx.set_global(Settings::test(cx));
 8132        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8133        let snapshot = buffer.read(cx).snapshot(cx);
 8134        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8135        editor.update(cx, |editor, cx| {
 8136            editor.insert_blocks(
 8137                [BlockProperties {
 8138                    position: snapshot.anchor_after(Point::new(2, 0)),
 8139                    disposition: BlockDisposition::Below,
 8140                    height: 1,
 8141                    render: Arc::new(|_| Empty::new().boxed()),
 8142                }],
 8143                cx,
 8144            );
 8145            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8146            editor.move_line_down(&MoveLineDown, cx);
 8147        });
 8148    }
 8149
 8150    #[gpui::test]
 8151    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8152        cx.set_global(Settings::test(cx));
 8153        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8154        let view = cx
 8155            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8156            .1;
 8157
 8158        // Cut with three selections. Clipboard text is divided into three slices.
 8159        view.update(cx, |view, cx| {
 8160            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8161            view.cut(&Cut, cx);
 8162            assert_eq!(view.display_text(cx), "two four six ");
 8163        });
 8164
 8165        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8166        view.update(cx, |view, cx| {
 8167            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8168            view.paste(&Paste, cx);
 8169            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8170            assert_eq!(
 8171                view.selected_display_ranges(cx),
 8172                &[
 8173                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8174                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8175                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8176                ]
 8177            );
 8178        });
 8179
 8180        // Paste again but with only two cursors. Since the number of cursors doesn't
 8181        // match the number of slices in the clipboard, the entire clipboard text
 8182        // is pasted at each cursor.
 8183        view.update(cx, |view, cx| {
 8184            view.select_ranges(vec![0..0, 31..31], None, cx);
 8185            view.handle_input(&Input("( ".into()), cx);
 8186            view.paste(&Paste, cx);
 8187            view.handle_input(&Input(") ".into()), cx);
 8188            assert_eq!(
 8189                view.display_text(cx),
 8190                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8191            );
 8192        });
 8193
 8194        view.update(cx, |view, cx| {
 8195            view.select_ranges(vec![0..0], None, cx);
 8196            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8197            assert_eq!(
 8198                view.display_text(cx),
 8199                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8200            );
 8201        });
 8202
 8203        // Cut with three selections, one of which is full-line.
 8204        view.update(cx, |view, cx| {
 8205            view.select_display_ranges(
 8206                &[
 8207                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8208                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8209                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8210                ],
 8211                cx,
 8212            );
 8213            view.cut(&Cut, cx);
 8214            assert_eq!(
 8215                view.display_text(cx),
 8216                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8217            );
 8218        });
 8219
 8220        // Paste with three selections, noticing how the copied selection that was full-line
 8221        // gets inserted before the second cursor.
 8222        view.update(cx, |view, cx| {
 8223            view.select_display_ranges(
 8224                &[
 8225                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8226                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8227                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8228                ],
 8229                cx,
 8230            );
 8231            view.paste(&Paste, cx);
 8232            assert_eq!(
 8233                view.display_text(cx),
 8234                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8235            );
 8236            assert_eq!(
 8237                view.selected_display_ranges(cx),
 8238                &[
 8239                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8240                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8241                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8242                ]
 8243            );
 8244        });
 8245
 8246        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8247        view.update(cx, |view, cx| {
 8248            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8249            view.copy(&Copy, cx);
 8250        });
 8251
 8252        // Paste with three selections, noticing how the copied full-line selection is inserted
 8253        // before the empty selections but replaces the selection that is non-empty.
 8254        view.update(cx, |view, cx| {
 8255            view.select_display_ranges(
 8256                &[
 8257                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8258                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8259                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8260                ],
 8261                cx,
 8262            );
 8263            view.paste(&Paste, cx);
 8264            assert_eq!(
 8265                view.display_text(cx),
 8266                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
 8267            );
 8268            assert_eq!(
 8269                view.selected_display_ranges(cx),
 8270                &[
 8271                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8272                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8273                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8274                ]
 8275            );
 8276        });
 8277    }
 8278
 8279    #[gpui::test]
 8280    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8281        cx.set_global(Settings::test(cx));
 8282        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8283        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8284        view.update(cx, |view, cx| {
 8285            view.select_all(&SelectAll, cx);
 8286            assert_eq!(
 8287                view.selected_display_ranges(cx),
 8288                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8289            );
 8290        });
 8291    }
 8292
 8293    #[gpui::test]
 8294    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8295        cx.set_global(Settings::test(cx));
 8296        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8297        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8298        view.update(cx, |view, cx| {
 8299            view.select_display_ranges(
 8300                &[
 8301                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8302                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8303                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8304                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8305                ],
 8306                cx,
 8307            );
 8308            view.select_line(&SelectLine, cx);
 8309            assert_eq!(
 8310                view.selected_display_ranges(cx),
 8311                vec![
 8312                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8313                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8314                ]
 8315            );
 8316        });
 8317
 8318        view.update(cx, |view, cx| {
 8319            view.select_line(&SelectLine, cx);
 8320            assert_eq!(
 8321                view.selected_display_ranges(cx),
 8322                vec![
 8323                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8324                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8325                ]
 8326            );
 8327        });
 8328
 8329        view.update(cx, |view, cx| {
 8330            view.select_line(&SelectLine, cx);
 8331            assert_eq!(
 8332                view.selected_display_ranges(cx),
 8333                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8334            );
 8335        });
 8336    }
 8337
 8338    #[gpui::test]
 8339    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8340        cx.set_global(Settings::test(cx));
 8341        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8342        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8343        view.update(cx, |view, cx| {
 8344            view.fold_ranges(
 8345                vec![
 8346                    Point::new(0, 2)..Point::new(1, 2),
 8347                    Point::new(2, 3)..Point::new(4, 1),
 8348                    Point::new(7, 0)..Point::new(8, 4),
 8349                ],
 8350                cx,
 8351            );
 8352            view.select_display_ranges(
 8353                &[
 8354                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8355                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8356                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8357                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8358                ],
 8359                cx,
 8360            );
 8361            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8362        });
 8363
 8364        view.update(cx, |view, cx| {
 8365            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8366            assert_eq!(
 8367                view.display_text(cx),
 8368                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8369            );
 8370            assert_eq!(
 8371                view.selected_display_ranges(cx),
 8372                [
 8373                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8374                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8375                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8376                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8377                ]
 8378            );
 8379        });
 8380
 8381        view.update(cx, |view, cx| {
 8382            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8383            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8384            assert_eq!(
 8385                view.display_text(cx),
 8386                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8387            );
 8388            assert_eq!(
 8389                view.selected_display_ranges(cx),
 8390                [
 8391                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8392                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8393                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8394                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8395                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8396                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8397                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8398                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8399                ]
 8400            );
 8401        });
 8402    }
 8403
 8404    #[gpui::test]
 8405    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8406        cx.set_global(Settings::test(cx));
 8407        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8408        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8409
 8410        view.update(cx, |view, cx| {
 8411            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8412        });
 8413        view.update(cx, |view, cx| {
 8414            view.add_selection_above(&AddSelectionAbove, cx);
 8415            assert_eq!(
 8416                view.selected_display_ranges(cx),
 8417                vec![
 8418                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8419                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8420                ]
 8421            );
 8422        });
 8423
 8424        view.update(cx, |view, cx| {
 8425            view.add_selection_above(&AddSelectionAbove, cx);
 8426            assert_eq!(
 8427                view.selected_display_ranges(cx),
 8428                vec![
 8429                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8430                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8431                ]
 8432            );
 8433        });
 8434
 8435        view.update(cx, |view, cx| {
 8436            view.add_selection_below(&AddSelectionBelow, cx);
 8437            assert_eq!(
 8438                view.selected_display_ranges(cx),
 8439                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8440            );
 8441
 8442            view.undo_selection(&UndoSelection, cx);
 8443            assert_eq!(
 8444                view.selected_display_ranges(cx),
 8445                vec![
 8446                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8447                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8448                ]
 8449            );
 8450
 8451            view.redo_selection(&RedoSelection, cx);
 8452            assert_eq!(
 8453                view.selected_display_ranges(cx),
 8454                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8455            );
 8456        });
 8457
 8458        view.update(cx, |view, cx| {
 8459            view.add_selection_below(&AddSelectionBelow, cx);
 8460            assert_eq!(
 8461                view.selected_display_ranges(cx),
 8462                vec![
 8463                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8464                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8465                ]
 8466            );
 8467        });
 8468
 8469        view.update(cx, |view, cx| {
 8470            view.add_selection_below(&AddSelectionBelow, cx);
 8471            assert_eq!(
 8472                view.selected_display_ranges(cx),
 8473                vec![
 8474                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8475                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8476                ]
 8477            );
 8478        });
 8479
 8480        view.update(cx, |view, cx| {
 8481            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8482        });
 8483        view.update(cx, |view, cx| {
 8484            view.add_selection_below(&AddSelectionBelow, cx);
 8485            assert_eq!(
 8486                view.selected_display_ranges(cx),
 8487                vec![
 8488                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8489                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8490                ]
 8491            );
 8492        });
 8493
 8494        view.update(cx, |view, cx| {
 8495            view.add_selection_below(&AddSelectionBelow, cx);
 8496            assert_eq!(
 8497                view.selected_display_ranges(cx),
 8498                vec![
 8499                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8500                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8501                ]
 8502            );
 8503        });
 8504
 8505        view.update(cx, |view, cx| {
 8506            view.add_selection_above(&AddSelectionAbove, cx);
 8507            assert_eq!(
 8508                view.selected_display_ranges(cx),
 8509                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8510            );
 8511        });
 8512
 8513        view.update(cx, |view, cx| {
 8514            view.add_selection_above(&AddSelectionAbove, cx);
 8515            assert_eq!(
 8516                view.selected_display_ranges(cx),
 8517                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8518            );
 8519        });
 8520
 8521        view.update(cx, |view, cx| {
 8522            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8523            view.add_selection_below(&AddSelectionBelow, cx);
 8524            assert_eq!(
 8525                view.selected_display_ranges(cx),
 8526                vec![
 8527                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8528                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8529                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8530                ]
 8531            );
 8532        });
 8533
 8534        view.update(cx, |view, cx| {
 8535            view.add_selection_below(&AddSelectionBelow, cx);
 8536            assert_eq!(
 8537                view.selected_display_ranges(cx),
 8538                vec![
 8539                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8540                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8541                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8542                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8543                ]
 8544            );
 8545        });
 8546
 8547        view.update(cx, |view, cx| {
 8548            view.add_selection_above(&AddSelectionAbove, cx);
 8549            assert_eq!(
 8550                view.selected_display_ranges(cx),
 8551                vec![
 8552                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8553                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8554                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8555                ]
 8556            );
 8557        });
 8558
 8559        view.update(cx, |view, cx| {
 8560            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8561        });
 8562        view.update(cx, |view, cx| {
 8563            view.add_selection_above(&AddSelectionAbove, cx);
 8564            assert_eq!(
 8565                view.selected_display_ranges(cx),
 8566                vec![
 8567                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8568                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8569                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8570                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8571                ]
 8572            );
 8573        });
 8574
 8575        view.update(cx, |view, cx| {
 8576            view.add_selection_below(&AddSelectionBelow, cx);
 8577            assert_eq!(
 8578                view.selected_display_ranges(cx),
 8579                vec![
 8580                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8581                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8582                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8583                ]
 8584            );
 8585        });
 8586    }
 8587
 8588    #[gpui::test]
 8589    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8590        cx.set_global(Settings::test(cx));
 8591
 8592        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8593        let buffer = MultiBuffer::build_simple(&text, cx);
 8594        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8595
 8596        view.update(cx, |view, cx| {
 8597            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8598            view.select_next(&SelectNext(false), cx);
 8599            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8600
 8601            view.select_next(&SelectNext(false), cx);
 8602            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8603
 8604            view.undo_selection(&UndoSelection, cx);
 8605            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8606
 8607            view.redo_selection(&RedoSelection, cx);
 8608            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8609
 8610            view.select_next(&SelectNext(false), cx);
 8611            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8612
 8613            view.select_next(&SelectNext(false), cx);
 8614            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8615        });
 8616    }
 8617
 8618    #[gpui::test]
 8619    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8620        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8621        let language = Arc::new(Language::new(
 8622            LanguageConfig::default(),
 8623            Some(tree_sitter_rust::language()),
 8624        ));
 8625
 8626        let text = r#"
 8627            use mod1::mod2::{mod3, mod4};
 8628
 8629            fn fn_1(param1: bool, param2: &str) {
 8630                let var1 = "text";
 8631            }
 8632        "#
 8633        .unindent();
 8634
 8635        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8636        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8637        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8638        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8639            .await;
 8640
 8641        view.update(cx, |view, cx| {
 8642            view.select_display_ranges(
 8643                &[
 8644                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8645                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8646                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8647                ],
 8648                cx,
 8649            );
 8650            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8651        });
 8652        assert_eq!(
 8653            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8654            &[
 8655                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8656                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8657                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8658            ]
 8659        );
 8660
 8661        view.update(cx, |view, cx| {
 8662            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8663        });
 8664        assert_eq!(
 8665            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8666            &[
 8667                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8668                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8669            ]
 8670        );
 8671
 8672        view.update(cx, |view, cx| {
 8673            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8674        });
 8675        assert_eq!(
 8676            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8677            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8678        );
 8679
 8680        // Trying to expand the selected syntax node one more time has no effect.
 8681        view.update(cx, |view, cx| {
 8682            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8683        });
 8684        assert_eq!(
 8685            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8686            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8687        );
 8688
 8689        view.update(cx, |view, cx| {
 8690            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8691        });
 8692        assert_eq!(
 8693            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8694            &[
 8695                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8696                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8697            ]
 8698        );
 8699
 8700        view.update(cx, |view, cx| {
 8701            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8702        });
 8703        assert_eq!(
 8704            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8705            &[
 8706                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8707                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8708                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8709            ]
 8710        );
 8711
 8712        view.update(cx, |view, cx| {
 8713            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8714        });
 8715        assert_eq!(
 8716            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8717            &[
 8718                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8719                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8720                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8721            ]
 8722        );
 8723
 8724        // Trying to shrink the selected syntax node one more time has no effect.
 8725        view.update(cx, |view, cx| {
 8726            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8727        });
 8728        assert_eq!(
 8729            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8730            &[
 8731                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8732                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8733                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8734            ]
 8735        );
 8736
 8737        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8738        // a fold.
 8739        view.update(cx, |view, cx| {
 8740            view.fold_ranges(
 8741                vec![
 8742                    Point::new(0, 21)..Point::new(0, 24),
 8743                    Point::new(3, 20)..Point::new(3, 22),
 8744                ],
 8745                cx,
 8746            );
 8747            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8748        });
 8749        assert_eq!(
 8750            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8751            &[
 8752                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8753                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8754                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8755            ]
 8756        );
 8757    }
 8758
 8759    #[gpui::test]
 8760    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8761        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8762        let language = Arc::new(
 8763            Language::new(
 8764                LanguageConfig {
 8765                    brackets: vec![
 8766                        BracketPair {
 8767                            start: "{".to_string(),
 8768                            end: "}".to_string(),
 8769                            close: false,
 8770                            newline: true,
 8771                        },
 8772                        BracketPair {
 8773                            start: "(".to_string(),
 8774                            end: ")".to_string(),
 8775                            close: false,
 8776                            newline: true,
 8777                        },
 8778                    ],
 8779                    ..Default::default()
 8780                },
 8781                Some(tree_sitter_rust::language()),
 8782            )
 8783            .with_indents_query(
 8784                r#"
 8785                (_ "(" ")" @end) @indent
 8786                (_ "{" "}" @end) @indent
 8787                "#,
 8788            )
 8789            .unwrap(),
 8790        );
 8791
 8792        let text = "fn a() {}";
 8793
 8794        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8795        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8796        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8797        editor
 8798            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8799            .await;
 8800
 8801        editor.update(cx, |editor, cx| {
 8802            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 8803            editor.newline(&Newline, cx);
 8804            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8805            assert_eq!(
 8806                editor.selected_ranges(cx),
 8807                &[
 8808                    Point::new(1, 4)..Point::new(1, 4),
 8809                    Point::new(3, 4)..Point::new(3, 4),
 8810                    Point::new(5, 0)..Point::new(5, 0)
 8811                ]
 8812            );
 8813        });
 8814    }
 8815
 8816    #[gpui::test]
 8817    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8818        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8819        let language = Arc::new(Language::new(
 8820            LanguageConfig {
 8821                brackets: vec![
 8822                    BracketPair {
 8823                        start: "{".to_string(),
 8824                        end: "}".to_string(),
 8825                        close: true,
 8826                        newline: true,
 8827                    },
 8828                    BracketPair {
 8829                        start: "/*".to_string(),
 8830                        end: " */".to_string(),
 8831                        close: true,
 8832                        newline: true,
 8833                    },
 8834                ],
 8835                autoclose_before: "})]".to_string(),
 8836                ..Default::default()
 8837            },
 8838            Some(tree_sitter_rust::language()),
 8839        ));
 8840
 8841        let text = r#"
 8842            a
 8843
 8844            /
 8845
 8846        "#
 8847        .unindent();
 8848
 8849        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8850        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8851        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8852        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8853            .await;
 8854
 8855        view.update(cx, |view, cx| {
 8856            view.select_display_ranges(
 8857                &[
 8858                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8859                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8860                ],
 8861                cx,
 8862            );
 8863
 8864            view.handle_input(&Input("{".to_string()), cx);
 8865            view.handle_input(&Input("{".to_string()), cx);
 8866            view.handle_input(&Input("{".to_string()), cx);
 8867            assert_eq!(
 8868                view.text(cx),
 8869                "
 8870                {{{}}}
 8871                {{{}}}
 8872                /
 8873
 8874                "
 8875                .unindent()
 8876            );
 8877
 8878            view.move_right(&MoveRight, cx);
 8879            view.handle_input(&Input("}".to_string()), cx);
 8880            view.handle_input(&Input("}".to_string()), cx);
 8881            view.handle_input(&Input("}".to_string()), cx);
 8882            assert_eq!(
 8883                view.text(cx),
 8884                "
 8885                {{{}}}}
 8886                {{{}}}}
 8887                /
 8888
 8889                "
 8890                .unindent()
 8891            );
 8892
 8893            view.undo(&Undo, cx);
 8894            view.handle_input(&Input("/".to_string()), cx);
 8895            view.handle_input(&Input("*".to_string()), cx);
 8896            assert_eq!(
 8897                view.text(cx),
 8898                "
 8899                /* */
 8900                /* */
 8901                /
 8902
 8903                "
 8904                .unindent()
 8905            );
 8906
 8907            view.undo(&Undo, cx);
 8908            view.select_display_ranges(
 8909                &[
 8910                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8911                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8912                ],
 8913                cx,
 8914            );
 8915            view.handle_input(&Input("*".to_string()), cx);
 8916            assert_eq!(
 8917                view.text(cx),
 8918                "
 8919                a
 8920
 8921                /*
 8922                *
 8923                "
 8924                .unindent()
 8925            );
 8926
 8927            // Don't autoclose if the next character isn't whitespace and isn't
 8928            // listed in the language's "autoclose_before" section.
 8929            view.finalize_last_transaction(cx);
 8930            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 8931            view.handle_input(&Input("{".to_string()), cx);
 8932            assert_eq!(
 8933                view.text(cx),
 8934                "
 8935                {a
 8936
 8937                /*
 8938                *
 8939                "
 8940                .unindent()
 8941            );
 8942
 8943            view.undo(&Undo, cx);
 8944            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 8945            view.handle_input(&Input("{".to_string()), cx);
 8946            assert_eq!(
 8947                view.text(cx),
 8948                "
 8949                {a}
 8950
 8951                /*
 8952                *
 8953                "
 8954                .unindent()
 8955            );
 8956            assert_eq!(
 8957                view.selected_display_ranges(cx),
 8958                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8959            );
 8960        });
 8961    }
 8962
 8963    #[gpui::test]
 8964    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 8965        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8966
 8967        let text = "
 8968            a. b
 8969            a. b
 8970            a. b
 8971        "
 8972        .unindent();
 8973        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 8974        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8975
 8976        editor.update(cx, |editor, cx| {
 8977            let buffer = &editor.snapshot(cx).buffer_snapshot;
 8978            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 8979            let insertion_ranges = [
 8980                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 8981                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 8982                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 8983            ];
 8984
 8985            editor
 8986                .insert_snippet(&insertion_ranges, snippet, cx)
 8987                .unwrap();
 8988            assert_eq!(
 8989                editor.text(cx),
 8990                "
 8991                    a.f(one, two, three) b
 8992                    a.f(one, two, three) b
 8993                    a.f(one, two, three) b
 8994                "
 8995                .unindent()
 8996            );
 8997            assert_eq!(
 8998                editor.selected_ranges::<Point>(cx),
 8999                &[
 9000                    Point::new(0, 4)..Point::new(0, 7),
 9001                    Point::new(0, 14)..Point::new(0, 19),
 9002                    Point::new(1, 4)..Point::new(1, 7),
 9003                    Point::new(1, 14)..Point::new(1, 19),
 9004                    Point::new(2, 4)..Point::new(2, 7),
 9005                    Point::new(2, 14)..Point::new(2, 19),
 9006                ]
 9007            );
 9008
 9009            // Can't move earlier than the first tab stop
 9010            editor.move_to_prev_snippet_tabstop(cx);
 9011            assert_eq!(
 9012                editor.selected_ranges::<Point>(cx),
 9013                &[
 9014                    Point::new(0, 4)..Point::new(0, 7),
 9015                    Point::new(0, 14)..Point::new(0, 19),
 9016                    Point::new(1, 4)..Point::new(1, 7),
 9017                    Point::new(1, 14)..Point::new(1, 19),
 9018                    Point::new(2, 4)..Point::new(2, 7),
 9019                    Point::new(2, 14)..Point::new(2, 19),
 9020                ]
 9021            );
 9022
 9023            assert!(editor.move_to_next_snippet_tabstop(cx));
 9024            assert_eq!(
 9025                editor.selected_ranges::<Point>(cx),
 9026                &[
 9027                    Point::new(0, 9)..Point::new(0, 12),
 9028                    Point::new(1, 9)..Point::new(1, 12),
 9029                    Point::new(2, 9)..Point::new(2, 12)
 9030                ]
 9031            );
 9032
 9033            editor.move_to_prev_snippet_tabstop(cx);
 9034            assert_eq!(
 9035                editor.selected_ranges::<Point>(cx),
 9036                &[
 9037                    Point::new(0, 4)..Point::new(0, 7),
 9038                    Point::new(0, 14)..Point::new(0, 19),
 9039                    Point::new(1, 4)..Point::new(1, 7),
 9040                    Point::new(1, 14)..Point::new(1, 19),
 9041                    Point::new(2, 4)..Point::new(2, 7),
 9042                    Point::new(2, 14)..Point::new(2, 19),
 9043                ]
 9044            );
 9045
 9046            assert!(editor.move_to_next_snippet_tabstop(cx));
 9047            assert!(editor.move_to_next_snippet_tabstop(cx));
 9048            assert_eq!(
 9049                editor.selected_ranges::<Point>(cx),
 9050                &[
 9051                    Point::new(0, 20)..Point::new(0, 20),
 9052                    Point::new(1, 20)..Point::new(1, 20),
 9053                    Point::new(2, 20)..Point::new(2, 20)
 9054                ]
 9055            );
 9056
 9057            // As soon as the last tab stop is reached, snippet state is gone
 9058            editor.move_to_prev_snippet_tabstop(cx);
 9059            assert_eq!(
 9060                editor.selected_ranges::<Point>(cx),
 9061                &[
 9062                    Point::new(0, 20)..Point::new(0, 20),
 9063                    Point::new(1, 20)..Point::new(1, 20),
 9064                    Point::new(2, 20)..Point::new(2, 20)
 9065                ]
 9066            );
 9067        });
 9068    }
 9069
 9070    #[gpui::test]
 9071    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9072        cx.foreground().forbid_parking();
 9073        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9074
 9075        let mut language = Language::new(
 9076            LanguageConfig {
 9077                name: "Rust".into(),
 9078                path_suffixes: vec!["rs".to_string()],
 9079                ..Default::default()
 9080            },
 9081            Some(tree_sitter_rust::language()),
 9082        );
 9083        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9084            capabilities: lsp::ServerCapabilities {
 9085                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9086                ..Default::default()
 9087            },
 9088            ..Default::default()
 9089        });
 9090
 9091        let fs = FakeFs::new(cx.background().clone());
 9092        fs.insert_file("/file.rs", Default::default()).await;
 9093
 9094        let project = Project::test(fs, cx);
 9095        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9096
 9097        let worktree_id = project
 9098            .update(cx, |project, cx| {
 9099                project.find_or_create_local_worktree("/file.rs", true, cx)
 9100            })
 9101            .await
 9102            .unwrap()
 9103            .0
 9104            .read_with(cx, |tree, _| tree.id());
 9105        let buffer = project
 9106            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9107            .await
 9108            .unwrap();
 9109
 9110        cx.foreground().start_waiting();
 9111        let fake_server = fake_servers.next().await.unwrap();
 9112
 9113        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9114        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9115        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9116        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9117
 9118        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9119        fake_server
 9120            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9121                assert_eq!(
 9122                    params.text_document.uri,
 9123                    lsp::Url::from_file_path("/file.rs").unwrap()
 9124                );
 9125                assert_eq!(params.options.tab_size, 4);
 9126                Ok(Some(vec![lsp::TextEdit::new(
 9127                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9128                    ", ".to_string(),
 9129                )]))
 9130            })
 9131            .next()
 9132            .await;
 9133        cx.foreground().start_waiting();
 9134        save.await.unwrap();
 9135        assert_eq!(
 9136            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9137            "one, two\nthree\n"
 9138        );
 9139        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9140
 9141        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9142        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9143
 9144        // Ensure we can still save even if formatting hangs.
 9145        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9146            assert_eq!(
 9147                params.text_document.uri,
 9148                lsp::Url::from_file_path("/file.rs").unwrap()
 9149            );
 9150            futures::future::pending::<()>().await;
 9151            unreachable!()
 9152        });
 9153        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9154        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9155        cx.foreground().start_waiting();
 9156        save.await.unwrap();
 9157        assert_eq!(
 9158            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9159            "one\ntwo\nthree\n"
 9160        );
 9161        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9162
 9163        // Set rust language override and assert overriden tabsize is sent to language server
 9164        cx.update(|cx| {
 9165            cx.update_global::<Settings, _, _>(|settings, _| {
 9166                settings.language_overrides.insert(
 9167                    "Rust".into(),
 9168                    LanguageOverride {
 9169                        tab_size: Some(8),
 9170                        ..Default::default()
 9171                    },
 9172                );
 9173            })
 9174        });
 9175
 9176        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9177        fake_server
 9178            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9179                assert_eq!(
 9180                    params.text_document.uri,
 9181                    lsp::Url::from_file_path("/file.rs").unwrap()
 9182                );
 9183                assert_eq!(params.options.tab_size, 8);
 9184                Ok(Some(vec![]))
 9185            })
 9186            .next()
 9187            .await;
 9188        cx.foreground().start_waiting();
 9189        save.await.unwrap();
 9190    }
 9191
 9192    #[gpui::test]
 9193    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9194        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9195
 9196        let mut language = Language::new(
 9197            LanguageConfig {
 9198                name: "Rust".into(),
 9199                path_suffixes: vec!["rs".to_string()],
 9200                ..Default::default()
 9201            },
 9202            Some(tree_sitter_rust::language()),
 9203        );
 9204        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9205            capabilities: lsp::ServerCapabilities {
 9206                completion_provider: Some(lsp::CompletionOptions {
 9207                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9208                    ..Default::default()
 9209                }),
 9210                ..Default::default()
 9211            },
 9212            ..Default::default()
 9213        });
 9214
 9215        let text = "
 9216            one
 9217            two
 9218            three
 9219        "
 9220        .unindent();
 9221
 9222        let fs = FakeFs::new(cx.background().clone());
 9223        fs.insert_file("/file.rs", text).await;
 9224
 9225        let project = Project::test(fs, cx);
 9226        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9227
 9228        let worktree_id = project
 9229            .update(cx, |project, cx| {
 9230                project.find_or_create_local_worktree("/file.rs", true, cx)
 9231            })
 9232            .await
 9233            .unwrap()
 9234            .0
 9235            .read_with(cx, |tree, _| tree.id());
 9236        let buffer = project
 9237            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9238            .await
 9239            .unwrap();
 9240        let mut fake_server = fake_servers.next().await.unwrap();
 9241
 9242        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9243        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9244
 9245        editor.update(cx, |editor, cx| {
 9246            editor.project = Some(project);
 9247            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9248            editor.handle_input(&Input(".".to_string()), cx);
 9249        });
 9250
 9251        handle_completion_request(
 9252            &mut fake_server,
 9253            "/file.rs",
 9254            Point::new(0, 4),
 9255            vec![
 9256                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9257                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9258            ],
 9259        )
 9260        .await;
 9261        editor
 9262            .condition(&cx, |editor, _| editor.context_menu_visible())
 9263            .await;
 9264
 9265        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9266            editor.move_down(&MoveDown, cx);
 9267            let apply_additional_edits = editor
 9268                .confirm_completion(&ConfirmCompletion(None), cx)
 9269                .unwrap();
 9270            assert_eq!(
 9271                editor.text(cx),
 9272                "
 9273                    one.second_completion
 9274                    two
 9275                    three
 9276                "
 9277                .unindent()
 9278            );
 9279            apply_additional_edits
 9280        });
 9281
 9282        handle_resolve_completion_request(
 9283            &mut fake_server,
 9284            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9285        )
 9286        .await;
 9287        apply_additional_edits.await.unwrap();
 9288        assert_eq!(
 9289            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9290            "
 9291                one.second_completion
 9292                two
 9293                three
 9294                additional edit
 9295            "
 9296            .unindent()
 9297        );
 9298
 9299        editor.update(cx, |editor, cx| {
 9300            editor.select_ranges(
 9301                [
 9302                    Point::new(1, 3)..Point::new(1, 3),
 9303                    Point::new(2, 5)..Point::new(2, 5),
 9304                ],
 9305                None,
 9306                cx,
 9307            );
 9308
 9309            editor.handle_input(&Input(" ".to_string()), cx);
 9310            assert!(editor.context_menu.is_none());
 9311            editor.handle_input(&Input("s".to_string()), cx);
 9312            assert!(editor.context_menu.is_none());
 9313        });
 9314
 9315        handle_completion_request(
 9316            &mut fake_server,
 9317            "/file.rs",
 9318            Point::new(2, 7),
 9319            vec![
 9320                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9321                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9322                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9323            ],
 9324        )
 9325        .await;
 9326        editor
 9327            .condition(&cx, |editor, _| editor.context_menu_visible())
 9328            .await;
 9329
 9330        editor.update(cx, |editor, cx| {
 9331            editor.handle_input(&Input("i".to_string()), cx);
 9332        });
 9333
 9334        handle_completion_request(
 9335            &mut fake_server,
 9336            "/file.rs",
 9337            Point::new(2, 8),
 9338            vec![
 9339                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9340                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9341                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9342            ],
 9343        )
 9344        .await;
 9345        editor
 9346            .condition(&cx, |editor, _| editor.context_menu_visible())
 9347            .await;
 9348
 9349        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9350            let apply_additional_edits = editor
 9351                .confirm_completion(&ConfirmCompletion(None), cx)
 9352                .unwrap();
 9353            assert_eq!(
 9354                editor.text(cx),
 9355                "
 9356                    one.second_completion
 9357                    two sixth_completion
 9358                    three sixth_completion
 9359                    additional edit
 9360                "
 9361                .unindent()
 9362            );
 9363            apply_additional_edits
 9364        });
 9365        handle_resolve_completion_request(&mut fake_server, None).await;
 9366        apply_additional_edits.await.unwrap();
 9367
 9368        async fn handle_completion_request(
 9369            fake: &mut FakeLanguageServer,
 9370            path: &'static str,
 9371            position: Point,
 9372            completions: Vec<(Range<Point>, &'static str)>,
 9373        ) {
 9374            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9375                let completions = completions.clone();
 9376                async move {
 9377                    assert_eq!(
 9378                        params.text_document_position.text_document.uri,
 9379                        lsp::Url::from_file_path(path).unwrap()
 9380                    );
 9381                    assert_eq!(
 9382                        params.text_document_position.position,
 9383                        lsp::Position::new(position.row, position.column)
 9384                    );
 9385                    Ok(Some(lsp::CompletionResponse::Array(
 9386                        completions
 9387                            .iter()
 9388                            .map(|(range, new_text)| lsp::CompletionItem {
 9389                                label: new_text.to_string(),
 9390                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9391                                    range: lsp::Range::new(
 9392                                        lsp::Position::new(range.start.row, range.start.column),
 9393                                        lsp::Position::new(range.start.row, range.start.column),
 9394                                    ),
 9395                                    new_text: new_text.to_string(),
 9396                                })),
 9397                                ..Default::default()
 9398                            })
 9399                            .collect(),
 9400                    )))
 9401                }
 9402            })
 9403            .next()
 9404            .await;
 9405        }
 9406
 9407        async fn handle_resolve_completion_request(
 9408            fake: &mut FakeLanguageServer,
 9409            edit: Option<(Range<Point>, &'static str)>,
 9410        ) {
 9411            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9412                let edit = edit.clone();
 9413                async move {
 9414                    Ok(lsp::CompletionItem {
 9415                        additional_text_edits: edit.map(|(range, new_text)| {
 9416                            vec![lsp::TextEdit::new(
 9417                                lsp::Range::new(
 9418                                    lsp::Position::new(range.start.row, range.start.column),
 9419                                    lsp::Position::new(range.end.row, range.end.column),
 9420                                ),
 9421                                new_text.to_string(),
 9422                            )]
 9423                        }),
 9424                        ..Default::default()
 9425                    })
 9426                }
 9427            })
 9428            .next()
 9429            .await;
 9430        }
 9431    }
 9432
 9433    #[gpui::test]
 9434    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9435        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9436        let language = Arc::new(Language::new(
 9437            LanguageConfig {
 9438                line_comment: Some("// ".to_string()),
 9439                ..Default::default()
 9440            },
 9441            Some(tree_sitter_rust::language()),
 9442        ));
 9443
 9444        let text = "
 9445            fn a() {
 9446                //b();
 9447                // c();
 9448                //  d();
 9449            }
 9450        "
 9451        .unindent();
 9452
 9453        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9454        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9455        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9456
 9457        view.update(cx, |editor, cx| {
 9458            // If multiple selections intersect a line, the line is only
 9459            // toggled once.
 9460            editor.select_display_ranges(
 9461                &[
 9462                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9463                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9464                ],
 9465                cx,
 9466            );
 9467            editor.toggle_comments(&ToggleComments, cx);
 9468            assert_eq!(
 9469                editor.text(cx),
 9470                "
 9471                    fn a() {
 9472                        b();
 9473                        c();
 9474                         d();
 9475                    }
 9476                "
 9477                .unindent()
 9478            );
 9479
 9480            // The comment prefix is inserted at the same column for every line
 9481            // in a selection.
 9482            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9483            editor.toggle_comments(&ToggleComments, cx);
 9484            assert_eq!(
 9485                editor.text(cx),
 9486                "
 9487                    fn a() {
 9488                        // b();
 9489                        // c();
 9490                        //  d();
 9491                    }
 9492                "
 9493                .unindent()
 9494            );
 9495
 9496            // If a selection ends at the beginning of a line, that line is not toggled.
 9497            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9498            editor.toggle_comments(&ToggleComments, cx);
 9499            assert_eq!(
 9500                editor.text(cx),
 9501                "
 9502                        fn a() {
 9503                            // b();
 9504                            c();
 9505                            //  d();
 9506                        }
 9507                    "
 9508                .unindent()
 9509            );
 9510        });
 9511    }
 9512
 9513    #[gpui::test]
 9514    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9515        cx.set_global(Settings::test(cx));
 9516        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9517        let multibuffer = cx.add_model(|cx| {
 9518            let mut multibuffer = MultiBuffer::new(0);
 9519            multibuffer.push_excerpts(
 9520                buffer.clone(),
 9521                [
 9522                    Point::new(0, 0)..Point::new(0, 4),
 9523                    Point::new(1, 0)..Point::new(1, 4),
 9524                ],
 9525                cx,
 9526            );
 9527            multibuffer
 9528        });
 9529
 9530        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9531
 9532        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9533        view.update(cx, |view, cx| {
 9534            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9535            view.select_ranges(
 9536                [
 9537                    Point::new(0, 0)..Point::new(0, 0),
 9538                    Point::new(1, 0)..Point::new(1, 0),
 9539                ],
 9540                None,
 9541                cx,
 9542            );
 9543
 9544            view.handle_input(&Input("X".to_string()), cx);
 9545            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9546            assert_eq!(
 9547                view.selected_ranges(cx),
 9548                [
 9549                    Point::new(0, 1)..Point::new(0, 1),
 9550                    Point::new(1, 1)..Point::new(1, 1),
 9551                ]
 9552            )
 9553        });
 9554    }
 9555
 9556    #[gpui::test]
 9557    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9558        cx.set_global(Settings::test(cx));
 9559        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9560        let multibuffer = cx.add_model(|cx| {
 9561            let mut multibuffer = MultiBuffer::new(0);
 9562            multibuffer.push_excerpts(
 9563                buffer,
 9564                [
 9565                    Point::new(0, 0)..Point::new(1, 4),
 9566                    Point::new(1, 0)..Point::new(2, 4),
 9567                ],
 9568                cx,
 9569            );
 9570            multibuffer
 9571        });
 9572
 9573        assert_eq!(
 9574            multibuffer.read(cx).read(cx).text(),
 9575            "aaaa\nbbbb\nbbbb\ncccc"
 9576        );
 9577
 9578        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9579        view.update(cx, |view, cx| {
 9580            view.select_ranges(
 9581                [
 9582                    Point::new(1, 1)..Point::new(1, 1),
 9583                    Point::new(2, 3)..Point::new(2, 3),
 9584                ],
 9585                None,
 9586                cx,
 9587            );
 9588
 9589            view.handle_input(&Input("X".to_string()), cx);
 9590            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9591            assert_eq!(
 9592                view.selected_ranges(cx),
 9593                [
 9594                    Point::new(1, 2)..Point::new(1, 2),
 9595                    Point::new(2, 5)..Point::new(2, 5),
 9596                ]
 9597            );
 9598
 9599            view.newline(&Newline, cx);
 9600            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9601            assert_eq!(
 9602                view.selected_ranges(cx),
 9603                [
 9604                    Point::new(2, 0)..Point::new(2, 0),
 9605                    Point::new(6, 0)..Point::new(6, 0),
 9606                ]
 9607            );
 9608        });
 9609    }
 9610
 9611    #[gpui::test]
 9612    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9613        cx.set_global(Settings::test(cx));
 9614        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9615        let mut excerpt1_id = None;
 9616        let multibuffer = cx.add_model(|cx| {
 9617            let mut multibuffer = MultiBuffer::new(0);
 9618            excerpt1_id = multibuffer
 9619                .push_excerpts(
 9620                    buffer.clone(),
 9621                    [
 9622                        Point::new(0, 0)..Point::new(1, 4),
 9623                        Point::new(1, 0)..Point::new(2, 4),
 9624                    ],
 9625                    cx,
 9626                )
 9627                .into_iter()
 9628                .next();
 9629            multibuffer
 9630        });
 9631        assert_eq!(
 9632            multibuffer.read(cx).read(cx).text(),
 9633            "aaaa\nbbbb\nbbbb\ncccc"
 9634        );
 9635        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9636            let mut editor = build_editor(multibuffer.clone(), cx);
 9637            let snapshot = editor.snapshot(cx);
 9638            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9639            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9640            assert_eq!(
 9641                editor.selected_ranges(cx),
 9642                [
 9643                    Point::new(1, 3)..Point::new(1, 3),
 9644                    Point::new(2, 1)..Point::new(2, 1),
 9645                ]
 9646            );
 9647            editor
 9648        });
 9649
 9650        // Refreshing selections is a no-op when excerpts haven't changed.
 9651        editor.update(cx, |editor, cx| {
 9652            editor.refresh_selections(cx);
 9653            assert_eq!(
 9654                editor.selected_ranges(cx),
 9655                [
 9656                    Point::new(1, 3)..Point::new(1, 3),
 9657                    Point::new(2, 1)..Point::new(2, 1),
 9658                ]
 9659            );
 9660        });
 9661
 9662        multibuffer.update(cx, |multibuffer, cx| {
 9663            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9664        });
 9665        editor.update(cx, |editor, cx| {
 9666            // Removing an excerpt causes the first selection to become degenerate.
 9667            assert_eq!(
 9668                editor.selected_ranges(cx),
 9669                [
 9670                    Point::new(0, 0)..Point::new(0, 0),
 9671                    Point::new(0, 1)..Point::new(0, 1)
 9672                ]
 9673            );
 9674
 9675            // Refreshing selections will relocate the first selection to the original buffer
 9676            // location.
 9677            editor.refresh_selections(cx);
 9678            assert_eq!(
 9679                editor.selected_ranges(cx),
 9680                [
 9681                    Point::new(0, 1)..Point::new(0, 1),
 9682                    Point::new(0, 3)..Point::new(0, 3)
 9683                ]
 9684            );
 9685            assert!(editor.pending_selection.is_some());
 9686        });
 9687    }
 9688
 9689    #[gpui::test]
 9690    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9691        cx.set_global(Settings::test(cx));
 9692        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9693        let mut excerpt1_id = None;
 9694        let multibuffer = cx.add_model(|cx| {
 9695            let mut multibuffer = MultiBuffer::new(0);
 9696            excerpt1_id = multibuffer
 9697                .push_excerpts(
 9698                    buffer.clone(),
 9699                    [
 9700                        Point::new(0, 0)..Point::new(1, 4),
 9701                        Point::new(1, 0)..Point::new(2, 4),
 9702                    ],
 9703                    cx,
 9704                )
 9705                .into_iter()
 9706                .next();
 9707            multibuffer
 9708        });
 9709        assert_eq!(
 9710            multibuffer.read(cx).read(cx).text(),
 9711            "aaaa\nbbbb\nbbbb\ncccc"
 9712        );
 9713        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9714            let mut editor = build_editor(multibuffer.clone(), cx);
 9715            let snapshot = editor.snapshot(cx);
 9716            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9717            assert_eq!(
 9718                editor.selected_ranges(cx),
 9719                [Point::new(1, 3)..Point::new(1, 3)]
 9720            );
 9721            editor
 9722        });
 9723
 9724        multibuffer.update(cx, |multibuffer, cx| {
 9725            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9726        });
 9727        editor.update(cx, |editor, cx| {
 9728            assert_eq!(
 9729                editor.selected_ranges(cx),
 9730                [Point::new(0, 0)..Point::new(0, 0)]
 9731            );
 9732
 9733            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9734            editor.refresh_selections(cx);
 9735            assert_eq!(
 9736                editor.selected_ranges(cx),
 9737                [Point::new(0, 3)..Point::new(0, 3)]
 9738            );
 9739            assert!(editor.pending_selection.is_some());
 9740        });
 9741    }
 9742
 9743    #[gpui::test]
 9744    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9745        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9746        let language = Arc::new(Language::new(
 9747            LanguageConfig {
 9748                brackets: vec![
 9749                    BracketPair {
 9750                        start: "{".to_string(),
 9751                        end: "}".to_string(),
 9752                        close: true,
 9753                        newline: true,
 9754                    },
 9755                    BracketPair {
 9756                        start: "/* ".to_string(),
 9757                        end: " */".to_string(),
 9758                        close: true,
 9759                        newline: true,
 9760                    },
 9761                ],
 9762                ..Default::default()
 9763            },
 9764            Some(tree_sitter_rust::language()),
 9765        ));
 9766
 9767        let text = concat!(
 9768            "{   }\n",     // Suppress rustfmt
 9769            "  x\n",       //
 9770            "  /*   */\n", //
 9771            "x\n",         //
 9772            "{{} }\n",     //
 9773        );
 9774
 9775        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9776        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9777        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9778        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9779            .await;
 9780
 9781        view.update(cx, |view, cx| {
 9782            view.select_display_ranges(
 9783                &[
 9784                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9785                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9786                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9787                ],
 9788                cx,
 9789            );
 9790            view.newline(&Newline, cx);
 9791
 9792            assert_eq!(
 9793                view.buffer().read(cx).read(cx).text(),
 9794                concat!(
 9795                    "{ \n",    // Suppress rustfmt
 9796                    "\n",      //
 9797                    "}\n",     //
 9798                    "  x\n",   //
 9799                    "  /* \n", //
 9800                    "  \n",    //
 9801                    "  */\n",  //
 9802                    "x\n",     //
 9803                    "{{} \n",  //
 9804                    "}\n",     //
 9805                )
 9806            );
 9807        });
 9808    }
 9809
 9810    #[gpui::test]
 9811    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9812        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9813
 9814        cx.set_global(Settings::test(cx));
 9815        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9816
 9817        editor.update(cx, |editor, cx| {
 9818            struct Type1;
 9819            struct Type2;
 9820
 9821            let buffer = buffer.read(cx).snapshot(cx);
 9822
 9823            let anchor_range = |range: Range<Point>| {
 9824                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9825            };
 9826
 9827            editor.highlight_background::<Type1>(
 9828                vec![
 9829                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
 9830                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
 9831                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
 9832                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
 9833                ],
 9834                Color::red(),
 9835                cx,
 9836            );
 9837            editor.highlight_background::<Type2>(
 9838                vec![
 9839                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
 9840                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
 9841                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
 9842                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
 9843                ],
 9844                Color::green(),
 9845                cx,
 9846            );
 9847
 9848            let snapshot = editor.snapshot(cx);
 9849            let mut highlighted_ranges = editor.background_highlights_in_range(
 9850                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
 9851                &snapshot,
 9852            );
 9853            // Enforce a consistent ordering based on color without relying on the ordering of the
 9854            // highlight's `TypeId` which is non-deterministic.
 9855            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
 9856            assert_eq!(
 9857                highlighted_ranges,
 9858                &[
 9859                    (
 9860                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
 9861                        Color::green(),
 9862                    ),
 9863                    (
 9864                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
 9865                        Color::green(),
 9866                    ),
 9867                    (
 9868                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
 9869                        Color::red(),
 9870                    ),
 9871                    (
 9872                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9873                        Color::red(),
 9874                    ),
 9875                ]
 9876            );
 9877            assert_eq!(
 9878                editor.background_highlights_in_range(
 9879                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
 9880                    &snapshot,
 9881                ),
 9882                &[(
 9883                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
 9884                    Color::red(),
 9885                )]
 9886            );
 9887        });
 9888    }
 9889
 9890    #[gpui::test]
 9891    fn test_following(cx: &mut gpui::MutableAppContext) {
 9892        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9893
 9894        cx.set_global(Settings::test(cx));
 9895
 9896        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9897        let (_, follower) = cx.add_window(
 9898            WindowOptions {
 9899                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
 9900                ..Default::default()
 9901            },
 9902            |cx| build_editor(buffer.clone(), cx),
 9903        );
 9904
 9905        let pending_update = Rc::new(RefCell::new(None));
 9906        follower.update(cx, {
 9907            let update = pending_update.clone();
 9908            |_, cx| {
 9909                cx.subscribe(&leader, move |_, leader, event, cx| {
 9910                    leader
 9911                        .read(cx)
 9912                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
 9913                })
 9914                .detach();
 9915            }
 9916        });
 9917
 9918        // Update the selections only
 9919        leader.update(cx, |leader, cx| {
 9920            leader.select_ranges([1..1], None, cx);
 9921        });
 9922        follower.update(cx, |follower, cx| {
 9923            follower
 9924                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9925                .unwrap();
 9926        });
 9927        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
 9928
 9929        // Update the scroll position only
 9930        leader.update(cx, |leader, cx| {
 9931            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9932        });
 9933        follower.update(cx, |follower, cx| {
 9934            follower
 9935                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9936                .unwrap();
 9937        });
 9938        assert_eq!(
 9939            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
 9940            vec2f(1.5, 3.5)
 9941        );
 9942
 9943        // Update the selections and scroll position
 9944        leader.update(cx, |leader, cx| {
 9945            leader.select_ranges([0..0], None, cx);
 9946            leader.request_autoscroll(Autoscroll::Newest, cx);
 9947            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
 9948        });
 9949        follower.update(cx, |follower, cx| {
 9950            let initial_scroll_position = follower.scroll_position(cx);
 9951            follower
 9952                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9953                .unwrap();
 9954            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
 9955            assert!(follower.autoscroll_request.is_some());
 9956        });
 9957        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
 9958
 9959        // Creating a pending selection that precedes another selection
 9960        leader.update(cx, |leader, cx| {
 9961            leader.select_ranges([1..1], None, cx);
 9962            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
 9963        });
 9964        follower.update(cx, |follower, cx| {
 9965            follower
 9966                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9967                .unwrap();
 9968        });
 9969        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
 9970
 9971        // Extend the pending selection so that it surrounds another selection
 9972        leader.update(cx, |leader, cx| {
 9973            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
 9974        });
 9975        follower.update(cx, |follower, cx| {
 9976            follower
 9977                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
 9978                .unwrap();
 9979        });
 9980        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
 9981    }
 9982
 9983    #[test]
 9984    fn test_combine_syntax_and_fuzzy_match_highlights() {
 9985        let string = "abcdefghijklmnop";
 9986        let syntax_ranges = [
 9987            (
 9988                0..3,
 9989                HighlightStyle {
 9990                    color: Some(Color::red()),
 9991                    ..Default::default()
 9992                },
 9993            ),
 9994            (
 9995                4..8,
 9996                HighlightStyle {
 9997                    color: Some(Color::green()),
 9998                    ..Default::default()
 9999                },
10000            ),
10001        ];
10002        let match_indices = [4, 6, 7, 8];
10003        assert_eq!(
10004            combine_syntax_and_fuzzy_match_highlights(
10005                &string,
10006                Default::default(),
10007                syntax_ranges.into_iter(),
10008                &match_indices,
10009            ),
10010            &[
10011                (
10012                    0..3,
10013                    HighlightStyle {
10014                        color: Some(Color::red()),
10015                        ..Default::default()
10016                    },
10017                ),
10018                (
10019                    4..5,
10020                    HighlightStyle {
10021                        color: Some(Color::green()),
10022                        weight: Some(fonts::Weight::BOLD),
10023                        ..Default::default()
10024                    },
10025                ),
10026                (
10027                    5..6,
10028                    HighlightStyle {
10029                        color: Some(Color::green()),
10030                        ..Default::default()
10031                    },
10032                ),
10033                (
10034                    6..8,
10035                    HighlightStyle {
10036                        color: Some(Color::green()),
10037                        weight: Some(fonts::Weight::BOLD),
10038                        ..Default::default()
10039                    },
10040                ),
10041                (
10042                    8..9,
10043                    HighlightStyle {
10044                        weight: Some(fonts::Weight::BOLD),
10045                        ..Default::default()
10046                    },
10047                ),
10048            ]
10049        );
10050    }
10051
10052    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10053        let point = DisplayPoint::new(row as u32, column as u32);
10054        point..point
10055    }
10056
10057    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10058        Editor::new(EditorMode::Full, buffer, None, None, cx)
10059    }
10060
10061    fn assert_selection_ranges(
10062        marked_text: &str,
10063        selection_marker_pairs: Vec<(char, char)>,
10064        view: &mut Editor,
10065        cx: &mut ViewContext<Editor>,
10066    ) {
10067        let snapshot = view.snapshot(cx).display_snapshot;
10068        let mut marker_chars = Vec::new();
10069        for (start, end) in selection_marker_pairs.iter() {
10070            marker_chars.push(*start);
10071            marker_chars.push(*end);
10072        }
10073        let (_, markers) = marked_text_by(marked_text, marker_chars);
10074        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10075            .iter()
10076            .map(|(start, end)| {
10077                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10078                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10079                start..end
10080            })
10081            .collect();
10082        assert_eq!(
10083            view.selected_display_ranges(cx),
10084            &asserted_ranges[..],
10085            "Assert selections are {}",
10086            marked_text
10087        );
10088    }
10089}
10090
10091trait RangeExt<T> {
10092    fn sorted(&self) -> Range<T>;
10093    fn to_inclusive(&self) -> RangeInclusive<T>;
10094}
10095
10096impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10097    fn sorted(&self) -> Self {
10098        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10099    }
10100
10101    fn to_inclusive(&self) -> RangeInclusive<T> {
10102        self.start.clone()..=self.end.clone()
10103    }
10104}