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::handle_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 handle_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                self.tab(false, cx);
2884            }
2885        }
2886    }
2887
2888    pub fn tab(&mut self, force_indentation: bool, cx: &mut ViewContext<Self>) {
2889        let tab_size = cx.global::<Settings>().tab_size;
2890        let mut selections = self.local_selections::<Point>(cx);
2891        self.transact(cx, |this, cx| {
2892            let mut last_indent = None;
2893            this.buffer.update(cx, |buffer, cx| {
2894                for selection in &mut selections {
2895                    if selection.is_empty() && !force_indentation {
2896                        let char_column = buffer
2897                            .read(cx)
2898                            .text_for_range(Point::new(selection.start.row, 0)..selection.start)
2899                            .flat_map(str::chars)
2900                            .count();
2901                        let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
2902                        buffer.edit(
2903                            [selection.start..selection.start],
2904                            " ".repeat(chars_to_next_tab_stop),
2905                            cx,
2906                        );
2907                        selection.start.column += chars_to_next_tab_stop as u32;
2908                        selection.end = selection.start;
2909                    } else {
2910                        let mut start_row = selection.start.row;
2911                        let mut end_row = selection.end.row + 1;
2912
2913                        // If a selection ends at the beginning of a line, don't indent
2914                        // that last line.
2915                        if selection.end.column == 0 {
2916                            end_row -= 1;
2917                        }
2918
2919                        // Avoid re-indenting a row that has already been indented by a
2920                        // previous selection, but still update this selection's column
2921                        // to reflect that indentation.
2922                        if let Some((last_indent_row, last_indent_len)) = last_indent {
2923                            if last_indent_row == selection.start.row {
2924                                selection.start.column += last_indent_len;
2925                                start_row += 1;
2926                            }
2927                            if last_indent_row == selection.end.row {
2928                                selection.end.column += last_indent_len;
2929                            }
2930                        }
2931
2932                        for row in start_row..end_row {
2933                            let indent_column =
2934                                buffer.read(cx).indent_column_for_line(row) as usize;
2935                            let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
2936                            let row_start = Point::new(row, 0);
2937                            buffer.edit(
2938                                [row_start..row_start],
2939                                " ".repeat(columns_to_next_tab_stop),
2940                                cx,
2941                            );
2942
2943                            // Update this selection's endpoints to reflect the indentation.
2944                            if row == selection.start.row {
2945                                selection.start.column += columns_to_next_tab_stop as u32;
2946                            }
2947                            if row == selection.end.row {
2948                                selection.end.column += columns_to_next_tab_stop as u32;
2949                            }
2950
2951                            last_indent = Some((row, columns_to_next_tab_stop as u32));
2952                        }
2953                    }
2954                }
2955            });
2956
2957            this.update_selections(selections, Some(Autoscroll::Fit), cx);
2958        });
2959    }
2960
2961    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
2962        self.tab(true, cx);
2963    }
2964
2965    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
2966        let tab_size = cx.global::<Settings>().tab_size;
2967        let selections = self.local_selections::<Point>(cx);
2968        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2969        let mut deletion_ranges = Vec::new();
2970        let mut last_outdent = None;
2971        {
2972            let buffer = self.buffer.read(cx).read(cx);
2973            for selection in &selections {
2974                let mut rows = selection.spanned_rows(false, &display_map);
2975
2976                // Avoid re-outdenting a row that has already been outdented by a
2977                // previous selection.
2978                if let Some(last_row) = last_outdent {
2979                    if last_row == rows.start {
2980                        rows.start += 1;
2981                    }
2982                }
2983
2984                for row in rows {
2985                    let column = buffer.indent_column_for_line(row) as usize;
2986                    if column > 0 {
2987                        let mut deletion_len = (column % tab_size) as u32;
2988                        if deletion_len == 0 {
2989                            deletion_len = tab_size as u32;
2990                        }
2991                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
2992                        last_outdent = Some(row);
2993                    }
2994                }
2995            }
2996        }
2997
2998        self.transact(cx, |this, cx| {
2999            this.buffer.update(cx, |buffer, cx| {
3000                buffer.edit(deletion_ranges, "", cx);
3001            });
3002            this.update_selections(
3003                this.local_selections::<usize>(cx),
3004                Some(Autoscroll::Fit),
3005                cx,
3006            );
3007        });
3008    }
3009
3010    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3011        let selections = self.local_selections::<Point>(cx);
3012        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3013        let buffer = self.buffer.read(cx).snapshot(cx);
3014
3015        let mut new_cursors = Vec::new();
3016        let mut edit_ranges = Vec::new();
3017        let mut selections = selections.iter().peekable();
3018        while let Some(selection) = selections.next() {
3019            let mut rows = selection.spanned_rows(false, &display_map);
3020            let goal_display_column = selection.head().to_display_point(&display_map).column();
3021
3022            // Accumulate contiguous regions of rows that we want to delete.
3023            while let Some(next_selection) = selections.peek() {
3024                let next_rows = next_selection.spanned_rows(false, &display_map);
3025                if next_rows.start <= rows.end {
3026                    rows.end = next_rows.end;
3027                    selections.next().unwrap();
3028                } else {
3029                    break;
3030                }
3031            }
3032
3033            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
3034            let edit_end;
3035            let cursor_buffer_row;
3036            if buffer.max_point().row >= rows.end {
3037                // If there's a line after the range, delete the \n from the end of the row range
3038                // and position the cursor on the next line.
3039                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
3040                cursor_buffer_row = rows.end;
3041            } else {
3042                // If there isn't a line after the range, delete the \n from the line before the
3043                // start of the row range and position the cursor there.
3044                edit_start = edit_start.saturating_sub(1);
3045                edit_end = buffer.len();
3046                cursor_buffer_row = rows.start.saturating_sub(1);
3047            }
3048
3049            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3050            *cursor.column_mut() =
3051                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3052
3053            new_cursors.push((
3054                selection.id,
3055                buffer.anchor_after(cursor.to_point(&display_map)),
3056            ));
3057            edit_ranges.push(edit_start..edit_end);
3058        }
3059
3060        self.transact(cx, |this, cx| {
3061            let buffer = this.buffer.update(cx, |buffer, cx| {
3062                buffer.edit(edit_ranges, "", cx);
3063                buffer.snapshot(cx)
3064            });
3065            let new_selections = new_cursors
3066                .into_iter()
3067                .map(|(id, cursor)| {
3068                    let cursor = cursor.to_point(&buffer);
3069                    Selection {
3070                        id,
3071                        start: cursor,
3072                        end: cursor,
3073                        reversed: false,
3074                        goal: SelectionGoal::None,
3075                    }
3076                })
3077                .collect();
3078            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
3079        });
3080    }
3081
3082    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3083        let selections = self.local_selections::<Point>(cx);
3084        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3085        let buffer = &display_map.buffer_snapshot;
3086
3087        let mut edits = Vec::new();
3088        let mut selections_iter = selections.iter().peekable();
3089        while let Some(selection) = selections_iter.next() {
3090            // Avoid duplicating the same lines twice.
3091            let mut rows = selection.spanned_rows(false, &display_map);
3092
3093            while let Some(next_selection) = selections_iter.peek() {
3094                let next_rows = next_selection.spanned_rows(false, &display_map);
3095                if next_rows.start <= rows.end - 1 {
3096                    rows.end = next_rows.end;
3097                    selections_iter.next().unwrap();
3098                } else {
3099                    break;
3100                }
3101            }
3102
3103            // Copy the text from the selected row region and splice it at the start of the region.
3104            let start = Point::new(rows.start, 0);
3105            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3106            let text = buffer
3107                .text_for_range(start..end)
3108                .chain(Some("\n"))
3109                .collect::<String>();
3110            edits.push((start, text, rows.len() as u32));
3111        }
3112
3113        self.transact(cx, |this, cx| {
3114            this.buffer.update(cx, |buffer, cx| {
3115                for (point, text, _) in edits.into_iter().rev() {
3116                    buffer.edit(Some(point..point), text, cx);
3117                }
3118            });
3119
3120            this.request_autoscroll(Autoscroll::Fit, cx);
3121        });
3122    }
3123
3124    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3125        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3126        let buffer = self.buffer.read(cx).snapshot(cx);
3127
3128        let mut edits = Vec::new();
3129        let mut unfold_ranges = Vec::new();
3130        let mut refold_ranges = Vec::new();
3131
3132        let selections = self.local_selections::<Point>(cx);
3133        let mut selections = selections.iter().peekable();
3134        let mut contiguous_row_selections = Vec::new();
3135        let mut new_selections = Vec::new();
3136
3137        while let Some(selection) = selections.next() {
3138            // Find all the selections that span a contiguous row range
3139            contiguous_row_selections.push(selection.clone());
3140            let start_row = selection.start.row;
3141            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3142                display_map.next_line_boundary(selection.end).0.row + 1
3143            } else {
3144                selection.end.row
3145            };
3146
3147            while let Some(next_selection) = selections.peek() {
3148                if next_selection.start.row <= end_row {
3149                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3150                        display_map.next_line_boundary(next_selection.end).0.row + 1
3151                    } else {
3152                        next_selection.end.row
3153                    };
3154                    contiguous_row_selections.push(selections.next().unwrap().clone());
3155                } else {
3156                    break;
3157                }
3158            }
3159
3160            // Move the text spanned by the row range to be before the line preceding the row range
3161            if start_row > 0 {
3162                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3163                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3164                let insertion_point = display_map
3165                    .prev_line_boundary(Point::new(start_row - 1, 0))
3166                    .0;
3167
3168                // Don't move lines across excerpts
3169                if buffer
3170                    .excerpt_boundaries_in_range((
3171                        Bound::Excluded(insertion_point),
3172                        Bound::Included(range_to_move.end),
3173                    ))
3174                    .next()
3175                    .is_none()
3176                {
3177                    let text = buffer
3178                        .text_for_range(range_to_move.clone())
3179                        .flat_map(|s| s.chars())
3180                        .skip(1)
3181                        .chain(['\n'])
3182                        .collect::<String>();
3183
3184                    edits.push((
3185                        buffer.anchor_after(range_to_move.start)
3186                            ..buffer.anchor_before(range_to_move.end),
3187                        String::new(),
3188                    ));
3189                    let insertion_anchor = buffer.anchor_after(insertion_point);
3190                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3191
3192                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3193
3194                    // Move selections up
3195                    new_selections.extend(contiguous_row_selections.drain(..).map(
3196                        |mut selection| {
3197                            selection.start.row -= row_delta;
3198                            selection.end.row -= row_delta;
3199                            selection
3200                        },
3201                    ));
3202
3203                    // Move folds up
3204                    unfold_ranges.push(range_to_move.clone());
3205                    for fold in display_map.folds_in_range(
3206                        buffer.anchor_before(range_to_move.start)
3207                            ..buffer.anchor_after(range_to_move.end),
3208                    ) {
3209                        let mut start = fold.start.to_point(&buffer);
3210                        let mut end = fold.end.to_point(&buffer);
3211                        start.row -= row_delta;
3212                        end.row -= row_delta;
3213                        refold_ranges.push(start..end);
3214                    }
3215                }
3216            }
3217
3218            // If we didn't move line(s), preserve the existing selections
3219            new_selections.extend(contiguous_row_selections.drain(..));
3220        }
3221
3222        self.transact(cx, |this, cx| {
3223            this.unfold_ranges(unfold_ranges, true, cx);
3224            this.buffer.update(cx, |buffer, cx| {
3225                for (range, text) in edits {
3226                    buffer.edit([range], text, cx);
3227                }
3228            });
3229            this.fold_ranges(refold_ranges, cx);
3230            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
3231        });
3232    }
3233
3234    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3235        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3236        let buffer = self.buffer.read(cx).snapshot(cx);
3237
3238        let mut edits = Vec::new();
3239        let mut unfold_ranges = Vec::new();
3240        let mut refold_ranges = Vec::new();
3241
3242        let selections = self.local_selections::<Point>(cx);
3243        let mut selections = selections.iter().peekable();
3244        let mut contiguous_row_selections = Vec::new();
3245        let mut new_selections = Vec::new();
3246
3247        while let Some(selection) = selections.next() {
3248            // Find all the selections that span a contiguous row range
3249            contiguous_row_selections.push(selection.clone());
3250            let start_row = selection.start.row;
3251            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3252                display_map.next_line_boundary(selection.end).0.row + 1
3253            } else {
3254                selection.end.row
3255            };
3256
3257            while let Some(next_selection) = selections.peek() {
3258                if next_selection.start.row <= end_row {
3259                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3260                        display_map.next_line_boundary(next_selection.end).0.row + 1
3261                    } else {
3262                        next_selection.end.row
3263                    };
3264                    contiguous_row_selections.push(selections.next().unwrap().clone());
3265                } else {
3266                    break;
3267                }
3268            }
3269
3270            // Move the text spanned by the row range to be after the last line of the row range
3271            if end_row <= buffer.max_point().row {
3272                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3273                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3274
3275                // Don't move lines across excerpt boundaries
3276                if buffer
3277                    .excerpt_boundaries_in_range((
3278                        Bound::Excluded(range_to_move.start),
3279                        Bound::Included(insertion_point),
3280                    ))
3281                    .next()
3282                    .is_none()
3283                {
3284                    let mut text = String::from("\n");
3285                    text.extend(buffer.text_for_range(range_to_move.clone()));
3286                    text.pop(); // Drop trailing newline
3287                    edits.push((
3288                        buffer.anchor_after(range_to_move.start)
3289                            ..buffer.anchor_before(range_to_move.end),
3290                        String::new(),
3291                    ));
3292                    let insertion_anchor = buffer.anchor_after(insertion_point);
3293                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3294
3295                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3296
3297                    // Move selections down
3298                    new_selections.extend(contiguous_row_selections.drain(..).map(
3299                        |mut selection| {
3300                            selection.start.row += row_delta;
3301                            selection.end.row += row_delta;
3302                            selection
3303                        },
3304                    ));
3305
3306                    // Move folds down
3307                    unfold_ranges.push(range_to_move.clone());
3308                    for fold in display_map.folds_in_range(
3309                        buffer.anchor_before(range_to_move.start)
3310                            ..buffer.anchor_after(range_to_move.end),
3311                    ) {
3312                        let mut start = fold.start.to_point(&buffer);
3313                        let mut end = fold.end.to_point(&buffer);
3314                        start.row += row_delta;
3315                        end.row += row_delta;
3316                        refold_ranges.push(start..end);
3317                    }
3318                }
3319            }
3320
3321            // If we didn't move line(s), preserve the existing selections
3322            new_selections.extend(contiguous_row_selections.drain(..));
3323        }
3324
3325        self.transact(cx, |this, cx| {
3326            this.unfold_ranges(unfold_ranges, true, cx);
3327            this.buffer.update(cx, |buffer, cx| {
3328                for (range, text) in edits {
3329                    buffer.edit([range], text, cx);
3330                }
3331            });
3332            this.fold_ranges(refold_ranges, cx);
3333            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
3334        });
3335    }
3336
3337    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3338        let mut text = String::new();
3339        let mut selections = self.local_selections::<Point>(cx);
3340        let mut clipboard_selections = Vec::with_capacity(selections.len());
3341        {
3342            let buffer = self.buffer.read(cx).read(cx);
3343            let max_point = buffer.max_point();
3344            for selection in &mut selections {
3345                let is_entire_line = selection.is_empty();
3346                if is_entire_line {
3347                    selection.start = Point::new(selection.start.row, 0);
3348                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3349                    selection.goal = SelectionGoal::None;
3350                }
3351                let mut len = 0;
3352                for chunk in buffer.text_for_range(selection.start..selection.end) {
3353                    text.push_str(chunk);
3354                    len += chunk.len();
3355                }
3356                clipboard_selections.push(ClipboardSelection {
3357                    len,
3358                    is_entire_line,
3359                });
3360            }
3361        }
3362
3363        self.transact(cx, |this, cx| {
3364            this.update_selections(selections, Some(Autoscroll::Fit), cx);
3365            this.insert("", cx);
3366            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3367        });
3368    }
3369
3370    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3371        let selections = self.local_selections::<Point>(cx);
3372        let mut text = String::new();
3373        let mut clipboard_selections = Vec::with_capacity(selections.len());
3374        {
3375            let buffer = self.buffer.read(cx).read(cx);
3376            let max_point = buffer.max_point();
3377            for selection in selections.iter() {
3378                let mut start = selection.start;
3379                let mut end = selection.end;
3380                let is_entire_line = selection.is_empty();
3381                if is_entire_line {
3382                    start = Point::new(start.row, 0);
3383                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
3384                }
3385                let mut len = 0;
3386                for chunk in buffer.text_for_range(start..end) {
3387                    text.push_str(chunk);
3388                    len += chunk.len();
3389                }
3390                clipboard_selections.push(ClipboardSelection {
3391                    len,
3392                    is_entire_line,
3393                });
3394            }
3395        }
3396
3397        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3398    }
3399
3400    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3401        self.transact(cx, |this, cx| {
3402            if let Some(item) = cx.as_mut().read_from_clipboard() {
3403                let clipboard_text = item.text();
3404                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3405                    let mut selections = this.local_selections::<usize>(cx);
3406                    let all_selections_were_entire_line =
3407                        clipboard_selections.iter().all(|s| s.is_entire_line);
3408                    if clipboard_selections.len() != selections.len() {
3409                        clipboard_selections.clear();
3410                    }
3411
3412                    let mut delta = 0_isize;
3413                    let mut start_offset = 0;
3414                    for (i, selection) in selections.iter_mut().enumerate() {
3415                        let to_insert;
3416                        let entire_line;
3417                        if let Some(clipboard_selection) = clipboard_selections.get(i) {
3418                            let end_offset = start_offset + clipboard_selection.len;
3419                            to_insert = &clipboard_text[start_offset..end_offset];
3420                            entire_line = clipboard_selection.is_entire_line;
3421                            start_offset = end_offset
3422                        } else {
3423                            to_insert = clipboard_text.as_str();
3424                            entire_line = all_selections_were_entire_line;
3425                        }
3426
3427                        selection.start = (selection.start as isize + delta) as usize;
3428                        selection.end = (selection.end as isize + delta) as usize;
3429
3430                        this.buffer.update(cx, |buffer, cx| {
3431                            // If the corresponding selection was empty when this slice of the
3432                            // clipboard text was written, then the entire line containing the
3433                            // selection was copied. If this selection is also currently empty,
3434                            // then paste the line before the current line of the buffer.
3435                            let range = if selection.is_empty() && entire_line {
3436                                let column =
3437                                    selection.start.to_point(&buffer.read(cx)).column as usize;
3438                                let line_start = selection.start - column;
3439                                line_start..line_start
3440                            } else {
3441                                selection.start..selection.end
3442                            };
3443
3444                            delta += to_insert.len() as isize - range.len() as isize;
3445                            buffer.edit([range], to_insert, cx);
3446                            selection.start += to_insert.len();
3447                            selection.end = selection.start;
3448                        });
3449                    }
3450                    this.update_selections(selections, Some(Autoscroll::Fit), cx);
3451                } else {
3452                    this.insert(clipboard_text, cx);
3453                }
3454            }
3455        });
3456    }
3457
3458    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3459        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3460            if let Some((selections, _)) = self.selection_history.get(&tx_id).cloned() {
3461                self.set_selections(selections, None, true, cx);
3462            }
3463            self.request_autoscroll(Autoscroll::Fit, cx);
3464            cx.emit(Event::Edited);
3465        }
3466    }
3467
3468    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3469        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3470            if let Some((_, Some(selections))) = self.selection_history.get(&tx_id).cloned() {
3471                self.set_selections(selections, None, true, cx);
3472            }
3473            self.request_autoscroll(Autoscroll::Fit, cx);
3474            cx.emit(Event::Edited);
3475        }
3476    }
3477
3478    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3479        self.buffer
3480            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3481    }
3482
3483    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3484        self.move_selections(cx, |map, selection| {
3485            let cursor = if selection.is_empty() {
3486                movement::left(map, selection.start)
3487            } else {
3488                selection.start
3489            };
3490            selection.collapse_to(cursor, SelectionGoal::None);
3491        });
3492    }
3493
3494    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3495        self.move_selection_heads(cx, |map, head, _| {
3496            (movement::left(map, head), SelectionGoal::None)
3497        });
3498    }
3499
3500    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3501        self.move_selections(cx, |map, selection| {
3502            let cursor = if selection.is_empty() {
3503                movement::right(map, selection.end)
3504            } else {
3505                selection.end
3506            };
3507            selection.collapse_to(cursor, SelectionGoal::None)
3508        });
3509    }
3510
3511    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3512        self.move_selection_heads(cx, |map, head, _| {
3513            (movement::right(map, head), SelectionGoal::None)
3514        });
3515    }
3516
3517    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3518        if self.take_rename(true, cx).is_some() {
3519            return;
3520        }
3521
3522        if let Some(context_menu) = self.context_menu.as_mut() {
3523            if context_menu.select_prev(cx) {
3524                return;
3525            }
3526        }
3527
3528        if matches!(self.mode, EditorMode::SingleLine) {
3529            cx.propagate_action();
3530            return;
3531        }
3532
3533        self.move_selections(cx, |map, selection| {
3534            if !selection.is_empty() {
3535                selection.goal = SelectionGoal::None;
3536            }
3537            let (cursor, goal) = movement::up(&map, selection.start, selection.goal);
3538            selection.collapse_to(cursor, goal);
3539        });
3540    }
3541
3542    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3543        self.move_selection_heads(cx, movement::up)
3544    }
3545
3546    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3547        self.take_rename(true, cx);
3548
3549        if let Some(context_menu) = self.context_menu.as_mut() {
3550            if context_menu.select_next(cx) {
3551                return;
3552            }
3553        }
3554
3555        if matches!(self.mode, EditorMode::SingleLine) {
3556            cx.propagate_action();
3557            return;
3558        }
3559
3560        self.move_selections(cx, |map, selection| {
3561            if !selection.is_empty() {
3562                selection.goal = SelectionGoal::None;
3563            }
3564            let (cursor, goal) = movement::down(&map, selection.end, selection.goal);
3565            selection.collapse_to(cursor, goal);
3566        });
3567    }
3568
3569    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3570        self.move_selection_heads(cx, movement::down)
3571    }
3572
3573    pub fn move_to_previous_word_start(
3574        &mut self,
3575        _: &MoveToPreviousWordStart,
3576        cx: &mut ViewContext<Self>,
3577    ) {
3578        self.move_cursors(cx, |map, head, _| {
3579            (
3580                movement::previous_word_start(map, head),
3581                SelectionGoal::None,
3582            )
3583        });
3584    }
3585
3586    pub fn move_to_previous_subword_start(
3587        &mut self,
3588        _: &MoveToPreviousSubwordStart,
3589        cx: &mut ViewContext<Self>,
3590    ) {
3591        self.move_cursors(cx, |map, head, _| {
3592            (
3593                movement::previous_subword_start(map, head),
3594                SelectionGoal::None,
3595            )
3596        });
3597    }
3598
3599    pub fn select_to_previous_word_start(
3600        &mut self,
3601        _: &SelectToPreviousWordStart,
3602        cx: &mut ViewContext<Self>,
3603    ) {
3604        self.move_selection_heads(cx, |map, head, _| {
3605            (
3606                movement::previous_word_start(map, head),
3607                SelectionGoal::None,
3608            )
3609        });
3610    }
3611
3612    pub fn select_to_previous_subword_start(
3613        &mut self,
3614        _: &SelectToPreviousSubwordStart,
3615        cx: &mut ViewContext<Self>,
3616    ) {
3617        self.move_selection_heads(cx, |map, head, _| {
3618            (
3619                movement::previous_subword_start(map, head),
3620                SelectionGoal::None,
3621            )
3622        });
3623    }
3624
3625    pub fn delete_to_previous_word_start(
3626        &mut self,
3627        _: &DeleteToPreviousWordStart,
3628        cx: &mut ViewContext<Self>,
3629    ) {
3630        self.transact(cx, |this, cx| {
3631            this.move_selections(cx, |map, selection| {
3632                if selection.is_empty() {
3633                    let cursor = movement::previous_word_start(map, selection.head());
3634                    selection.set_head(cursor, SelectionGoal::None);
3635                }
3636            });
3637            this.insert("", cx);
3638        });
3639    }
3640
3641    pub fn delete_to_previous_subword_start(
3642        &mut self,
3643        _: &DeleteToPreviousSubwordStart,
3644        cx: &mut ViewContext<Self>,
3645    ) {
3646        self.transact(cx, |this, cx| {
3647            this.move_selections(cx, |map, selection| {
3648                if selection.is_empty() {
3649                    let cursor = movement::previous_subword_start(map, selection.head());
3650                    selection.set_head(cursor, SelectionGoal::None);
3651                }
3652            });
3653            this.insert("", cx);
3654        });
3655    }
3656
3657    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3658        self.move_cursors(cx, |map, head, _| {
3659            (movement::next_word_end(map, head), SelectionGoal::None)
3660        });
3661    }
3662
3663    pub fn move_to_next_subword_end(
3664        &mut self,
3665        _: &MoveToNextSubwordEnd,
3666        cx: &mut ViewContext<Self>,
3667    ) {
3668        self.move_cursors(cx, |map, head, _| {
3669            (movement::next_subword_end(map, head), SelectionGoal::None)
3670        });
3671    }
3672
3673    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
3674        self.move_selection_heads(cx, |map, head, _| {
3675            (movement::next_word_end(map, head), SelectionGoal::None)
3676        });
3677    }
3678
3679    pub fn select_to_next_subword_end(
3680        &mut self,
3681        _: &SelectToNextSubwordEnd,
3682        cx: &mut ViewContext<Self>,
3683    ) {
3684        self.move_selection_heads(cx, |map, head, _| {
3685            (movement::next_subword_end(map, head), SelectionGoal::None)
3686        });
3687    }
3688
3689    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
3690        self.transact(cx, |this, cx| {
3691            this.move_selections(cx, |map, selection| {
3692                if selection.is_empty() {
3693                    let cursor = movement::next_word_end(map, selection.head());
3694                    selection.set_head(cursor, SelectionGoal::None);
3695                }
3696            });
3697            this.insert("", cx);
3698        });
3699    }
3700
3701    pub fn delete_to_next_subword_end(
3702        &mut self,
3703        _: &DeleteToNextSubwordEnd,
3704        cx: &mut ViewContext<Self>,
3705    ) {
3706        self.transact(cx, |this, cx| {
3707            this.move_selections(cx, |map, selection| {
3708                if selection.is_empty() {
3709                    let cursor = movement::next_subword_end(map, selection.head());
3710                    selection.set_head(cursor, SelectionGoal::None);
3711                }
3712            });
3713            this.insert("", cx);
3714        });
3715    }
3716
3717    pub fn move_to_beginning_of_line(
3718        &mut self,
3719        _: &MoveToBeginningOfLine,
3720        cx: &mut ViewContext<Self>,
3721    ) {
3722        self.move_cursors(cx, |map, head, _| {
3723            (
3724                movement::line_beginning(map, head, true),
3725                SelectionGoal::None,
3726            )
3727        });
3728    }
3729
3730    pub fn select_to_beginning_of_line(
3731        &mut self,
3732        SelectToBeginningOfLine(stop_at_soft_boundaries): &SelectToBeginningOfLine,
3733        cx: &mut ViewContext<Self>,
3734    ) {
3735        self.move_selection_heads(cx, |map, head, _| {
3736            (
3737                movement::line_beginning(map, head, *stop_at_soft_boundaries),
3738                SelectionGoal::None,
3739            )
3740        });
3741    }
3742
3743    pub fn delete_to_beginning_of_line(
3744        &mut self,
3745        _: &DeleteToBeginningOfLine,
3746        cx: &mut ViewContext<Self>,
3747    ) {
3748        self.transact(cx, |this, cx| {
3749            this.select_to_beginning_of_line(&SelectToBeginningOfLine(false), cx);
3750            this.backspace(&Backspace, cx);
3751        });
3752    }
3753
3754    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
3755        self.move_cursors(cx, |map, head, _| {
3756            (movement::line_end(map, head, true), SelectionGoal::None)
3757        });
3758    }
3759
3760    pub fn select_to_end_of_line(
3761        &mut self,
3762        SelectToEndOfLine(stop_at_soft_boundaries): &SelectToEndOfLine,
3763        cx: &mut ViewContext<Self>,
3764    ) {
3765        self.move_selection_heads(cx, |map, head, _| {
3766            (
3767                movement::line_end(map, head, *stop_at_soft_boundaries),
3768                SelectionGoal::None,
3769            )
3770        });
3771    }
3772
3773    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
3774        self.transact(cx, |this, cx| {
3775            this.select_to_end_of_line(&SelectToEndOfLine(false), cx);
3776            this.delete(&Delete, cx);
3777        });
3778    }
3779
3780    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
3781        self.transact(cx, |this, cx| {
3782            this.select_to_end_of_line(&SelectToEndOfLine(false), cx);
3783            this.cut(&Cut, cx);
3784        });
3785    }
3786
3787    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
3788        if matches!(self.mode, EditorMode::SingleLine) {
3789            cx.propagate_action();
3790            return;
3791        }
3792
3793        let selection = Selection {
3794            id: post_inc(&mut self.next_selection_id),
3795            start: 0,
3796            end: 0,
3797            reversed: false,
3798            goal: SelectionGoal::None,
3799        };
3800        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
3801    }
3802
3803    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
3804        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
3805        selection.set_head(Point::zero(), SelectionGoal::None);
3806        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
3807    }
3808
3809    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
3810        if matches!(self.mode, EditorMode::SingleLine) {
3811            cx.propagate_action();
3812            return;
3813        }
3814
3815        let cursor = self.buffer.read(cx).read(cx).len();
3816        let selection = Selection {
3817            id: post_inc(&mut self.next_selection_id),
3818            start: cursor,
3819            end: cursor,
3820            reversed: false,
3821            goal: SelectionGoal::None,
3822        };
3823        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
3824    }
3825
3826    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
3827        self.nav_history = nav_history;
3828    }
3829
3830    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
3831        self.nav_history.as_ref()
3832    }
3833
3834    fn push_to_nav_history(
3835        &self,
3836        position: Anchor,
3837        new_position: Option<Point>,
3838        cx: &mut ViewContext<Self>,
3839    ) {
3840        if let Some(nav_history) = &self.nav_history {
3841            let buffer = self.buffer.read(cx).read(cx);
3842            let offset = position.to_offset(&buffer);
3843            let point = position.to_point(&buffer);
3844            drop(buffer);
3845
3846            if let Some(new_position) = new_position {
3847                let row_delta = (new_position.row as i64 - point.row as i64).abs();
3848                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
3849                    return;
3850                }
3851            }
3852
3853            nav_history.push(Some(NavigationData {
3854                anchor: position,
3855                offset,
3856            }));
3857        }
3858    }
3859
3860    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
3861        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
3862        selection.set_head(self.buffer.read(cx).read(cx).len(), SelectionGoal::None);
3863        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
3864    }
3865
3866    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
3867        let selection = Selection {
3868            id: post_inc(&mut self.next_selection_id),
3869            start: 0,
3870            end: self.buffer.read(cx).read(cx).len(),
3871            reversed: false,
3872            goal: SelectionGoal::None,
3873        };
3874        self.update_selections(vec![selection], None, cx);
3875    }
3876
3877    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
3878        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3879        let mut selections = self.local_selections::<Point>(cx);
3880        let max_point = display_map.buffer_snapshot.max_point();
3881        for selection in &mut selections {
3882            let rows = selection.spanned_rows(true, &display_map);
3883            selection.start = Point::new(rows.start, 0);
3884            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
3885            selection.reversed = false;
3886        }
3887        self.update_selections(selections, Some(Autoscroll::Fit), cx);
3888    }
3889
3890    pub fn split_selection_into_lines(
3891        &mut self,
3892        _: &SplitSelectionIntoLines,
3893        cx: &mut ViewContext<Self>,
3894    ) {
3895        let mut to_unfold = Vec::new();
3896        let mut new_selections = Vec::new();
3897        {
3898            let selections = self.local_selections::<Point>(cx);
3899            let buffer = self.buffer.read(cx).read(cx);
3900            for selection in selections {
3901                for row in selection.start.row..selection.end.row {
3902                    let cursor = Point::new(row, buffer.line_len(row));
3903                    new_selections.push(Selection {
3904                        id: post_inc(&mut self.next_selection_id),
3905                        start: cursor,
3906                        end: cursor,
3907                        reversed: false,
3908                        goal: SelectionGoal::None,
3909                    });
3910                }
3911                new_selections.push(Selection {
3912                    id: selection.id,
3913                    start: selection.end,
3914                    end: selection.end,
3915                    reversed: false,
3916                    goal: SelectionGoal::None,
3917                });
3918                to_unfold.push(selection.start..selection.end);
3919            }
3920        }
3921        self.unfold_ranges(to_unfold, true, cx);
3922        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
3923    }
3924
3925    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
3926        self.add_selection(true, cx);
3927    }
3928
3929    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
3930        self.add_selection(false, cx);
3931    }
3932
3933    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
3934        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3935        let mut selections = self.local_selections::<Point>(cx);
3936        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
3937            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
3938            let range = oldest_selection.display_range(&display_map).sorted();
3939            let columns = cmp::min(range.start.column(), range.end.column())
3940                ..cmp::max(range.start.column(), range.end.column());
3941
3942            selections.clear();
3943            let mut stack = Vec::new();
3944            for row in range.start.row()..=range.end.row() {
3945                if let Some(selection) = self.build_columnar_selection(
3946                    &display_map,
3947                    row,
3948                    &columns,
3949                    oldest_selection.reversed,
3950                ) {
3951                    stack.push(selection.id);
3952                    selections.push(selection);
3953                }
3954            }
3955
3956            if above {
3957                stack.reverse();
3958            }
3959
3960            AddSelectionsState { above, stack }
3961        });
3962
3963        let last_added_selection = *state.stack.last().unwrap();
3964        let mut new_selections = Vec::new();
3965        if above == state.above {
3966            let end_row = if above {
3967                0
3968            } else {
3969                display_map.max_point().row()
3970            };
3971
3972            'outer: for selection in selections {
3973                if selection.id == last_added_selection {
3974                    let range = selection.display_range(&display_map).sorted();
3975                    debug_assert_eq!(range.start.row(), range.end.row());
3976                    let mut row = range.start.row();
3977                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
3978                    {
3979                        start..end
3980                    } else {
3981                        cmp::min(range.start.column(), range.end.column())
3982                            ..cmp::max(range.start.column(), range.end.column())
3983                    };
3984
3985                    while row != end_row {
3986                        if above {
3987                            row -= 1;
3988                        } else {
3989                            row += 1;
3990                        }
3991
3992                        if let Some(new_selection) = self.build_columnar_selection(
3993                            &display_map,
3994                            row,
3995                            &columns,
3996                            selection.reversed,
3997                        ) {
3998                            state.stack.push(new_selection.id);
3999                            if above {
4000                                new_selections.push(new_selection);
4001                                new_selections.push(selection);
4002                            } else {
4003                                new_selections.push(selection);
4004                                new_selections.push(new_selection);
4005                            }
4006
4007                            continue 'outer;
4008                        }
4009                    }
4010                }
4011
4012                new_selections.push(selection);
4013            }
4014        } else {
4015            new_selections = selections;
4016            new_selections.retain(|s| s.id != last_added_selection);
4017            state.stack.pop();
4018        }
4019
4020        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
4021        if state.stack.len() > 1 {
4022            self.add_selections_state = Some(state);
4023        }
4024    }
4025
4026    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4027        let replace_newest = action.0;
4028        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4029        let buffer = &display_map.buffer_snapshot;
4030        let mut selections = self.local_selections::<usize>(cx);
4031        if let Some(mut select_next_state) = self.select_next_state.take() {
4032            let query = &select_next_state.query;
4033            if !select_next_state.done {
4034                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4035                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4036                let mut next_selected_range = None;
4037
4038                let bytes_after_last_selection =
4039                    buffer.bytes_in_range(last_selection.end..buffer.len());
4040                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4041                let query_matches = query
4042                    .stream_find_iter(bytes_after_last_selection)
4043                    .map(|result| (last_selection.end, result))
4044                    .chain(
4045                        query
4046                            .stream_find_iter(bytes_before_first_selection)
4047                            .map(|result| (0, result)),
4048                    );
4049                for (start_offset, query_match) in query_matches {
4050                    let query_match = query_match.unwrap(); // can only fail due to I/O
4051                    let offset_range =
4052                        start_offset + query_match.start()..start_offset + query_match.end();
4053                    let display_range = offset_range.start.to_display_point(&display_map)
4054                        ..offset_range.end.to_display_point(&display_map);
4055
4056                    if !select_next_state.wordwise
4057                        || (!movement::is_inside_word(&display_map, display_range.start)
4058                            && !movement::is_inside_word(&display_map, display_range.end))
4059                    {
4060                        next_selected_range = Some(offset_range);
4061                        break;
4062                    }
4063                }
4064
4065                if let Some(next_selected_range) = next_selected_range {
4066                    if replace_newest {
4067                        if let Some(newest_id) =
4068                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
4069                        {
4070                            selections.retain(|s| s.id != newest_id);
4071                        }
4072                    }
4073                    selections.push(Selection {
4074                        id: post_inc(&mut self.next_selection_id),
4075                        start: next_selected_range.start,
4076                        end: next_selected_range.end,
4077                        reversed: false,
4078                        goal: SelectionGoal::None,
4079                    });
4080                    self.unfold_ranges([next_selected_range], false, cx);
4081                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
4082                } else {
4083                    select_next_state.done = true;
4084                }
4085            }
4086
4087            self.select_next_state = Some(select_next_state);
4088        } else if selections.len() == 1 {
4089            let selection = selections.last_mut().unwrap();
4090            if selection.start == selection.end {
4091                let word_range = movement::surrounding_word(
4092                    &display_map,
4093                    selection.start.to_display_point(&display_map),
4094                );
4095                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4096                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4097                selection.goal = SelectionGoal::None;
4098                selection.reversed = false;
4099
4100                let query = buffer
4101                    .text_for_range(selection.start..selection.end)
4102                    .collect::<String>();
4103                let select_state = SelectNextState {
4104                    query: AhoCorasick::new_auto_configured(&[query]),
4105                    wordwise: true,
4106                    done: false,
4107                };
4108                self.unfold_ranges([selection.start..selection.end], false, cx);
4109                self.update_selections(selections, Some(Autoscroll::Newest), cx);
4110                self.select_next_state = Some(select_state);
4111            } else {
4112                let query = buffer
4113                    .text_for_range(selection.start..selection.end)
4114                    .collect::<String>();
4115                self.select_next_state = Some(SelectNextState {
4116                    query: AhoCorasick::new_auto_configured(&[query]),
4117                    wordwise: false,
4118                    done: false,
4119                });
4120                self.select_next(action, cx);
4121            }
4122        }
4123    }
4124
4125    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4126        // Get the line comment prefix. Split its trailing whitespace into a separate string,
4127        // as that portion won't be used for detecting if a line is a comment.
4128        let full_comment_prefix =
4129            if let Some(prefix) = self.language(cx).and_then(|l| l.line_comment_prefix()) {
4130                prefix.to_string()
4131            } else {
4132                return;
4133            };
4134        let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4135        let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4136
4137        self.transact(cx, |this, cx| {
4138            let mut selections = this.local_selections::<Point>(cx);
4139            let mut all_selection_lines_are_comments = true;
4140            let mut edit_ranges = Vec::new();
4141            let mut last_toggled_row = None;
4142            this.buffer.update(cx, |buffer, cx| {
4143                for selection in &mut selections {
4144                    edit_ranges.clear();
4145                    let snapshot = buffer.snapshot(cx);
4146
4147                    let end_row =
4148                        if selection.end.row > selection.start.row && selection.end.column == 0 {
4149                            selection.end.row
4150                        } else {
4151                            selection.end.row + 1
4152                        };
4153
4154                    for row in selection.start.row..end_row {
4155                        // If multiple selections contain a given row, avoid processing that
4156                        // row more than once.
4157                        if last_toggled_row == Some(row) {
4158                            continue;
4159                        } else {
4160                            last_toggled_row = Some(row);
4161                        }
4162
4163                        if snapshot.is_line_blank(row) {
4164                            continue;
4165                        }
4166
4167                        let start = Point::new(row, snapshot.indent_column_for_line(row));
4168                        let mut line_bytes = snapshot
4169                            .bytes_in_range(start..snapshot.max_point())
4170                            .flatten()
4171                            .copied();
4172
4173                        // If this line currently begins with the line comment prefix, then record
4174                        // the range containing the prefix.
4175                        if all_selection_lines_are_comments
4176                            && line_bytes
4177                                .by_ref()
4178                                .take(comment_prefix.len())
4179                                .eq(comment_prefix.bytes())
4180                        {
4181                            // Include any whitespace that matches the comment prefix.
4182                            let matching_whitespace_len = line_bytes
4183                                .zip(comment_prefix_whitespace.bytes())
4184                                .take_while(|(a, b)| a == b)
4185                                .count()
4186                                as u32;
4187                            let end = Point::new(
4188                                row,
4189                                start.column
4190                                    + comment_prefix.len() as u32
4191                                    + matching_whitespace_len,
4192                            );
4193                            edit_ranges.push(start..end);
4194                        }
4195                        // If this line does not begin with the line comment prefix, then record
4196                        // the position where the prefix should be inserted.
4197                        else {
4198                            all_selection_lines_are_comments = false;
4199                            edit_ranges.push(start..start);
4200                        }
4201                    }
4202
4203                    if !edit_ranges.is_empty() {
4204                        if all_selection_lines_are_comments {
4205                            buffer.edit(edit_ranges.iter().cloned(), "", cx);
4206                        } else {
4207                            let min_column =
4208                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
4209                            let edit_ranges = edit_ranges.iter().map(|range| {
4210                                let position = Point::new(range.start.row, min_column);
4211                                position..position
4212                            });
4213                            buffer.edit(edit_ranges, &full_comment_prefix, cx);
4214                        }
4215                    }
4216                }
4217            });
4218
4219            this.update_selections(
4220                this.local_selections::<usize>(cx),
4221                Some(Autoscroll::Fit),
4222                cx,
4223            );
4224        });
4225    }
4226
4227    pub fn select_larger_syntax_node(
4228        &mut self,
4229        _: &SelectLargerSyntaxNode,
4230        cx: &mut ViewContext<Self>,
4231    ) {
4232        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
4233        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4234        let buffer = self.buffer.read(cx).snapshot(cx);
4235
4236        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4237        let mut selected_larger_node = false;
4238        let new_selections = old_selections
4239            .iter()
4240            .map(|selection| {
4241                let old_range = selection.start..selection.end;
4242                let mut new_range = old_range.clone();
4243                while let Some(containing_range) =
4244                    buffer.range_for_syntax_ancestor(new_range.clone())
4245                {
4246                    new_range = containing_range;
4247                    if !display_map.intersects_fold(new_range.start)
4248                        && !display_map.intersects_fold(new_range.end)
4249                    {
4250                        break;
4251                    }
4252                }
4253
4254                selected_larger_node |= new_range != old_range;
4255                Selection {
4256                    id: selection.id,
4257                    start: new_range.start,
4258                    end: new_range.end,
4259                    goal: SelectionGoal::None,
4260                    reversed: selection.reversed,
4261                }
4262            })
4263            .collect::<Vec<_>>();
4264
4265        if selected_larger_node {
4266            stack.push(old_selections);
4267            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
4268        }
4269        self.select_larger_syntax_node_stack = stack;
4270    }
4271
4272    pub fn select_smaller_syntax_node(
4273        &mut self,
4274        _: &SelectSmallerSyntaxNode,
4275        cx: &mut ViewContext<Self>,
4276    ) {
4277        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4278        if let Some(selections) = stack.pop() {
4279            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
4280        }
4281        self.select_larger_syntax_node_stack = stack;
4282    }
4283
4284    pub fn move_to_enclosing_bracket(
4285        &mut self,
4286        _: &MoveToEnclosingBracket,
4287        cx: &mut ViewContext<Self>,
4288    ) {
4289        let mut selections = self.local_selections::<usize>(cx);
4290        let buffer = self.buffer.read(cx).snapshot(cx);
4291        for selection in &mut selections {
4292            if let Some((open_range, close_range)) =
4293                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4294            {
4295                let close_range = close_range.to_inclusive();
4296                let destination = if close_range.contains(&selection.start)
4297                    && close_range.contains(&selection.end)
4298                {
4299                    open_range.end
4300                } else {
4301                    *close_range.start()
4302                };
4303                selection.start = destination;
4304                selection.end = destination;
4305            }
4306        }
4307
4308        self.update_selections(selections, Some(Autoscroll::Fit), cx);
4309    }
4310
4311    pub fn go_to_diagnostic(
4312        &mut self,
4313        &GoToDiagnostic(direction): &GoToDiagnostic,
4314        cx: &mut ViewContext<Self>,
4315    ) {
4316        let buffer = self.buffer.read(cx).snapshot(cx);
4317        let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
4318        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4319            active_diagnostics
4320                .primary_range
4321                .to_offset(&buffer)
4322                .to_inclusive()
4323        });
4324        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4325            if active_primary_range.contains(&selection.head()) {
4326                *active_primary_range.end()
4327            } else {
4328                selection.head()
4329            }
4330        } else {
4331            selection.head()
4332        };
4333
4334        loop {
4335            let mut diagnostics = if direction == Direction::Prev {
4336                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4337            } else {
4338                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4339            };
4340            let group = diagnostics.find_map(|entry| {
4341                if entry.diagnostic.is_primary
4342                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4343                    && !entry.range.is_empty()
4344                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4345                {
4346                    Some((entry.range, entry.diagnostic.group_id))
4347                } else {
4348                    None
4349                }
4350            });
4351
4352            if let Some((primary_range, group_id)) = group {
4353                self.activate_diagnostics(group_id, cx);
4354                self.update_selections(
4355                    vec![Selection {
4356                        id: selection.id,
4357                        start: primary_range.start,
4358                        end: primary_range.start,
4359                        reversed: false,
4360                        goal: SelectionGoal::None,
4361                    }],
4362                    Some(Autoscroll::Center),
4363                    cx,
4364                );
4365                break;
4366            } else {
4367                // Cycle around to the start of the buffer, potentially moving back to the start of
4368                // the currently active diagnostic.
4369                active_primary_range.take();
4370                if direction == Direction::Prev {
4371                    if search_start == buffer.len() {
4372                        break;
4373                    } else {
4374                        search_start = buffer.len();
4375                    }
4376                } else {
4377                    if search_start == 0 {
4378                        break;
4379                    } else {
4380                        search_start = 0;
4381                    }
4382                }
4383            }
4384        }
4385    }
4386
4387    pub fn go_to_definition(
4388        workspace: &mut Workspace,
4389        _: &GoToDefinition,
4390        cx: &mut ViewContext<Workspace>,
4391    ) {
4392        let active_item = workspace.active_item(cx);
4393        let editor_handle = if let Some(editor) = active_item
4394            .as_ref()
4395            .and_then(|item| item.act_as::<Self>(cx))
4396        {
4397            editor
4398        } else {
4399            return;
4400        };
4401
4402        let editor = editor_handle.read(cx);
4403        let head = editor.newest_selection::<usize>(cx).head();
4404        let (buffer, head) =
4405            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
4406                text_anchor
4407            } else {
4408                return;
4409            };
4410
4411        let project = workspace.project().clone();
4412        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
4413        cx.spawn(|workspace, mut cx| async move {
4414            let definitions = definitions.await?;
4415            workspace.update(&mut cx, |workspace, cx| {
4416                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
4417                for definition in definitions {
4418                    let range = definition.range.to_offset(definition.buffer.read(cx));
4419
4420                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
4421                    target_editor_handle.update(cx, |target_editor, cx| {
4422                        // When selecting a definition in a different buffer, disable the nav history
4423                        // to avoid creating a history entry at the previous cursor location.
4424                        if editor_handle != target_editor_handle {
4425                            nav_history.borrow_mut().disable();
4426                        }
4427                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
4428                        nav_history.borrow_mut().enable();
4429                    });
4430                }
4431            });
4432
4433            Ok::<(), anyhow::Error>(())
4434        })
4435        .detach_and_log_err(cx);
4436    }
4437
4438    pub fn find_all_references(
4439        workspace: &mut Workspace,
4440        _: &FindAllReferences,
4441        cx: &mut ViewContext<Workspace>,
4442    ) -> Option<Task<Result<()>>> {
4443        let active_item = workspace.active_item(cx)?;
4444        let editor_handle = active_item.act_as::<Self>(cx)?;
4445
4446        let editor = editor_handle.read(cx);
4447        let head = editor.newest_selection::<usize>(cx).head();
4448        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
4449        let replica_id = editor.replica_id(cx);
4450
4451        let project = workspace.project().clone();
4452        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
4453        Some(cx.spawn(|workspace, mut cx| async move {
4454            let mut locations = references.await?;
4455            if locations.is_empty() {
4456                return Ok(());
4457            }
4458
4459            locations.sort_by_key(|location| location.buffer.id());
4460            let mut locations = locations.into_iter().peekable();
4461            let mut ranges_to_highlight = Vec::new();
4462
4463            let excerpt_buffer = cx.add_model(|cx| {
4464                let mut symbol_name = None;
4465                let mut multibuffer = MultiBuffer::new(replica_id);
4466                while let Some(location) = locations.next() {
4467                    let buffer = location.buffer.read(cx);
4468                    let mut ranges_for_buffer = Vec::new();
4469                    let range = location.range.to_offset(buffer);
4470                    ranges_for_buffer.push(range.clone());
4471                    if symbol_name.is_none() {
4472                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
4473                    }
4474
4475                    while let Some(next_location) = locations.peek() {
4476                        if next_location.buffer == location.buffer {
4477                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
4478                            locations.next();
4479                        } else {
4480                            break;
4481                        }
4482                    }
4483
4484                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
4485                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
4486                        location.buffer.clone(),
4487                        ranges_for_buffer,
4488                        1,
4489                        cx,
4490                    ));
4491                }
4492                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
4493            });
4494
4495            workspace.update(&mut cx, |workspace, cx| {
4496                let editor =
4497                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
4498                editor.update(cx, |editor, cx| {
4499                    let color = editor.style(cx).highlighted_line_background;
4500                    editor.highlight_background::<Self>(ranges_to_highlight, color, cx);
4501                });
4502                workspace.add_item(Box::new(editor), cx);
4503            });
4504
4505            Ok(())
4506        }))
4507    }
4508
4509    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
4510        use language::ToOffset as _;
4511
4512        let project = self.project.clone()?;
4513        let selection = self.newest_anchor_selection().clone();
4514        let (cursor_buffer, cursor_buffer_position) = self
4515            .buffer
4516            .read(cx)
4517            .text_anchor_for_position(selection.head(), cx)?;
4518        let (tail_buffer, _) = self
4519            .buffer
4520            .read(cx)
4521            .text_anchor_for_position(selection.tail(), cx)?;
4522        if tail_buffer != cursor_buffer {
4523            return None;
4524        }
4525
4526        let snapshot = cursor_buffer.read(cx).snapshot();
4527        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
4528        let prepare_rename = project.update(cx, |project, cx| {
4529            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
4530        });
4531
4532        Some(cx.spawn(|this, mut cx| async move {
4533            if let Some(rename_range) = prepare_rename.await? {
4534                let rename_buffer_range = rename_range.to_offset(&snapshot);
4535                let cursor_offset_in_rename_range =
4536                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
4537
4538                this.update(&mut cx, |this, cx| {
4539                    this.take_rename(false, cx);
4540                    let style = this.style(cx);
4541                    let buffer = this.buffer.read(cx).read(cx);
4542                    let cursor_offset = selection.head().to_offset(&buffer);
4543                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
4544                    let rename_end = rename_start + rename_buffer_range.len();
4545                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
4546                    let mut old_highlight_id = None;
4547                    let old_name = buffer
4548                        .chunks(rename_start..rename_end, true)
4549                        .map(|chunk| {
4550                            if old_highlight_id.is_none() {
4551                                old_highlight_id = chunk.syntax_highlight_id;
4552                            }
4553                            chunk.text
4554                        })
4555                        .collect();
4556
4557                    drop(buffer);
4558
4559                    // Position the selection in the rename editor so that it matches the current selection.
4560                    this.show_local_selections = false;
4561                    let rename_editor = cx.add_view(|cx| {
4562                        let mut editor = Editor::single_line(None, cx);
4563                        if let Some(old_highlight_id) = old_highlight_id {
4564                            editor.override_text_style =
4565                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
4566                        }
4567                        editor
4568                            .buffer
4569                            .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
4570                        editor.select_all(&SelectAll, cx);
4571                        editor
4572                    });
4573
4574                    let ranges = this
4575                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
4576                        .into_iter()
4577                        .flat_map(|(_, ranges)| ranges)
4578                        .chain(
4579                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
4580                                .into_iter()
4581                                .flat_map(|(_, ranges)| ranges),
4582                        )
4583                        .collect();
4584
4585                    this.highlight_text::<Rename>(
4586                        ranges,
4587                        HighlightStyle {
4588                            fade_out: Some(style.rename_fade),
4589                            ..Default::default()
4590                        },
4591                        cx,
4592                    );
4593                    cx.focus(&rename_editor);
4594                    let block_id = this.insert_blocks(
4595                        [BlockProperties {
4596                            position: range.start.clone(),
4597                            height: 1,
4598                            render: Arc::new({
4599                                let editor = rename_editor.clone();
4600                                move |cx: &BlockContext| {
4601                                    ChildView::new(editor.clone())
4602                                        .contained()
4603                                        .with_padding_left(cx.anchor_x)
4604                                        .boxed()
4605                                }
4606                            }),
4607                            disposition: BlockDisposition::Below,
4608                        }],
4609                        cx,
4610                    )[0];
4611                    this.pending_rename = Some(RenameState {
4612                        range,
4613                        old_name,
4614                        editor: rename_editor,
4615                        block_id,
4616                    });
4617                });
4618            }
4619
4620            Ok(())
4621        }))
4622    }
4623
4624    pub fn confirm_rename(
4625        workspace: &mut Workspace,
4626        _: &ConfirmRename,
4627        cx: &mut ViewContext<Workspace>,
4628    ) -> Option<Task<Result<()>>> {
4629        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
4630
4631        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
4632            let rename = editor.take_rename(false, cx)?;
4633            let buffer = editor.buffer.read(cx);
4634            let (start_buffer, start) =
4635                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
4636            let (end_buffer, end) =
4637                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
4638            if start_buffer == end_buffer {
4639                let new_name = rename.editor.read(cx).text(cx);
4640                Some((start_buffer, start..end, rename.old_name, new_name))
4641            } else {
4642                None
4643            }
4644        })?;
4645
4646        let rename = workspace.project().clone().update(cx, |project, cx| {
4647            project.perform_rename(
4648                buffer.clone(),
4649                range.start.clone(),
4650                new_name.clone(),
4651                true,
4652                cx,
4653            )
4654        });
4655
4656        Some(cx.spawn(|workspace, mut cx| async move {
4657            let project_transaction = rename.await?;
4658            Self::open_project_transaction(
4659                editor.clone(),
4660                workspace,
4661                project_transaction,
4662                format!("Rename: {}{}", old_name, new_name),
4663                cx.clone(),
4664            )
4665            .await?;
4666
4667            editor.update(&mut cx, |editor, cx| {
4668                editor.refresh_document_highlights(cx);
4669            });
4670            Ok(())
4671        }))
4672    }
4673
4674    fn take_rename(
4675        &mut self,
4676        moving_cursor: bool,
4677        cx: &mut ViewContext<Self>,
4678    ) -> Option<RenameState> {
4679        let rename = self.pending_rename.take()?;
4680        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
4681        self.clear_text_highlights::<Rename>(cx);
4682        self.show_local_selections = true;
4683
4684        if moving_cursor {
4685            let cursor_in_rename_editor =
4686                rename.editor.read(cx).newest_selection::<usize>(cx).head();
4687
4688            // Update the selection to match the position of the selection inside
4689            // the rename editor.
4690            let snapshot = self.buffer.read(cx).read(cx);
4691            let rename_range = rename.range.to_offset(&snapshot);
4692            let cursor_in_editor = snapshot
4693                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
4694                .min(rename_range.end);
4695            drop(snapshot);
4696
4697            self.update_selections(
4698                vec![Selection {
4699                    id: self.newest_anchor_selection().id,
4700                    start: cursor_in_editor,
4701                    end: cursor_in_editor,
4702                    reversed: false,
4703                    goal: SelectionGoal::None,
4704                }],
4705                None,
4706                cx,
4707            );
4708        }
4709
4710        Some(rename)
4711    }
4712
4713    fn invalidate_rename_range(
4714        &mut self,
4715        buffer: &MultiBufferSnapshot,
4716        cx: &mut ViewContext<Self>,
4717    ) {
4718        if let Some(rename) = self.pending_rename.as_ref() {
4719            if self.selections.len() == 1 {
4720                let head = self.selections[0].head().to_offset(buffer);
4721                let range = rename.range.to_offset(buffer).to_inclusive();
4722                if range.contains(&head) {
4723                    return;
4724                }
4725            }
4726            let rename = self.pending_rename.take().unwrap();
4727            self.remove_blocks([rename.block_id].into_iter().collect(), cx);
4728            self.clear_background_highlights::<Rename>(cx);
4729        }
4730    }
4731
4732    #[cfg(any(test, feature = "test-support"))]
4733    pub fn pending_rename(&self) -> Option<&RenameState> {
4734        self.pending_rename.as_ref()
4735    }
4736
4737    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
4738        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
4739            let buffer = self.buffer.read(cx).snapshot(cx);
4740            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
4741            let is_valid = buffer
4742                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
4743                .any(|entry| {
4744                    entry.diagnostic.is_primary
4745                        && !entry.range.is_empty()
4746                        && entry.range.start == primary_range_start
4747                        && entry.diagnostic.message == active_diagnostics.primary_message
4748                });
4749
4750            if is_valid != active_diagnostics.is_valid {
4751                active_diagnostics.is_valid = is_valid;
4752                let mut new_styles = HashMap::default();
4753                for (block_id, diagnostic) in &active_diagnostics.blocks {
4754                    new_styles.insert(
4755                        *block_id,
4756                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
4757                    );
4758                }
4759                self.display_map
4760                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
4761            }
4762        }
4763    }
4764
4765    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
4766        self.dismiss_diagnostics(cx);
4767        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
4768            let buffer = self.buffer.read(cx).snapshot(cx);
4769
4770            let mut primary_range = None;
4771            let mut primary_message = None;
4772            let mut group_end = Point::zero();
4773            let diagnostic_group = buffer
4774                .diagnostic_group::<Point>(group_id)
4775                .map(|entry| {
4776                    if entry.range.end > group_end {
4777                        group_end = entry.range.end;
4778                    }
4779                    if entry.diagnostic.is_primary {
4780                        primary_range = Some(entry.range.clone());
4781                        primary_message = Some(entry.diagnostic.message.clone());
4782                    }
4783                    entry
4784                })
4785                .collect::<Vec<_>>();
4786            let primary_range = primary_range.unwrap();
4787            let primary_message = primary_message.unwrap();
4788            let primary_range =
4789                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
4790
4791            let blocks = display_map
4792                .insert_blocks(
4793                    diagnostic_group.iter().map(|entry| {
4794                        let diagnostic = entry.diagnostic.clone();
4795                        let message_height = diagnostic.message.lines().count() as u8;
4796                        BlockProperties {
4797                            position: buffer.anchor_after(entry.range.start),
4798                            height: message_height,
4799                            render: diagnostic_block_renderer(diagnostic, true),
4800                            disposition: BlockDisposition::Below,
4801                        }
4802                    }),
4803                    cx,
4804                )
4805                .into_iter()
4806                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
4807                .collect();
4808
4809            Some(ActiveDiagnosticGroup {
4810                primary_range,
4811                primary_message,
4812                blocks,
4813                is_valid: true,
4814            })
4815        });
4816    }
4817
4818    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
4819        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
4820            self.display_map.update(cx, |display_map, cx| {
4821                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
4822            });
4823            cx.notify();
4824        }
4825    }
4826
4827    fn build_columnar_selection(
4828        &mut self,
4829        display_map: &DisplaySnapshot,
4830        row: u32,
4831        columns: &Range<u32>,
4832        reversed: bool,
4833    ) -> Option<Selection<Point>> {
4834        let is_empty = columns.start == columns.end;
4835        let line_len = display_map.line_len(row);
4836        if columns.start < line_len || (is_empty && columns.start == line_len) {
4837            let start = DisplayPoint::new(row, columns.start);
4838            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
4839            Some(Selection {
4840                id: post_inc(&mut self.next_selection_id),
4841                start: start.to_point(display_map),
4842                end: end.to_point(display_map),
4843                reversed,
4844                goal: SelectionGoal::ColumnRange {
4845                    start: columns.start,
4846                    end: columns.end,
4847                },
4848            })
4849        } else {
4850            None
4851        }
4852    }
4853
4854    pub fn local_selections_in_range(
4855        &self,
4856        range: Range<Anchor>,
4857        display_map: &DisplaySnapshot,
4858    ) -> Vec<Selection<Point>> {
4859        let buffer = &display_map.buffer_snapshot;
4860
4861        let start_ix = match self
4862            .selections
4863            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
4864        {
4865            Ok(ix) | Err(ix) => ix,
4866        };
4867        let end_ix = match self
4868            .selections
4869            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
4870        {
4871            Ok(ix) => ix + 1,
4872            Err(ix) => ix,
4873        };
4874
4875        fn point_selection(
4876            selection: &Selection<Anchor>,
4877            buffer: &MultiBufferSnapshot,
4878        ) -> Selection<Point> {
4879            let start = selection.start.to_point(&buffer);
4880            let end = selection.end.to_point(&buffer);
4881            Selection {
4882                id: selection.id,
4883                start,
4884                end,
4885                reversed: selection.reversed,
4886                goal: selection.goal,
4887            }
4888        }
4889
4890        self.selections[start_ix..end_ix]
4891            .iter()
4892            .chain(
4893                self.pending_selection
4894                    .as_ref()
4895                    .map(|pending| &pending.selection),
4896            )
4897            .map(|s| point_selection(s, &buffer))
4898            .collect()
4899    }
4900
4901    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
4902    where
4903        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
4904    {
4905        let buffer = self.buffer.read(cx).snapshot(cx);
4906        let mut selections = self
4907            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
4908            .peekable();
4909
4910        let mut pending_selection = self.pending_selection::<D>(&buffer);
4911
4912        iter::from_fn(move || {
4913            if let Some(pending) = pending_selection.as_mut() {
4914                while let Some(next_selection) = selections.peek() {
4915                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
4916                        let next_selection = selections.next().unwrap();
4917                        if next_selection.start < pending.start {
4918                            pending.start = next_selection.start;
4919                        }
4920                        if next_selection.end > pending.end {
4921                            pending.end = next_selection.end;
4922                        }
4923                    } else if next_selection.end < pending.start {
4924                        return selections.next();
4925                    } else {
4926                        break;
4927                    }
4928                }
4929
4930                pending_selection.take()
4931            } else {
4932                selections.next()
4933            }
4934        })
4935        .collect()
4936    }
4937
4938    fn resolve_selections<'a, D, I>(
4939        &self,
4940        selections: I,
4941        snapshot: &MultiBufferSnapshot,
4942    ) -> impl 'a + Iterator<Item = Selection<D>>
4943    where
4944        D: TextDimension + Ord + Sub<D, Output = D>,
4945        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
4946    {
4947        let (to_summarize, selections) = selections.into_iter().tee();
4948        let mut summaries = snapshot
4949            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
4950            .into_iter();
4951        selections.map(move |s| Selection {
4952            id: s.id,
4953            start: summaries.next().unwrap(),
4954            end: summaries.next().unwrap(),
4955            reversed: s.reversed,
4956            goal: s.goal,
4957        })
4958    }
4959
4960    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4961        &self,
4962        snapshot: &MultiBufferSnapshot,
4963    ) -> Option<Selection<D>> {
4964        self.pending_selection
4965            .as_ref()
4966            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
4967    }
4968
4969    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4970        &self,
4971        selection: &Selection<Anchor>,
4972        buffer: &MultiBufferSnapshot,
4973    ) -> Selection<D> {
4974        Selection {
4975            id: selection.id,
4976            start: selection.start.summary::<D>(&buffer),
4977            end: selection.end.summary::<D>(&buffer),
4978            reversed: selection.reversed,
4979            goal: selection.goal,
4980        }
4981    }
4982
4983    fn selection_count<'a>(&self) -> usize {
4984        let mut count = self.selections.len();
4985        if self.pending_selection.is_some() {
4986            count += 1;
4987        }
4988        count
4989    }
4990
4991    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4992        &self,
4993        cx: &AppContext,
4994    ) -> Selection<D> {
4995        let snapshot = self.buffer.read(cx).read(cx);
4996        self.selections
4997            .iter()
4998            .min_by_key(|s| s.id)
4999            .map(|selection| self.resolve_selection(selection, &snapshot))
5000            .or_else(|| self.pending_selection(&snapshot))
5001            .unwrap()
5002    }
5003
5004    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
5005        &self,
5006        cx: &AppContext,
5007    ) -> Selection<D> {
5008        self.resolve_selection(
5009            self.newest_anchor_selection(),
5010            &self.buffer.read(cx).read(cx),
5011        )
5012    }
5013
5014    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
5015        &self,
5016        snapshot: &MultiBufferSnapshot,
5017    ) -> Selection<D> {
5018        self.resolve_selection(self.newest_anchor_selection(), snapshot)
5019    }
5020
5021    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
5022        self.pending_selection
5023            .as_ref()
5024            .map(|s| &s.selection)
5025            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
5026            .unwrap()
5027    }
5028
5029    pub fn update_selections<T>(
5030        &mut self,
5031        mut selections: Vec<Selection<T>>,
5032        autoscroll: Option<Autoscroll>,
5033        cx: &mut ViewContext<Self>,
5034    ) where
5035        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
5036    {
5037        let buffer = self.buffer.read(cx).snapshot(cx);
5038        selections.sort_unstable_by_key(|s| s.start);
5039
5040        // Merge overlapping selections.
5041        let mut i = 1;
5042        while i < selections.len() {
5043            if selections[i - 1].end >= selections[i].start {
5044                let removed = selections.remove(i);
5045                if removed.start < selections[i - 1].start {
5046                    selections[i - 1].start = removed.start;
5047                }
5048                if removed.end > selections[i - 1].end {
5049                    selections[i - 1].end = removed.end;
5050                }
5051            } else {
5052                i += 1;
5053            }
5054        }
5055
5056        if let Some(autoscroll) = autoscroll {
5057            self.request_autoscroll(autoscroll, cx);
5058        }
5059
5060        self.set_selections(
5061            Arc::from_iter(selections.into_iter().map(|selection| {
5062                let end_bias = if selection.end > selection.start {
5063                    Bias::Left
5064                } else {
5065                    Bias::Right
5066                };
5067                Selection {
5068                    id: selection.id,
5069                    start: buffer.anchor_after(selection.start),
5070                    end: buffer.anchor_at(selection.end, end_bias),
5071                    reversed: selection.reversed,
5072                    goal: selection.goal,
5073                }
5074            })),
5075            None,
5076            true,
5077            cx,
5078        );
5079    }
5080
5081    pub fn set_selections_from_remote(
5082        &mut self,
5083        mut selections: Vec<Selection<Anchor>>,
5084        cx: &mut ViewContext<Self>,
5085    ) {
5086        let buffer = self.buffer.read(cx);
5087        let buffer = buffer.read(cx);
5088        selections.sort_by(|a, b| {
5089            a.start
5090                .cmp(&b.start, &*buffer)
5091                .then_with(|| b.end.cmp(&a.end, &*buffer))
5092        });
5093
5094        // Merge overlapping selections
5095        let mut i = 1;
5096        while i < selections.len() {
5097            if selections[i - 1]
5098                .end
5099                .cmp(&selections[i].start, &*buffer)
5100                .is_ge()
5101            {
5102                let removed = selections.remove(i);
5103                if removed
5104                    .start
5105                    .cmp(&selections[i - 1].start, &*buffer)
5106                    .is_lt()
5107                {
5108                    selections[i - 1].start = removed.start;
5109                }
5110                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
5111                    selections[i - 1].end = removed.end;
5112                }
5113            } else {
5114                i += 1;
5115            }
5116        }
5117
5118        drop(buffer);
5119        self.set_selections(selections.into(), None, false, cx);
5120    }
5121
5122    /// Compute new ranges for any selections that were located in excerpts that have
5123    /// since been removed.
5124    ///
5125    /// Returns a `HashMap` indicating which selections whose former head position
5126    /// was no longer present. The keys of the map are selection ids. The values are
5127    /// the id of the new excerpt where the head of the selection has been moved.
5128    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
5129        let snapshot = self.buffer.read(cx).read(cx);
5130        let mut selections_with_lost_position = HashMap::default();
5131
5132        let mut pending_selection = self.pending_selection.take();
5133        if let Some(pending) = pending_selection.as_mut() {
5134            let anchors =
5135                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
5136            let (_, start, kept_start) = anchors[0].clone();
5137            let (_, end, kept_end) = anchors[1].clone();
5138            let kept_head = if pending.selection.reversed {
5139                kept_start
5140            } else {
5141                kept_end
5142            };
5143            if !kept_head {
5144                selections_with_lost_position.insert(
5145                    pending.selection.id,
5146                    pending.selection.head().excerpt_id.clone(),
5147                );
5148            }
5149
5150            pending.selection.start = start;
5151            pending.selection.end = end;
5152        }
5153
5154        let anchors_with_status = snapshot.refresh_anchors(
5155            self.selections
5156                .iter()
5157                .flat_map(|selection| [&selection.start, &selection.end]),
5158        );
5159        self.selections = anchors_with_status
5160            .chunks(2)
5161            .map(|selection_anchors| {
5162                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
5163                let (_, end, kept_end) = selection_anchors[1].clone();
5164                let selection = &self.selections[anchor_ix / 2];
5165                let kept_head = if selection.reversed {
5166                    kept_start
5167                } else {
5168                    kept_end
5169                };
5170                if !kept_head {
5171                    selections_with_lost_position
5172                        .insert(selection.id, selection.head().excerpt_id.clone());
5173                }
5174
5175                Selection {
5176                    id: selection.id,
5177                    start,
5178                    end,
5179                    reversed: selection.reversed,
5180                    goal: selection.goal,
5181                }
5182            })
5183            .collect();
5184        drop(snapshot);
5185
5186        let new_selections = self.local_selections::<usize>(cx);
5187        if !new_selections.is_empty() {
5188            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
5189        }
5190        self.pending_selection = pending_selection;
5191
5192        selections_with_lost_position
5193    }
5194
5195    fn set_selections(
5196        &mut self,
5197        selections: Arc<[Selection<Anchor>]>,
5198        pending_selection: Option<PendingSelection>,
5199        local: bool,
5200        cx: &mut ViewContext<Self>,
5201    ) {
5202        assert!(
5203            !selections.is_empty() || pending_selection.is_some(),
5204            "must have at least one selection"
5205        );
5206
5207        let old_cursor_position = self.newest_anchor_selection().head();
5208
5209        self.selections = selections;
5210        self.pending_selection = pending_selection;
5211        if self.focused && self.leader_replica_id.is_none() {
5212            self.buffer.update(cx, |buffer, cx| {
5213                buffer.set_active_selections(&self.selections, cx)
5214            });
5215        }
5216
5217        let display_map = self
5218            .display_map
5219            .update(cx, |display_map, cx| display_map.snapshot(cx));
5220        let buffer = &display_map.buffer_snapshot;
5221        self.add_selections_state = None;
5222        self.select_next_state = None;
5223        self.select_larger_syntax_node_stack.clear();
5224        self.autoclose_stack.invalidate(&self.selections, &buffer);
5225        self.snippet_stack.invalidate(&self.selections, &buffer);
5226        self.invalidate_rename_range(&buffer, cx);
5227
5228        let new_cursor_position = self.newest_anchor_selection().head();
5229
5230        self.push_to_nav_history(
5231            old_cursor_position.clone(),
5232            Some(new_cursor_position.to_point(&buffer)),
5233            cx,
5234        );
5235
5236        if local {
5237            let completion_menu = match self.context_menu.as_mut() {
5238                Some(ContextMenu::Completions(menu)) => Some(menu),
5239                _ => {
5240                    self.context_menu.take();
5241                    None
5242                }
5243            };
5244
5245            if let Some(completion_menu) = completion_menu {
5246                let cursor_position = new_cursor_position.to_offset(&buffer);
5247                let (word_range, kind) =
5248                    buffer.surrounding_word(completion_menu.initial_position.clone());
5249                if kind == Some(CharKind::Word)
5250                    && word_range.to_inclusive().contains(&cursor_position)
5251                {
5252                    let query = Self::completion_query(&buffer, cursor_position);
5253                    cx.background()
5254                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
5255                    self.show_completions(&ShowCompletions, cx);
5256                } else {
5257                    self.hide_context_menu(cx);
5258                }
5259            }
5260
5261            if old_cursor_position.to_display_point(&display_map).row()
5262                != new_cursor_position.to_display_point(&display_map).row()
5263            {
5264                self.available_code_actions.take();
5265            }
5266            self.refresh_code_actions(cx);
5267            self.refresh_document_highlights(cx);
5268        }
5269
5270        self.pause_cursor_blinking(cx);
5271        cx.emit(Event::SelectionsChanged { local });
5272    }
5273
5274    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5275        self.autoscroll_request = Some((autoscroll, true));
5276        cx.notify();
5277    }
5278
5279    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5280        self.autoscroll_request = Some((autoscroll, false));
5281        cx.notify();
5282    }
5283
5284    pub fn transact(
5285        &mut self,
5286        cx: &mut ViewContext<Self>,
5287        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5288    ) {
5289        self.start_transaction_at(Instant::now(), cx);
5290        update(self, cx);
5291        self.end_transaction_at(Instant::now(), cx);
5292    }
5293
5294    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5295        self.end_selection(cx);
5296        if let Some(tx_id) = self
5297            .buffer
5298            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5299        {
5300            self.selection_history
5301                .insert(tx_id, (self.selections.clone(), None));
5302        }
5303    }
5304
5305    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5306        if let Some(tx_id) = self
5307            .buffer
5308            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5309        {
5310            if let Some((_, end_selections)) = self.selection_history.get_mut(&tx_id) {
5311                *end_selections = Some(self.selections.clone());
5312            } else {
5313                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5314            }
5315
5316            cx.emit(Event::Edited);
5317        }
5318    }
5319
5320    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
5321        log::info!("Editor::page_up");
5322    }
5323
5324    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
5325        log::info!("Editor::page_down");
5326    }
5327
5328    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5329        let mut fold_ranges = Vec::new();
5330
5331        let selections = self.local_selections::<Point>(cx);
5332        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5333        for selection in selections {
5334            let range = selection.display_range(&display_map).sorted();
5335            let buffer_start_row = range.start.to_point(&display_map).row;
5336
5337            for row in (0..=range.end.row()).rev() {
5338                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5339                    let fold_range = self.foldable_range_for_line(&display_map, row);
5340                    if fold_range.end.row >= buffer_start_row {
5341                        fold_ranges.push(fold_range);
5342                        if row <= range.start.row() {
5343                            break;
5344                        }
5345                    }
5346                }
5347            }
5348        }
5349
5350        self.fold_ranges(fold_ranges, cx);
5351    }
5352
5353    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5354        let selections = self.local_selections::<Point>(cx);
5355        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5356        let buffer = &display_map.buffer_snapshot;
5357        let ranges = selections
5358            .iter()
5359            .map(|s| {
5360                let range = s.display_range(&display_map).sorted();
5361                let mut start = range.start.to_point(&display_map);
5362                let mut end = range.end.to_point(&display_map);
5363                start.column = 0;
5364                end.column = buffer.line_len(end.row);
5365                start..end
5366            })
5367            .collect::<Vec<_>>();
5368        self.unfold_ranges(ranges, true, cx);
5369    }
5370
5371    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5372        let max_point = display_map.max_point();
5373        if display_row >= max_point.row() {
5374            false
5375        } else {
5376            let (start_indent, is_blank) = display_map.line_indent(display_row);
5377            if is_blank {
5378                false
5379            } else {
5380                for display_row in display_row + 1..=max_point.row() {
5381                    let (indent, is_blank) = display_map.line_indent(display_row);
5382                    if !is_blank {
5383                        return indent > start_indent;
5384                    }
5385                }
5386                false
5387            }
5388        }
5389    }
5390
5391    fn foldable_range_for_line(
5392        &self,
5393        display_map: &DisplaySnapshot,
5394        start_row: u32,
5395    ) -> Range<Point> {
5396        let max_point = display_map.max_point();
5397
5398        let (start_indent, _) = display_map.line_indent(start_row);
5399        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5400        let mut end = None;
5401        for row in start_row + 1..=max_point.row() {
5402            let (indent, is_blank) = display_map.line_indent(row);
5403            if !is_blank && indent <= start_indent {
5404                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5405                break;
5406            }
5407        }
5408
5409        let end = end.unwrap_or(max_point);
5410        return start.to_point(display_map)..end.to_point(display_map);
5411    }
5412
5413    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5414        let selections = self.local_selections::<Point>(cx);
5415        let ranges = selections.into_iter().map(|s| s.start..s.end);
5416        self.fold_ranges(ranges, cx);
5417    }
5418
5419    pub fn fold_ranges<T: ToOffset>(
5420        &mut self,
5421        ranges: impl IntoIterator<Item = Range<T>>,
5422        cx: &mut ViewContext<Self>,
5423    ) {
5424        let mut ranges = ranges.into_iter().peekable();
5425        if ranges.peek().is_some() {
5426            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5427            self.request_autoscroll(Autoscroll::Fit, cx);
5428            cx.notify();
5429        }
5430    }
5431
5432    pub fn unfold_ranges<T: ToOffset>(
5433        &mut self,
5434        ranges: impl IntoIterator<Item = Range<T>>,
5435        inclusive: bool,
5436        cx: &mut ViewContext<Self>,
5437    ) {
5438        let mut ranges = ranges.into_iter().peekable();
5439        if ranges.peek().is_some() {
5440            self.display_map
5441                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5442            self.request_autoscroll(Autoscroll::Fit, cx);
5443            cx.notify();
5444        }
5445    }
5446
5447    pub fn insert_blocks(
5448        &mut self,
5449        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5450        cx: &mut ViewContext<Self>,
5451    ) -> Vec<BlockId> {
5452        let blocks = self
5453            .display_map
5454            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5455        self.request_autoscroll(Autoscroll::Fit, cx);
5456        blocks
5457    }
5458
5459    pub fn replace_blocks(
5460        &mut self,
5461        blocks: HashMap<BlockId, RenderBlock>,
5462        cx: &mut ViewContext<Self>,
5463    ) {
5464        self.display_map
5465            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5466        self.request_autoscroll(Autoscroll::Fit, cx);
5467    }
5468
5469    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5470        self.display_map.update(cx, |display_map, cx| {
5471            display_map.remove_blocks(block_ids, cx)
5472        });
5473    }
5474
5475    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5476        self.display_map
5477            .update(cx, |map, cx| map.snapshot(cx))
5478            .longest_row()
5479    }
5480
5481    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5482        self.display_map
5483            .update(cx, |map, cx| map.snapshot(cx))
5484            .max_point()
5485    }
5486
5487    pub fn text(&self, cx: &AppContext) -> String {
5488        self.buffer.read(cx).read(cx).text()
5489    }
5490
5491    pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
5492        self.transact(cx, |this, cx| {
5493            this.buffer
5494                .read(cx)
5495                .as_singleton()
5496                .expect("you can only call set_text on editors for singleton buffers")
5497                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5498        });
5499    }
5500
5501    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5502        self.display_map
5503            .update(cx, |map, cx| map.snapshot(cx))
5504            .text()
5505    }
5506
5507    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5508        let language = self.language(cx);
5509        let settings = cx.global::<Settings>();
5510        let mode = self
5511            .soft_wrap_mode_override
5512            .unwrap_or_else(|| settings.soft_wrap(language));
5513        match mode {
5514            settings::SoftWrap::None => SoftWrap::None,
5515            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5516            settings::SoftWrap::PreferredLineLength => {
5517                SoftWrap::Column(settings.preferred_line_length(language))
5518            }
5519        }
5520    }
5521
5522    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5523        self.soft_wrap_mode_override = Some(mode);
5524        cx.notify();
5525    }
5526
5527    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5528        self.display_map
5529            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5530    }
5531
5532    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5533        self.highlighted_rows = rows;
5534    }
5535
5536    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5537        self.highlighted_rows.clone()
5538    }
5539
5540    pub fn highlight_background<T: 'static>(
5541        &mut self,
5542        ranges: Vec<Range<Anchor>>,
5543        color: Color,
5544        cx: &mut ViewContext<Self>,
5545    ) {
5546        self.background_highlights
5547            .insert(TypeId::of::<T>(), (color, ranges));
5548        cx.notify();
5549    }
5550
5551    pub fn clear_background_highlights<T: 'static>(
5552        &mut self,
5553        cx: &mut ViewContext<Self>,
5554    ) -> Option<(Color, Vec<Range<Anchor>>)> {
5555        cx.notify();
5556        self.background_highlights.remove(&TypeId::of::<T>())
5557    }
5558
5559    #[cfg(feature = "test-support")]
5560    pub fn all_background_highlights(
5561        &mut self,
5562        cx: &mut ViewContext<Self>,
5563    ) -> Vec<(Range<DisplayPoint>, Color)> {
5564        let snapshot = self.snapshot(cx);
5565        let buffer = &snapshot.buffer_snapshot;
5566        let start = buffer.anchor_before(0);
5567        let end = buffer.anchor_after(buffer.len());
5568        self.background_highlights_in_range(start..end, &snapshot)
5569    }
5570
5571    pub fn background_highlights_for_type<T: 'static>(&self) -> Option<(Color, &[Range<Anchor>])> {
5572        self.background_highlights
5573            .get(&TypeId::of::<T>())
5574            .map(|(color, ranges)| (*color, ranges.as_slice()))
5575    }
5576
5577    pub fn background_highlights_in_range(
5578        &self,
5579        search_range: Range<Anchor>,
5580        display_snapshot: &DisplaySnapshot,
5581    ) -> Vec<(Range<DisplayPoint>, Color)> {
5582        let mut results = Vec::new();
5583        let buffer = &display_snapshot.buffer_snapshot;
5584        for (color, ranges) in self.background_highlights.values() {
5585            let start_ix = match ranges.binary_search_by(|probe| {
5586                let cmp = probe.end.cmp(&search_range.start, &buffer);
5587                if cmp.is_gt() {
5588                    Ordering::Greater
5589                } else {
5590                    Ordering::Less
5591                }
5592            }) {
5593                Ok(i) | Err(i) => i,
5594            };
5595            for range in &ranges[start_ix..] {
5596                if range.start.cmp(&search_range.end, &buffer).is_ge() {
5597                    break;
5598                }
5599                let start = range
5600                    .start
5601                    .to_point(buffer)
5602                    .to_display_point(display_snapshot);
5603                let end = range
5604                    .end
5605                    .to_point(buffer)
5606                    .to_display_point(display_snapshot);
5607                results.push((start..end, *color))
5608            }
5609        }
5610        results
5611    }
5612
5613    pub fn highlight_text<T: 'static>(
5614        &mut self,
5615        ranges: Vec<Range<Anchor>>,
5616        style: HighlightStyle,
5617        cx: &mut ViewContext<Self>,
5618    ) {
5619        self.display_map.update(cx, |map, _| {
5620            map.highlight_text(TypeId::of::<T>(), ranges, style)
5621        });
5622        cx.notify();
5623    }
5624
5625    pub fn clear_text_highlights<T: 'static>(
5626        &mut self,
5627        cx: &mut ViewContext<Self>,
5628    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5629        cx.notify();
5630        self.display_map
5631            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
5632    }
5633
5634    fn next_blink_epoch(&mut self) -> usize {
5635        self.blink_epoch += 1;
5636        self.blink_epoch
5637    }
5638
5639    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5640        if !self.focused {
5641            return;
5642        }
5643
5644        self.show_local_cursors = true;
5645        cx.notify();
5646
5647        let epoch = self.next_blink_epoch();
5648        cx.spawn(|this, mut cx| {
5649            let this = this.downgrade();
5650            async move {
5651                Timer::after(CURSOR_BLINK_INTERVAL).await;
5652                if let Some(this) = this.upgrade(&cx) {
5653                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5654                }
5655            }
5656        })
5657        .detach();
5658    }
5659
5660    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5661        if epoch == self.blink_epoch {
5662            self.blinking_paused = false;
5663            self.blink_cursors(epoch, cx);
5664        }
5665    }
5666
5667    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5668        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5669            self.show_local_cursors = !self.show_local_cursors;
5670            cx.notify();
5671
5672            let epoch = self.next_blink_epoch();
5673            cx.spawn(|this, mut cx| {
5674                let this = this.downgrade();
5675                async move {
5676                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5677                    if let Some(this) = this.upgrade(&cx) {
5678                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5679                    }
5680                }
5681            })
5682            .detach();
5683        }
5684    }
5685
5686    pub fn show_local_cursors(&self) -> bool {
5687        self.show_local_cursors && self.focused
5688    }
5689
5690    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5691        cx.notify();
5692    }
5693
5694    fn on_buffer_event(
5695        &mut self,
5696        _: ModelHandle<MultiBuffer>,
5697        event: &language::Event,
5698        cx: &mut ViewContext<Self>,
5699    ) {
5700        match event {
5701            language::Event::Edited => {
5702                self.refresh_active_diagnostics(cx);
5703                self.refresh_code_actions(cx);
5704                cx.emit(Event::BufferEdited);
5705            }
5706            language::Event::Dirtied => cx.emit(Event::Dirtied),
5707            language::Event::Saved => cx.emit(Event::Saved),
5708            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5709            language::Event::Reloaded => cx.emit(Event::TitleChanged),
5710            language::Event::Closed => cx.emit(Event::Closed),
5711            language::Event::DiagnosticsUpdated => {
5712                self.refresh_active_diagnostics(cx);
5713            }
5714            _ => {}
5715        }
5716    }
5717
5718    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5719        cx.notify();
5720    }
5721
5722    pub fn set_searchable(&mut self, searchable: bool) {
5723        self.searchable = searchable;
5724    }
5725
5726    pub fn searchable(&self) -> bool {
5727        self.searchable
5728    }
5729
5730    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
5731        let active_item = workspace.active_item(cx);
5732        let editor_handle = if let Some(editor) = active_item
5733            .as_ref()
5734            .and_then(|item| item.act_as::<Self>(cx))
5735        {
5736            editor
5737        } else {
5738            cx.propagate_action();
5739            return;
5740        };
5741
5742        let editor = editor_handle.read(cx);
5743        let buffer = editor.buffer.read(cx);
5744        if buffer.is_singleton() {
5745            cx.propagate_action();
5746            return;
5747        }
5748
5749        let mut new_selections_by_buffer = HashMap::default();
5750        for selection in editor.local_selections::<usize>(cx) {
5751            for (buffer, mut range) in
5752                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
5753            {
5754                if selection.reversed {
5755                    mem::swap(&mut range.start, &mut range.end);
5756                }
5757                new_selections_by_buffer
5758                    .entry(buffer)
5759                    .or_insert(Vec::new())
5760                    .push(range)
5761            }
5762        }
5763
5764        editor_handle.update(cx, |editor, cx| {
5765            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
5766        });
5767        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
5768        nav_history.borrow_mut().disable();
5769
5770        // We defer the pane interaction because we ourselves are a workspace item
5771        // and activating a new item causes the pane to call a method on us reentrantly,
5772        // which panics if we're on the stack.
5773        cx.defer(move |workspace, cx| {
5774            workspace.activate_next_pane(cx);
5775
5776            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
5777                let editor = workspace.open_project_item::<Self>(buffer, cx);
5778                editor.update(cx, |editor, cx| {
5779                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
5780                });
5781            }
5782
5783            nav_history.borrow_mut().enable();
5784        });
5785    }
5786}
5787
5788impl EditorSnapshot {
5789    pub fn is_focused(&self) -> bool {
5790        self.is_focused
5791    }
5792
5793    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
5794        self.placeholder_text.as_ref()
5795    }
5796
5797    pub fn scroll_position(&self) -> Vector2F {
5798        compute_scroll_position(
5799            &self.display_snapshot,
5800            self.scroll_position,
5801            &self.scroll_top_anchor,
5802        )
5803    }
5804}
5805
5806impl Deref for EditorSnapshot {
5807    type Target = DisplaySnapshot;
5808
5809    fn deref(&self) -> &Self::Target {
5810        &self.display_snapshot
5811    }
5812}
5813
5814fn compute_scroll_position(
5815    snapshot: &DisplaySnapshot,
5816    mut scroll_position: Vector2F,
5817    scroll_top_anchor: &Anchor,
5818) -> Vector2F {
5819    if *scroll_top_anchor != Anchor::min() {
5820        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
5821        scroll_position.set_y(scroll_top + scroll_position.y());
5822    } else {
5823        scroll_position.set_y(0.);
5824    }
5825    scroll_position
5826}
5827
5828#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5829pub enum Event {
5830    Activate,
5831    BufferEdited,
5832    Edited,
5833    Blurred,
5834    Dirtied,
5835    Saved,
5836    TitleChanged,
5837    SelectionsChanged { local: bool },
5838    ScrollPositionChanged { local: bool },
5839    Closed,
5840}
5841
5842pub struct EditorFocused(pub ViewHandle<Editor>);
5843pub struct EditorBlurred(pub ViewHandle<Editor>);
5844pub struct EditorReleased(pub WeakViewHandle<Editor>);
5845
5846impl Entity for Editor {
5847    type Event = Event;
5848
5849    fn release(&mut self, cx: &mut MutableAppContext) {
5850        cx.emit_global(EditorReleased(self.handle.clone()));
5851    }
5852}
5853
5854impl View for Editor {
5855    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5856        let style = self.style(cx);
5857        self.display_map.update(cx, |map, cx| {
5858            map.set_font(style.text.font_id, style.text.font_size, cx)
5859        });
5860        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
5861    }
5862
5863    fn ui_name() -> &'static str {
5864        "Editor"
5865    }
5866
5867    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
5868        let focused_event = EditorFocused(cx.handle());
5869        cx.emit_global(focused_event);
5870        if let Some(rename) = self.pending_rename.as_ref() {
5871            cx.focus(&rename.editor);
5872        } else {
5873            self.focused = true;
5874            self.blink_cursors(self.blink_epoch, cx);
5875            self.buffer.update(cx, |buffer, cx| {
5876                buffer.finalize_last_transaction(cx);
5877                if self.leader_replica_id.is_none() {
5878                    buffer.set_active_selections(&self.selections, cx);
5879                }
5880            });
5881        }
5882    }
5883
5884    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
5885        let blurred_event = EditorBlurred(cx.handle());
5886        cx.emit_global(blurred_event);
5887        self.focused = false;
5888        self.buffer
5889            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
5890        self.hide_context_menu(cx);
5891        cx.emit(Event::Blurred);
5892        cx.notify();
5893    }
5894
5895    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
5896        let mut context = Self::default_keymap_context();
5897        let mode = match self.mode {
5898            EditorMode::SingleLine => "single_line",
5899            EditorMode::AutoHeight { .. } => "auto_height",
5900            EditorMode::Full => "full",
5901        };
5902        context.map.insert("mode".into(), mode.into());
5903        if self.pending_rename.is_some() {
5904            context.set.insert("renaming".into());
5905        }
5906        match self.context_menu.as_ref() {
5907            Some(ContextMenu::Completions(_)) => {
5908                context.set.insert("showing_completions".into());
5909            }
5910            Some(ContextMenu::CodeActions(_)) => {
5911                context.set.insert("showing_code_actions".into());
5912            }
5913            None => {}
5914        }
5915
5916        for layer in self.keymap_context_layers.values() {
5917            context.extend(layer);
5918        }
5919
5920        context
5921    }
5922}
5923
5924fn build_style(
5925    settings: &Settings,
5926    get_field_editor_theme: Option<GetFieldEditorTheme>,
5927    override_text_style: Option<&OverrideTextStyle>,
5928    cx: &AppContext,
5929) -> EditorStyle {
5930    let font_cache = cx.font_cache();
5931
5932    let mut theme = settings.theme.editor.clone();
5933    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
5934        let field_editor_theme = get_field_editor_theme(&settings.theme);
5935        theme.text_color = field_editor_theme.text.color;
5936        theme.selection = field_editor_theme.selection;
5937        theme.background = field_editor_theme
5938            .container
5939            .background_color
5940            .unwrap_or_default();
5941        EditorStyle {
5942            text: field_editor_theme.text,
5943            placeholder_text: field_editor_theme.placeholder_text,
5944            theme,
5945        }
5946    } else {
5947        let font_family_id = settings.buffer_font_family;
5948        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
5949        let font_properties = Default::default();
5950        let font_id = font_cache
5951            .select_font(font_family_id, &font_properties)
5952            .unwrap();
5953        let font_size = settings.buffer_font_size;
5954        EditorStyle {
5955            text: TextStyle {
5956                color: settings.theme.editor.text_color,
5957                font_family_name,
5958                font_family_id,
5959                font_id,
5960                font_size,
5961                font_properties,
5962                underline: Default::default(),
5963            },
5964            placeholder_text: None,
5965            theme,
5966        }
5967    };
5968
5969    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
5970        if let Some(highlighted) = style
5971            .text
5972            .clone()
5973            .highlight(highlight_style, font_cache)
5974            .log_err()
5975        {
5976            style.text = highlighted;
5977        }
5978    }
5979
5980    style
5981}
5982
5983trait SelectionExt {
5984    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
5985    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
5986    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
5987    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
5988        -> Range<u32>;
5989}
5990
5991impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
5992    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
5993        let start = self.start.to_point(buffer);
5994        let end = self.end.to_point(buffer);
5995        if self.reversed {
5996            end..start
5997        } else {
5998            start..end
5999        }
6000    }
6001
6002    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6003        let start = self.start.to_offset(buffer);
6004        let end = self.end.to_offset(buffer);
6005        if self.reversed {
6006            end..start
6007        } else {
6008            start..end
6009        }
6010    }
6011
6012    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6013        let start = self
6014            .start
6015            .to_point(&map.buffer_snapshot)
6016            .to_display_point(map);
6017        let end = self
6018            .end
6019            .to_point(&map.buffer_snapshot)
6020            .to_display_point(map);
6021        if self.reversed {
6022            end..start
6023        } else {
6024            start..end
6025        }
6026    }
6027
6028    fn spanned_rows(
6029        &self,
6030        include_end_if_at_line_start: bool,
6031        map: &DisplaySnapshot,
6032    ) -> Range<u32> {
6033        let start = self.start.to_point(&map.buffer_snapshot);
6034        let mut end = self.end.to_point(&map.buffer_snapshot);
6035        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6036            end.row -= 1;
6037        }
6038
6039        let buffer_start = map.prev_line_boundary(start).0;
6040        let buffer_end = map.next_line_boundary(end).0;
6041        buffer_start.row..buffer_end.row + 1
6042    }
6043}
6044
6045impl<T: InvalidationRegion> InvalidationStack<T> {
6046    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6047    where
6048        S: Clone + ToOffset,
6049    {
6050        while let Some(region) = self.last() {
6051            let all_selections_inside_invalidation_ranges =
6052                if selections.len() == region.ranges().len() {
6053                    selections
6054                        .iter()
6055                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
6056                        .all(|(selection, invalidation_range)| {
6057                            let head = selection.head().to_offset(&buffer);
6058                            invalidation_range.start <= head && invalidation_range.end >= head
6059                        })
6060                } else {
6061                    false
6062                };
6063
6064            if all_selections_inside_invalidation_ranges {
6065                break;
6066            } else {
6067                self.pop();
6068            }
6069        }
6070    }
6071}
6072
6073impl<T> Default for InvalidationStack<T> {
6074    fn default() -> Self {
6075        Self(Default::default())
6076    }
6077}
6078
6079impl<T> Deref for InvalidationStack<T> {
6080    type Target = Vec<T>;
6081
6082    fn deref(&self) -> &Self::Target {
6083        &self.0
6084    }
6085}
6086
6087impl<T> DerefMut for InvalidationStack<T> {
6088    fn deref_mut(&mut self) -> &mut Self::Target {
6089        &mut self.0
6090    }
6091}
6092
6093impl InvalidationRegion for BracketPairState {
6094    fn ranges(&self) -> &[Range<Anchor>] {
6095        &self.ranges
6096    }
6097}
6098
6099impl InvalidationRegion for SnippetState {
6100    fn ranges(&self) -> &[Range<Anchor>] {
6101        &self.ranges[self.active_index]
6102    }
6103}
6104
6105impl Deref for EditorStyle {
6106    type Target = theme::Editor;
6107
6108    fn deref(&self) -> &Self::Target {
6109        &self.theme
6110    }
6111}
6112
6113pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6114    let mut highlighted_lines = Vec::new();
6115    for line in diagnostic.message.lines() {
6116        highlighted_lines.push(highlight_diagnostic_message(line));
6117    }
6118
6119    Arc::new(move |cx: &BlockContext| {
6120        let settings = cx.global::<Settings>();
6121        let theme = &settings.theme.editor;
6122        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6123        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6124        Flex::column()
6125            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6126                Label::new(
6127                    line.clone(),
6128                    style.message.clone().with_font_size(font_size),
6129                )
6130                .with_highlights(highlights.clone())
6131                .contained()
6132                .with_margin_left(cx.anchor_x)
6133                .boxed()
6134            }))
6135            .aligned()
6136            .left()
6137            .boxed()
6138    })
6139}
6140
6141pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6142    let mut message_without_backticks = String::new();
6143    let mut prev_offset = 0;
6144    let mut inside_block = false;
6145    let mut highlights = Vec::new();
6146    for (match_ix, (offset, _)) in message
6147        .match_indices('`')
6148        .chain([(message.len(), "")])
6149        .enumerate()
6150    {
6151        message_without_backticks.push_str(&message[prev_offset..offset]);
6152        if inside_block {
6153            highlights.extend(prev_offset - match_ix..offset - match_ix);
6154        }
6155
6156        inside_block = !inside_block;
6157        prev_offset = offset + 1;
6158    }
6159
6160    (message_without_backticks, highlights)
6161}
6162
6163pub fn diagnostic_style(
6164    severity: DiagnosticSeverity,
6165    valid: bool,
6166    theme: &theme::Editor,
6167) -> DiagnosticStyle {
6168    match (severity, valid) {
6169        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6170        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6171        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6172        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6173        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6174        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6175        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6176        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6177        _ => theme.invalid_hint_diagnostic.clone(),
6178    }
6179}
6180
6181pub fn combine_syntax_and_fuzzy_match_highlights(
6182    text: &str,
6183    default_style: HighlightStyle,
6184    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6185    match_indices: &[usize],
6186) -> Vec<(Range<usize>, HighlightStyle)> {
6187    let mut result = Vec::new();
6188    let mut match_indices = match_indices.iter().copied().peekable();
6189
6190    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6191    {
6192        syntax_highlight.weight = None;
6193
6194        // Add highlights for any fuzzy match characters before the next
6195        // syntax highlight range.
6196        while let Some(&match_index) = match_indices.peek() {
6197            if match_index >= range.start {
6198                break;
6199            }
6200            match_indices.next();
6201            let end_index = char_ix_after(match_index, text);
6202            let mut match_style = default_style;
6203            match_style.weight = Some(fonts::Weight::BOLD);
6204            result.push((match_index..end_index, match_style));
6205        }
6206
6207        if range.start == usize::MAX {
6208            break;
6209        }
6210
6211        // Add highlights for any fuzzy match characters within the
6212        // syntax highlight range.
6213        let mut offset = range.start;
6214        while let Some(&match_index) = match_indices.peek() {
6215            if match_index >= range.end {
6216                break;
6217            }
6218
6219            match_indices.next();
6220            if match_index > offset {
6221                result.push((offset..match_index, syntax_highlight));
6222            }
6223
6224            let mut end_index = char_ix_after(match_index, text);
6225            while let Some(&next_match_index) = match_indices.peek() {
6226                if next_match_index == end_index && next_match_index < range.end {
6227                    end_index = char_ix_after(next_match_index, text);
6228                    match_indices.next();
6229                } else {
6230                    break;
6231                }
6232            }
6233
6234            let mut match_style = syntax_highlight;
6235            match_style.weight = Some(fonts::Weight::BOLD);
6236            result.push((match_index..end_index, match_style));
6237            offset = end_index;
6238        }
6239
6240        if offset < range.end {
6241            result.push((offset..range.end, syntax_highlight));
6242        }
6243    }
6244
6245    fn char_ix_after(ix: usize, text: &str) -> usize {
6246        ix + text[ix..].chars().next().unwrap().len_utf8()
6247    }
6248
6249    result
6250}
6251
6252pub fn styled_runs_for_code_label<'a>(
6253    label: &'a CodeLabel,
6254    syntax_theme: &'a theme::SyntaxTheme,
6255) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6256    let fade_out = HighlightStyle {
6257        fade_out: Some(0.35),
6258        ..Default::default()
6259    };
6260
6261    let mut prev_end = label.filter_range.end;
6262    label
6263        .runs
6264        .iter()
6265        .enumerate()
6266        .flat_map(move |(ix, (range, highlight_id))| {
6267            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6268                style
6269            } else {
6270                return Default::default();
6271            };
6272            let mut muted_style = style.clone();
6273            muted_style.highlight(fade_out);
6274
6275            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6276            if range.start >= label.filter_range.end {
6277                if range.start > prev_end {
6278                    runs.push((prev_end..range.start, fade_out));
6279                }
6280                runs.push((range.clone(), muted_style));
6281            } else if range.end <= label.filter_range.end {
6282                runs.push((range.clone(), style));
6283            } else {
6284                runs.push((range.start..label.filter_range.end, style));
6285                runs.push((label.filter_range.end..range.end, muted_style));
6286            }
6287            prev_end = cmp::max(prev_end, range.end);
6288
6289            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6290                runs.push((prev_end..label.text.len(), fade_out));
6291            }
6292
6293            runs
6294        })
6295}
6296
6297#[cfg(test)]
6298mod tests {
6299
6300    use super::*;
6301    use gpui::{
6302        geometry::rect::RectF,
6303        platform::{WindowBounds, WindowOptions},
6304    };
6305    use language::{LanguageConfig, LanguageServerConfig};
6306    use lsp::FakeLanguageServer;
6307    use project::FakeFs;
6308    use smol::stream::StreamExt;
6309    use std::{cell::RefCell, rc::Rc, time::Instant};
6310    use text::Point;
6311    use unindent::Unindent;
6312    use util::test::{marked_text_by, sample_text};
6313    use workspace::FollowableItem;
6314
6315    #[gpui::test]
6316    fn test_edit_events(cx: &mut MutableAppContext) {
6317        populate_settings(cx);
6318        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6319
6320        let events = Rc::new(RefCell::new(Vec::new()));
6321        let (_, editor1) = cx.add_window(Default::default(), {
6322            let events = events.clone();
6323            |cx| {
6324                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6325                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6326                        events.borrow_mut().push(("editor1", *event));
6327                    }
6328                })
6329                .detach();
6330                Editor::for_buffer(buffer.clone(), None, cx)
6331            }
6332        });
6333        let (_, editor2) = cx.add_window(Default::default(), {
6334            let events = events.clone();
6335            |cx| {
6336                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6337                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6338                        events.borrow_mut().push(("editor2", *event));
6339                    }
6340                })
6341                .detach();
6342                Editor::for_buffer(buffer.clone(), None, cx)
6343            }
6344        });
6345        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6346
6347        // Mutating editor 1 will emit an `Edited` event only for that editor.
6348        editor1.update(cx, |editor, cx| editor.insert("X", cx));
6349        assert_eq!(
6350            mem::take(&mut *events.borrow_mut()),
6351            [
6352                ("editor1", Event::Edited),
6353                ("editor1", Event::BufferEdited),
6354                ("editor2", Event::BufferEdited),
6355                ("editor1", Event::Dirtied),
6356                ("editor2", Event::Dirtied)
6357            ]
6358        );
6359
6360        // Mutating editor 2 will emit an `Edited` event only for that editor.
6361        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
6362        assert_eq!(
6363            mem::take(&mut *events.borrow_mut()),
6364            [
6365                ("editor2", Event::Edited),
6366                ("editor1", Event::BufferEdited),
6367                ("editor2", Event::BufferEdited),
6368            ]
6369        );
6370
6371        // Undoing on editor 1 will emit an `Edited` event only for that editor.
6372        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
6373        assert_eq!(
6374            mem::take(&mut *events.borrow_mut()),
6375            [
6376                ("editor1", Event::Edited),
6377                ("editor1", Event::BufferEdited),
6378                ("editor2", Event::BufferEdited),
6379            ]
6380        );
6381
6382        // Redoing on editor 1 will emit an `Edited` event only for that editor.
6383        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
6384        assert_eq!(
6385            mem::take(&mut *events.borrow_mut()),
6386            [
6387                ("editor1", Event::Edited),
6388                ("editor1", Event::BufferEdited),
6389                ("editor2", Event::BufferEdited),
6390            ]
6391        );
6392
6393        // Undoing on editor 2 will emit an `Edited` event only for that editor.
6394        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
6395        assert_eq!(
6396            mem::take(&mut *events.borrow_mut()),
6397            [
6398                ("editor2", Event::Edited),
6399                ("editor1", Event::BufferEdited),
6400                ("editor2", Event::BufferEdited),
6401            ]
6402        );
6403
6404        // Redoing on editor 2 will emit an `Edited` event only for that editor.
6405        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
6406        assert_eq!(
6407            mem::take(&mut *events.borrow_mut()),
6408            [
6409                ("editor2", Event::Edited),
6410                ("editor1", Event::BufferEdited),
6411                ("editor2", Event::BufferEdited),
6412            ]
6413        );
6414
6415        // No event is emitted when the mutation is a no-op.
6416        editor2.update(cx, |editor, cx| {
6417            editor.select_ranges([0..0], None, cx);
6418            editor.backspace(&Backspace, cx);
6419        });
6420        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6421    }
6422
6423    #[gpui::test]
6424    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
6425        populate_settings(cx);
6426        let mut now = Instant::now();
6427        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6428        let group_interval = buffer.read(cx).transaction_group_interval();
6429        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
6430        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6431
6432        editor.update(cx, |editor, cx| {
6433            editor.start_transaction_at(now, cx);
6434            editor.select_ranges([2..4], None, cx);
6435            editor.insert("cd", cx);
6436            editor.end_transaction_at(now, cx);
6437            assert_eq!(editor.text(cx), "12cd56");
6438            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
6439
6440            editor.start_transaction_at(now, cx);
6441            editor.select_ranges([4..5], None, cx);
6442            editor.insert("e", cx);
6443            editor.end_transaction_at(now, cx);
6444            assert_eq!(editor.text(cx), "12cde6");
6445            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
6446
6447            now += group_interval + Duration::from_millis(1);
6448            editor.select_ranges([2..2], None, cx);
6449
6450            // Simulate an edit in another editor
6451            buffer.update(cx, |buffer, cx| {
6452                buffer.start_transaction_at(now, cx);
6453                buffer.edit([0..1], "a", cx);
6454                buffer.edit([1..1], "b", cx);
6455                buffer.end_transaction_at(now, cx);
6456            });
6457
6458            assert_eq!(editor.text(cx), "ab2cde6");
6459            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
6460
6461            // Last transaction happened past the group interval in a different editor.
6462            // Undo it individually and don't restore selections.
6463            editor.undo(&Undo, cx);
6464            assert_eq!(editor.text(cx), "12cde6");
6465            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
6466
6467            // First two transactions happened within the group interval in this editor.
6468            // Undo them together and restore selections.
6469            editor.undo(&Undo, cx);
6470            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
6471            assert_eq!(editor.text(cx), "123456");
6472            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
6473
6474            // Redo the first two transactions together.
6475            editor.redo(&Redo, cx);
6476            assert_eq!(editor.text(cx), "12cde6");
6477            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
6478
6479            // Redo the last transaction on its own.
6480            editor.redo(&Redo, cx);
6481            assert_eq!(editor.text(cx), "ab2cde6");
6482            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
6483
6484            // Test empty transactions.
6485            editor.start_transaction_at(now, cx);
6486            editor.end_transaction_at(now, cx);
6487            editor.undo(&Undo, cx);
6488            assert_eq!(editor.text(cx), "12cde6");
6489        });
6490    }
6491
6492    #[gpui::test]
6493    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
6494        populate_settings(cx);
6495
6496        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
6497        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6498        editor.update(cx, |view, cx| {
6499            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6500        });
6501        assert_eq!(
6502            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6503            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6504        );
6505
6506        editor.update(cx, |view, cx| {
6507            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6508        });
6509
6510        assert_eq!(
6511            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6512            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6513        );
6514
6515        editor.update(cx, |view, cx| {
6516            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6517        });
6518
6519        assert_eq!(
6520            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6521            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6522        );
6523
6524        editor.update(cx, |view, cx| {
6525            view.end_selection(cx);
6526            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6527        });
6528
6529        assert_eq!(
6530            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6531            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6532        );
6533
6534        editor.update(cx, |view, cx| {
6535            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
6536            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
6537        });
6538
6539        assert_eq!(
6540            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6541            [
6542                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
6543                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
6544            ]
6545        );
6546
6547        editor.update(cx, |view, cx| {
6548            view.end_selection(cx);
6549        });
6550
6551        assert_eq!(
6552            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6553            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
6554        );
6555    }
6556
6557    #[gpui::test]
6558    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
6559        populate_settings(cx);
6560        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6561        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6562
6563        view.update(cx, |view, cx| {
6564            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6565            assert_eq!(
6566                view.selected_display_ranges(cx),
6567                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6568            );
6569        });
6570
6571        view.update(cx, |view, cx| {
6572            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6573            assert_eq!(
6574                view.selected_display_ranges(cx),
6575                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6576            );
6577        });
6578
6579        view.update(cx, |view, cx| {
6580            view.cancel(&Cancel, cx);
6581            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6582            assert_eq!(
6583                view.selected_display_ranges(cx),
6584                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6585            );
6586        });
6587    }
6588
6589    #[gpui::test]
6590    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
6591        populate_settings(cx);
6592        use workspace::Item;
6593        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
6594        let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx);
6595
6596        cx.add_window(Default::default(), |cx| {
6597            let mut editor = build_editor(buffer.clone(), cx);
6598            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
6599
6600            // Move the cursor a small distance.
6601            // Nothing is added to the navigation history.
6602            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
6603            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
6604            assert!(nav_history.borrow_mut().pop_backward().is_none());
6605
6606            // Move the cursor a large distance.
6607            // The history can jump back to the previous position.
6608            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
6609            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6610            editor.navigate(nav_entry.data.unwrap(), cx);
6611            assert_eq!(nav_entry.item.id(), cx.view_id());
6612            assert_eq!(
6613                editor.selected_display_ranges(cx),
6614                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
6615            );
6616            assert!(nav_history.borrow_mut().pop_backward().is_none());
6617
6618            // Move the cursor a small distance via the mouse.
6619            // Nothing is added to the navigation history.
6620            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
6621            editor.end_selection(cx);
6622            assert_eq!(
6623                editor.selected_display_ranges(cx),
6624                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6625            );
6626            assert!(nav_history.borrow_mut().pop_backward().is_none());
6627
6628            // Move the cursor a large distance via the mouse.
6629            // The history can jump back to the previous position.
6630            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
6631            editor.end_selection(cx);
6632            assert_eq!(
6633                editor.selected_display_ranges(cx),
6634                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
6635            );
6636            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6637            editor.navigate(nav_entry.data.unwrap(), cx);
6638            assert_eq!(nav_entry.item.id(), cx.view_id());
6639            assert_eq!(
6640                editor.selected_display_ranges(cx),
6641                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6642            );
6643            assert!(nav_history.borrow_mut().pop_backward().is_none());
6644
6645            editor
6646        });
6647    }
6648
6649    #[gpui::test]
6650    fn test_cancel(cx: &mut gpui::MutableAppContext) {
6651        populate_settings(cx);
6652        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6653        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6654
6655        view.update(cx, |view, cx| {
6656            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
6657            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6658            view.end_selection(cx);
6659
6660            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
6661            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
6662            view.end_selection(cx);
6663            assert_eq!(
6664                view.selected_display_ranges(cx),
6665                [
6666                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
6667                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
6668                ]
6669            );
6670        });
6671
6672        view.update(cx, |view, cx| {
6673            view.cancel(&Cancel, cx);
6674            assert_eq!(
6675                view.selected_display_ranges(cx),
6676                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
6677            );
6678        });
6679
6680        view.update(cx, |view, cx| {
6681            view.cancel(&Cancel, cx);
6682            assert_eq!(
6683                view.selected_display_ranges(cx),
6684                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
6685            );
6686        });
6687    }
6688
6689    #[gpui::test]
6690    fn test_fold(cx: &mut gpui::MutableAppContext) {
6691        populate_settings(cx);
6692        let buffer = MultiBuffer::build_simple(
6693            &"
6694                impl Foo {
6695                    // Hello!
6696
6697                    fn a() {
6698                        1
6699                    }
6700
6701                    fn b() {
6702                        2
6703                    }
6704
6705                    fn c() {
6706                        3
6707                    }
6708                }
6709            "
6710            .unindent(),
6711            cx,
6712        );
6713        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6714
6715        view.update(cx, |view, cx| {
6716            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
6717            view.fold(&Fold, cx);
6718            assert_eq!(
6719                view.display_text(cx),
6720                "
6721                    impl Foo {
6722                        // Hello!
6723
6724                        fn a() {
6725                            1
6726                        }
6727
6728                        fn b() {…
6729                        }
6730
6731                        fn c() {…
6732                        }
6733                    }
6734                "
6735                .unindent(),
6736            );
6737
6738            view.fold(&Fold, cx);
6739            assert_eq!(
6740                view.display_text(cx),
6741                "
6742                    impl Foo {…
6743                    }
6744                "
6745                .unindent(),
6746            );
6747
6748            view.unfold_lines(&UnfoldLines, cx);
6749            assert_eq!(
6750                view.display_text(cx),
6751                "
6752                    impl Foo {
6753                        // Hello!
6754
6755                        fn a() {
6756                            1
6757                        }
6758
6759                        fn b() {…
6760                        }
6761
6762                        fn c() {…
6763                        }
6764                    }
6765                "
6766                .unindent(),
6767            );
6768
6769            view.unfold_lines(&UnfoldLines, cx);
6770            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
6771        });
6772    }
6773
6774    #[gpui::test]
6775    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
6776        populate_settings(cx);
6777        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
6778        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6779
6780        buffer.update(cx, |buffer, cx| {
6781            buffer.edit(
6782                vec![
6783                    Point::new(1, 0)..Point::new(1, 0),
6784                    Point::new(1, 1)..Point::new(1, 1),
6785                ],
6786                "\t",
6787                cx,
6788            );
6789        });
6790
6791        view.update(cx, |view, cx| {
6792            assert_eq!(
6793                view.selected_display_ranges(cx),
6794                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6795            );
6796
6797            view.move_down(&MoveDown, cx);
6798            assert_eq!(
6799                view.selected_display_ranges(cx),
6800                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6801            );
6802
6803            view.move_right(&MoveRight, cx);
6804            assert_eq!(
6805                view.selected_display_ranges(cx),
6806                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
6807            );
6808
6809            view.move_left(&MoveLeft, cx);
6810            assert_eq!(
6811                view.selected_display_ranges(cx),
6812                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6813            );
6814
6815            view.move_up(&MoveUp, cx);
6816            assert_eq!(
6817                view.selected_display_ranges(cx),
6818                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6819            );
6820
6821            view.move_to_end(&MoveToEnd, cx);
6822            assert_eq!(
6823                view.selected_display_ranges(cx),
6824                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
6825            );
6826
6827            view.move_to_beginning(&MoveToBeginning, cx);
6828            assert_eq!(
6829                view.selected_display_ranges(cx),
6830                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6831            );
6832
6833            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
6834            view.select_to_beginning(&SelectToBeginning, cx);
6835            assert_eq!(
6836                view.selected_display_ranges(cx),
6837                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
6838            );
6839
6840            view.select_to_end(&SelectToEnd, cx);
6841            assert_eq!(
6842                view.selected_display_ranges(cx),
6843                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
6844            );
6845        });
6846    }
6847
6848    #[gpui::test]
6849    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
6850        populate_settings(cx);
6851        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
6852        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6853
6854        assert_eq!('ⓐ'.len_utf8(), 3);
6855        assert_eq!('α'.len_utf8(), 2);
6856
6857        view.update(cx, |view, cx| {
6858            view.fold_ranges(
6859                vec![
6860                    Point::new(0, 6)..Point::new(0, 12),
6861                    Point::new(1, 2)..Point::new(1, 4),
6862                    Point::new(2, 4)..Point::new(2, 8),
6863                ],
6864                cx,
6865            );
6866            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
6867
6868            view.move_right(&MoveRight, cx);
6869            assert_eq!(
6870                view.selected_display_ranges(cx),
6871                &[empty_range(0, "".len())]
6872            );
6873            view.move_right(&MoveRight, cx);
6874            assert_eq!(
6875                view.selected_display_ranges(cx),
6876                &[empty_range(0, "ⓐⓑ".len())]
6877            );
6878            view.move_right(&MoveRight, cx);
6879            assert_eq!(
6880                view.selected_display_ranges(cx),
6881                &[empty_range(0, "ⓐⓑ…".len())]
6882            );
6883
6884            view.move_down(&MoveDown, cx);
6885            assert_eq!(
6886                view.selected_display_ranges(cx),
6887                &[empty_range(1, "ab…".len())]
6888            );
6889            view.move_left(&MoveLeft, cx);
6890            assert_eq!(
6891                view.selected_display_ranges(cx),
6892                &[empty_range(1, "ab".len())]
6893            );
6894            view.move_left(&MoveLeft, cx);
6895            assert_eq!(
6896                view.selected_display_ranges(cx),
6897                &[empty_range(1, "a".len())]
6898            );
6899
6900            view.move_down(&MoveDown, cx);
6901            assert_eq!(
6902                view.selected_display_ranges(cx),
6903                &[empty_range(2, "α".len())]
6904            );
6905            view.move_right(&MoveRight, cx);
6906            assert_eq!(
6907                view.selected_display_ranges(cx),
6908                &[empty_range(2, "αβ".len())]
6909            );
6910            view.move_right(&MoveRight, cx);
6911            assert_eq!(
6912                view.selected_display_ranges(cx),
6913                &[empty_range(2, "αβ…".len())]
6914            );
6915            view.move_right(&MoveRight, cx);
6916            assert_eq!(
6917                view.selected_display_ranges(cx),
6918                &[empty_range(2, "αβ…ε".len())]
6919            );
6920
6921            view.move_up(&MoveUp, cx);
6922            assert_eq!(
6923                view.selected_display_ranges(cx),
6924                &[empty_range(1, "ab…e".len())]
6925            );
6926            view.move_up(&MoveUp, cx);
6927            assert_eq!(
6928                view.selected_display_ranges(cx),
6929                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
6930            );
6931            view.move_left(&MoveLeft, cx);
6932            assert_eq!(
6933                view.selected_display_ranges(cx),
6934                &[empty_range(0, "ⓐⓑ…".len())]
6935            );
6936            view.move_left(&MoveLeft, cx);
6937            assert_eq!(
6938                view.selected_display_ranges(cx),
6939                &[empty_range(0, "ⓐⓑ".len())]
6940            );
6941            view.move_left(&MoveLeft, cx);
6942            assert_eq!(
6943                view.selected_display_ranges(cx),
6944                &[empty_range(0, "".len())]
6945            );
6946        });
6947    }
6948
6949    #[gpui::test]
6950    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
6951        populate_settings(cx);
6952        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
6953        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6954        view.update(cx, |view, cx| {
6955            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
6956            view.move_down(&MoveDown, cx);
6957            assert_eq!(
6958                view.selected_display_ranges(cx),
6959                &[empty_range(1, "abcd".len())]
6960            );
6961
6962            view.move_down(&MoveDown, cx);
6963            assert_eq!(
6964                view.selected_display_ranges(cx),
6965                &[empty_range(2, "αβγ".len())]
6966            );
6967
6968            view.move_down(&MoveDown, cx);
6969            assert_eq!(
6970                view.selected_display_ranges(cx),
6971                &[empty_range(3, "abcd".len())]
6972            );
6973
6974            view.move_down(&MoveDown, cx);
6975            assert_eq!(
6976                view.selected_display_ranges(cx),
6977                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
6978            );
6979
6980            view.move_up(&MoveUp, cx);
6981            assert_eq!(
6982                view.selected_display_ranges(cx),
6983                &[empty_range(3, "abcd".len())]
6984            );
6985
6986            view.move_up(&MoveUp, cx);
6987            assert_eq!(
6988                view.selected_display_ranges(cx),
6989                &[empty_range(2, "αβγ".len())]
6990            );
6991        });
6992    }
6993
6994    #[gpui::test]
6995    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
6996        populate_settings(cx);
6997        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
6998        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6999        view.update(cx, |view, cx| {
7000            view.select_display_ranges(
7001                &[
7002                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7003                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
7004                ],
7005                cx,
7006            );
7007        });
7008
7009        view.update(cx, |view, cx| {
7010            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7011            assert_eq!(
7012                view.selected_display_ranges(cx),
7013                &[
7014                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7015                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7016                ]
7017            );
7018        });
7019
7020        view.update(cx, |view, cx| {
7021            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7022            assert_eq!(
7023                view.selected_display_ranges(cx),
7024                &[
7025                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7026                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7027                ]
7028            );
7029        });
7030
7031        view.update(cx, |view, cx| {
7032            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7033            assert_eq!(
7034                view.selected_display_ranges(cx),
7035                &[
7036                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7037                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7038                ]
7039            );
7040        });
7041
7042        view.update(cx, |view, cx| {
7043            view.move_to_end_of_line(&MoveToEndOfLine, cx);
7044            assert_eq!(
7045                view.selected_display_ranges(cx),
7046                &[
7047                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7048                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
7049                ]
7050            );
7051        });
7052
7053        // Moving to the end of line again is a no-op.
7054        view.update(cx, |view, cx| {
7055            view.move_to_end_of_line(&MoveToEndOfLine, cx);
7056            assert_eq!(
7057                view.selected_display_ranges(cx),
7058                &[
7059                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7060                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
7061                ]
7062            );
7063        });
7064
7065        view.update(cx, |view, cx| {
7066            view.move_left(&MoveLeft, cx);
7067            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
7068            assert_eq!(
7069                view.selected_display_ranges(cx),
7070                &[
7071                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7072                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7073                ]
7074            );
7075        });
7076
7077        view.update(cx, |view, cx| {
7078            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
7079            assert_eq!(
7080                view.selected_display_ranges(cx),
7081                &[
7082                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7083                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
7084                ]
7085            );
7086        });
7087
7088        view.update(cx, |view, cx| {
7089            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
7090            assert_eq!(
7091                view.selected_display_ranges(cx),
7092                &[
7093                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7094                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7095                ]
7096            );
7097        });
7098
7099        view.update(cx, |view, cx| {
7100            view.select_to_end_of_line(&SelectToEndOfLine(true), cx);
7101            assert_eq!(
7102                view.selected_display_ranges(cx),
7103                &[
7104                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
7105                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
7106                ]
7107            );
7108        });
7109
7110        view.update(cx, |view, cx| {
7111            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
7112            assert_eq!(view.display_text(cx), "ab\n  de");
7113            assert_eq!(
7114                view.selected_display_ranges(cx),
7115                &[
7116                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7117                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
7118                ]
7119            );
7120        });
7121
7122        view.update(cx, |view, cx| {
7123            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
7124            assert_eq!(view.display_text(cx), "\n");
7125            assert_eq!(
7126                view.selected_display_ranges(cx),
7127                &[
7128                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7129                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7130                ]
7131            );
7132        });
7133    }
7134
7135    #[gpui::test]
7136    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
7137        populate_settings(cx);
7138        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
7139        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7140        view.update(cx, |view, cx| {
7141            view.select_display_ranges(
7142                &[
7143                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
7144                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
7145                ],
7146                cx,
7147            );
7148
7149            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7150            assert_selection_ranges(
7151                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7152                vec![('<', '>'), ('[', ']')],
7153                view,
7154                cx,
7155            );
7156
7157            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7158            assert_selection_ranges(
7159                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
7160                vec![('<', '>'), ('[', ']')],
7161                view,
7162                cx,
7163            );
7164
7165            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7166            assert_selection_ranges(
7167                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
7168                vec![('<', '>'), ('[', ']')],
7169                view,
7170                cx,
7171            );
7172
7173            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7174            assert_selection_ranges(
7175                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
7176                vec![('<', '>'), ('[', ']')],
7177                view,
7178                cx,
7179            );
7180
7181            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7182            assert_selection_ranges(
7183                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
7184                vec![('<', '>'), ('[', ']')],
7185                view,
7186                cx,
7187            );
7188
7189            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7190            assert_selection_ranges(
7191                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
7192                vec![('<', '>'), ('[', ']')],
7193                view,
7194                cx,
7195            );
7196
7197            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7198            assert_selection_ranges(
7199                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
7200                vec![('<', '>'), ('[', ']')],
7201                view,
7202                cx,
7203            );
7204
7205            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7206            assert_selection_ranges(
7207                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7208                vec![('<', '>'), ('[', ']')],
7209                view,
7210                cx,
7211            );
7212
7213            view.move_right(&MoveRight, cx);
7214            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7215            assert_selection_ranges(
7216                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7217                vec![('<', '>'), ('[', ']')],
7218                view,
7219                cx,
7220            );
7221
7222            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7223            assert_selection_ranges(
7224                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
7225                vec![('<', '>'), ('[', ']')],
7226                view,
7227                cx,
7228            );
7229
7230            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
7231            assert_selection_ranges(
7232                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7233                vec![('<', '>'), ('[', ']')],
7234                view,
7235                cx,
7236            );
7237        });
7238    }
7239
7240    #[gpui::test]
7241    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
7242        populate_settings(cx);
7243        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
7244        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7245
7246        view.update(cx, |view, cx| {
7247            view.set_wrap_width(Some(140.), cx);
7248            assert_eq!(
7249                view.display_text(cx),
7250                "use one::{\n    two::three::\n    four::five\n};"
7251            );
7252
7253            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
7254
7255            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7256            assert_eq!(
7257                view.selected_display_ranges(cx),
7258                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
7259            );
7260
7261            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7262            assert_eq!(
7263                view.selected_display_ranges(cx),
7264                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7265            );
7266
7267            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7268            assert_eq!(
7269                view.selected_display_ranges(cx),
7270                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7271            );
7272
7273            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7274            assert_eq!(
7275                view.selected_display_ranges(cx),
7276                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
7277            );
7278
7279            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7280            assert_eq!(
7281                view.selected_display_ranges(cx),
7282                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7283            );
7284
7285            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7286            assert_eq!(
7287                view.selected_display_ranges(cx),
7288                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7289            );
7290        });
7291    }
7292
7293    #[gpui::test]
7294    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
7295        populate_settings(cx);
7296        let buffer = MultiBuffer::build_simple("one two three four", cx);
7297        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7298
7299        view.update(cx, |view, cx| {
7300            view.select_display_ranges(
7301                &[
7302                    // an empty selection - the preceding word fragment is deleted
7303                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7304                    // characters selected - they are deleted
7305                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
7306                ],
7307                cx,
7308            );
7309            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
7310        });
7311
7312        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
7313
7314        view.update(cx, |view, cx| {
7315            view.select_display_ranges(
7316                &[
7317                    // an empty selection - the following word fragment is deleted
7318                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7319                    // characters selected - they are deleted
7320                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
7321                ],
7322                cx,
7323            );
7324            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
7325        });
7326
7327        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
7328    }
7329
7330    #[gpui::test]
7331    fn test_newline(cx: &mut gpui::MutableAppContext) {
7332        populate_settings(cx);
7333        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
7334        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7335
7336        view.update(cx, |view, cx| {
7337            view.select_display_ranges(
7338                &[
7339                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7340                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7341                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
7342                ],
7343                cx,
7344            );
7345
7346            view.newline(&Newline, cx);
7347            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
7348        });
7349    }
7350
7351    #[gpui::test]
7352    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
7353        populate_settings(cx);
7354        let buffer = MultiBuffer::build_simple(
7355            "
7356                a
7357                b(
7358                    X
7359                )
7360                c(
7361                    X
7362                )
7363            "
7364            .unindent()
7365            .as_str(),
7366            cx,
7367        );
7368
7369        let (_, editor) = cx.add_window(Default::default(), |cx| {
7370            let mut editor = build_editor(buffer.clone(), cx);
7371            editor.select_ranges(
7372                [
7373                    Point::new(2, 4)..Point::new(2, 5),
7374                    Point::new(5, 4)..Point::new(5, 5),
7375                ],
7376                None,
7377                cx,
7378            );
7379            editor
7380        });
7381
7382        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7383        buffer.update(cx, |buffer, cx| {
7384            buffer.edit(
7385                [
7386                    Point::new(1, 2)..Point::new(3, 0),
7387                    Point::new(4, 2)..Point::new(6, 0),
7388                ],
7389                "",
7390                cx,
7391            );
7392            assert_eq!(
7393                buffer.read(cx).text(),
7394                "
7395                    a
7396                    b()
7397                    c()
7398                "
7399                .unindent()
7400            );
7401        });
7402
7403        editor.update(cx, |editor, cx| {
7404            assert_eq!(
7405                editor.selected_ranges(cx),
7406                &[
7407                    Point::new(1, 2)..Point::new(1, 2),
7408                    Point::new(2, 2)..Point::new(2, 2),
7409                ],
7410            );
7411
7412            editor.newline(&Newline, cx);
7413            assert_eq!(
7414                editor.text(cx),
7415                "
7416                    a
7417                    b(
7418                    )
7419                    c(
7420                    )
7421                "
7422                .unindent()
7423            );
7424
7425            // The selections are moved after the inserted newlines
7426            assert_eq!(
7427                editor.selected_ranges(cx),
7428                &[
7429                    Point::new(2, 0)..Point::new(2, 0),
7430                    Point::new(4, 0)..Point::new(4, 0),
7431                ],
7432            );
7433        });
7434    }
7435
7436    #[gpui::test]
7437    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
7438        populate_settings(cx);
7439        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
7440        let (_, editor) = cx.add_window(Default::default(), |cx| {
7441            let mut editor = build_editor(buffer.clone(), cx);
7442            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
7443            editor
7444        });
7445
7446        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7447        buffer.update(cx, |buffer, cx| {
7448            buffer.edit([2..5, 10..13, 18..21], "", cx);
7449            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
7450        });
7451
7452        editor.update(cx, |editor, cx| {
7453            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
7454
7455            editor.insert("Z", cx);
7456            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
7457
7458            // The selections are moved after the inserted characters
7459            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
7460        });
7461    }
7462
7463    #[gpui::test]
7464    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
7465        populate_settings(cx);
7466        let buffer = MultiBuffer::build_simple("  one two\nthree\n four", cx);
7467        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7468
7469        view.update(cx, |view, cx| {
7470            // two selections on the same line
7471            view.select_display_ranges(
7472                &[
7473                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 5),
7474                    DisplayPoint::new(0, 6)..DisplayPoint::new(0, 9),
7475                ],
7476                cx,
7477            );
7478
7479            // indent from mid-tabstop to full tabstop
7480            view.tab(false, cx);
7481            assert_eq!(view.text(cx), "    one two\nthree\n four");
7482            assert_eq!(
7483                view.selected_display_ranges(cx),
7484                &[
7485                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
7486                    DisplayPoint::new(0, 8)..DisplayPoint::new(0, 11),
7487                ]
7488            );
7489
7490            // outdent from 1 tabstop to 0 tabstops
7491            view.outdent(&Outdent, cx);
7492            assert_eq!(view.text(cx), "one two\nthree\n four");
7493            assert_eq!(
7494                view.selected_display_ranges(cx),
7495                &[
7496                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 3),
7497                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
7498                ]
7499            );
7500
7501            // select across line ending
7502            view.select_display_ranges(&[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)], cx);
7503
7504            // indent and outdent affect only the preceding line
7505            view.tab(false, cx);
7506            assert_eq!(view.text(cx), "one two\n    three\n four");
7507            assert_eq!(
7508                view.selected_display_ranges(cx),
7509                &[DisplayPoint::new(1, 5)..DisplayPoint::new(2, 0)]
7510            );
7511            view.outdent(&Outdent, cx);
7512            assert_eq!(view.text(cx), "one two\nthree\n four");
7513            assert_eq!(
7514                view.selected_display_ranges(cx),
7515                &[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)]
7516            );
7517
7518            // Ensure that indenting/outdenting works when the cursor is at column 0.
7519            view.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
7520            view.tab(false, cx);
7521            assert_eq!(view.text(cx), "one two\n    three\n four");
7522            assert_eq!(
7523                view.selected_display_ranges(cx),
7524                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
7525            );
7526
7527            view.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
7528            view.outdent(&Outdent, cx);
7529            assert_eq!(view.text(cx), "one two\nthree\n four");
7530            assert_eq!(
7531                view.selected_display_ranges(cx),
7532                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
7533            );
7534        });
7535    }
7536
7537    #[gpui::test]
7538    fn test_backspace(cx: &mut gpui::MutableAppContext) {
7539        populate_settings(cx);
7540        let (_, view) = cx.add_window(Default::default(), |cx| {
7541            build_editor(MultiBuffer::build_simple("", cx), cx)
7542        });
7543
7544        view.update(cx, |view, cx| {
7545            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
7546            view.select_display_ranges(
7547                &[
7548                    // an empty selection - the preceding character is deleted
7549                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7550                    // one character selected - it is deleted
7551                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7552                    // a line suffix selected - it is deleted
7553                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
7554                ],
7555                cx,
7556            );
7557            view.backspace(&Backspace, cx);
7558            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
7559
7560            view.set_text("    one\n        two\n        three\n   four", cx);
7561            view.select_display_ranges(
7562                &[
7563                    // cursors at the the end of leading indent - last indent is deleted
7564                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
7565                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
7566                    // cursors inside leading indent - overlapping indent deletions are coalesced
7567                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
7568                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
7569                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
7570                    // cursor at the beginning of a line - preceding newline is deleted
7571                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7572                    // selection inside leading indent - only the selected character is deleted
7573                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
7574                ],
7575                cx,
7576            );
7577            view.backspace(&Backspace, cx);
7578            assert_eq!(view.text(cx), "one\n    two\n  three  four");
7579        });
7580    }
7581
7582    #[gpui::test]
7583    fn test_delete(cx: &mut gpui::MutableAppContext) {
7584        populate_settings(cx);
7585        let buffer =
7586            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
7587        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7588
7589        view.update(cx, |view, cx| {
7590            view.select_display_ranges(
7591                &[
7592                    // an empty selection - the following character is deleted
7593                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7594                    // one character selected - it is deleted
7595                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7596                    // a line suffix selected - it is deleted
7597                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
7598                ],
7599                cx,
7600            );
7601            view.delete(&Delete, cx);
7602        });
7603
7604        assert_eq!(
7605            buffer.read(cx).read(cx).text(),
7606            "on two three\nfou five six\nseven ten\n"
7607        );
7608    }
7609
7610    #[gpui::test]
7611    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
7612        populate_settings(cx);
7613        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7614        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7615        view.update(cx, |view, cx| {
7616            view.select_display_ranges(
7617                &[
7618                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7619                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7620                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7621                ],
7622                cx,
7623            );
7624            view.delete_line(&DeleteLine, cx);
7625            assert_eq!(view.display_text(cx), "ghi");
7626            assert_eq!(
7627                view.selected_display_ranges(cx),
7628                vec![
7629                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7630                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
7631                ]
7632            );
7633        });
7634
7635        populate_settings(cx);
7636        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7637        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7638        view.update(cx, |view, cx| {
7639            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
7640            view.delete_line(&DeleteLine, cx);
7641            assert_eq!(view.display_text(cx), "ghi\n");
7642            assert_eq!(
7643                view.selected_display_ranges(cx),
7644                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
7645            );
7646        });
7647    }
7648
7649    #[gpui::test]
7650    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
7651        populate_settings(cx);
7652        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7653        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7654        view.update(cx, |view, cx| {
7655            view.select_display_ranges(
7656                &[
7657                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7658                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7659                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7660                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7661                ],
7662                cx,
7663            );
7664            view.duplicate_line(&DuplicateLine, cx);
7665            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
7666            assert_eq!(
7667                view.selected_display_ranges(cx),
7668                vec![
7669                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7670                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7671                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7672                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
7673                ]
7674            );
7675        });
7676
7677        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7678        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7679        view.update(cx, |view, cx| {
7680            view.select_display_ranges(
7681                &[
7682                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
7683                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
7684                ],
7685                cx,
7686            );
7687            view.duplicate_line(&DuplicateLine, cx);
7688            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
7689            assert_eq!(
7690                view.selected_display_ranges(cx),
7691                vec![
7692                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
7693                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
7694                ]
7695            );
7696        });
7697    }
7698
7699    #[gpui::test]
7700    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
7701        populate_settings(cx);
7702        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7703        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7704        view.update(cx, |view, cx| {
7705            view.fold_ranges(
7706                vec![
7707                    Point::new(0, 2)..Point::new(1, 2),
7708                    Point::new(2, 3)..Point::new(4, 1),
7709                    Point::new(7, 0)..Point::new(8, 4),
7710                ],
7711                cx,
7712            );
7713            view.select_display_ranges(
7714                &[
7715                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7716                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7717                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7718                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
7719                ],
7720                cx,
7721            );
7722            assert_eq!(
7723                view.display_text(cx),
7724                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
7725            );
7726
7727            view.move_line_up(&MoveLineUp, cx);
7728            assert_eq!(
7729                view.display_text(cx),
7730                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
7731            );
7732            assert_eq!(
7733                view.selected_display_ranges(cx),
7734                vec![
7735                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7736                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7737                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7738                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7739                ]
7740            );
7741        });
7742
7743        view.update(cx, |view, cx| {
7744            view.move_line_down(&MoveLineDown, cx);
7745            assert_eq!(
7746                view.display_text(cx),
7747                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
7748            );
7749            assert_eq!(
7750                view.selected_display_ranges(cx),
7751                vec![
7752                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7753                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7754                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7755                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7756                ]
7757            );
7758        });
7759
7760        view.update(cx, |view, cx| {
7761            view.move_line_down(&MoveLineDown, cx);
7762            assert_eq!(
7763                view.display_text(cx),
7764                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
7765            );
7766            assert_eq!(
7767                view.selected_display_ranges(cx),
7768                vec![
7769                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7770                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7771                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7772                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7773                ]
7774            );
7775        });
7776
7777        view.update(cx, |view, cx| {
7778            view.move_line_up(&MoveLineUp, cx);
7779            assert_eq!(
7780                view.display_text(cx),
7781                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
7782            );
7783            assert_eq!(
7784                view.selected_display_ranges(cx),
7785                vec![
7786                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7787                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7788                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7789                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7790                ]
7791            );
7792        });
7793    }
7794
7795    #[gpui::test]
7796    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
7797        populate_settings(cx);
7798        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7799        let snapshot = buffer.read(cx).snapshot(cx);
7800        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7801        editor.update(cx, |editor, cx| {
7802            editor.insert_blocks(
7803                [BlockProperties {
7804                    position: snapshot.anchor_after(Point::new(2, 0)),
7805                    disposition: BlockDisposition::Below,
7806                    height: 1,
7807                    render: Arc::new(|_| Empty::new().boxed()),
7808                }],
7809                cx,
7810            );
7811            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
7812            editor.move_line_down(&MoveLineDown, cx);
7813        });
7814    }
7815
7816    #[gpui::test]
7817    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
7818        populate_settings(cx);
7819        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
7820        let view = cx
7821            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
7822            .1;
7823
7824        // Cut with three selections. Clipboard text is divided into three slices.
7825        view.update(cx, |view, cx| {
7826            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
7827            view.cut(&Cut, cx);
7828            assert_eq!(view.display_text(cx), "two four six ");
7829        });
7830
7831        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
7832        view.update(cx, |view, cx| {
7833            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
7834            view.paste(&Paste, cx);
7835            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
7836            assert_eq!(
7837                view.selected_display_ranges(cx),
7838                &[
7839                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
7840                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
7841                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
7842                ]
7843            );
7844        });
7845
7846        // Paste again but with only two cursors. Since the number of cursors doesn't
7847        // match the number of slices in the clipboard, the entire clipboard text
7848        // is pasted at each cursor.
7849        view.update(cx, |view, cx| {
7850            view.select_ranges(vec![0..0, 31..31], None, cx);
7851            view.handle_input(&Input("( ".into()), cx);
7852            view.paste(&Paste, cx);
7853            view.handle_input(&Input(") ".into()), cx);
7854            assert_eq!(
7855                view.display_text(cx),
7856                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7857            );
7858        });
7859
7860        view.update(cx, |view, cx| {
7861            view.select_ranges(vec![0..0], None, cx);
7862            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
7863            assert_eq!(
7864                view.display_text(cx),
7865                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7866            );
7867        });
7868
7869        // Cut with three selections, one of which is full-line.
7870        view.update(cx, |view, cx| {
7871            view.select_display_ranges(
7872                &[
7873                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
7874                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7875                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
7876                ],
7877                cx,
7878            );
7879            view.cut(&Cut, cx);
7880            assert_eq!(
7881                view.display_text(cx),
7882                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7883            );
7884        });
7885
7886        // Paste with three selections, noticing how the copied selection that was full-line
7887        // gets inserted before the second cursor.
7888        view.update(cx, |view, cx| {
7889            view.select_display_ranges(
7890                &[
7891                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7892                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7893                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
7894                ],
7895                cx,
7896            );
7897            view.paste(&Paste, cx);
7898            assert_eq!(
7899                view.display_text(cx),
7900                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
7901            );
7902            assert_eq!(
7903                view.selected_display_ranges(cx),
7904                &[
7905                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7906                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7907                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
7908                ]
7909            );
7910        });
7911
7912        // Copy with a single cursor only, which writes the whole line into the clipboard.
7913        view.update(cx, |view, cx| {
7914            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
7915            view.copy(&Copy, cx);
7916        });
7917
7918        // Paste with three selections, noticing how the copied full-line selection is inserted
7919        // before the empty selections but replaces the selection that is non-empty.
7920        view.update(cx, |view, cx| {
7921            view.select_display_ranges(
7922                &[
7923                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7924                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
7925                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7926                ],
7927                cx,
7928            );
7929            view.paste(&Paste, cx);
7930            assert_eq!(
7931                view.display_text(cx),
7932                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
7933            );
7934            assert_eq!(
7935                view.selected_display_ranges(cx),
7936                &[
7937                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7938                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7939                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
7940                ]
7941            );
7942        });
7943    }
7944
7945    #[gpui::test]
7946    fn test_select_all(cx: &mut gpui::MutableAppContext) {
7947        populate_settings(cx);
7948        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
7949        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7950        view.update(cx, |view, cx| {
7951            view.select_all(&SelectAll, cx);
7952            assert_eq!(
7953                view.selected_display_ranges(cx),
7954                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
7955            );
7956        });
7957    }
7958
7959    #[gpui::test]
7960    fn test_select_line(cx: &mut gpui::MutableAppContext) {
7961        populate_settings(cx);
7962        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
7963        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7964        view.update(cx, |view, cx| {
7965            view.select_display_ranges(
7966                &[
7967                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7968                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7969                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7970                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
7971                ],
7972                cx,
7973            );
7974            view.select_line(&SelectLine, cx);
7975            assert_eq!(
7976                view.selected_display_ranges(cx),
7977                vec![
7978                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
7979                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
7980                ]
7981            );
7982        });
7983
7984        view.update(cx, |view, cx| {
7985            view.select_line(&SelectLine, cx);
7986            assert_eq!(
7987                view.selected_display_ranges(cx),
7988                vec![
7989                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
7990                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
7991                ]
7992            );
7993        });
7994
7995        view.update(cx, |view, cx| {
7996            view.select_line(&SelectLine, cx);
7997            assert_eq!(
7998                view.selected_display_ranges(cx),
7999                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
8000            );
8001        });
8002    }
8003
8004    #[gpui::test]
8005    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
8006        populate_settings(cx);
8007        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
8008        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8009        view.update(cx, |view, cx| {
8010            view.fold_ranges(
8011                vec![
8012                    Point::new(0, 2)..Point::new(1, 2),
8013                    Point::new(2, 3)..Point::new(4, 1),
8014                    Point::new(7, 0)..Point::new(8, 4),
8015                ],
8016                cx,
8017            );
8018            view.select_display_ranges(
8019                &[
8020                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8021                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8022                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8023                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
8024                ],
8025                cx,
8026            );
8027            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
8028        });
8029
8030        view.update(cx, |view, cx| {
8031            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8032            assert_eq!(
8033                view.display_text(cx),
8034                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
8035            );
8036            assert_eq!(
8037                view.selected_display_ranges(cx),
8038                [
8039                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
8040                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8041                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
8042                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
8043                ]
8044            );
8045        });
8046
8047        view.update(cx, |view, cx| {
8048            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
8049            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8050            assert_eq!(
8051                view.display_text(cx),
8052                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
8053            );
8054            assert_eq!(
8055                view.selected_display_ranges(cx),
8056                [
8057                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
8058                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
8059                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
8060                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
8061                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
8062                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
8063                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
8064                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
8065                ]
8066            );
8067        });
8068    }
8069
8070    #[gpui::test]
8071    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
8072        populate_settings(cx);
8073        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
8074        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8075
8076        view.update(cx, |view, cx| {
8077            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
8078        });
8079        view.update(cx, |view, cx| {
8080            view.add_selection_above(&AddSelectionAbove, cx);
8081            assert_eq!(
8082                view.selected_display_ranges(cx),
8083                vec![
8084                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8085                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8086                ]
8087            );
8088        });
8089
8090        view.update(cx, |view, cx| {
8091            view.add_selection_above(&AddSelectionAbove, cx);
8092            assert_eq!(
8093                view.selected_display_ranges(cx),
8094                vec![
8095                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8096                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8097                ]
8098            );
8099        });
8100
8101        view.update(cx, |view, cx| {
8102            view.add_selection_below(&AddSelectionBelow, cx);
8103            assert_eq!(
8104                view.selected_display_ranges(cx),
8105                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
8106            );
8107        });
8108
8109        view.update(cx, |view, cx| {
8110            view.add_selection_below(&AddSelectionBelow, cx);
8111            assert_eq!(
8112                view.selected_display_ranges(cx),
8113                vec![
8114                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8115                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8116                ]
8117            );
8118        });
8119
8120        view.update(cx, |view, cx| {
8121            view.add_selection_below(&AddSelectionBelow, cx);
8122            assert_eq!(
8123                view.selected_display_ranges(cx),
8124                vec![
8125                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8126                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8127                ]
8128            );
8129        });
8130
8131        view.update(cx, |view, cx| {
8132            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
8133        });
8134        view.update(cx, |view, cx| {
8135            view.add_selection_below(&AddSelectionBelow, cx);
8136            assert_eq!(
8137                view.selected_display_ranges(cx),
8138                vec![
8139                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8140                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8141                ]
8142            );
8143        });
8144
8145        view.update(cx, |view, cx| {
8146            view.add_selection_below(&AddSelectionBelow, cx);
8147            assert_eq!(
8148                view.selected_display_ranges(cx),
8149                vec![
8150                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8151                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8152                ]
8153            );
8154        });
8155
8156        view.update(cx, |view, cx| {
8157            view.add_selection_above(&AddSelectionAbove, cx);
8158            assert_eq!(
8159                view.selected_display_ranges(cx),
8160                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8161            );
8162        });
8163
8164        view.update(cx, |view, cx| {
8165            view.add_selection_above(&AddSelectionAbove, cx);
8166            assert_eq!(
8167                view.selected_display_ranges(cx),
8168                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8169            );
8170        });
8171
8172        view.update(cx, |view, cx| {
8173            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
8174            view.add_selection_below(&AddSelectionBelow, cx);
8175            assert_eq!(
8176                view.selected_display_ranges(cx),
8177                vec![
8178                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8179                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8180                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8181                ]
8182            );
8183        });
8184
8185        view.update(cx, |view, cx| {
8186            view.add_selection_below(&AddSelectionBelow, cx);
8187            assert_eq!(
8188                view.selected_display_ranges(cx),
8189                vec![
8190                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8191                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8192                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8193                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
8194                ]
8195            );
8196        });
8197
8198        view.update(cx, |view, cx| {
8199            view.add_selection_above(&AddSelectionAbove, cx);
8200            assert_eq!(
8201                view.selected_display_ranges(cx),
8202                vec![
8203                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8204                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8205                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8206                ]
8207            );
8208        });
8209
8210        view.update(cx, |view, cx| {
8211            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
8212        });
8213        view.update(cx, |view, cx| {
8214            view.add_selection_above(&AddSelectionAbove, cx);
8215            assert_eq!(
8216                view.selected_display_ranges(cx),
8217                vec![
8218                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
8219                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8220                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8221                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8222                ]
8223            );
8224        });
8225
8226        view.update(cx, |view, cx| {
8227            view.add_selection_below(&AddSelectionBelow, cx);
8228            assert_eq!(
8229                view.selected_display_ranges(cx),
8230                vec![
8231                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8232                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8233                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8234                ]
8235            );
8236        });
8237    }
8238
8239    #[gpui::test]
8240    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
8241        cx.update(populate_settings);
8242        let language = Arc::new(Language::new(
8243            LanguageConfig::default(),
8244            Some(tree_sitter_rust::language()),
8245        ));
8246
8247        let text = r#"
8248            use mod1::mod2::{mod3, mod4};
8249
8250            fn fn_1(param1: bool, param2: &str) {
8251                let var1 = "text";
8252            }
8253        "#
8254        .unindent();
8255
8256        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8257        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8258        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8259        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8260            .await;
8261
8262        view.update(cx, |view, cx| {
8263            view.select_display_ranges(
8264                &[
8265                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8266                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8267                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8268                ],
8269                cx,
8270            );
8271            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8272        });
8273        assert_eq!(
8274            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8275            &[
8276                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8277                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8278                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8279            ]
8280        );
8281
8282        view.update(cx, |view, cx| {
8283            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8284        });
8285        assert_eq!(
8286            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8287            &[
8288                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8289                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8290            ]
8291        );
8292
8293        view.update(cx, |view, cx| {
8294            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8295        });
8296        assert_eq!(
8297            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8298            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8299        );
8300
8301        // Trying to expand the selected syntax node one more time has no effect.
8302        view.update(cx, |view, cx| {
8303            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8304        });
8305        assert_eq!(
8306            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8307            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8308        );
8309
8310        view.update(cx, |view, cx| {
8311            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8312        });
8313        assert_eq!(
8314            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8315            &[
8316                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8317                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8318            ]
8319        );
8320
8321        view.update(cx, |view, cx| {
8322            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8323        });
8324        assert_eq!(
8325            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8326            &[
8327                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8328                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8329                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8330            ]
8331        );
8332
8333        view.update(cx, |view, cx| {
8334            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8335        });
8336        assert_eq!(
8337            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8338            &[
8339                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8340                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8341                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8342            ]
8343        );
8344
8345        // Trying to shrink the selected syntax node one more time has no effect.
8346        view.update(cx, |view, cx| {
8347            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8348        });
8349        assert_eq!(
8350            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8351            &[
8352                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8353                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8354                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8355            ]
8356        );
8357
8358        // Ensure that we keep expanding the selection if the larger selection starts or ends within
8359        // a fold.
8360        view.update(cx, |view, cx| {
8361            view.fold_ranges(
8362                vec![
8363                    Point::new(0, 21)..Point::new(0, 24),
8364                    Point::new(3, 20)..Point::new(3, 22),
8365                ],
8366                cx,
8367            );
8368            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8369        });
8370        assert_eq!(
8371            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
8372            &[
8373                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8374                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8375                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
8376            ]
8377        );
8378    }
8379
8380    #[gpui::test]
8381    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
8382        cx.update(populate_settings);
8383        let language = Arc::new(
8384            Language::new(
8385                LanguageConfig {
8386                    brackets: vec![
8387                        BracketPair {
8388                            start: "{".to_string(),
8389                            end: "}".to_string(),
8390                            close: false,
8391                            newline: true,
8392                        },
8393                        BracketPair {
8394                            start: "(".to_string(),
8395                            end: ")".to_string(),
8396                            close: false,
8397                            newline: true,
8398                        },
8399                    ],
8400                    ..Default::default()
8401                },
8402                Some(tree_sitter_rust::language()),
8403            )
8404            .with_indents_query(
8405                r#"
8406                (_ "(" ")" @end) @indent
8407                (_ "{" "}" @end) @indent
8408                "#,
8409            )
8410            .unwrap(),
8411        );
8412
8413        let text = "fn a() {}";
8414
8415        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8416        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8417        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8418        editor
8419            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
8420            .await;
8421
8422        editor.update(cx, |editor, cx| {
8423            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
8424            editor.newline(&Newline, cx);
8425            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
8426            assert_eq!(
8427                editor.selected_ranges(cx),
8428                &[
8429                    Point::new(1, 4)..Point::new(1, 4),
8430                    Point::new(3, 4)..Point::new(3, 4),
8431                    Point::new(5, 0)..Point::new(5, 0)
8432                ]
8433            );
8434        });
8435    }
8436
8437    #[gpui::test]
8438    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
8439        cx.update(populate_settings);
8440        let language = Arc::new(Language::new(
8441            LanguageConfig {
8442                brackets: vec![
8443                    BracketPair {
8444                        start: "{".to_string(),
8445                        end: "}".to_string(),
8446                        close: true,
8447                        newline: true,
8448                    },
8449                    BracketPair {
8450                        start: "/*".to_string(),
8451                        end: " */".to_string(),
8452                        close: true,
8453                        newline: true,
8454                    },
8455                ],
8456                autoclose_before: "})]".to_string(),
8457                ..Default::default()
8458            },
8459            Some(tree_sitter_rust::language()),
8460        ));
8461
8462        let text = r#"
8463            a
8464
8465            /
8466
8467        "#
8468        .unindent();
8469
8470        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8471        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8472        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8473        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8474            .await;
8475
8476        view.update(cx, |view, cx| {
8477            view.select_display_ranges(
8478                &[
8479                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8480                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8481                ],
8482                cx,
8483            );
8484
8485            view.handle_input(&Input("{".to_string()), cx);
8486            view.handle_input(&Input("{".to_string()), cx);
8487            view.handle_input(&Input("{".to_string()), cx);
8488            assert_eq!(
8489                view.text(cx),
8490                "
8491                {{{}}}
8492                {{{}}}
8493                /
8494
8495                "
8496                .unindent()
8497            );
8498
8499            view.move_right(&MoveRight, cx);
8500            view.handle_input(&Input("}".to_string()), cx);
8501            view.handle_input(&Input("}".to_string()), cx);
8502            view.handle_input(&Input("}".to_string()), cx);
8503            assert_eq!(
8504                view.text(cx),
8505                "
8506                {{{}}}}
8507                {{{}}}}
8508                /
8509
8510                "
8511                .unindent()
8512            );
8513
8514            view.undo(&Undo, cx);
8515            view.handle_input(&Input("/".to_string()), cx);
8516            view.handle_input(&Input("*".to_string()), cx);
8517            assert_eq!(
8518                view.text(cx),
8519                "
8520                /* */
8521                /* */
8522                /
8523
8524                "
8525                .unindent()
8526            );
8527
8528            view.undo(&Undo, cx);
8529            view.select_display_ranges(
8530                &[
8531                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
8532                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
8533                ],
8534                cx,
8535            );
8536            view.handle_input(&Input("*".to_string()), cx);
8537            assert_eq!(
8538                view.text(cx),
8539                "
8540                a
8541
8542                /*
8543                *
8544                "
8545                .unindent()
8546            );
8547
8548            // Don't autoclose if the next character isn't whitespace and isn't
8549            // listed in the language's "autoclose_before" section.
8550            view.finalize_last_transaction(cx);
8551            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
8552            view.handle_input(&Input("{".to_string()), cx);
8553            assert_eq!(
8554                view.text(cx),
8555                "
8556                {a
8557
8558                /*
8559                *
8560                "
8561                .unindent()
8562            );
8563
8564            view.undo(&Undo, cx);
8565            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
8566            view.handle_input(&Input("{".to_string()), cx);
8567            assert_eq!(
8568                view.text(cx),
8569                "
8570                {a}
8571
8572                /*
8573                *
8574                "
8575                .unindent()
8576            );
8577            assert_eq!(
8578                view.selected_display_ranges(cx),
8579                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
8580            );
8581        });
8582    }
8583
8584    #[gpui::test]
8585    async fn test_snippets(cx: &mut gpui::TestAppContext) {
8586        cx.update(populate_settings);
8587
8588        let text = "
8589            a. b
8590            a. b
8591            a. b
8592        "
8593        .unindent();
8594        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
8595        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8596
8597        editor.update(cx, |editor, cx| {
8598            let buffer = &editor.snapshot(cx).buffer_snapshot;
8599            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
8600            let insertion_ranges = [
8601                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
8602                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
8603                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
8604            ];
8605
8606            editor
8607                .insert_snippet(&insertion_ranges, snippet, cx)
8608                .unwrap();
8609            assert_eq!(
8610                editor.text(cx),
8611                "
8612                    a.f(one, two, three) b
8613                    a.f(one, two, three) b
8614                    a.f(one, two, three) b
8615                "
8616                .unindent()
8617            );
8618            assert_eq!(
8619                editor.selected_ranges::<Point>(cx),
8620                &[
8621                    Point::new(0, 4)..Point::new(0, 7),
8622                    Point::new(0, 14)..Point::new(0, 19),
8623                    Point::new(1, 4)..Point::new(1, 7),
8624                    Point::new(1, 14)..Point::new(1, 19),
8625                    Point::new(2, 4)..Point::new(2, 7),
8626                    Point::new(2, 14)..Point::new(2, 19),
8627                ]
8628            );
8629
8630            // Can't move earlier than the first tab stop
8631            editor.move_to_prev_snippet_tabstop(cx);
8632            assert_eq!(
8633                editor.selected_ranges::<Point>(cx),
8634                &[
8635                    Point::new(0, 4)..Point::new(0, 7),
8636                    Point::new(0, 14)..Point::new(0, 19),
8637                    Point::new(1, 4)..Point::new(1, 7),
8638                    Point::new(1, 14)..Point::new(1, 19),
8639                    Point::new(2, 4)..Point::new(2, 7),
8640                    Point::new(2, 14)..Point::new(2, 19),
8641                ]
8642            );
8643
8644            assert!(editor.move_to_next_snippet_tabstop(cx));
8645            assert_eq!(
8646                editor.selected_ranges::<Point>(cx),
8647                &[
8648                    Point::new(0, 9)..Point::new(0, 12),
8649                    Point::new(1, 9)..Point::new(1, 12),
8650                    Point::new(2, 9)..Point::new(2, 12)
8651                ]
8652            );
8653
8654            editor.move_to_prev_snippet_tabstop(cx);
8655            assert_eq!(
8656                editor.selected_ranges::<Point>(cx),
8657                &[
8658                    Point::new(0, 4)..Point::new(0, 7),
8659                    Point::new(0, 14)..Point::new(0, 19),
8660                    Point::new(1, 4)..Point::new(1, 7),
8661                    Point::new(1, 14)..Point::new(1, 19),
8662                    Point::new(2, 4)..Point::new(2, 7),
8663                    Point::new(2, 14)..Point::new(2, 19),
8664                ]
8665            );
8666
8667            assert!(editor.move_to_next_snippet_tabstop(cx));
8668            assert!(editor.move_to_next_snippet_tabstop(cx));
8669            assert_eq!(
8670                editor.selected_ranges::<Point>(cx),
8671                &[
8672                    Point::new(0, 20)..Point::new(0, 20),
8673                    Point::new(1, 20)..Point::new(1, 20),
8674                    Point::new(2, 20)..Point::new(2, 20)
8675                ]
8676            );
8677
8678            // As soon as the last tab stop is reached, snippet state is gone
8679            editor.move_to_prev_snippet_tabstop(cx);
8680            assert_eq!(
8681                editor.selected_ranges::<Point>(cx),
8682                &[
8683                    Point::new(0, 20)..Point::new(0, 20),
8684                    Point::new(1, 20)..Point::new(1, 20),
8685                    Point::new(2, 20)..Point::new(2, 20)
8686                ]
8687            );
8688        });
8689    }
8690
8691    #[gpui::test]
8692    async fn test_completion(cx: &mut gpui::TestAppContext) {
8693        cx.update(populate_settings);
8694
8695        let (mut language_server_config, mut fake_servers) = LanguageServerConfig::fake();
8696        language_server_config.set_fake_capabilities(lsp::ServerCapabilities {
8697            completion_provider: Some(lsp::CompletionOptions {
8698                trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
8699                ..Default::default()
8700            }),
8701            ..Default::default()
8702        });
8703        let language = Arc::new(Language::new(
8704            LanguageConfig {
8705                name: "Rust".into(),
8706                path_suffixes: vec!["rs".to_string()],
8707                language_server: Some(language_server_config),
8708                ..Default::default()
8709            },
8710            Some(tree_sitter_rust::language()),
8711        ));
8712
8713        let text = "
8714            one
8715            two
8716            three
8717        "
8718        .unindent();
8719
8720        let fs = FakeFs::new(cx.background().clone());
8721        fs.insert_file("/file.rs", text).await;
8722
8723        let project = Project::test(fs, cx);
8724        project.update(cx, |project, _| project.languages().add(language));
8725
8726        let worktree_id = project
8727            .update(cx, |project, cx| {
8728                project.find_or_create_local_worktree("/file.rs", true, cx)
8729            })
8730            .await
8731            .unwrap()
8732            .0
8733            .read_with(cx, |tree, _| tree.id());
8734        let buffer = project
8735            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
8736            .await
8737            .unwrap();
8738        let mut fake_server = fake_servers.next().await.unwrap();
8739
8740        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8741        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8742
8743        editor.update(cx, |editor, cx| {
8744            editor.project = Some(project);
8745            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
8746            editor.handle_input(&Input(".".to_string()), cx);
8747        });
8748
8749        handle_completion_request(
8750            &mut fake_server,
8751            "/file.rs",
8752            Point::new(0, 4),
8753            vec![
8754                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
8755                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
8756            ],
8757        )
8758        .await;
8759        editor
8760            .condition(&cx, |editor, _| editor.context_menu_visible())
8761            .await;
8762
8763        let apply_additional_edits = editor.update(cx, |editor, cx| {
8764            editor.move_down(&MoveDown, cx);
8765            let apply_additional_edits = editor
8766                .confirm_completion(&ConfirmCompletion(None), cx)
8767                .unwrap();
8768            assert_eq!(
8769                editor.text(cx),
8770                "
8771                    one.second_completion
8772                    two
8773                    three
8774                "
8775                .unindent()
8776            );
8777            apply_additional_edits
8778        });
8779
8780        handle_resolve_completion_request(
8781            &mut fake_server,
8782            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
8783        )
8784        .await;
8785        apply_additional_edits.await.unwrap();
8786        assert_eq!(
8787            editor.read_with(cx, |editor, cx| editor.text(cx)),
8788            "
8789                one.second_completion
8790                two
8791                three
8792                additional edit
8793            "
8794            .unindent()
8795        );
8796
8797        editor.update(cx, |editor, cx| {
8798            editor.select_ranges(
8799                [
8800                    Point::new(1, 3)..Point::new(1, 3),
8801                    Point::new(2, 5)..Point::new(2, 5),
8802                ],
8803                None,
8804                cx,
8805            );
8806
8807            editor.handle_input(&Input(" ".to_string()), cx);
8808            assert!(editor.context_menu.is_none());
8809            editor.handle_input(&Input("s".to_string()), cx);
8810            assert!(editor.context_menu.is_none());
8811        });
8812
8813        handle_completion_request(
8814            &mut fake_server,
8815            "/file.rs",
8816            Point::new(2, 7),
8817            vec![
8818                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
8819                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
8820                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
8821            ],
8822        )
8823        .await;
8824        editor
8825            .condition(&cx, |editor, _| editor.context_menu_visible())
8826            .await;
8827
8828        editor.update(cx, |editor, cx| {
8829            editor.handle_input(&Input("i".to_string()), cx);
8830        });
8831
8832        handle_completion_request(
8833            &mut fake_server,
8834            "/file.rs",
8835            Point::new(2, 8),
8836            vec![
8837                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
8838                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
8839                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
8840            ],
8841        )
8842        .await;
8843        editor
8844            .condition(&cx, |editor, _| editor.context_menu_visible())
8845            .await;
8846
8847        let apply_additional_edits = editor.update(cx, |editor, cx| {
8848            let apply_additional_edits = editor
8849                .confirm_completion(&ConfirmCompletion(None), cx)
8850                .unwrap();
8851            assert_eq!(
8852                editor.text(cx),
8853                "
8854                    one.second_completion
8855                    two sixth_completion
8856                    three sixth_completion
8857                    additional edit
8858                "
8859                .unindent()
8860            );
8861            apply_additional_edits
8862        });
8863        handle_resolve_completion_request(&mut fake_server, None).await;
8864        apply_additional_edits.await.unwrap();
8865
8866        async fn handle_completion_request(
8867            fake: &mut FakeLanguageServer,
8868            path: &'static str,
8869            position: Point,
8870            completions: Vec<(Range<Point>, &'static str)>,
8871        ) {
8872            fake.handle_request::<lsp::request::Completion, _>(move |params, _| {
8873                assert_eq!(
8874                    params.text_document_position.text_document.uri,
8875                    lsp::Url::from_file_path(path).unwrap()
8876                );
8877                assert_eq!(
8878                    params.text_document_position.position,
8879                    lsp::Position::new(position.row, position.column)
8880                );
8881                Some(lsp::CompletionResponse::Array(
8882                    completions
8883                        .iter()
8884                        .map(|(range, new_text)| lsp::CompletionItem {
8885                            label: new_text.to_string(),
8886                            text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
8887                                range: lsp::Range::new(
8888                                    lsp::Position::new(range.start.row, range.start.column),
8889                                    lsp::Position::new(range.start.row, range.start.column),
8890                                ),
8891                                new_text: new_text.to_string(),
8892                            })),
8893                            ..Default::default()
8894                        })
8895                        .collect(),
8896                ))
8897            })
8898            .next()
8899            .await;
8900        }
8901
8902        async fn handle_resolve_completion_request(
8903            fake: &mut FakeLanguageServer,
8904            edit: Option<(Range<Point>, &'static str)>,
8905        ) {
8906            fake.handle_request::<lsp::request::ResolveCompletionItem, _>(move |_, _| {
8907                lsp::CompletionItem {
8908                    additional_text_edits: edit.clone().map(|(range, new_text)| {
8909                        vec![lsp::TextEdit::new(
8910                            lsp::Range::new(
8911                                lsp::Position::new(range.start.row, range.start.column),
8912                                lsp::Position::new(range.end.row, range.end.column),
8913                            ),
8914                            new_text.to_string(),
8915                        )]
8916                    }),
8917                    ..Default::default()
8918                }
8919            })
8920            .next()
8921            .await;
8922        }
8923    }
8924
8925    #[gpui::test]
8926    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
8927        cx.update(populate_settings);
8928        let language = Arc::new(Language::new(
8929            LanguageConfig {
8930                line_comment: Some("// ".to_string()),
8931                ..Default::default()
8932            },
8933            Some(tree_sitter_rust::language()),
8934        ));
8935
8936        let text = "
8937            fn a() {
8938                //b();
8939                // c();
8940                //  d();
8941            }
8942        "
8943        .unindent();
8944
8945        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8946        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8947        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8948
8949        view.update(cx, |editor, cx| {
8950            // If multiple selections intersect a line, the line is only
8951            // toggled once.
8952            editor.select_display_ranges(
8953                &[
8954                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
8955                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
8956                ],
8957                cx,
8958            );
8959            editor.toggle_comments(&ToggleComments, cx);
8960            assert_eq!(
8961                editor.text(cx),
8962                "
8963                    fn a() {
8964                        b();
8965                        c();
8966                         d();
8967                    }
8968                "
8969                .unindent()
8970            );
8971
8972            // The comment prefix is inserted at the same column for every line
8973            // in a selection.
8974            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
8975            editor.toggle_comments(&ToggleComments, cx);
8976            assert_eq!(
8977                editor.text(cx),
8978                "
8979                    fn a() {
8980                        // b();
8981                        // c();
8982                        //  d();
8983                    }
8984                "
8985                .unindent()
8986            );
8987
8988            // If a selection ends at the beginning of a line, that line is not toggled.
8989            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
8990            editor.toggle_comments(&ToggleComments, cx);
8991            assert_eq!(
8992                editor.text(cx),
8993                "
8994                        fn a() {
8995                            // b();
8996                            c();
8997                            //  d();
8998                        }
8999                    "
9000                .unindent()
9001            );
9002        });
9003    }
9004
9005    #[gpui::test]
9006    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
9007        populate_settings(cx);
9008        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9009        let multibuffer = cx.add_model(|cx| {
9010            let mut multibuffer = MultiBuffer::new(0);
9011            multibuffer.push_excerpts(
9012                buffer.clone(),
9013                [
9014                    Point::new(0, 0)..Point::new(0, 4),
9015                    Point::new(1, 0)..Point::new(1, 4),
9016                ],
9017                cx,
9018            );
9019            multibuffer
9020        });
9021
9022        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
9023
9024        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9025        view.update(cx, |view, cx| {
9026            assert_eq!(view.text(cx), "aaaa\nbbbb");
9027            view.select_ranges(
9028                [
9029                    Point::new(0, 0)..Point::new(0, 0),
9030                    Point::new(1, 0)..Point::new(1, 0),
9031                ],
9032                None,
9033                cx,
9034            );
9035
9036            view.handle_input(&Input("X".to_string()), cx);
9037            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
9038            assert_eq!(
9039                view.selected_ranges(cx),
9040                [
9041                    Point::new(0, 1)..Point::new(0, 1),
9042                    Point::new(1, 1)..Point::new(1, 1),
9043                ]
9044            )
9045        });
9046    }
9047
9048    #[gpui::test]
9049    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
9050        populate_settings(cx);
9051        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9052        let multibuffer = cx.add_model(|cx| {
9053            let mut multibuffer = MultiBuffer::new(0);
9054            multibuffer.push_excerpts(
9055                buffer,
9056                [
9057                    Point::new(0, 0)..Point::new(1, 4),
9058                    Point::new(1, 0)..Point::new(2, 4),
9059                ],
9060                cx,
9061            );
9062            multibuffer
9063        });
9064
9065        assert_eq!(
9066            multibuffer.read(cx).read(cx).text(),
9067            "aaaa\nbbbb\nbbbb\ncccc"
9068        );
9069
9070        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9071        view.update(cx, |view, cx| {
9072            view.select_ranges(
9073                [
9074                    Point::new(1, 1)..Point::new(1, 1),
9075                    Point::new(2, 3)..Point::new(2, 3),
9076                ],
9077                None,
9078                cx,
9079            );
9080
9081            view.handle_input(&Input("X".to_string()), cx);
9082            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
9083            assert_eq!(
9084                view.selected_ranges(cx),
9085                [
9086                    Point::new(1, 2)..Point::new(1, 2),
9087                    Point::new(2, 5)..Point::new(2, 5),
9088                ]
9089            );
9090
9091            view.newline(&Newline, cx);
9092            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
9093            assert_eq!(
9094                view.selected_ranges(cx),
9095                [
9096                    Point::new(2, 0)..Point::new(2, 0),
9097                    Point::new(6, 0)..Point::new(6, 0),
9098                ]
9099            );
9100        });
9101    }
9102
9103    #[gpui::test]
9104    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
9105        populate_settings(cx);
9106        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9107        let mut excerpt1_id = None;
9108        let multibuffer = cx.add_model(|cx| {
9109            let mut multibuffer = MultiBuffer::new(0);
9110            excerpt1_id = multibuffer
9111                .push_excerpts(
9112                    buffer.clone(),
9113                    [
9114                        Point::new(0, 0)..Point::new(1, 4),
9115                        Point::new(1, 0)..Point::new(2, 4),
9116                    ],
9117                    cx,
9118                )
9119                .into_iter()
9120                .next();
9121            multibuffer
9122        });
9123        assert_eq!(
9124            multibuffer.read(cx).read(cx).text(),
9125            "aaaa\nbbbb\nbbbb\ncccc"
9126        );
9127        let (_, editor) = cx.add_window(Default::default(), |cx| {
9128            let mut editor = build_editor(multibuffer.clone(), cx);
9129            let snapshot = editor.snapshot(cx);
9130            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
9131            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
9132            assert_eq!(
9133                editor.selected_ranges(cx),
9134                [
9135                    Point::new(1, 3)..Point::new(1, 3),
9136                    Point::new(2, 1)..Point::new(2, 1),
9137                ]
9138            );
9139            editor
9140        });
9141
9142        // Refreshing selections is a no-op when excerpts haven't changed.
9143        editor.update(cx, |editor, cx| {
9144            editor.refresh_selections(cx);
9145            assert_eq!(
9146                editor.selected_ranges(cx),
9147                [
9148                    Point::new(1, 3)..Point::new(1, 3),
9149                    Point::new(2, 1)..Point::new(2, 1),
9150                ]
9151            );
9152        });
9153
9154        multibuffer.update(cx, |multibuffer, cx| {
9155            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9156        });
9157        editor.update(cx, |editor, cx| {
9158            // Removing an excerpt causes the first selection to become degenerate.
9159            assert_eq!(
9160                editor.selected_ranges(cx),
9161                [
9162                    Point::new(0, 0)..Point::new(0, 0),
9163                    Point::new(0, 1)..Point::new(0, 1)
9164                ]
9165            );
9166
9167            // Refreshing selections will relocate the first selection to the original buffer
9168            // location.
9169            editor.refresh_selections(cx);
9170            assert_eq!(
9171                editor.selected_ranges(cx),
9172                [
9173                    Point::new(0, 1)..Point::new(0, 1),
9174                    Point::new(0, 3)..Point::new(0, 3)
9175                ]
9176            );
9177            assert!(editor.pending_selection.is_some());
9178        });
9179    }
9180
9181    #[gpui::test]
9182    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
9183        populate_settings(cx);
9184        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9185        let mut excerpt1_id = None;
9186        let multibuffer = cx.add_model(|cx| {
9187            let mut multibuffer = MultiBuffer::new(0);
9188            excerpt1_id = multibuffer
9189                .push_excerpts(
9190                    buffer.clone(),
9191                    [
9192                        Point::new(0, 0)..Point::new(1, 4),
9193                        Point::new(1, 0)..Point::new(2, 4),
9194                    ],
9195                    cx,
9196                )
9197                .into_iter()
9198                .next();
9199            multibuffer
9200        });
9201        assert_eq!(
9202            multibuffer.read(cx).read(cx).text(),
9203            "aaaa\nbbbb\nbbbb\ncccc"
9204        );
9205        let (_, editor) = cx.add_window(Default::default(), |cx| {
9206            let mut editor = build_editor(multibuffer.clone(), cx);
9207            let snapshot = editor.snapshot(cx);
9208            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
9209            assert_eq!(
9210                editor.selected_ranges(cx),
9211                [Point::new(1, 3)..Point::new(1, 3)]
9212            );
9213            editor
9214        });
9215
9216        multibuffer.update(cx, |multibuffer, cx| {
9217            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9218        });
9219        editor.update(cx, |editor, cx| {
9220            assert_eq!(
9221                editor.selected_ranges(cx),
9222                [Point::new(0, 0)..Point::new(0, 0)]
9223            );
9224
9225            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
9226            editor.refresh_selections(cx);
9227            assert_eq!(
9228                editor.selected_ranges(cx),
9229                [Point::new(0, 3)..Point::new(0, 3)]
9230            );
9231            assert!(editor.pending_selection.is_some());
9232        });
9233    }
9234
9235    #[gpui::test]
9236    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
9237        cx.update(populate_settings);
9238        let language = Arc::new(Language::new(
9239            LanguageConfig {
9240                brackets: vec![
9241                    BracketPair {
9242                        start: "{".to_string(),
9243                        end: "}".to_string(),
9244                        close: true,
9245                        newline: true,
9246                    },
9247                    BracketPair {
9248                        start: "/* ".to_string(),
9249                        end: " */".to_string(),
9250                        close: true,
9251                        newline: true,
9252                    },
9253                ],
9254                ..Default::default()
9255            },
9256            Some(tree_sitter_rust::language()),
9257        ));
9258
9259        let text = concat!(
9260            "{   }\n",     // Suppress rustfmt
9261            "  x\n",       //
9262            "  /*   */\n", //
9263            "x\n",         //
9264            "{{} }\n",     //
9265        );
9266
9267        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
9268        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9269        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
9270        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
9271            .await;
9272
9273        view.update(cx, |view, cx| {
9274            view.select_display_ranges(
9275                &[
9276                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
9277                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
9278                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
9279                ],
9280                cx,
9281            );
9282            view.newline(&Newline, cx);
9283
9284            assert_eq!(
9285                view.buffer().read(cx).read(cx).text(),
9286                concat!(
9287                    "{ \n",    // Suppress rustfmt
9288                    "\n",      //
9289                    "}\n",     //
9290                    "  x\n",   //
9291                    "  /* \n", //
9292                    "  \n",    //
9293                    "  */\n",  //
9294                    "x\n",     //
9295                    "{{} \n",  //
9296                    "}\n",     //
9297                )
9298            );
9299        });
9300    }
9301
9302    #[gpui::test]
9303    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
9304        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9305        populate_settings(cx);
9306        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9307
9308        editor.update(cx, |editor, cx| {
9309            struct Type1;
9310            struct Type2;
9311
9312            let buffer = buffer.read(cx).snapshot(cx);
9313
9314            let anchor_range = |range: Range<Point>| {
9315                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
9316            };
9317
9318            editor.highlight_background::<Type1>(
9319                vec![
9320                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
9321                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
9322                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
9323                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
9324                ],
9325                Color::red(),
9326                cx,
9327            );
9328            editor.highlight_background::<Type2>(
9329                vec![
9330                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
9331                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
9332                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
9333                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
9334                ],
9335                Color::green(),
9336                cx,
9337            );
9338
9339            let snapshot = editor.snapshot(cx);
9340            let mut highlighted_ranges = editor.background_highlights_in_range(
9341                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
9342                &snapshot,
9343            );
9344            // Enforce a consistent ordering based on color without relying on the ordering of the
9345            // highlight's `TypeId` which is non-deterministic.
9346            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
9347            assert_eq!(
9348                highlighted_ranges,
9349                &[
9350                    (
9351                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
9352                        Color::green(),
9353                    ),
9354                    (
9355                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
9356                        Color::green(),
9357                    ),
9358                    (
9359                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
9360                        Color::red(),
9361                    ),
9362                    (
9363                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9364                        Color::red(),
9365                    ),
9366                ]
9367            );
9368            assert_eq!(
9369                editor.background_highlights_in_range(
9370                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
9371                    &snapshot,
9372                ),
9373                &[(
9374                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9375                    Color::red(),
9376                )]
9377            );
9378        });
9379    }
9380
9381    #[gpui::test]
9382    fn test_following(cx: &mut gpui::MutableAppContext) {
9383        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9384        populate_settings(cx);
9385
9386        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9387        let (_, follower) = cx.add_window(
9388            WindowOptions {
9389                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
9390                ..Default::default()
9391            },
9392            |cx| build_editor(buffer.clone(), cx),
9393        );
9394
9395        let pending_update = Rc::new(RefCell::new(None));
9396        follower.update(cx, {
9397            let update = pending_update.clone();
9398            |_, cx| {
9399                cx.subscribe(&leader, move |_, leader, event, cx| {
9400                    leader
9401                        .read(cx)
9402                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
9403                })
9404                .detach();
9405            }
9406        });
9407
9408        // Update the selections only
9409        leader.update(cx, |leader, cx| {
9410            leader.select_ranges([1..1], None, cx);
9411        });
9412        follower.update(cx, |follower, cx| {
9413            follower
9414                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9415                .unwrap();
9416        });
9417        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
9418
9419        // Update the scroll position only
9420        leader.update(cx, |leader, cx| {
9421            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9422        });
9423        follower.update(cx, |follower, cx| {
9424            follower
9425                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9426                .unwrap();
9427        });
9428        assert_eq!(
9429            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
9430            vec2f(1.5, 3.5)
9431        );
9432
9433        // Update the selections and scroll position
9434        leader.update(cx, |leader, cx| {
9435            leader.select_ranges([0..0], None, cx);
9436            leader.request_autoscroll(Autoscroll::Newest, cx);
9437            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9438        });
9439        follower.update(cx, |follower, cx| {
9440            let initial_scroll_position = follower.scroll_position(cx);
9441            follower
9442                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9443                .unwrap();
9444            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
9445            assert!(follower.autoscroll_request.is_some());
9446        });
9447        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
9448
9449        // Creating a pending selection that precedes another selection
9450        leader.update(cx, |leader, cx| {
9451            leader.select_ranges([1..1], None, cx);
9452            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
9453        });
9454        follower.update(cx, |follower, cx| {
9455            follower
9456                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9457                .unwrap();
9458        });
9459        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
9460
9461        // Extend the pending selection so that it surrounds another selection
9462        leader.update(cx, |leader, cx| {
9463            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
9464        });
9465        follower.update(cx, |follower, cx| {
9466            follower
9467                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9468                .unwrap();
9469        });
9470        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
9471    }
9472
9473    #[test]
9474    fn test_combine_syntax_and_fuzzy_match_highlights() {
9475        let string = "abcdefghijklmnop";
9476        let syntax_ranges = [
9477            (
9478                0..3,
9479                HighlightStyle {
9480                    color: Some(Color::red()),
9481                    ..Default::default()
9482                },
9483            ),
9484            (
9485                4..8,
9486                HighlightStyle {
9487                    color: Some(Color::green()),
9488                    ..Default::default()
9489                },
9490            ),
9491        ];
9492        let match_indices = [4, 6, 7, 8];
9493        assert_eq!(
9494            combine_syntax_and_fuzzy_match_highlights(
9495                &string,
9496                Default::default(),
9497                syntax_ranges.into_iter(),
9498                &match_indices,
9499            ),
9500            &[
9501                (
9502                    0..3,
9503                    HighlightStyle {
9504                        color: Some(Color::red()),
9505                        ..Default::default()
9506                    },
9507                ),
9508                (
9509                    4..5,
9510                    HighlightStyle {
9511                        color: Some(Color::green()),
9512                        weight: Some(fonts::Weight::BOLD),
9513                        ..Default::default()
9514                    },
9515                ),
9516                (
9517                    5..6,
9518                    HighlightStyle {
9519                        color: Some(Color::green()),
9520                        ..Default::default()
9521                    },
9522                ),
9523                (
9524                    6..8,
9525                    HighlightStyle {
9526                        color: Some(Color::green()),
9527                        weight: Some(fonts::Weight::BOLD),
9528                        ..Default::default()
9529                    },
9530                ),
9531                (
9532                    8..9,
9533                    HighlightStyle {
9534                        weight: Some(fonts::Weight::BOLD),
9535                        ..Default::default()
9536                    },
9537                ),
9538            ]
9539        );
9540    }
9541
9542    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
9543        let point = DisplayPoint::new(row as u32, column as u32);
9544        point..point
9545    }
9546
9547    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
9548        Editor::new(EditorMode::Full, buffer, None, None, cx)
9549    }
9550
9551    fn populate_settings(cx: &mut gpui::MutableAppContext) {
9552        let settings = Settings::test(cx);
9553        cx.set_global(settings);
9554    }
9555
9556    fn assert_selection_ranges(
9557        marked_text: &str,
9558        selection_marker_pairs: Vec<(char, char)>,
9559        view: &mut Editor,
9560        cx: &mut ViewContext<Editor>,
9561    ) {
9562        let snapshot = view.snapshot(cx).display_snapshot;
9563        let mut marker_chars = Vec::new();
9564        for (start, end) in selection_marker_pairs.iter() {
9565            marker_chars.push(*start);
9566            marker_chars.push(*end);
9567        }
9568        let (_, markers) = marked_text_by(marked_text, marker_chars);
9569        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
9570            .iter()
9571            .map(|(start, end)| {
9572                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
9573                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
9574                start..end
9575            })
9576            .collect();
9577        assert_eq!(
9578            view.selected_display_ranges(cx),
9579            &asserted_ranges[..],
9580            "Assert selections are {}",
9581            marked_text
9582        );
9583    }
9584}
9585
9586trait RangeExt<T> {
9587    fn sorted(&self) -> Range<T>;
9588    fn to_inclusive(&self) -> RangeInclusive<T>;
9589}
9590
9591impl<T: Ord + Clone> RangeExt<T> for Range<T> {
9592    fn sorted(&self) -> Self {
9593        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
9594    }
9595
9596    fn to_inclusive(&self) -> RangeInclusive<T> {
9597        self.start.clone()..=self.end.clone()
9598    }
9599}