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