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