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