editor.rs

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