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