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