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 =
1065                self.newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot);
1066            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
1067            last_cursor_bottom = first_cursor_top + 1.;
1068        } else {
1069            let selections = self.local_selections::<Point>(cx);
1070            first_cursor_top = selections
1071                .first()
1072                .unwrap()
1073                .head()
1074                .to_display_point(&display_map)
1075                .row() as f32;
1076            last_cursor_bottom = selections
1077                .last()
1078                .unwrap()
1079                .head()
1080                .to_display_point(&display_map)
1081                .row() as f32
1082                + 1.0;
1083        }
1084
1085        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
1086            0.
1087        } else {
1088            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
1089        };
1090        if margin < 0.0 {
1091            return false;
1092        }
1093
1094        match autoscroll {
1095            Autoscroll::Fit | Autoscroll::Newest => {
1096                let margin = margin.min(self.vertical_scroll_margin);
1097                let target_top = (first_cursor_top - margin).max(0.0);
1098                let target_bottom = last_cursor_bottom + margin;
1099                let start_row = scroll_position.y();
1100                let end_row = start_row + visible_lines;
1101
1102                if target_top < start_row {
1103                    scroll_position.set_y(target_top);
1104                    self.set_scroll_position(scroll_position, cx);
1105                } else if target_bottom >= end_row {
1106                    scroll_position.set_y(target_bottom - visible_lines);
1107                    self.set_scroll_position(scroll_position, cx);
1108                }
1109            }
1110            Autoscroll::Center => {
1111                scroll_position.set_y((first_cursor_top - margin).max(0.0));
1112                self.set_scroll_position(scroll_position, cx);
1113            }
1114        }
1115
1116        true
1117    }
1118
1119    pub fn autoscroll_horizontally(
1120        &mut self,
1121        start_row: u32,
1122        viewport_width: f32,
1123        scroll_width: f32,
1124        max_glyph_width: f32,
1125        layouts: &[text_layout::Line],
1126        cx: &mut ViewContext<Self>,
1127    ) -> bool {
1128        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1129        let selections = self.local_selections::<Point>(cx);
1130
1131        let mut target_left;
1132        let mut target_right;
1133
1134        if self.highlighted_rows.is_some() {
1135            target_left = 0.0_f32;
1136            target_right = 0.0_f32;
1137        } else {
1138            target_left = std::f32::INFINITY;
1139            target_right = 0.0_f32;
1140            for selection in selections {
1141                let head = selection.head().to_display_point(&display_map);
1142                if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
1143                    let start_column = head.column().saturating_sub(3);
1144                    let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
1145                    target_left = target_left.min(
1146                        layouts[(head.row() - start_row) as usize]
1147                            .x_for_index(start_column as usize),
1148                    );
1149                    target_right = target_right.max(
1150                        layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
1151                            + max_glyph_width,
1152                    );
1153                }
1154            }
1155        }
1156
1157        target_right = target_right.min(scroll_width);
1158
1159        if target_right - target_left > viewport_width {
1160            return false;
1161        }
1162
1163        let scroll_left = self.scroll_position.x() * max_glyph_width;
1164        let scroll_right = scroll_left + viewport_width;
1165
1166        if target_left < scroll_left {
1167            self.scroll_position.set_x(target_left / max_glyph_width);
1168            true
1169        } else if target_right > scroll_right {
1170            self.scroll_position
1171                .set_x((target_right - viewport_width) / max_glyph_width);
1172            true
1173        } else {
1174            false
1175        }
1176    }
1177
1178    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
1179        self.hide_context_menu(cx);
1180
1181        match phase {
1182            SelectPhase::Begin {
1183                position,
1184                add,
1185                click_count,
1186            } => self.begin_selection(*position, *add, *click_count, cx),
1187            SelectPhase::BeginColumnar {
1188                position,
1189                overshoot,
1190            } => self.begin_columnar_selection(*position, *overshoot, cx),
1191            SelectPhase::Extend {
1192                position,
1193                click_count,
1194            } => self.extend_selection(*position, *click_count, cx),
1195            SelectPhase::Update {
1196                position,
1197                overshoot,
1198                scroll_position,
1199            } => self.update_selection(*position, *overshoot, *scroll_position, cx),
1200            SelectPhase::End => self.end_selection(cx),
1201        }
1202    }
1203
1204    fn extend_selection(
1205        &mut self,
1206        position: DisplayPoint,
1207        click_count: usize,
1208        cx: &mut ViewContext<Self>,
1209    ) {
1210        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1211        let tail = self
1212            .newest_selection_with_snapshot::<usize>(&display_map.buffer_snapshot)
1213            .tail();
1214        self.begin_selection(position, false, click_count, cx);
1215
1216        let position = position.to_offset(&display_map, Bias::Left);
1217        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1218        let mut pending = self.pending_selection.clone().unwrap();
1219
1220        if position >= tail {
1221            pending.selection.start = tail_anchor.clone();
1222        } else {
1223            pending.selection.end = tail_anchor.clone();
1224            pending.selection.reversed = true;
1225        }
1226
1227        match &mut pending.mode {
1228            SelectMode::Word(range) | SelectMode::Line(range) => {
1229                *range = tail_anchor.clone()..tail_anchor
1230            }
1231            _ => {}
1232        }
1233
1234        self.set_selections(self.selections.clone(), Some(pending), cx);
1235    }
1236
1237    fn begin_selection(
1238        &mut self,
1239        position: DisplayPoint,
1240        add: bool,
1241        click_count: usize,
1242        cx: &mut ViewContext<Self>,
1243    ) {
1244        if !self.focused {
1245            cx.focus_self();
1246            cx.emit(Event::Activate);
1247        }
1248
1249        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1250        let buffer = &display_map.buffer_snapshot;
1251        let newest_selection = self.newest_anchor_selection().clone();
1252
1253        let start;
1254        let end;
1255        let mode;
1256        match click_count {
1257            1 => {
1258                start = buffer.anchor_before(position.to_point(&display_map));
1259                end = start.clone();
1260                mode = SelectMode::Character;
1261            }
1262            2 => {
1263                let range = movement::surrounding_word(&display_map, position);
1264                start = buffer.anchor_before(range.start.to_point(&display_map));
1265                end = buffer.anchor_before(range.end.to_point(&display_map));
1266                mode = SelectMode::Word(start.clone()..end.clone());
1267            }
1268            3 => {
1269                let position = display_map
1270                    .clip_point(position, Bias::Left)
1271                    .to_point(&display_map);
1272                let line_start = display_map.prev_line_boundary(position).0;
1273                let next_line_start = buffer.clip_point(
1274                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1275                    Bias::Left,
1276                );
1277                start = buffer.anchor_before(line_start);
1278                end = buffer.anchor_before(next_line_start);
1279                mode = SelectMode::Line(start.clone()..end.clone());
1280            }
1281            _ => {
1282                start = buffer.anchor_before(0);
1283                end = buffer.anchor_before(buffer.len());
1284                mode = SelectMode::All;
1285            }
1286        }
1287
1288        self.push_to_nav_history(newest_selection.head(), Some(end.to_point(&buffer)), cx);
1289
1290        let selection = Selection {
1291            id: post_inc(&mut self.next_selection_id),
1292            start,
1293            end,
1294            reversed: false,
1295            goal: SelectionGoal::None,
1296        };
1297
1298        let mut selections;
1299        if add {
1300            selections = self.selections.clone();
1301            // Remove the newest selection if it was added due to a previous mouse up
1302            // within this multi-click.
1303            if click_count > 1 {
1304                selections = self
1305                    .selections
1306                    .iter()
1307                    .filter(|selection| selection.id != newest_selection.id)
1308                    .cloned()
1309                    .collect();
1310            }
1311        } else {
1312            selections = Arc::from([]);
1313        }
1314        self.set_selections(selections, Some(PendingSelection { selection, mode }), cx);
1315
1316        cx.notify();
1317    }
1318
1319    fn begin_columnar_selection(
1320        &mut self,
1321        position: DisplayPoint,
1322        overshoot: u32,
1323        cx: &mut ViewContext<Self>,
1324    ) {
1325        if !self.focused {
1326            cx.focus_self();
1327            cx.emit(Event::Activate);
1328        }
1329
1330        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1331        let tail = self
1332            .newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot)
1333            .tail();
1334        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1335
1336        self.select_columns(
1337            tail.to_display_point(&display_map),
1338            position,
1339            overshoot,
1340            &display_map,
1341            cx,
1342        );
1343    }
1344
1345    fn update_selection(
1346        &mut self,
1347        position: DisplayPoint,
1348        overshoot: u32,
1349        scroll_position: Vector2F,
1350        cx: &mut ViewContext<Self>,
1351    ) {
1352        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1353
1354        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1355            let tail = tail.to_display_point(&display_map);
1356            self.select_columns(tail, position, overshoot, &display_map, cx);
1357        } else if let Some(mut pending) = self.pending_selection.clone() {
1358            let buffer = self.buffer.read(cx).snapshot(cx);
1359            let head;
1360            let tail;
1361            match &pending.mode {
1362                SelectMode::Character => {
1363                    head = position.to_point(&display_map);
1364                    tail = pending.selection.tail().to_point(&buffer);
1365                }
1366                SelectMode::Word(original_range) => {
1367                    let original_display_range = original_range.start.to_display_point(&display_map)
1368                        ..original_range.end.to_display_point(&display_map);
1369                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1370                        ..original_display_range.end.to_point(&display_map);
1371                    if movement::is_inside_word(&display_map, position)
1372                        || original_display_range.contains(&position)
1373                    {
1374                        let word_range = movement::surrounding_word(&display_map, position);
1375                        if word_range.start < original_display_range.start {
1376                            head = word_range.start.to_point(&display_map);
1377                        } else {
1378                            head = word_range.end.to_point(&display_map);
1379                        }
1380                    } else {
1381                        head = position.to_point(&display_map);
1382                    }
1383
1384                    if head <= original_buffer_range.start {
1385                        tail = original_buffer_range.end;
1386                    } else {
1387                        tail = original_buffer_range.start;
1388                    }
1389                }
1390                SelectMode::Line(original_range) => {
1391                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1392
1393                    let position = display_map
1394                        .clip_point(position, Bias::Left)
1395                        .to_point(&display_map);
1396                    let line_start = display_map.prev_line_boundary(position).0;
1397                    let next_line_start = buffer.clip_point(
1398                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1399                        Bias::Left,
1400                    );
1401
1402                    if line_start < original_range.start {
1403                        head = line_start
1404                    } else {
1405                        head = next_line_start
1406                    }
1407
1408                    if head <= original_range.start {
1409                        tail = original_range.end;
1410                    } else {
1411                        tail = original_range.start;
1412                    }
1413                }
1414                SelectMode::All => {
1415                    return;
1416                }
1417            };
1418
1419            if head < tail {
1420                pending.selection.start = buffer.anchor_before(head);
1421                pending.selection.end = buffer.anchor_before(tail);
1422                pending.selection.reversed = true;
1423            } else {
1424                pending.selection.start = buffer.anchor_before(tail);
1425                pending.selection.end = buffer.anchor_before(head);
1426                pending.selection.reversed = false;
1427            }
1428            self.set_selections(self.selections.clone(), Some(pending), cx);
1429        } else {
1430            log::error!("update_selection dispatched with no pending selection");
1431            return;
1432        }
1433
1434        self.set_scroll_position(scroll_position, cx);
1435        cx.notify();
1436    }
1437
1438    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1439        self.columnar_selection_tail.take();
1440        if self.pending_selection.is_some() {
1441            let selections = self.local_selections::<usize>(cx);
1442            self.update_selections(selections, None, cx);
1443        }
1444    }
1445
1446    fn select_columns(
1447        &mut self,
1448        tail: DisplayPoint,
1449        head: DisplayPoint,
1450        overshoot: u32,
1451        display_map: &DisplaySnapshot,
1452        cx: &mut ViewContext<Self>,
1453    ) {
1454        let start_row = cmp::min(tail.row(), head.row());
1455        let end_row = cmp::max(tail.row(), head.row());
1456        let start_column = cmp::min(tail.column(), head.column() + overshoot);
1457        let end_column = cmp::max(tail.column(), head.column() + overshoot);
1458        let reversed = start_column < tail.column();
1459
1460        let selections = (start_row..=end_row)
1461            .filter_map(|row| {
1462                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1463                    let start = display_map
1464                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1465                        .to_point(&display_map);
1466                    let end = display_map
1467                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1468                        .to_point(&display_map);
1469                    Some(Selection {
1470                        id: post_inc(&mut self.next_selection_id),
1471                        start,
1472                        end,
1473                        reversed,
1474                        goal: SelectionGoal::None,
1475                    })
1476                } else {
1477                    None
1478                }
1479            })
1480            .collect::<Vec<_>>();
1481
1482        self.update_selections(selections, None, cx);
1483        cx.notify();
1484    }
1485
1486    pub fn is_selecting(&self) -> bool {
1487        self.pending_selection.is_some() || self.columnar_selection_tail.is_some()
1488    }
1489
1490    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1491        if self.take_rename(cx).is_some() {
1492            return;
1493        }
1494
1495        if self.hide_context_menu(cx).is_some() {
1496            return;
1497        }
1498
1499        if self.snippet_stack.pop().is_some() {
1500            return;
1501        }
1502
1503        if self.mode != EditorMode::Full {
1504            cx.propagate_action();
1505            return;
1506        }
1507
1508        if self.active_diagnostics.is_some() {
1509            self.dismiss_diagnostics(cx);
1510        } else if let Some(pending) = self.pending_selection.clone() {
1511            let mut selections = self.selections.clone();
1512            if selections.is_empty() {
1513                selections = Arc::from([pending.selection]);
1514            }
1515            self.set_selections(selections, None, cx);
1516            self.request_autoscroll(Autoscroll::Fit, cx);
1517        } else {
1518            let mut oldest_selection = self.oldest_selection::<usize>(&cx);
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_with_snapshot::<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 head = editor.newest_selection::<usize>(cx).head();
4162        let (buffer, head) =
4163            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
4164                text_anchor
4165            } else {
4166                return;
4167            };
4168
4169        let definitions = workspace
4170            .project()
4171            .update(cx, |project, cx| project.definition(&buffer, head, cx));
4172        cx.spawn(|workspace, mut cx| async move {
4173            let definitions = definitions.await?;
4174            workspace.update(&mut cx, |workspace, cx| {
4175                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
4176                for definition in definitions {
4177                    let range = definition.range.to_offset(definition.buffer.read(cx));
4178                    let target_editor_handle = workspace
4179                        .open_item(BufferItemHandle(definition.buffer), cx)
4180                        .downcast::<Self>()
4181                        .unwrap();
4182
4183                    target_editor_handle.update(cx, |target_editor, cx| {
4184                        // When selecting a definition in a different buffer, disable the nav history
4185                        // to avoid creating a history entry at the previous cursor location.
4186                        if editor_handle != target_editor_handle {
4187                            nav_history.borrow_mut().disable();
4188                        }
4189                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
4190                        nav_history.borrow_mut().enable();
4191                    });
4192                }
4193            });
4194
4195            Ok::<(), anyhow::Error>(())
4196        })
4197        .detach_and_log_err(cx);
4198    }
4199
4200    pub fn find_all_references(
4201        workspace: &mut Workspace,
4202        _: &FindAllReferences,
4203        cx: &mut ViewContext<Workspace>,
4204    ) -> Option<Task<Result<()>>> {
4205        let active_item = workspace.active_item(cx)?;
4206        let editor_handle = active_item.act_as::<Self>(cx)?;
4207
4208        let editor = editor_handle.read(cx);
4209        let head = editor.newest_selection::<usize>(cx).head();
4210        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
4211        let replica_id = editor.replica_id(cx);
4212
4213        let references = workspace
4214            .project()
4215            .update(cx, |project, cx| project.references(&buffer, head, cx));
4216        Some(cx.spawn(|workspace, mut cx| async move {
4217            let mut locations = references.await?;
4218            if locations.is_empty() {
4219                return Ok(());
4220            }
4221
4222            locations.sort_by_key(|location| location.buffer.id());
4223            let mut locations = locations.into_iter().peekable();
4224            let mut ranges_to_highlight = Vec::new();
4225
4226            let excerpt_buffer = cx.add_model(|cx| {
4227                let mut symbol_name = None;
4228                let mut multibuffer = MultiBuffer::new(replica_id);
4229                while let Some(location) = locations.next() {
4230                    let buffer = location.buffer.read(cx);
4231                    let mut ranges_for_buffer = Vec::new();
4232                    let range = location.range.to_offset(buffer);
4233                    ranges_for_buffer.push(range.clone());
4234                    if symbol_name.is_none() {
4235                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
4236                    }
4237
4238                    while let Some(next_location) = locations.peek() {
4239                        if next_location.buffer == location.buffer {
4240                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
4241                            locations.next();
4242                        } else {
4243                            break;
4244                        }
4245                    }
4246
4247                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
4248                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
4249                        location.buffer.clone(),
4250                        ranges_for_buffer,
4251                        1,
4252                        cx,
4253                    ));
4254                }
4255                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
4256            });
4257
4258            workspace.update(&mut cx, |workspace, cx| {
4259                let editor = workspace.open_item(MultiBufferItemHandle(excerpt_buffer), cx);
4260                if let Some(editor) = editor.act_as::<Self>(cx) {
4261                    editor.update(cx, |editor, cx| {
4262                        let color = editor.style(cx).highlighted_line_background;
4263                        editor.highlight_ranges::<Self>(ranges_to_highlight, color, cx);
4264                    });
4265                }
4266            });
4267
4268            Ok(())
4269        }))
4270    }
4271
4272    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
4273        use language::ToOffset as _;
4274
4275        let project = self.project.clone()?;
4276        let selection = self.newest_anchor_selection().clone();
4277        let (cursor_buffer, cursor_buffer_position) = self
4278            .buffer
4279            .read(cx)
4280            .text_anchor_for_position(selection.head(), cx)?;
4281        let (tail_buffer, tail_buffer_position) = self
4282            .buffer
4283            .read(cx)
4284            .text_anchor_for_position(selection.tail(), cx)?;
4285        if tail_buffer != cursor_buffer {
4286            return None;
4287        }
4288
4289        let snapshot = cursor_buffer.read(cx).snapshot();
4290        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
4291        let tail_buffer_offset = tail_buffer_position.to_offset(&snapshot);
4292        let prepare_rename = project.update(cx, |project, cx| {
4293            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
4294        });
4295
4296        Some(cx.spawn(|this, mut cx| async move {
4297            if let Some(rename_range) = prepare_rename.await? {
4298                let rename_buffer_range = rename_range.to_offset(&snapshot);
4299                let cursor_offset_in_rename_range =
4300                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
4301                let tail_offset_in_rename_range =
4302                    tail_buffer_offset.saturating_sub(rename_buffer_range.start);
4303
4304                this.update(&mut cx, |this, cx| {
4305                    this.take_rename(cx);
4306                    let style = this.style(cx);
4307                    let buffer = this.buffer.read(cx).read(cx);
4308                    let cursor_offset = selection.head().to_offset(&buffer);
4309                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
4310                    let rename_end = rename_start + rename_buffer_range.len();
4311                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
4312                    let old_name = buffer
4313                        .text_for_range(rename_start..rename_end)
4314                        .collect::<String>();
4315                    drop(buffer);
4316
4317                    // Position the selection in the rename editor so that it matches the current selection.
4318                    let rename_editor = cx.add_view(|cx| {
4319                        let mut editor = Editor::single_line(this.settings.clone(), None, cx);
4320                        editor
4321                            .buffer
4322                            .update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
4323                        editor.select_ranges(
4324                            [tail_offset_in_rename_range..cursor_offset_in_rename_range],
4325                            None,
4326                            cx,
4327                        );
4328                        editor.highlight_ranges::<Rename>(
4329                            vec![Anchor::min()..Anchor::max()],
4330                            style.diff_background_inserted,
4331                            cx,
4332                        );
4333                        editor
4334                    });
4335                    this.highlight_ranges::<Rename>(
4336                        vec![range.clone()],
4337                        style.diff_background_deleted,
4338                        cx,
4339                    );
4340                    this.update_selections(
4341                        vec![Selection {
4342                            id: selection.id,
4343                            start: rename_end,
4344                            end: rename_end,
4345                            reversed: false,
4346                            goal: SelectionGoal::None,
4347                        }],
4348                        None,
4349                        cx,
4350                    );
4351                    cx.focus(&rename_editor);
4352                    let block_id = this.insert_blocks(
4353                        [BlockProperties {
4354                            position: range.start.clone(),
4355                            height: 1,
4356                            render: Arc::new({
4357                                let editor = rename_editor.clone();
4358                                move |cx: &BlockContext| {
4359                                    ChildView::new(editor.clone())
4360                                        .contained()
4361                                        .with_padding_left(cx.anchor_x)
4362                                        .boxed()
4363                                }
4364                            }),
4365                            disposition: BlockDisposition::Below,
4366                        }],
4367                        cx,
4368                    )[0];
4369                    this.pending_rename = Some(RenameState {
4370                        range,
4371                        old_name,
4372                        editor: rename_editor,
4373                        block_id,
4374                    });
4375                });
4376            }
4377
4378            Ok(())
4379        }))
4380    }
4381
4382    pub fn confirm_rename(
4383        workspace: &mut Workspace,
4384        _: &ConfirmRename,
4385        cx: &mut ViewContext<Workspace>,
4386    ) -> Option<Task<Result<()>>> {
4387        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
4388
4389        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
4390            let rename = editor.take_rename(cx)?;
4391            let buffer = editor.buffer.read(cx);
4392            let (start_buffer, start) =
4393                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
4394            let (end_buffer, end) =
4395                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
4396            if start_buffer == end_buffer {
4397                let new_name = rename.editor.read(cx).text(cx);
4398                Some((start_buffer, start..end, rename.old_name, new_name))
4399            } else {
4400                None
4401            }
4402        })?;
4403
4404        let rename = workspace.project().clone().update(cx, |project, cx| {
4405            project.perform_rename(
4406                buffer.clone(),
4407                range.start.clone(),
4408                new_name.clone(),
4409                true,
4410                cx,
4411            )
4412        });
4413
4414        Some(cx.spawn(|workspace, cx| async move {
4415            let project_transaction = rename.await?;
4416            Self::open_project_transaction(
4417                editor,
4418                workspace,
4419                project_transaction,
4420                format!("Rename: {}{}", old_name, new_name),
4421                cx,
4422            )
4423            .await
4424        }))
4425    }
4426
4427    fn take_rename(&mut self, cx: &mut ViewContext<Self>) -> Option<RenameState> {
4428        let rename = self.pending_rename.take()?;
4429        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
4430        self.clear_highlighted_ranges::<Rename>(cx);
4431
4432        let editor = rename.editor.read(cx);
4433        let snapshot = self.buffer.read(cx).snapshot(cx);
4434        let selection = editor.newest_selection_with_snapshot::<usize>(&snapshot);
4435
4436        // Update the selection to match the position of the selection inside
4437        // the rename editor.
4438        let rename_range = rename.range.to_offset(&snapshot);
4439        let start = snapshot
4440            .clip_offset(rename_range.start + selection.start, Bias::Left)
4441            .min(rename_range.end);
4442        let end = snapshot
4443            .clip_offset(rename_range.start + selection.end, Bias::Left)
4444            .min(rename_range.end);
4445        self.update_selections(
4446            vec![Selection {
4447                id: self.newest_anchor_selection().id,
4448                start,
4449                end,
4450                reversed: selection.reversed,
4451                goal: SelectionGoal::None,
4452            }],
4453            None,
4454            cx,
4455        );
4456
4457        Some(rename)
4458    }
4459
4460    fn invalidate_rename_range(
4461        &mut self,
4462        buffer: &MultiBufferSnapshot,
4463        cx: &mut ViewContext<Self>,
4464    ) {
4465        if let Some(rename) = self.pending_rename.as_ref() {
4466            if self.selections.len() == 1 {
4467                let head = self.selections[0].head().to_offset(buffer);
4468                let range = rename.range.to_offset(buffer).to_inclusive();
4469                if range.contains(&head) {
4470                    return;
4471                }
4472            }
4473            let rename = self.pending_rename.take().unwrap();
4474            self.remove_blocks([rename.block_id].into_iter().collect(), cx);
4475            self.clear_highlighted_ranges::<Rename>(cx);
4476        }
4477    }
4478
4479    #[cfg(any(test, feature = "test-support"))]
4480    pub fn pending_rename(&self) -> Option<&RenameState> {
4481        self.pending_rename.as_ref()
4482    }
4483
4484    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
4485        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
4486            let buffer = self.buffer.read(cx).snapshot(cx);
4487            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
4488            let is_valid = buffer
4489                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone())
4490                .any(|entry| {
4491                    entry.diagnostic.is_primary
4492                        && !entry.range.is_empty()
4493                        && entry.range.start == primary_range_start
4494                        && entry.diagnostic.message == active_diagnostics.primary_message
4495                });
4496
4497            if is_valid != active_diagnostics.is_valid {
4498                active_diagnostics.is_valid = is_valid;
4499                let mut new_styles = HashMap::default();
4500                for (block_id, diagnostic) in &active_diagnostics.blocks {
4501                    new_styles.insert(
4502                        *block_id,
4503                        diagnostic_block_renderer(
4504                            diagnostic.clone(),
4505                            is_valid,
4506                            self.settings.clone(),
4507                        ),
4508                    );
4509                }
4510                self.display_map
4511                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
4512            }
4513        }
4514    }
4515
4516    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
4517        self.dismiss_diagnostics(cx);
4518        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
4519            let buffer = self.buffer.read(cx).snapshot(cx);
4520
4521            let mut primary_range = None;
4522            let mut primary_message = None;
4523            let mut group_end = Point::zero();
4524            let diagnostic_group = buffer
4525                .diagnostic_group::<Point>(group_id)
4526                .map(|entry| {
4527                    if entry.range.end > group_end {
4528                        group_end = entry.range.end;
4529                    }
4530                    if entry.diagnostic.is_primary {
4531                        primary_range = Some(entry.range.clone());
4532                        primary_message = Some(entry.diagnostic.message.clone());
4533                    }
4534                    entry
4535                })
4536                .collect::<Vec<_>>();
4537            let primary_range = primary_range.unwrap();
4538            let primary_message = primary_message.unwrap();
4539            let primary_range =
4540                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
4541
4542            let blocks = display_map
4543                .insert_blocks(
4544                    diagnostic_group.iter().map(|entry| {
4545                        let diagnostic = entry.diagnostic.clone();
4546                        let message_height = diagnostic.message.lines().count() as u8;
4547                        BlockProperties {
4548                            position: buffer.anchor_after(entry.range.start),
4549                            height: message_height,
4550                            render: diagnostic_block_renderer(
4551                                diagnostic,
4552                                true,
4553                                self.settings.clone(),
4554                            ),
4555                            disposition: BlockDisposition::Below,
4556                        }
4557                    }),
4558                    cx,
4559                )
4560                .into_iter()
4561                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
4562                .collect();
4563
4564            Some(ActiveDiagnosticGroup {
4565                primary_range,
4566                primary_message,
4567                blocks,
4568                is_valid: true,
4569            })
4570        });
4571    }
4572
4573    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
4574        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
4575            self.display_map.update(cx, |display_map, cx| {
4576                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
4577            });
4578            cx.notify();
4579        }
4580    }
4581
4582    fn build_columnar_selection(
4583        &mut self,
4584        display_map: &DisplaySnapshot,
4585        row: u32,
4586        columns: &Range<u32>,
4587        reversed: bool,
4588    ) -> Option<Selection<Point>> {
4589        let is_empty = columns.start == columns.end;
4590        let line_len = display_map.line_len(row);
4591        if columns.start < line_len || (is_empty && columns.start == line_len) {
4592            let start = DisplayPoint::new(row, columns.start);
4593            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
4594            Some(Selection {
4595                id: post_inc(&mut self.next_selection_id),
4596                start: start.to_point(display_map),
4597                end: end.to_point(display_map),
4598                reversed,
4599                goal: SelectionGoal::ColumnRange {
4600                    start: columns.start,
4601                    end: columns.end,
4602                },
4603            })
4604        } else {
4605            None
4606        }
4607    }
4608
4609    pub fn local_selections_in_range(
4610        &self,
4611        range: Range<Anchor>,
4612        display_map: &DisplaySnapshot,
4613    ) -> Vec<Selection<Point>> {
4614        let buffer = &display_map.buffer_snapshot;
4615
4616        let start_ix = match self
4617            .selections
4618            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer).unwrap())
4619        {
4620            Ok(ix) | Err(ix) => ix,
4621        };
4622        let end_ix = match self
4623            .selections
4624            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer).unwrap())
4625        {
4626            Ok(ix) => ix + 1,
4627            Err(ix) => ix,
4628        };
4629
4630        fn point_selection(
4631            selection: &Selection<Anchor>,
4632            buffer: &MultiBufferSnapshot,
4633        ) -> Selection<Point> {
4634            let start = selection.start.to_point(&buffer);
4635            let end = selection.end.to_point(&buffer);
4636            Selection {
4637                id: selection.id,
4638                start,
4639                end,
4640                reversed: selection.reversed,
4641                goal: selection.goal,
4642            }
4643        }
4644
4645        self.selections[start_ix..end_ix]
4646            .iter()
4647            .chain(
4648                self.pending_selection
4649                    .as_ref()
4650                    .map(|pending| &pending.selection),
4651            )
4652            .map(|s| point_selection(s, &buffer))
4653            .collect()
4654    }
4655
4656    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
4657    where
4658        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
4659    {
4660        let buffer = self.buffer.read(cx).snapshot(cx);
4661        let mut selections = self
4662            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
4663            .peekable();
4664
4665        let mut pending_selection = self.pending_selection::<D>(&buffer);
4666
4667        iter::from_fn(move || {
4668            if let Some(pending) = pending_selection.as_mut() {
4669                while let Some(next_selection) = selections.peek() {
4670                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
4671                        let next_selection = selections.next().unwrap();
4672                        if next_selection.start < pending.start {
4673                            pending.start = next_selection.start;
4674                        }
4675                        if next_selection.end > pending.end {
4676                            pending.end = next_selection.end;
4677                        }
4678                    } else if next_selection.end < pending.start {
4679                        return selections.next();
4680                    } else {
4681                        break;
4682                    }
4683                }
4684
4685                pending_selection.take()
4686            } else {
4687                selections.next()
4688            }
4689        })
4690        .collect()
4691    }
4692
4693    fn resolve_selections<'a, D, I>(
4694        &self,
4695        selections: I,
4696        snapshot: &MultiBufferSnapshot,
4697    ) -> impl 'a + Iterator<Item = Selection<D>>
4698    where
4699        D: TextDimension + Ord + Sub<D, Output = D>,
4700        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
4701    {
4702        let (to_summarize, selections) = selections.into_iter().tee();
4703        let mut summaries = snapshot
4704            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
4705            .into_iter();
4706        selections.map(move |s| Selection {
4707            id: s.id,
4708            start: summaries.next().unwrap(),
4709            end: summaries.next().unwrap(),
4710            reversed: s.reversed,
4711            goal: s.goal,
4712        })
4713    }
4714
4715    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4716        &self,
4717        snapshot: &MultiBufferSnapshot,
4718    ) -> Option<Selection<D>> {
4719        self.pending_selection
4720            .as_ref()
4721            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
4722    }
4723
4724    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4725        &self,
4726        selection: &Selection<Anchor>,
4727        buffer: &MultiBufferSnapshot,
4728    ) -> Selection<D> {
4729        Selection {
4730            id: selection.id,
4731            start: selection.start.summary::<D>(&buffer),
4732            end: selection.end.summary::<D>(&buffer),
4733            reversed: selection.reversed,
4734            goal: selection.goal,
4735        }
4736    }
4737
4738    fn selection_count<'a>(&self) -> usize {
4739        let mut count = self.selections.len();
4740        if self.pending_selection.is_some() {
4741            count += 1;
4742        }
4743        count
4744    }
4745
4746    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4747        &self,
4748        cx: &AppContext,
4749    ) -> Selection<D> {
4750        let snapshot = self.buffer.read(cx).read(cx);
4751        self.selections
4752            .iter()
4753            .min_by_key(|s| s.id)
4754            .map(|selection| self.resolve_selection(selection, &snapshot))
4755            .or_else(|| self.pending_selection(&snapshot))
4756            .unwrap()
4757    }
4758
4759    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
4760        &self,
4761        cx: &AppContext,
4762    ) -> Selection<D> {
4763        self.resolve_selection(
4764            self.newest_anchor_selection(),
4765            &self.buffer.read(cx).read(cx),
4766        )
4767    }
4768
4769    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
4770        &self,
4771        snapshot: &MultiBufferSnapshot,
4772    ) -> Selection<D> {
4773        self.resolve_selection(self.newest_anchor_selection(), snapshot)
4774    }
4775
4776    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
4777        self.pending_selection
4778            .as_ref()
4779            .map(|s| &s.selection)
4780            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
4781            .unwrap()
4782    }
4783
4784    pub fn update_selections<T>(
4785        &mut self,
4786        mut selections: Vec<Selection<T>>,
4787        autoscroll: Option<Autoscroll>,
4788        cx: &mut ViewContext<Self>,
4789    ) where
4790        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
4791    {
4792        let buffer = self.buffer.read(cx).snapshot(cx);
4793        selections.sort_unstable_by_key(|s| s.start);
4794
4795        // Merge overlapping selections.
4796        let mut i = 1;
4797        while i < selections.len() {
4798            if selections[i - 1].end >= selections[i].start {
4799                let removed = selections.remove(i);
4800                if removed.start < selections[i - 1].start {
4801                    selections[i - 1].start = removed.start;
4802                }
4803                if removed.end > selections[i - 1].end {
4804                    selections[i - 1].end = removed.end;
4805                }
4806            } else {
4807                i += 1;
4808            }
4809        }
4810
4811        if let Some(autoscroll) = autoscroll {
4812            self.request_autoscroll(autoscroll, cx);
4813        }
4814
4815        self.set_selections(
4816            Arc::from_iter(selections.into_iter().map(|selection| {
4817                let end_bias = if selection.end > selection.start {
4818                    Bias::Left
4819                } else {
4820                    Bias::Right
4821                };
4822                Selection {
4823                    id: selection.id,
4824                    start: buffer.anchor_after(selection.start),
4825                    end: buffer.anchor_at(selection.end, end_bias),
4826                    reversed: selection.reversed,
4827                    goal: selection.goal,
4828                }
4829            })),
4830            None,
4831            cx,
4832        );
4833    }
4834
4835    /// Compute new ranges for any selections that were located in excerpts that have
4836    /// since been removed.
4837    ///
4838    /// Returns a `HashMap` indicating which selections whose former head position
4839    /// was no longer present. The keys of the map are selection ids. The values are
4840    /// the id of the new excerpt where the head of the selection has been moved.
4841    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
4842        let snapshot = self.buffer.read(cx).read(cx);
4843        let anchors_with_status = snapshot.refresh_anchors(
4844            self.selections
4845                .iter()
4846                .flat_map(|selection| [&selection.start, &selection.end]),
4847        );
4848        let offsets =
4849            snapshot.summaries_for_anchors::<usize, _>(anchors_with_status.iter().map(|a| &a.1));
4850        let offsets = offsets.chunks(2);
4851        let statuses = anchors_with_status
4852            .chunks(2)
4853            .map(|a| (a[0].0 / 2, a[0].2, a[1].2));
4854
4855        let mut selections_with_lost_position = HashMap::default();
4856        let new_selections = offsets
4857            .zip(statuses)
4858            .map(|(offsets, (selection_ix, kept_start, kept_end))| {
4859                let selection = &self.selections[selection_ix];
4860                let kept_head = if selection.reversed {
4861                    kept_start
4862                } else {
4863                    kept_end
4864                };
4865                if !kept_head {
4866                    selections_with_lost_position
4867                        .insert(selection.id, selection.head().excerpt_id.clone());
4868                }
4869
4870                Selection {
4871                    id: selection.id,
4872                    start: offsets[0],
4873                    end: offsets[1],
4874                    reversed: selection.reversed,
4875                    goal: selection.goal,
4876                }
4877            })
4878            .collect();
4879        drop(snapshot);
4880        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
4881        selections_with_lost_position
4882    }
4883
4884    fn set_selections(
4885        &mut self,
4886        selections: Arc<[Selection<Anchor>]>,
4887        pending_selection: Option<PendingSelection>,
4888        cx: &mut ViewContext<Self>,
4889    ) {
4890        let old_cursor_position = self.newest_anchor_selection().head();
4891
4892        self.selections = selections;
4893        self.pending_selection = pending_selection;
4894        if self.focused {
4895            self.buffer.update(cx, |buffer, cx| {
4896                buffer.set_active_selections(&self.selections, cx)
4897            });
4898        }
4899
4900        let display_map = self
4901            .display_map
4902            .update(cx, |display_map, cx| display_map.snapshot(cx));
4903        let buffer = &display_map.buffer_snapshot;
4904        self.add_selections_state = None;
4905        self.select_next_state = None;
4906        self.select_larger_syntax_node_stack.clear();
4907        self.autoclose_stack.invalidate(&self.selections, &buffer);
4908        self.snippet_stack.invalidate(&self.selections, &buffer);
4909        self.invalidate_rename_range(&buffer, cx);
4910
4911        let new_cursor_position = self.newest_anchor_selection().head();
4912
4913        self.push_to_nav_history(
4914            old_cursor_position.clone(),
4915            Some(new_cursor_position.to_point(&buffer)),
4916            cx,
4917        );
4918
4919        let completion_menu = match self.context_menu.as_mut() {
4920            Some(ContextMenu::Completions(menu)) => Some(menu),
4921            _ => {
4922                self.context_menu.take();
4923                None
4924            }
4925        };
4926
4927        if let Some(completion_menu) = completion_menu {
4928            let cursor_position = new_cursor_position.to_offset(&buffer);
4929            let (word_range, kind) =
4930                buffer.surrounding_word(completion_menu.initial_position.clone());
4931            if kind == Some(CharKind::Word) && word_range.to_inclusive().contains(&cursor_position)
4932            {
4933                let query = Self::completion_query(&buffer, cursor_position);
4934                cx.background()
4935                    .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
4936                self.show_completions(&ShowCompletions, cx);
4937            } else {
4938                self.hide_context_menu(cx);
4939            }
4940        }
4941
4942        if old_cursor_position.to_display_point(&display_map).row()
4943            != new_cursor_position.to_display_point(&display_map).row()
4944        {
4945            self.available_code_actions.take();
4946        }
4947        self.refresh_code_actions(cx);
4948        self.refresh_document_highlights(cx);
4949
4950        self.pause_cursor_blinking(cx);
4951        cx.emit(Event::SelectionsChanged);
4952    }
4953
4954    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
4955        self.autoscroll_request = Some(autoscroll);
4956        cx.notify();
4957    }
4958
4959    fn start_transaction(&mut self, cx: &mut ViewContext<Self>) {
4960        self.start_transaction_at(Instant::now(), cx);
4961    }
4962
4963    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
4964        self.end_selection(cx);
4965        if let Some(tx_id) = self
4966            .buffer
4967            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
4968        {
4969            self.selection_history
4970                .insert(tx_id, (self.selections.clone(), None));
4971        }
4972    }
4973
4974    fn end_transaction(&mut self, cx: &mut ViewContext<Self>) {
4975        self.end_transaction_at(Instant::now(), cx);
4976    }
4977
4978    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
4979        if let Some(tx_id) = self
4980            .buffer
4981            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
4982        {
4983            if let Some((_, end_selections)) = self.selection_history.get_mut(&tx_id) {
4984                *end_selections = Some(self.selections.clone());
4985            } else {
4986                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
4987            }
4988        }
4989    }
4990
4991    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
4992        log::info!("Editor::page_up");
4993    }
4994
4995    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
4996        log::info!("Editor::page_down");
4997    }
4998
4999    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5000        let mut fold_ranges = Vec::new();
5001
5002        let selections = self.local_selections::<Point>(cx);
5003        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5004        for selection in selections {
5005            let range = selection.display_range(&display_map).sorted();
5006            let buffer_start_row = range.start.to_point(&display_map).row;
5007
5008            for row in (0..=range.end.row()).rev() {
5009                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5010                    let fold_range = self.foldable_range_for_line(&display_map, row);
5011                    if fold_range.end.row >= buffer_start_row {
5012                        fold_ranges.push(fold_range);
5013                        if row <= range.start.row() {
5014                            break;
5015                        }
5016                    }
5017                }
5018            }
5019        }
5020
5021        self.fold_ranges(fold_ranges, cx);
5022    }
5023
5024    pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
5025        let selections = self.local_selections::<Point>(cx);
5026        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5027        let buffer = &display_map.buffer_snapshot;
5028        let ranges = selections
5029            .iter()
5030            .map(|s| {
5031                let range = s.display_range(&display_map).sorted();
5032                let mut start = range.start.to_point(&display_map);
5033                let mut end = range.end.to_point(&display_map);
5034                start.column = 0;
5035                end.column = buffer.line_len(end.row);
5036                start..end
5037            })
5038            .collect::<Vec<_>>();
5039        self.unfold_ranges(ranges, cx);
5040    }
5041
5042    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5043        let max_point = display_map.max_point();
5044        if display_row >= max_point.row() {
5045            false
5046        } else {
5047            let (start_indent, is_blank) = display_map.line_indent(display_row);
5048            if is_blank {
5049                false
5050            } else {
5051                for display_row in display_row + 1..=max_point.row() {
5052                    let (indent, is_blank) = display_map.line_indent(display_row);
5053                    if !is_blank {
5054                        return indent > start_indent;
5055                    }
5056                }
5057                false
5058            }
5059        }
5060    }
5061
5062    fn foldable_range_for_line(
5063        &self,
5064        display_map: &DisplaySnapshot,
5065        start_row: u32,
5066    ) -> Range<Point> {
5067        let max_point = display_map.max_point();
5068
5069        let (start_indent, _) = display_map.line_indent(start_row);
5070        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5071        let mut end = None;
5072        for row in start_row + 1..=max_point.row() {
5073            let (indent, is_blank) = display_map.line_indent(row);
5074            if !is_blank && indent <= start_indent {
5075                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5076                break;
5077            }
5078        }
5079
5080        let end = end.unwrap_or(max_point);
5081        return start.to_point(display_map)..end.to_point(display_map);
5082    }
5083
5084    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5085        let selections = self.local_selections::<Point>(cx);
5086        let ranges = selections.into_iter().map(|s| s.start..s.end);
5087        self.fold_ranges(ranges, cx);
5088    }
5089
5090    fn fold_ranges<T: ToOffset>(
5091        &mut self,
5092        ranges: impl IntoIterator<Item = Range<T>>,
5093        cx: &mut ViewContext<Self>,
5094    ) {
5095        let mut ranges = ranges.into_iter().peekable();
5096        if ranges.peek().is_some() {
5097            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5098            self.request_autoscroll(Autoscroll::Fit, cx);
5099            cx.notify();
5100        }
5101    }
5102
5103    fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
5104        if !ranges.is_empty() {
5105            self.display_map
5106                .update(cx, |map, cx| map.unfold(ranges, cx));
5107            self.request_autoscroll(Autoscroll::Fit, cx);
5108            cx.notify();
5109        }
5110    }
5111
5112    pub fn insert_blocks(
5113        &mut self,
5114        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5115        cx: &mut ViewContext<Self>,
5116    ) -> Vec<BlockId> {
5117        let blocks = self
5118            .display_map
5119            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5120        self.request_autoscroll(Autoscroll::Fit, cx);
5121        blocks
5122    }
5123
5124    pub fn replace_blocks(
5125        &mut self,
5126        blocks: HashMap<BlockId, RenderBlock>,
5127        cx: &mut ViewContext<Self>,
5128    ) {
5129        self.display_map
5130            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5131        self.request_autoscroll(Autoscroll::Fit, cx);
5132    }
5133
5134    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5135        self.display_map.update(cx, |display_map, cx| {
5136            display_map.remove_blocks(block_ids, cx)
5137        });
5138    }
5139
5140    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5141        self.display_map
5142            .update(cx, |map, cx| map.snapshot(cx))
5143            .longest_row()
5144    }
5145
5146    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5147        self.display_map
5148            .update(cx, |map, cx| map.snapshot(cx))
5149            .max_point()
5150    }
5151
5152    pub fn text(&self, cx: &AppContext) -> String {
5153        self.buffer.read(cx).read(cx).text()
5154    }
5155
5156    pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
5157        self.buffer
5158            .read(cx)
5159            .as_singleton()
5160            .expect("you can only call set_text on editors for singleton buffers")
5161            .update(cx, |buffer, cx| buffer.set_text(text, cx));
5162    }
5163
5164    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5165        self.display_map
5166            .update(cx, |map, cx| map.snapshot(cx))
5167            .text()
5168    }
5169
5170    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5171        let language = self.language(cx);
5172        let settings = self.settings.borrow();
5173        let mode = self
5174            .soft_wrap_mode_override
5175            .unwrap_or_else(|| settings.soft_wrap(language));
5176        match mode {
5177            settings::SoftWrap::None => SoftWrap::None,
5178            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5179            settings::SoftWrap::PreferredLineLength => {
5180                SoftWrap::Column(settings.preferred_line_length(language))
5181            }
5182        }
5183    }
5184
5185    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5186        self.soft_wrap_mode_override = Some(mode);
5187        cx.notify();
5188    }
5189
5190    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5191        self.display_map
5192            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5193    }
5194
5195    pub fn set_highlighted_rows(&mut self, rows: Option<Range<u32>>) {
5196        self.highlighted_rows = rows;
5197    }
5198
5199    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5200        self.highlighted_rows.clone()
5201    }
5202
5203    pub fn highlight_ranges<T: 'static>(
5204        &mut self,
5205        ranges: Vec<Range<Anchor>>,
5206        color: Color,
5207        cx: &mut ViewContext<Self>,
5208    ) {
5209        self.highlighted_ranges
5210            .insert(TypeId::of::<T>(), (color, ranges));
5211        cx.notify();
5212    }
5213
5214    pub fn clear_highlighted_ranges<T: 'static>(
5215        &mut self,
5216        cx: &mut ViewContext<Self>,
5217    ) -> Option<(Color, Vec<Range<Anchor>>)> {
5218        cx.notify();
5219        self.highlighted_ranges.remove(&TypeId::of::<T>())
5220    }
5221
5222    #[cfg(feature = "test-support")]
5223    pub fn all_highlighted_ranges(
5224        &mut self,
5225        cx: &mut ViewContext<Self>,
5226    ) -> Vec<(Range<DisplayPoint>, Color)> {
5227        let snapshot = self.snapshot(cx);
5228        let buffer = &snapshot.buffer_snapshot;
5229        let start = buffer.anchor_before(0);
5230        let end = buffer.anchor_after(buffer.len());
5231        self.highlighted_ranges_in_range(start..end, &snapshot)
5232    }
5233
5234    pub fn highlighted_ranges_for_type<T: 'static>(&self) -> Option<(Color, &[Range<Anchor>])> {
5235        self.highlighted_ranges
5236            .get(&TypeId::of::<T>())
5237            .map(|(color, ranges)| (*color, ranges.as_slice()))
5238    }
5239
5240    pub fn highlighted_ranges_in_range(
5241        &self,
5242        search_range: Range<Anchor>,
5243        display_snapshot: &DisplaySnapshot,
5244    ) -> Vec<(Range<DisplayPoint>, Color)> {
5245        let mut results = Vec::new();
5246        let buffer = &display_snapshot.buffer_snapshot;
5247        for (color, ranges) in self.highlighted_ranges.values() {
5248            let start_ix = match ranges.binary_search_by(|probe| {
5249                let cmp = probe.end.cmp(&search_range.start, &buffer).unwrap();
5250                if cmp.is_gt() {
5251                    Ordering::Greater
5252                } else {
5253                    Ordering::Less
5254                }
5255            }) {
5256                Ok(i) | Err(i) => i,
5257            };
5258            for range in &ranges[start_ix..] {
5259                if range.start.cmp(&search_range.end, &buffer).unwrap().is_ge() {
5260                    break;
5261                }
5262                let start = range
5263                    .start
5264                    .to_point(buffer)
5265                    .to_display_point(display_snapshot);
5266                let end = range
5267                    .end
5268                    .to_point(buffer)
5269                    .to_display_point(display_snapshot);
5270                results.push((start..end, *color))
5271            }
5272        }
5273        results
5274    }
5275
5276    fn next_blink_epoch(&mut self) -> usize {
5277        self.blink_epoch += 1;
5278        self.blink_epoch
5279    }
5280
5281    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5282        if !self.focused {
5283            return;
5284        }
5285
5286        self.show_local_cursors = true;
5287        cx.notify();
5288
5289        let epoch = self.next_blink_epoch();
5290        cx.spawn(|this, mut cx| {
5291            let this = this.downgrade();
5292            async move {
5293                Timer::after(CURSOR_BLINK_INTERVAL).await;
5294                if let Some(this) = this.upgrade(&cx) {
5295                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5296                }
5297            }
5298        })
5299        .detach();
5300    }
5301
5302    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5303        if epoch == self.blink_epoch {
5304            self.blinking_paused = false;
5305            self.blink_cursors(epoch, cx);
5306        }
5307    }
5308
5309    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5310        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5311            self.show_local_cursors = !self.show_local_cursors;
5312            cx.notify();
5313
5314            let epoch = self.next_blink_epoch();
5315            cx.spawn(|this, mut cx| {
5316                let this = this.downgrade();
5317                async move {
5318                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5319                    if let Some(this) = this.upgrade(&cx) {
5320                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5321                    }
5322                }
5323            })
5324            .detach();
5325        }
5326    }
5327
5328    pub fn show_local_cursors(&self) -> bool {
5329        self.show_local_cursors
5330    }
5331
5332    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5333        cx.notify();
5334    }
5335
5336    fn on_buffer_event(
5337        &mut self,
5338        _: ModelHandle<MultiBuffer>,
5339        event: &language::Event,
5340        cx: &mut ViewContext<Self>,
5341    ) {
5342        match event {
5343            language::Event::Edited => {
5344                self.refresh_active_diagnostics(cx);
5345                self.refresh_code_actions(cx);
5346                cx.emit(Event::Edited);
5347            }
5348            language::Event::Dirtied => cx.emit(Event::Dirtied),
5349            language::Event::Saved => cx.emit(Event::Saved),
5350            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5351            language::Event::Reloaded => cx.emit(Event::TitleChanged),
5352            language::Event::Closed => cx.emit(Event::Closed),
5353            language::Event::DiagnosticsUpdated => {
5354                self.refresh_active_diagnostics(cx);
5355            }
5356            _ => {}
5357        }
5358    }
5359
5360    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5361        cx.notify();
5362    }
5363
5364    pub fn set_searchable(&mut self, searchable: bool) {
5365        self.searchable = searchable;
5366    }
5367
5368    pub fn searchable(&self) -> bool {
5369        self.searchable
5370    }
5371
5372    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
5373        let active_item = workspace.active_item(cx);
5374        let editor_handle = if let Some(editor) = active_item
5375            .as_ref()
5376            .and_then(|item| item.act_as::<Self>(cx))
5377        {
5378            editor
5379        } else {
5380            cx.propagate_action();
5381            return;
5382        };
5383
5384        let editor = editor_handle.read(cx);
5385        let buffer = editor.buffer.read(cx);
5386        if buffer.is_singleton() {
5387            cx.propagate_action();
5388            return;
5389        }
5390
5391        let mut new_selections_by_buffer = HashMap::default();
5392        for selection in editor.local_selections::<usize>(cx) {
5393            for (buffer, mut range) in
5394                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
5395            {
5396                if selection.reversed {
5397                    mem::swap(&mut range.start, &mut range.end);
5398                }
5399                new_selections_by_buffer
5400                    .entry(buffer)
5401                    .or_insert(Vec::new())
5402                    .push(range)
5403            }
5404        }
5405
5406        editor_handle.update(cx, |editor, cx| {
5407            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
5408        });
5409        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
5410        nav_history.borrow_mut().disable();
5411
5412        // We defer the pane interaction because we ourselves are a workspace item
5413        // and activating a new item causes the pane to call a method on us reentrantly,
5414        // which panics if we're on the stack.
5415        cx.defer(move |workspace, cx| {
5416            for (ix, (buffer, ranges)) in new_selections_by_buffer.into_iter().enumerate() {
5417                let buffer = BufferItemHandle(buffer);
5418                if ix == 0 && !workspace.activate_pane_for_item(&buffer, cx) {
5419                    workspace.activate_next_pane(cx);
5420                }
5421
5422                let editor = workspace
5423                    .open_item(buffer, cx)
5424                    .downcast::<Editor>()
5425                    .unwrap();
5426
5427                editor.update(cx, |editor, cx| {
5428                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
5429                });
5430            }
5431
5432            nav_history.borrow_mut().enable();
5433        });
5434    }
5435}
5436
5437impl EditorSnapshot {
5438    pub fn is_focused(&self) -> bool {
5439        self.is_focused
5440    }
5441
5442    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
5443        self.placeholder_text.as_ref()
5444    }
5445
5446    pub fn scroll_position(&self) -> Vector2F {
5447        compute_scroll_position(
5448            &self.display_snapshot,
5449            self.scroll_position,
5450            &self.scroll_top_anchor,
5451        )
5452    }
5453}
5454
5455impl Deref for EditorSnapshot {
5456    type Target = DisplaySnapshot;
5457
5458    fn deref(&self) -> &Self::Target {
5459        &self.display_snapshot
5460    }
5461}
5462
5463fn compute_scroll_position(
5464    snapshot: &DisplaySnapshot,
5465    mut scroll_position: Vector2F,
5466    scroll_top_anchor: &Option<Anchor>,
5467) -> Vector2F {
5468    if let Some(anchor) = scroll_top_anchor {
5469        let scroll_top = anchor.to_display_point(snapshot).row() as f32;
5470        scroll_position.set_y(scroll_top + scroll_position.y());
5471    } else {
5472        scroll_position.set_y(0.);
5473    }
5474    scroll_position
5475}
5476
5477#[derive(Copy, Clone)]
5478pub enum Event {
5479    Activate,
5480    Edited,
5481    Blurred,
5482    Dirtied,
5483    Saved,
5484    TitleChanged,
5485    SelectionsChanged,
5486    Closed,
5487}
5488
5489impl Entity for Editor {
5490    type Event = Event;
5491}
5492
5493impl View for Editor {
5494    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5495        let style = self.style(cx);
5496        self.display_map.update(cx, |map, cx| {
5497            map.set_font(style.text.font_id, style.text.font_size, cx)
5498        });
5499        EditorElement::new(self.handle.clone(), style.clone()).boxed()
5500    }
5501
5502    fn ui_name() -> &'static str {
5503        "Editor"
5504    }
5505
5506    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
5507        self.focused = true;
5508        self.blink_cursors(self.blink_epoch, cx);
5509        self.buffer.update(cx, |buffer, cx| {
5510            buffer.finalize_last_transaction(cx);
5511            buffer.set_active_selections(&self.selections, cx)
5512        });
5513    }
5514
5515    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
5516        self.focused = false;
5517        self.show_local_cursors = false;
5518        self.buffer
5519            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
5520        self.hide_context_menu(cx);
5521        cx.emit(Event::Blurred);
5522        cx.notify();
5523    }
5524
5525    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
5526        let mut cx = Self::default_keymap_context();
5527        let mode = match self.mode {
5528            EditorMode::SingleLine => "single_line",
5529            EditorMode::AutoHeight { .. } => "auto_height",
5530            EditorMode::Full => "full",
5531        };
5532        cx.map.insert("mode".into(), mode.into());
5533        if self.pending_rename.is_some() {
5534            cx.set.insert("renaming".into());
5535        }
5536        match self.context_menu.as_ref() {
5537            Some(ContextMenu::Completions(_)) => {
5538                cx.set.insert("showing_completions".into());
5539            }
5540            Some(ContextMenu::CodeActions(_)) => {
5541                cx.set.insert("showing_code_actions".into());
5542            }
5543            None => {}
5544        }
5545        cx
5546    }
5547}
5548
5549fn build_style(
5550    settings: &Settings,
5551    get_field_editor_theme: Option<GetFieldEditorTheme>,
5552    cx: &AppContext,
5553) -> EditorStyle {
5554    let mut theme = settings.theme.editor.clone();
5555    if let Some(get_field_editor_theme) = get_field_editor_theme {
5556        let field_editor_theme = get_field_editor_theme(&settings.theme);
5557        if let Some(background) = field_editor_theme.container.background_color {
5558            theme.background = background;
5559        }
5560        theme.text_color = field_editor_theme.text.color;
5561        theme.selection = field_editor_theme.selection;
5562        EditorStyle {
5563            text: field_editor_theme.text,
5564            placeholder_text: field_editor_theme.placeholder_text,
5565            theme,
5566        }
5567    } else {
5568        let font_cache = cx.font_cache();
5569        let font_family_id = settings.buffer_font_family;
5570        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
5571        let font_properties = Default::default();
5572        let font_id = font_cache
5573            .select_font(font_family_id, &font_properties)
5574            .unwrap();
5575        let font_size = settings.buffer_font_size;
5576        EditorStyle {
5577            text: TextStyle {
5578                color: settings.theme.editor.text_color,
5579                font_family_name,
5580                font_family_id,
5581                font_id,
5582                font_size,
5583                font_properties,
5584                underline: None,
5585            },
5586            placeholder_text: None,
5587            theme,
5588        }
5589    }
5590}
5591
5592impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
5593    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
5594        let start = self.start.to_point(buffer);
5595        let end = self.end.to_point(buffer);
5596        if self.reversed {
5597            end..start
5598        } else {
5599            start..end
5600        }
5601    }
5602
5603    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
5604        let start = self.start.to_offset(buffer);
5605        let end = self.end.to_offset(buffer);
5606        if self.reversed {
5607            end..start
5608        } else {
5609            start..end
5610        }
5611    }
5612
5613    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
5614        let start = self
5615            .start
5616            .to_point(&map.buffer_snapshot)
5617            .to_display_point(map);
5618        let end = self
5619            .end
5620            .to_point(&map.buffer_snapshot)
5621            .to_display_point(map);
5622        if self.reversed {
5623            end..start
5624        } else {
5625            start..end
5626        }
5627    }
5628
5629    fn spanned_rows(
5630        &self,
5631        include_end_if_at_line_start: bool,
5632        map: &DisplaySnapshot,
5633    ) -> Range<u32> {
5634        let start = self.start.to_point(&map.buffer_snapshot);
5635        let mut end = self.end.to_point(&map.buffer_snapshot);
5636        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
5637            end.row -= 1;
5638        }
5639
5640        let buffer_start = map.prev_line_boundary(start).0;
5641        let buffer_end = map.next_line_boundary(end).0;
5642        buffer_start.row..buffer_end.row + 1
5643    }
5644}
5645
5646impl<T: InvalidationRegion> InvalidationStack<T> {
5647    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
5648    where
5649        S: Clone + ToOffset,
5650    {
5651        while let Some(region) = self.last() {
5652            let all_selections_inside_invalidation_ranges =
5653                if selections.len() == region.ranges().len() {
5654                    selections
5655                        .iter()
5656                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
5657                        .all(|(selection, invalidation_range)| {
5658                            let head = selection.head().to_offset(&buffer);
5659                            invalidation_range.start <= head && invalidation_range.end >= head
5660                        })
5661                } else {
5662                    false
5663                };
5664
5665            if all_selections_inside_invalidation_ranges {
5666                break;
5667            } else {
5668                self.pop();
5669            }
5670        }
5671    }
5672}
5673
5674impl<T> Default for InvalidationStack<T> {
5675    fn default() -> Self {
5676        Self(Default::default())
5677    }
5678}
5679
5680impl<T> Deref for InvalidationStack<T> {
5681    type Target = Vec<T>;
5682
5683    fn deref(&self) -> &Self::Target {
5684        &self.0
5685    }
5686}
5687
5688impl<T> DerefMut for InvalidationStack<T> {
5689    fn deref_mut(&mut self) -> &mut Self::Target {
5690        &mut self.0
5691    }
5692}
5693
5694impl InvalidationRegion for BracketPairState {
5695    fn ranges(&self) -> &[Range<Anchor>] {
5696        &self.ranges
5697    }
5698}
5699
5700impl InvalidationRegion for SnippetState {
5701    fn ranges(&self) -> &[Range<Anchor>] {
5702        &self.ranges[self.active_index]
5703    }
5704}
5705
5706impl Deref for EditorStyle {
5707    type Target = theme::Editor;
5708
5709    fn deref(&self) -> &Self::Target {
5710        &self.theme
5711    }
5712}
5713
5714pub fn diagnostic_block_renderer(
5715    diagnostic: Diagnostic,
5716    is_valid: bool,
5717    settings: watch::Receiver<Settings>,
5718) -> RenderBlock {
5719    let mut highlighted_lines = Vec::new();
5720    for line in diagnostic.message.lines() {
5721        highlighted_lines.push(highlight_diagnostic_message(line));
5722    }
5723
5724    Arc::new(move |cx: &BlockContext| {
5725        let settings = settings.borrow();
5726        let theme = &settings.theme.editor;
5727        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
5728        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
5729        Flex::column()
5730            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
5731                Label::new(
5732                    line.clone(),
5733                    style.message.clone().with_font_size(font_size),
5734                )
5735                .with_highlights(highlights.clone())
5736                .contained()
5737                .with_margin_left(cx.anchor_x)
5738                .boxed()
5739            }))
5740            .aligned()
5741            .left()
5742            .boxed()
5743    })
5744}
5745
5746pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
5747    let mut message_without_backticks = String::new();
5748    let mut prev_offset = 0;
5749    let mut inside_block = false;
5750    let mut highlights = Vec::new();
5751    for (match_ix, (offset, _)) in message
5752        .match_indices('`')
5753        .chain([(message.len(), "")])
5754        .enumerate()
5755    {
5756        message_without_backticks.push_str(&message[prev_offset..offset]);
5757        if inside_block {
5758            highlights.extend(prev_offset - match_ix..offset - match_ix);
5759        }
5760
5761        inside_block = !inside_block;
5762        prev_offset = offset + 1;
5763    }
5764
5765    (message_without_backticks, highlights)
5766}
5767
5768pub fn diagnostic_style(
5769    severity: DiagnosticSeverity,
5770    valid: bool,
5771    theme: &theme::Editor,
5772) -> DiagnosticStyle {
5773    match (severity, valid) {
5774        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
5775        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
5776        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
5777        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
5778        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
5779        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
5780        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
5781        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
5782        _ => theme.invalid_hint_diagnostic.clone(),
5783    }
5784}
5785
5786pub fn combine_syntax_and_fuzzy_match_highlights(
5787    text: &str,
5788    default_style: HighlightStyle,
5789    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
5790    match_indices: &[usize],
5791) -> Vec<(Range<usize>, HighlightStyle)> {
5792    let mut result = Vec::new();
5793    let mut match_indices = match_indices.iter().copied().peekable();
5794
5795    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
5796    {
5797        syntax_highlight.font_properties.weight(Default::default());
5798
5799        // Add highlights for any fuzzy match characters before the next
5800        // syntax highlight range.
5801        while let Some(&match_index) = match_indices.peek() {
5802            if match_index >= range.start {
5803                break;
5804            }
5805            match_indices.next();
5806            let end_index = char_ix_after(match_index, text);
5807            let mut match_style = default_style;
5808            match_style.font_properties.weight(fonts::Weight::BOLD);
5809            result.push((match_index..end_index, match_style));
5810        }
5811
5812        if range.start == usize::MAX {
5813            break;
5814        }
5815
5816        // Add highlights for any fuzzy match characters within the
5817        // syntax highlight range.
5818        let mut offset = range.start;
5819        while let Some(&match_index) = match_indices.peek() {
5820            if match_index >= range.end {
5821                break;
5822            }
5823
5824            match_indices.next();
5825            if match_index > offset {
5826                result.push((offset..match_index, syntax_highlight));
5827            }
5828
5829            let mut end_index = char_ix_after(match_index, text);
5830            while let Some(&next_match_index) = match_indices.peek() {
5831                if next_match_index == end_index && next_match_index < range.end {
5832                    end_index = char_ix_after(next_match_index, text);
5833                    match_indices.next();
5834                } else {
5835                    break;
5836                }
5837            }
5838
5839            let mut match_style = syntax_highlight;
5840            match_style.font_properties.weight(fonts::Weight::BOLD);
5841            result.push((match_index..end_index, match_style));
5842            offset = end_index;
5843        }
5844
5845        if offset < range.end {
5846            result.push((offset..range.end, syntax_highlight));
5847        }
5848    }
5849
5850    fn char_ix_after(ix: usize, text: &str) -> usize {
5851        ix + text[ix..].chars().next().unwrap().len_utf8()
5852    }
5853
5854    result
5855}
5856
5857pub fn styled_runs_for_code_label<'a>(
5858    label: &'a CodeLabel,
5859    default_color: Color,
5860    syntax_theme: &'a theme::SyntaxTheme,
5861) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
5862    const MUTED_OPACITY: usize = 165;
5863
5864    let mut muted_default_style = HighlightStyle {
5865        color: default_color,
5866        ..Default::default()
5867    };
5868    muted_default_style.color.a = ((default_color.a as usize * MUTED_OPACITY) / 255) as u8;
5869
5870    let mut prev_end = label.filter_range.end;
5871    label
5872        .runs
5873        .iter()
5874        .enumerate()
5875        .flat_map(move |(ix, (range, highlight_id))| {
5876            let style = if let Some(style) = highlight_id.style(syntax_theme) {
5877                style
5878            } else {
5879                return Default::default();
5880            };
5881            let mut muted_style = style.clone();
5882            muted_style.color.a = ((style.color.a as usize * MUTED_OPACITY) / 255) as u8;
5883
5884            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
5885            if range.start >= label.filter_range.end {
5886                if range.start > prev_end {
5887                    runs.push((prev_end..range.start, muted_default_style));
5888                }
5889                runs.push((range.clone(), muted_style));
5890            } else if range.end <= label.filter_range.end {
5891                runs.push((range.clone(), style));
5892            } else {
5893                runs.push((range.start..label.filter_range.end, style));
5894                runs.push((label.filter_range.end..range.end, muted_style));
5895            }
5896            prev_end = cmp::max(prev_end, range.end);
5897
5898            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
5899                runs.push((prev_end..label.text.len(), muted_default_style));
5900            }
5901
5902            runs
5903        })
5904}
5905
5906#[cfg(test)]
5907mod tests {
5908    use super::*;
5909    use language::LanguageConfig;
5910    use lsp::FakeLanguageServer;
5911    use project::{FakeFs, ProjectPath};
5912    use smol::stream::StreamExt;
5913    use std::{cell::RefCell, rc::Rc, time::Instant};
5914    use text::Point;
5915    use unindent::Unindent;
5916    use util::test::sample_text;
5917
5918    #[gpui::test]
5919    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
5920        let mut now = Instant::now();
5921        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
5922        let group_interval = buffer.read(cx).transaction_group_interval();
5923        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5924        let settings = Settings::test(cx);
5925        let (_, editor) = cx.add_window(Default::default(), |cx| {
5926            build_editor(buffer.clone(), settings, cx)
5927        });
5928
5929        editor.update(cx, |editor, cx| {
5930            editor.start_transaction_at(now, cx);
5931            editor.select_ranges([2..4], None, cx);
5932            editor.insert("cd", cx);
5933            editor.end_transaction_at(now, cx);
5934            assert_eq!(editor.text(cx), "12cd56");
5935            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
5936
5937            editor.start_transaction_at(now, cx);
5938            editor.select_ranges([4..5], None, cx);
5939            editor.insert("e", cx);
5940            editor.end_transaction_at(now, cx);
5941            assert_eq!(editor.text(cx), "12cde6");
5942            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
5943
5944            now += group_interval + Duration::from_millis(1);
5945            editor.select_ranges([2..2], None, cx);
5946
5947            // Simulate an edit in another editor
5948            buffer.update(cx, |buffer, cx| {
5949                buffer.start_transaction_at(now, cx);
5950                buffer.edit([0..1], "a", cx);
5951                buffer.edit([1..1], "b", cx);
5952                buffer.end_transaction_at(now, cx);
5953            });
5954
5955            assert_eq!(editor.text(cx), "ab2cde6");
5956            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
5957
5958            // Last transaction happened past the group interval in a different editor.
5959            // Undo it individually and don't restore selections.
5960            editor.undo(&Undo, cx);
5961            assert_eq!(editor.text(cx), "12cde6");
5962            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
5963
5964            // First two transactions happened within the group interval in this editor.
5965            // Undo them together and restore selections.
5966            editor.undo(&Undo, cx);
5967            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
5968            assert_eq!(editor.text(cx), "123456");
5969            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
5970
5971            // Redo the first two transactions together.
5972            editor.redo(&Redo, cx);
5973            assert_eq!(editor.text(cx), "12cde6");
5974            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
5975
5976            // Redo the last transaction on its own.
5977            editor.redo(&Redo, cx);
5978            assert_eq!(editor.text(cx), "ab2cde6");
5979            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
5980
5981            // Test empty transactions.
5982            editor.start_transaction_at(now, cx);
5983            editor.end_transaction_at(now, cx);
5984            editor.undo(&Undo, cx);
5985            assert_eq!(editor.text(cx), "12cde6");
5986        });
5987    }
5988
5989    #[gpui::test]
5990    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
5991        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
5992        let settings = Settings::test(cx);
5993        let (_, editor) =
5994            cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
5995
5996        editor.update(cx, |view, cx| {
5997            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
5998        });
5999
6000        assert_eq!(
6001            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6002            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6003        );
6004
6005        editor.update(cx, |view, cx| {
6006            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6007        });
6008
6009        assert_eq!(
6010            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6011            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6012        );
6013
6014        editor.update(cx, |view, cx| {
6015            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6016        });
6017
6018        assert_eq!(
6019            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6020            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6021        );
6022
6023        editor.update(cx, |view, cx| {
6024            view.end_selection(cx);
6025            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6026        });
6027
6028        assert_eq!(
6029            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6030            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6031        );
6032
6033        editor.update(cx, |view, cx| {
6034            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
6035            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
6036        });
6037
6038        assert_eq!(
6039            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6040            [
6041                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
6042                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
6043            ]
6044        );
6045
6046        editor.update(cx, |view, cx| {
6047            view.end_selection(cx);
6048        });
6049
6050        assert_eq!(
6051            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
6052            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
6053        );
6054    }
6055
6056    #[gpui::test]
6057    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
6058        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6059        let settings = Settings::test(cx);
6060        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
6061
6062        view.update(cx, |view, cx| {
6063            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6064            assert_eq!(
6065                view.selected_display_ranges(cx),
6066                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6067            );
6068        });
6069
6070        view.update(cx, |view, cx| {
6071            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6072            assert_eq!(
6073                view.selected_display_ranges(cx),
6074                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6075            );
6076        });
6077
6078        view.update(cx, |view, cx| {
6079            view.cancel(&Cancel, cx);
6080            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6081            assert_eq!(
6082                view.selected_display_ranges(cx),
6083                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6084            );
6085        });
6086    }
6087
6088    #[gpui::test]
6089    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
6090        cx.add_window(Default::default(), |cx| {
6091            use workspace::ItemView;
6092            let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
6093            let settings = Settings::test(&cx);
6094            let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx);
6095            let mut editor = build_editor(buffer.clone(), settings, cx);
6096            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
6097
6098            // Move the cursor a small distance.
6099            // Nothing is added to the navigation history.
6100            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
6101            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
6102            assert!(nav_history.borrow_mut().pop_backward().is_none());
6103
6104            // Move the cursor a large distance.
6105            // The history can jump back to the previous position.
6106            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
6107            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6108            editor.navigate(nav_entry.data.unwrap(), cx);
6109            assert_eq!(nav_entry.item_view.id(), cx.view_id());
6110            assert_eq!(
6111                editor.selected_display_ranges(cx),
6112                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
6113            );
6114
6115            // Move the cursor a small distance via the mouse.
6116            // Nothing is added to the navigation history.
6117            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
6118            editor.end_selection(cx);
6119            assert_eq!(
6120                editor.selected_display_ranges(cx),
6121                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6122            );
6123            assert!(nav_history.borrow_mut().pop_backward().is_none());
6124
6125            // Move the cursor a large distance via the mouse.
6126            // The history can jump back to the previous position.
6127            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
6128            editor.end_selection(cx);
6129            assert_eq!(
6130                editor.selected_display_ranges(cx),
6131                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
6132            );
6133            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6134            editor.navigate(nav_entry.data.unwrap(), cx);
6135            assert_eq!(nav_entry.item_view.id(), cx.view_id());
6136            assert_eq!(
6137                editor.selected_display_ranges(cx),
6138                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6139            );
6140
6141            editor
6142        });
6143    }
6144
6145    #[gpui::test]
6146    fn test_cancel(cx: &mut gpui::MutableAppContext) {
6147        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6148        let settings = Settings::test(cx);
6149        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
6150
6151        view.update(cx, |view, cx| {
6152            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
6153            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6154            view.end_selection(cx);
6155
6156            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
6157            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
6158            view.end_selection(cx);
6159            assert_eq!(
6160                view.selected_display_ranges(cx),
6161                [
6162                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
6163                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
6164                ]
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(3, 4)..DisplayPoint::new(1, 1)]
6173            );
6174        });
6175
6176        view.update(cx, |view, cx| {
6177            view.cancel(&Cancel, cx);
6178            assert_eq!(
6179                view.selected_display_ranges(cx),
6180                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
6181            );
6182        });
6183    }
6184
6185    #[gpui::test]
6186    fn test_fold(cx: &mut gpui::MutableAppContext) {
6187        let buffer = MultiBuffer::build_simple(
6188            &"
6189                impl Foo {
6190                    // Hello!
6191
6192                    fn a() {
6193                        1
6194                    }
6195
6196                    fn b() {
6197                        2
6198                    }
6199
6200                    fn c() {
6201                        3
6202                    }
6203                }
6204            "
6205            .unindent(),
6206            cx,
6207        );
6208        let settings = Settings::test(&cx);
6209        let (_, view) = cx.add_window(Default::default(), |cx| {
6210            build_editor(buffer.clone(), settings, cx)
6211        });
6212
6213        view.update(cx, |view, cx| {
6214            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
6215            view.fold(&Fold, cx);
6216            assert_eq!(
6217                view.display_text(cx),
6218                "
6219                    impl Foo {
6220                        // Hello!
6221
6222                        fn a() {
6223                            1
6224                        }
6225
6226                        fn b() {…
6227                        }
6228
6229                        fn c() {…
6230                        }
6231                    }
6232                "
6233                .unindent(),
6234            );
6235
6236            view.fold(&Fold, cx);
6237            assert_eq!(
6238                view.display_text(cx),
6239                "
6240                    impl Foo {…
6241                    }
6242                "
6243                .unindent(),
6244            );
6245
6246            view.unfold(&Unfold, cx);
6247            assert_eq!(
6248                view.display_text(cx),
6249                "
6250                    impl Foo {
6251                        // Hello!
6252
6253                        fn a() {
6254                            1
6255                        }
6256
6257                        fn b() {…
6258                        }
6259
6260                        fn c() {…
6261                        }
6262                    }
6263                "
6264                .unindent(),
6265            );
6266
6267            view.unfold(&Unfold, cx);
6268            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
6269        });
6270    }
6271
6272    #[gpui::test]
6273    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
6274        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
6275        let settings = Settings::test(&cx);
6276        let (_, view) = cx.add_window(Default::default(), |cx| {
6277            build_editor(buffer.clone(), settings, cx)
6278        });
6279
6280        buffer.update(cx, |buffer, cx| {
6281            buffer.edit(
6282                vec![
6283                    Point::new(1, 0)..Point::new(1, 0),
6284                    Point::new(1, 1)..Point::new(1, 1),
6285                ],
6286                "\t",
6287                cx,
6288            );
6289        });
6290
6291        view.update(cx, |view, cx| {
6292            assert_eq!(
6293                view.selected_display_ranges(cx),
6294                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6295            );
6296
6297            view.move_down(&MoveDown, cx);
6298            assert_eq!(
6299                view.selected_display_ranges(cx),
6300                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6301            );
6302
6303            view.move_right(&MoveRight, cx);
6304            assert_eq!(
6305                view.selected_display_ranges(cx),
6306                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
6307            );
6308
6309            view.move_left(&MoveLeft, cx);
6310            assert_eq!(
6311                view.selected_display_ranges(cx),
6312                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6313            );
6314
6315            view.move_up(&MoveUp, cx);
6316            assert_eq!(
6317                view.selected_display_ranges(cx),
6318                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6319            );
6320
6321            view.move_to_end(&MoveToEnd, cx);
6322            assert_eq!(
6323                view.selected_display_ranges(cx),
6324                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
6325            );
6326
6327            view.move_to_beginning(&MoveToBeginning, cx);
6328            assert_eq!(
6329                view.selected_display_ranges(cx),
6330                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6331            );
6332
6333            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
6334            view.select_to_beginning(&SelectToBeginning, cx);
6335            assert_eq!(
6336                view.selected_display_ranges(cx),
6337                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
6338            );
6339
6340            view.select_to_end(&SelectToEnd, cx);
6341            assert_eq!(
6342                view.selected_display_ranges(cx),
6343                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
6344            );
6345        });
6346    }
6347
6348    #[gpui::test]
6349    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
6350        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
6351        let settings = Settings::test(&cx);
6352        let (_, view) = cx.add_window(Default::default(), |cx| {
6353            build_editor(buffer.clone(), settings, cx)
6354        });
6355
6356        assert_eq!('ⓐ'.len_utf8(), 3);
6357        assert_eq!('α'.len_utf8(), 2);
6358
6359        view.update(cx, |view, cx| {
6360            view.fold_ranges(
6361                vec![
6362                    Point::new(0, 6)..Point::new(0, 12),
6363                    Point::new(1, 2)..Point::new(1, 4),
6364                    Point::new(2, 4)..Point::new(2, 8),
6365                ],
6366                cx,
6367            );
6368            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
6369
6370            view.move_right(&MoveRight, cx);
6371            assert_eq!(
6372                view.selected_display_ranges(cx),
6373                &[empty_range(0, "".len())]
6374            );
6375            view.move_right(&MoveRight, cx);
6376            assert_eq!(
6377                view.selected_display_ranges(cx),
6378                &[empty_range(0, "ⓐⓑ".len())]
6379            );
6380            view.move_right(&MoveRight, cx);
6381            assert_eq!(
6382                view.selected_display_ranges(cx),
6383                &[empty_range(0, "ⓐⓑ…".len())]
6384            );
6385
6386            view.move_down(&MoveDown, cx);
6387            assert_eq!(
6388                view.selected_display_ranges(cx),
6389                &[empty_range(1, "ab…".len())]
6390            );
6391            view.move_left(&MoveLeft, cx);
6392            assert_eq!(
6393                view.selected_display_ranges(cx),
6394                &[empty_range(1, "ab".len())]
6395            );
6396            view.move_left(&MoveLeft, cx);
6397            assert_eq!(
6398                view.selected_display_ranges(cx),
6399                &[empty_range(1, "a".len())]
6400            );
6401
6402            view.move_down(&MoveDown, cx);
6403            assert_eq!(
6404                view.selected_display_ranges(cx),
6405                &[empty_range(2, "α".len())]
6406            );
6407            view.move_right(&MoveRight, cx);
6408            assert_eq!(
6409                view.selected_display_ranges(cx),
6410                &[empty_range(2, "αβ".len())]
6411            );
6412            view.move_right(&MoveRight, cx);
6413            assert_eq!(
6414                view.selected_display_ranges(cx),
6415                &[empty_range(2, "αβ…".len())]
6416            );
6417            view.move_right(&MoveRight, cx);
6418            assert_eq!(
6419                view.selected_display_ranges(cx),
6420                &[empty_range(2, "αβ…ε".len())]
6421            );
6422
6423            view.move_up(&MoveUp, cx);
6424            assert_eq!(
6425                view.selected_display_ranges(cx),
6426                &[empty_range(1, "ab…e".len())]
6427            );
6428            view.move_up(&MoveUp, cx);
6429            assert_eq!(
6430                view.selected_display_ranges(cx),
6431                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
6432            );
6433            view.move_left(&MoveLeft, cx);
6434            assert_eq!(
6435                view.selected_display_ranges(cx),
6436                &[empty_range(0, "ⓐⓑ…".len())]
6437            );
6438            view.move_left(&MoveLeft, cx);
6439            assert_eq!(
6440                view.selected_display_ranges(cx),
6441                &[empty_range(0, "ⓐⓑ".len())]
6442            );
6443            view.move_left(&MoveLeft, cx);
6444            assert_eq!(
6445                view.selected_display_ranges(cx),
6446                &[empty_range(0, "".len())]
6447            );
6448        });
6449    }
6450
6451    #[gpui::test]
6452    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
6453        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
6454        let settings = Settings::test(&cx);
6455        let (_, view) = cx.add_window(Default::default(), |cx| {
6456            build_editor(buffer.clone(), settings, cx)
6457        });
6458        view.update(cx, |view, cx| {
6459            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
6460            view.move_down(&MoveDown, cx);
6461            assert_eq!(
6462                view.selected_display_ranges(cx),
6463                &[empty_range(1, "abcd".len())]
6464            );
6465
6466            view.move_down(&MoveDown, cx);
6467            assert_eq!(
6468                view.selected_display_ranges(cx),
6469                &[empty_range(2, "αβγ".len())]
6470            );
6471
6472            view.move_down(&MoveDown, cx);
6473            assert_eq!(
6474                view.selected_display_ranges(cx),
6475                &[empty_range(3, "abcd".len())]
6476            );
6477
6478            view.move_down(&MoveDown, cx);
6479            assert_eq!(
6480                view.selected_display_ranges(cx),
6481                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
6482            );
6483
6484            view.move_up(&MoveUp, cx);
6485            assert_eq!(
6486                view.selected_display_ranges(cx),
6487                &[empty_range(3, "abcd".len())]
6488            );
6489
6490            view.move_up(&MoveUp, cx);
6491            assert_eq!(
6492                view.selected_display_ranges(cx),
6493                &[empty_range(2, "αβγ".len())]
6494            );
6495        });
6496    }
6497
6498    #[gpui::test]
6499    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
6500        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
6501        let settings = Settings::test(&cx);
6502        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
6503        view.update(cx, |view, cx| {
6504            view.select_display_ranges(
6505                &[
6506                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
6507                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
6508                ],
6509                cx,
6510            );
6511        });
6512
6513        view.update(cx, |view, cx| {
6514            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6515            assert_eq!(
6516                view.selected_display_ranges(cx),
6517                &[
6518                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6519                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
6520                ]
6521            );
6522        });
6523
6524        view.update(cx, |view, cx| {
6525            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6526            assert_eq!(
6527                view.selected_display_ranges(cx),
6528                &[
6529                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6530                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
6531                ]
6532            );
6533        });
6534
6535        view.update(cx, |view, cx| {
6536            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6537            assert_eq!(
6538                view.selected_display_ranges(cx),
6539                &[
6540                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6541                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
6542                ]
6543            );
6544        });
6545
6546        view.update(cx, |view, cx| {
6547            view.move_to_end_of_line(&MoveToEndOfLine, cx);
6548            assert_eq!(
6549                view.selected_display_ranges(cx),
6550                &[
6551                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6552                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
6553                ]
6554            );
6555        });
6556
6557        // Moving to the end of line again is a no-op.
6558        view.update(cx, |view, cx| {
6559            view.move_to_end_of_line(&MoveToEndOfLine, cx);
6560            assert_eq!(
6561                view.selected_display_ranges(cx),
6562                &[
6563                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6564                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
6565                ]
6566            );
6567        });
6568
6569        view.update(cx, |view, cx| {
6570            view.move_left(&MoveLeft, cx);
6571            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
6572            assert_eq!(
6573                view.selected_display_ranges(cx),
6574                &[
6575                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
6576                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
6577                ]
6578            );
6579        });
6580
6581        view.update(cx, |view, cx| {
6582            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
6583            assert_eq!(
6584                view.selected_display_ranges(cx),
6585                &[
6586                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
6587                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
6588                ]
6589            );
6590        });
6591
6592        view.update(cx, |view, cx| {
6593            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
6594            assert_eq!(
6595                view.selected_display_ranges(cx),
6596                &[
6597                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
6598                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
6599                ]
6600            );
6601        });
6602
6603        view.update(cx, |view, cx| {
6604            view.select_to_end_of_line(&SelectToEndOfLine(true), cx);
6605            assert_eq!(
6606                view.selected_display_ranges(cx),
6607                &[
6608                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
6609                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
6610                ]
6611            );
6612        });
6613
6614        view.update(cx, |view, cx| {
6615            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
6616            assert_eq!(view.display_text(cx), "ab\n  de");
6617            assert_eq!(
6618                view.selected_display_ranges(cx),
6619                &[
6620                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
6621                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
6622                ]
6623            );
6624        });
6625
6626        view.update(cx, |view, cx| {
6627            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
6628            assert_eq!(view.display_text(cx), "\n");
6629            assert_eq!(
6630                view.selected_display_ranges(cx),
6631                &[
6632                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6633                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
6634                ]
6635            );
6636        });
6637    }
6638
6639    #[gpui::test]
6640    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
6641        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
6642        let settings = Settings::test(&cx);
6643        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
6644        view.update(cx, |view, cx| {
6645            view.select_display_ranges(
6646                &[
6647                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
6648                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
6649                ],
6650                cx,
6651            );
6652        });
6653
6654        view.update(cx, |view, cx| {
6655            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6656            assert_eq!(
6657                view.selected_display_ranges(cx),
6658                &[
6659                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
6660                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
6661                ]
6662            );
6663        });
6664
6665        view.update(cx, |view, cx| {
6666            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6667            assert_eq!(
6668                view.selected_display_ranges(cx),
6669                &[
6670                    DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
6671                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
6672                ]
6673            );
6674        });
6675
6676        view.update(cx, |view, cx| {
6677            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6678            assert_eq!(
6679                view.selected_display_ranges(cx),
6680                &[
6681                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
6682                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
6683                ]
6684            );
6685        });
6686
6687        view.update(cx, |view, cx| {
6688            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6689            assert_eq!(
6690                view.selected_display_ranges(cx),
6691                &[
6692                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6693                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
6694                ]
6695            );
6696        });
6697
6698        view.update(cx, |view, cx| {
6699            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6700            assert_eq!(
6701                view.selected_display_ranges(cx),
6702                &[
6703                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6704                    DisplayPoint::new(0, 23)..DisplayPoint::new(0, 23),
6705                ]
6706            );
6707        });
6708
6709        view.update(cx, |view, cx| {
6710            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6711            assert_eq!(
6712                view.selected_display_ranges(cx),
6713                &[
6714                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6715                    DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
6716                ]
6717            );
6718        });
6719
6720        view.update(cx, |view, cx| {
6721            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6722            assert_eq!(
6723                view.selected_display_ranges(cx),
6724                &[
6725                    DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
6726                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
6727                ]
6728            );
6729        });
6730
6731        view.update(cx, |view, cx| {
6732            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6733            assert_eq!(
6734                view.selected_display_ranges(cx),
6735                &[
6736                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
6737                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
6738                ]
6739            );
6740        });
6741
6742        view.update(cx, |view, cx| {
6743            view.move_right(&MoveRight, cx);
6744            view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
6745            assert_eq!(
6746                view.selected_display_ranges(cx),
6747                &[
6748                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
6749                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
6750                ]
6751            );
6752        });
6753
6754        view.update(cx, |view, cx| {
6755            view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
6756            assert_eq!(
6757                view.selected_display_ranges(cx),
6758                &[
6759                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 7),
6760                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 2),
6761                ]
6762            );
6763        });
6764
6765        view.update(cx, |view, cx| {
6766            view.select_to_next_word_boundary(&SelectToNextWordBoundary, cx);
6767            assert_eq!(
6768                view.selected_display_ranges(cx),
6769                &[
6770                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
6771                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
6772                ]
6773            );
6774        });
6775    }
6776
6777    #[gpui::test]
6778    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
6779        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
6780        let settings = Settings::test(&cx);
6781        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
6782
6783        view.update(cx, |view, cx| {
6784            view.set_wrap_width(Some(140.), cx);
6785            assert_eq!(
6786                view.display_text(cx),
6787                "use one::{\n    two::three::\n    four::five\n};"
6788            );
6789
6790            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
6791
6792            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6793            assert_eq!(
6794                view.selected_display_ranges(cx),
6795                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
6796            );
6797
6798            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6799            assert_eq!(
6800                view.selected_display_ranges(cx),
6801                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
6802            );
6803
6804            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6805            assert_eq!(
6806                view.selected_display_ranges(cx),
6807                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
6808            );
6809
6810            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
6811            assert_eq!(
6812                view.selected_display_ranges(cx),
6813                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
6814            );
6815
6816            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6817            assert_eq!(
6818                view.selected_display_ranges(cx),
6819                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
6820            );
6821
6822            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
6823            assert_eq!(
6824                view.selected_display_ranges(cx),
6825                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
6826            );
6827        });
6828    }
6829
6830    #[gpui::test]
6831    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
6832        let buffer = MultiBuffer::build_simple("one two three four", cx);
6833        let settings = Settings::test(&cx);
6834        let (_, view) = cx.add_window(Default::default(), |cx| {
6835            build_editor(buffer.clone(), settings, cx)
6836        });
6837
6838        view.update(cx, |view, cx| {
6839            view.select_display_ranges(
6840                &[
6841                    // an empty selection - the preceding word fragment is deleted
6842                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
6843                    // characters selected - they are deleted
6844                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
6845                ],
6846                cx,
6847            );
6848            view.delete_to_previous_word_boundary(&DeleteToPreviousWordBoundary, cx);
6849        });
6850
6851        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
6852
6853        view.update(cx, |view, cx| {
6854            view.select_display_ranges(
6855                &[
6856                    // an empty selection - the following word fragment is deleted
6857                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6858                    // characters selected - they are deleted
6859                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
6860                ],
6861                cx,
6862            );
6863            view.delete_to_next_word_boundary(&DeleteToNextWordBoundary, cx);
6864        });
6865
6866        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
6867    }
6868
6869    #[gpui::test]
6870    fn test_newline(cx: &mut gpui::MutableAppContext) {
6871        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
6872        let settings = Settings::test(&cx);
6873        let (_, view) = cx.add_window(Default::default(), |cx| {
6874            build_editor(buffer.clone(), settings, cx)
6875        });
6876
6877        view.update(cx, |view, cx| {
6878            view.select_display_ranges(
6879                &[
6880                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
6881                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
6882                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
6883                ],
6884                cx,
6885            );
6886
6887            view.newline(&Newline, cx);
6888            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
6889        });
6890    }
6891
6892    #[gpui::test]
6893    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
6894        let buffer = MultiBuffer::build_simple(
6895            "
6896                a
6897                b(
6898                    X
6899                )
6900                c(
6901                    X
6902                )
6903            "
6904            .unindent()
6905            .as_str(),
6906            cx,
6907        );
6908
6909        let settings = Settings::test(&cx);
6910        let (_, editor) = cx.add_window(Default::default(), |cx| {
6911            let mut editor = build_editor(buffer.clone(), settings, cx);
6912            editor.select_ranges(
6913                [
6914                    Point::new(2, 4)..Point::new(2, 5),
6915                    Point::new(5, 4)..Point::new(5, 5),
6916                ],
6917                None,
6918                cx,
6919            );
6920            editor
6921        });
6922
6923        // Edit the buffer directly, deleting ranges surrounding the editor's selections
6924        buffer.update(cx, |buffer, cx| {
6925            buffer.edit(
6926                [
6927                    Point::new(1, 2)..Point::new(3, 0),
6928                    Point::new(4, 2)..Point::new(6, 0),
6929                ],
6930                "",
6931                cx,
6932            );
6933            assert_eq!(
6934                buffer.read(cx).text(),
6935                "
6936                    a
6937                    b()
6938                    c()
6939                "
6940                .unindent()
6941            );
6942        });
6943
6944        editor.update(cx, |editor, cx| {
6945            assert_eq!(
6946                editor.selected_ranges(cx),
6947                &[
6948                    Point::new(1, 2)..Point::new(1, 2),
6949                    Point::new(2, 2)..Point::new(2, 2),
6950                ],
6951            );
6952
6953            editor.newline(&Newline, cx);
6954            assert_eq!(
6955                editor.text(cx),
6956                "
6957                    a
6958                    b(
6959                    )
6960                    c(
6961                    )
6962                "
6963                .unindent()
6964            );
6965
6966            // The selections are moved after the inserted newlines
6967            assert_eq!(
6968                editor.selected_ranges(cx),
6969                &[
6970                    Point::new(2, 0)..Point::new(2, 0),
6971                    Point::new(4, 0)..Point::new(4, 0),
6972                ],
6973            );
6974        });
6975    }
6976
6977    #[gpui::test]
6978    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
6979        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
6980
6981        let settings = Settings::test(&cx);
6982        let (_, editor) = cx.add_window(Default::default(), |cx| {
6983            let mut editor = build_editor(buffer.clone(), settings, cx);
6984            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
6985            editor
6986        });
6987
6988        // Edit the buffer directly, deleting ranges surrounding the editor's selections
6989        buffer.update(cx, |buffer, cx| {
6990            buffer.edit([2..5, 10..13, 18..21], "", cx);
6991            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
6992        });
6993
6994        editor.update(cx, |editor, cx| {
6995            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
6996
6997            editor.insert("Z", cx);
6998            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
6999
7000            // The selections are moved after the inserted characters
7001            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
7002        });
7003    }
7004
7005    #[gpui::test]
7006    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
7007        let buffer = MultiBuffer::build_simple("  one two\nthree\n four", cx);
7008        let settings = Settings::test(&cx);
7009        let (_, view) = cx.add_window(Default::default(), |cx| {
7010            build_editor(buffer.clone(), settings, cx)
7011        });
7012
7013        view.update(cx, |view, cx| {
7014            // two selections on the same line
7015            view.select_display_ranges(
7016                &[
7017                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 5),
7018                    DisplayPoint::new(0, 6)..DisplayPoint::new(0, 9),
7019                ],
7020                cx,
7021            );
7022
7023            // indent from mid-tabstop to full tabstop
7024            view.tab(&Tab, cx);
7025            assert_eq!(view.text(cx), "    one two\nthree\n four");
7026            assert_eq!(
7027                view.selected_display_ranges(cx),
7028                &[
7029                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
7030                    DisplayPoint::new(0, 8)..DisplayPoint::new(0, 11),
7031                ]
7032            );
7033
7034            // outdent from 1 tabstop to 0 tabstops
7035            view.outdent(&Outdent, cx);
7036            assert_eq!(view.text(cx), "one two\nthree\n four");
7037            assert_eq!(
7038                view.selected_display_ranges(cx),
7039                &[
7040                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 3),
7041                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
7042                ]
7043            );
7044
7045            // select across line ending
7046            view.select_display_ranges(&[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)], cx);
7047
7048            // indent and outdent affect only the preceding line
7049            view.tab(&Tab, cx);
7050            assert_eq!(view.text(cx), "one two\n    three\n four");
7051            assert_eq!(
7052                view.selected_display_ranges(cx),
7053                &[DisplayPoint::new(1, 5)..DisplayPoint::new(2, 0)]
7054            );
7055            view.outdent(&Outdent, cx);
7056            assert_eq!(view.text(cx), "one two\nthree\n four");
7057            assert_eq!(
7058                view.selected_display_ranges(cx),
7059                &[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)]
7060            );
7061
7062            // Ensure that indenting/outdenting works when the cursor is at column 0.
7063            view.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
7064            view.tab(&Tab, cx);
7065            assert_eq!(view.text(cx), "one two\n    three\n four");
7066            assert_eq!(
7067                view.selected_display_ranges(cx),
7068                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
7069            );
7070
7071            view.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
7072            view.outdent(&Outdent, cx);
7073            assert_eq!(view.text(cx), "one two\nthree\n four");
7074            assert_eq!(
7075                view.selected_display_ranges(cx),
7076                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
7077            );
7078        });
7079    }
7080
7081    #[gpui::test]
7082    fn test_backspace(cx: &mut gpui::MutableAppContext) {
7083        let buffer =
7084            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
7085        let settings = Settings::test(&cx);
7086        let (_, view) = cx.add_window(Default::default(), |cx| {
7087            build_editor(buffer.clone(), settings, cx)
7088        });
7089
7090        view.update(cx, |view, cx| {
7091            view.select_display_ranges(
7092                &[
7093                    // an empty selection - the preceding character is deleted
7094                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7095                    // one character selected - it is deleted
7096                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7097                    // a line suffix selected - it is deleted
7098                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
7099                ],
7100                cx,
7101            );
7102            view.backspace(&Backspace, cx);
7103        });
7104
7105        assert_eq!(
7106            buffer.read(cx).read(cx).text(),
7107            "oe two three\nfou five six\nseven ten\n"
7108        );
7109    }
7110
7111    #[gpui::test]
7112    fn test_delete(cx: &mut gpui::MutableAppContext) {
7113        let buffer =
7114            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
7115        let settings = Settings::test(&cx);
7116        let (_, view) = cx.add_window(Default::default(), |cx| {
7117            build_editor(buffer.clone(), settings, cx)
7118        });
7119
7120        view.update(cx, |view, cx| {
7121            view.select_display_ranges(
7122                &[
7123                    // an empty selection - the following character is deleted
7124                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7125                    // one character selected - it is deleted
7126                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7127                    // a line suffix selected - it is deleted
7128                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
7129                ],
7130                cx,
7131            );
7132            view.delete(&Delete, cx);
7133        });
7134
7135        assert_eq!(
7136            buffer.read(cx).read(cx).text(),
7137            "on two three\nfou five six\nseven ten\n"
7138        );
7139    }
7140
7141    #[gpui::test]
7142    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
7143        let settings = Settings::test(&cx);
7144        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7145        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7146        view.update(cx, |view, cx| {
7147            view.select_display_ranges(
7148                &[
7149                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7150                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7151                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7152                ],
7153                cx,
7154            );
7155            view.delete_line(&DeleteLine, cx);
7156            assert_eq!(view.display_text(cx), "ghi");
7157            assert_eq!(
7158                view.selected_display_ranges(cx),
7159                vec![
7160                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7161                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
7162                ]
7163            );
7164        });
7165
7166        let settings = Settings::test(&cx);
7167        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7168        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7169        view.update(cx, |view, cx| {
7170            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
7171            view.delete_line(&DeleteLine, cx);
7172            assert_eq!(view.display_text(cx), "ghi\n");
7173            assert_eq!(
7174                view.selected_display_ranges(cx),
7175                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
7176            );
7177        });
7178    }
7179
7180    #[gpui::test]
7181    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
7182        let settings = Settings::test(&cx);
7183        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7184        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7185        view.update(cx, |view, cx| {
7186            view.select_display_ranges(
7187                &[
7188                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7189                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7190                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7191                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7192                ],
7193                cx,
7194            );
7195            view.duplicate_line(&DuplicateLine, cx);
7196            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
7197            assert_eq!(
7198                view.selected_display_ranges(cx),
7199                vec![
7200                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7201                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7202                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7203                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
7204                ]
7205            );
7206        });
7207
7208        let settings = Settings::test(&cx);
7209        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7210        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7211        view.update(cx, |view, cx| {
7212            view.select_display_ranges(
7213                &[
7214                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
7215                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
7216                ],
7217                cx,
7218            );
7219            view.duplicate_line(&DuplicateLine, cx);
7220            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
7221            assert_eq!(
7222                view.selected_display_ranges(cx),
7223                vec![
7224                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
7225                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
7226                ]
7227            );
7228        });
7229    }
7230
7231    #[gpui::test]
7232    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
7233        let settings = Settings::test(&cx);
7234        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7235        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7236        view.update(cx, |view, cx| {
7237            view.fold_ranges(
7238                vec![
7239                    Point::new(0, 2)..Point::new(1, 2),
7240                    Point::new(2, 3)..Point::new(4, 1),
7241                    Point::new(7, 0)..Point::new(8, 4),
7242                ],
7243                cx,
7244            );
7245            view.select_display_ranges(
7246                &[
7247                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7248                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7249                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7250                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
7251                ],
7252                cx,
7253            );
7254            assert_eq!(
7255                view.display_text(cx),
7256                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
7257            );
7258
7259            view.move_line_up(&MoveLineUp, cx);
7260            assert_eq!(
7261                view.display_text(cx),
7262                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
7263            );
7264            assert_eq!(
7265                view.selected_display_ranges(cx),
7266                vec![
7267                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7268                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7269                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7270                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7271                ]
7272            );
7273        });
7274
7275        view.update(cx, |view, cx| {
7276            view.move_line_down(&MoveLineDown, cx);
7277            assert_eq!(
7278                view.display_text(cx),
7279                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
7280            );
7281            assert_eq!(
7282                view.selected_display_ranges(cx),
7283                vec![
7284                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7285                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7286                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7287                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7288                ]
7289            );
7290        });
7291
7292        view.update(cx, |view, cx| {
7293            view.move_line_down(&MoveLineDown, cx);
7294            assert_eq!(
7295                view.display_text(cx),
7296                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
7297            );
7298            assert_eq!(
7299                view.selected_display_ranges(cx),
7300                vec![
7301                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7302                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7303                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7304                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7305                ]
7306            );
7307        });
7308
7309        view.update(cx, |view, cx| {
7310            view.move_line_up(&MoveLineUp, cx);
7311            assert_eq!(
7312                view.display_text(cx),
7313                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
7314            );
7315            assert_eq!(
7316                view.selected_display_ranges(cx),
7317                vec![
7318                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7319                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7320                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7321                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7322                ]
7323            );
7324        });
7325    }
7326
7327    #[gpui::test]
7328    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
7329        let settings = Settings::test(&cx);
7330        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7331        let snapshot = buffer.read(cx).snapshot(cx);
7332        let (_, editor) =
7333            cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7334        editor.update(cx, |editor, cx| {
7335            editor.insert_blocks(
7336                [BlockProperties {
7337                    position: snapshot.anchor_after(Point::new(2, 0)),
7338                    disposition: BlockDisposition::Below,
7339                    height: 1,
7340                    render: Arc::new(|_| Empty::new().boxed()),
7341                }],
7342                cx,
7343            );
7344            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
7345            editor.move_line_down(&MoveLineDown, cx);
7346        });
7347    }
7348
7349    #[gpui::test]
7350    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
7351        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
7352        let settings = Settings::test(&cx);
7353        let view = cx
7354            .add_window(Default::default(), |cx| {
7355                build_editor(buffer.clone(), settings, cx)
7356            })
7357            .1;
7358
7359        // Cut with three selections. Clipboard text is divided into three slices.
7360        view.update(cx, |view, cx| {
7361            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
7362            view.cut(&Cut, cx);
7363            assert_eq!(view.display_text(cx), "two four six ");
7364        });
7365
7366        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
7367        view.update(cx, |view, cx| {
7368            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
7369            view.paste(&Paste, cx);
7370            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
7371            assert_eq!(
7372                view.selected_display_ranges(cx),
7373                &[
7374                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
7375                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
7376                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
7377                ]
7378            );
7379        });
7380
7381        // Paste again but with only two cursors. Since the number of cursors doesn't
7382        // match the number of slices in the clipboard, the entire clipboard text
7383        // is pasted at each cursor.
7384        view.update(cx, |view, cx| {
7385            view.select_ranges(vec![0..0, 31..31], None, cx);
7386            view.handle_input(&Input("( ".into()), cx);
7387            view.paste(&Paste, cx);
7388            view.handle_input(&Input(") ".into()), cx);
7389            assert_eq!(
7390                view.display_text(cx),
7391                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7392            );
7393        });
7394
7395        view.update(cx, |view, cx| {
7396            view.select_ranges(vec![0..0], None, cx);
7397            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
7398            assert_eq!(
7399                view.display_text(cx),
7400                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7401            );
7402        });
7403
7404        // Cut with three selections, one of which is full-line.
7405        view.update(cx, |view, cx| {
7406            view.select_display_ranges(
7407                &[
7408                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
7409                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7410                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
7411                ],
7412                cx,
7413            );
7414            view.cut(&Cut, cx);
7415            assert_eq!(
7416                view.display_text(cx),
7417                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
7418            );
7419        });
7420
7421        // Paste with three selections, noticing how the copied selection that was full-line
7422        // gets inserted before the second cursor.
7423        view.update(cx, |view, cx| {
7424            view.select_display_ranges(
7425                &[
7426                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7427                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7428                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
7429                ],
7430                cx,
7431            );
7432            view.paste(&Paste, cx);
7433            assert_eq!(
7434                view.display_text(cx),
7435                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
7436            );
7437            assert_eq!(
7438                view.selected_display_ranges(cx),
7439                &[
7440                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7441                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7442                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
7443                ]
7444            );
7445        });
7446
7447        // Copy with a single cursor only, which writes the whole line into the clipboard.
7448        view.update(cx, |view, cx| {
7449            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
7450            view.copy(&Copy, cx);
7451        });
7452
7453        // Paste with three selections, noticing how the copied full-line selection is inserted
7454        // before the empty selections but replaces the selection that is non-empty.
7455        view.update(cx, |view, cx| {
7456            view.select_display_ranges(
7457                &[
7458                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7459                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
7460                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7461                ],
7462                cx,
7463            );
7464            view.paste(&Paste, cx);
7465            assert_eq!(
7466                view.display_text(cx),
7467                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
7468            );
7469            assert_eq!(
7470                view.selected_display_ranges(cx),
7471                &[
7472                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7473                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7474                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
7475                ]
7476            );
7477        });
7478    }
7479
7480    #[gpui::test]
7481    fn test_select_all(cx: &mut gpui::MutableAppContext) {
7482        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
7483        let settings = Settings::test(&cx);
7484        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7485        view.update(cx, |view, cx| {
7486            view.select_all(&SelectAll, cx);
7487            assert_eq!(
7488                view.selected_display_ranges(cx),
7489                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
7490            );
7491        });
7492    }
7493
7494    #[gpui::test]
7495    fn test_select_line(cx: &mut gpui::MutableAppContext) {
7496        let settings = Settings::test(&cx);
7497        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
7498        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7499        view.update(cx, |view, cx| {
7500            view.select_display_ranges(
7501                &[
7502                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7503                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7504                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7505                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
7506                ],
7507                cx,
7508            );
7509            view.select_line(&SelectLine, cx);
7510            assert_eq!(
7511                view.selected_display_ranges(cx),
7512                vec![
7513                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
7514                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
7515                ]
7516            );
7517        });
7518
7519        view.update(cx, |view, cx| {
7520            view.select_line(&SelectLine, cx);
7521            assert_eq!(
7522                view.selected_display_ranges(cx),
7523                vec![
7524                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
7525                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
7526                ]
7527            );
7528        });
7529
7530        view.update(cx, |view, cx| {
7531            view.select_line(&SelectLine, cx);
7532            assert_eq!(
7533                view.selected_display_ranges(cx),
7534                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
7535            );
7536        });
7537    }
7538
7539    #[gpui::test]
7540    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
7541        let settings = Settings::test(&cx);
7542        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
7543        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7544        view.update(cx, |view, cx| {
7545            view.fold_ranges(
7546                vec![
7547                    Point::new(0, 2)..Point::new(1, 2),
7548                    Point::new(2, 3)..Point::new(4, 1),
7549                    Point::new(7, 0)..Point::new(8, 4),
7550                ],
7551                cx,
7552            );
7553            view.select_display_ranges(
7554                &[
7555                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7556                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7557                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7558                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
7559                ],
7560                cx,
7561            );
7562            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
7563        });
7564
7565        view.update(cx, |view, cx| {
7566            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
7567            assert_eq!(
7568                view.display_text(cx),
7569                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
7570            );
7571            assert_eq!(
7572                view.selected_display_ranges(cx),
7573                [
7574                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7575                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7576                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
7577                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
7578                ]
7579            );
7580        });
7581
7582        view.update(cx, |view, cx| {
7583            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
7584            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
7585            assert_eq!(
7586                view.display_text(cx),
7587                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
7588            );
7589            assert_eq!(
7590                view.selected_display_ranges(cx),
7591                [
7592                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
7593                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
7594                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
7595                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
7596                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
7597                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
7598                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
7599                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
7600                ]
7601            );
7602        });
7603    }
7604
7605    #[gpui::test]
7606    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
7607        let settings = Settings::test(&cx);
7608        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
7609        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
7610
7611        view.update(cx, |view, cx| {
7612            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
7613        });
7614        view.update(cx, |view, cx| {
7615            view.add_selection_above(&AddSelectionAbove, cx);
7616            assert_eq!(
7617                view.selected_display_ranges(cx),
7618                vec![
7619                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7620                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
7621                ]
7622            );
7623        });
7624
7625        view.update(cx, |view, cx| {
7626            view.add_selection_above(&AddSelectionAbove, cx);
7627            assert_eq!(
7628                view.selected_display_ranges(cx),
7629                vec![
7630                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7631                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
7632                ]
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![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
7641            );
7642        });
7643
7644        view.update(cx, |view, cx| {
7645            view.add_selection_below(&AddSelectionBelow, cx);
7646            assert_eq!(
7647                view.selected_display_ranges(cx),
7648                vec![
7649                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
7650                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
7651                ]
7652            );
7653        });
7654
7655        view.update(cx, |view, cx| {
7656            view.add_selection_below(&AddSelectionBelow, cx);
7657            assert_eq!(
7658                view.selected_display_ranges(cx),
7659                vec![
7660                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
7661                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
7662                ]
7663            );
7664        });
7665
7666        view.update(cx, |view, cx| {
7667            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
7668        });
7669        view.update(cx, |view, cx| {
7670            view.add_selection_below(&AddSelectionBelow, cx);
7671            assert_eq!(
7672                view.selected_display_ranges(cx),
7673                vec![
7674                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7675                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
7676                ]
7677            );
7678        });
7679
7680        view.update(cx, |view, cx| {
7681            view.add_selection_below(&AddSelectionBelow, cx);
7682            assert_eq!(
7683                view.selected_display_ranges(cx),
7684                vec![
7685                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
7686                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
7687                ]
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.add_selection_above(&AddSelectionAbove, cx);
7701            assert_eq!(
7702                view.selected_display_ranges(cx),
7703                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
7704            );
7705        });
7706
7707        view.update(cx, |view, cx| {
7708            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
7709            view.add_selection_below(&AddSelectionBelow, cx);
7710            assert_eq!(
7711                view.selected_display_ranges(cx),
7712                vec![
7713                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
7714                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
7715                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
7716                ]
7717            );
7718        });
7719
7720        view.update(cx, |view, cx| {
7721            view.add_selection_below(&AddSelectionBelow, cx);
7722            assert_eq!(
7723                view.selected_display_ranges(cx),
7724                vec![
7725                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
7726                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
7727                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
7728                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
7729                ]
7730            );
7731        });
7732
7733        view.update(cx, |view, cx| {
7734            view.add_selection_above(&AddSelectionAbove, cx);
7735            assert_eq!(
7736                view.selected_display_ranges(cx),
7737                vec![
7738                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
7739                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
7740                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
7741                ]
7742            );
7743        });
7744
7745        view.update(cx, |view, cx| {
7746            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
7747        });
7748        view.update(cx, |view, cx| {
7749            view.add_selection_above(&AddSelectionAbove, cx);
7750            assert_eq!(
7751                view.selected_display_ranges(cx),
7752                vec![
7753                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
7754                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
7755                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
7756                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
7757                ]
7758            );
7759        });
7760
7761        view.update(cx, |view, cx| {
7762            view.add_selection_below(&AddSelectionBelow, cx);
7763            assert_eq!(
7764                view.selected_display_ranges(cx),
7765                vec![
7766                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
7767                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
7768                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
7769                ]
7770            );
7771        });
7772    }
7773
7774    #[gpui::test]
7775    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
7776        let settings = cx.read(Settings::test);
7777        let language = Arc::new(Language::new(
7778            LanguageConfig::default(),
7779            Some(tree_sitter_rust::language()),
7780        ));
7781
7782        let text = r#"
7783            use mod1::mod2::{mod3, mod4};
7784
7785            fn fn_1(param1: bool, param2: &str) {
7786                let var1 = "text";
7787            }
7788        "#
7789        .unindent();
7790
7791        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
7792        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
7793        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
7794        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
7795            .await;
7796
7797        view.update(cx, |view, cx| {
7798            view.select_display_ranges(
7799                &[
7800                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
7801                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
7802                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
7803                ],
7804                cx,
7805            );
7806            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
7807        });
7808        assert_eq!(
7809            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7810            &[
7811                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
7812                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
7813                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
7814            ]
7815        );
7816
7817        view.update(cx, |view, cx| {
7818            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
7819        });
7820        assert_eq!(
7821            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7822            &[
7823                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
7824                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
7825            ]
7826        );
7827
7828        view.update(cx, |view, cx| {
7829            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
7830        });
7831        assert_eq!(
7832            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7833            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
7834        );
7835
7836        // Trying to expand the selected syntax node one more time has no effect.
7837        view.update(cx, |view, cx| {
7838            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
7839        });
7840        assert_eq!(
7841            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7842            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
7843        );
7844
7845        view.update(cx, |view, cx| {
7846            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
7847        });
7848        assert_eq!(
7849            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7850            &[
7851                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
7852                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
7853            ]
7854        );
7855
7856        view.update(cx, |view, cx| {
7857            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
7858        });
7859        assert_eq!(
7860            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7861            &[
7862                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
7863                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
7864                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
7865            ]
7866        );
7867
7868        view.update(cx, |view, cx| {
7869            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
7870        });
7871        assert_eq!(
7872            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7873            &[
7874                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
7875                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
7876                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
7877            ]
7878        );
7879
7880        // Trying to shrink the selected syntax node one more time has no effect.
7881        view.update(cx, |view, cx| {
7882            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
7883        });
7884        assert_eq!(
7885            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7886            &[
7887                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
7888                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
7889                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
7890            ]
7891        );
7892
7893        // Ensure that we keep expanding the selection if the larger selection starts or ends within
7894        // a fold.
7895        view.update(cx, |view, cx| {
7896            view.fold_ranges(
7897                vec![
7898                    Point::new(0, 21)..Point::new(0, 24),
7899                    Point::new(3, 20)..Point::new(3, 22),
7900                ],
7901                cx,
7902            );
7903            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
7904        });
7905        assert_eq!(
7906            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
7907            &[
7908                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
7909                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
7910                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
7911            ]
7912        );
7913    }
7914
7915    #[gpui::test]
7916    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
7917        let settings = cx.read(Settings::test);
7918        let language = Arc::new(
7919            Language::new(
7920                LanguageConfig {
7921                    brackets: vec![
7922                        BracketPair {
7923                            start: "{".to_string(),
7924                            end: "}".to_string(),
7925                            close: false,
7926                            newline: true,
7927                        },
7928                        BracketPair {
7929                            start: "(".to_string(),
7930                            end: ")".to_string(),
7931                            close: false,
7932                            newline: true,
7933                        },
7934                    ],
7935                    ..Default::default()
7936                },
7937                Some(tree_sitter_rust::language()),
7938            )
7939            .with_indents_query(
7940                r#"
7941                (_ "(" ")" @end) @indent
7942                (_ "{" "}" @end) @indent
7943                "#,
7944            )
7945            .unwrap(),
7946        );
7947
7948        let text = "fn a() {}";
7949
7950        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
7951        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
7952        let (_, editor) = cx.add_window(|cx| build_editor(buffer, settings, cx));
7953        editor
7954            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
7955            .await;
7956
7957        editor.update(cx, |editor, cx| {
7958            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
7959            editor.newline(&Newline, cx);
7960            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
7961            assert_eq!(
7962                editor.selected_ranges(cx),
7963                &[
7964                    Point::new(1, 4)..Point::new(1, 4),
7965                    Point::new(3, 4)..Point::new(3, 4),
7966                    Point::new(5, 0)..Point::new(5, 0)
7967                ]
7968            );
7969        });
7970    }
7971
7972    #[gpui::test]
7973    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
7974        let settings = cx.read(Settings::test);
7975        let language = Arc::new(Language::new(
7976            LanguageConfig {
7977                brackets: vec![
7978                    BracketPair {
7979                        start: "{".to_string(),
7980                        end: "}".to_string(),
7981                        close: true,
7982                        newline: true,
7983                    },
7984                    BracketPair {
7985                        start: "/*".to_string(),
7986                        end: " */".to_string(),
7987                        close: true,
7988                        newline: true,
7989                    },
7990                ],
7991                ..Default::default()
7992            },
7993            Some(tree_sitter_rust::language()),
7994        ));
7995
7996        let text = r#"
7997            a
7998
7999            /
8000
8001        "#
8002        .unindent();
8003
8004        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8005        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8006        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
8007        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8008            .await;
8009
8010        view.update(cx, |view, cx| {
8011            view.select_display_ranges(
8012                &[
8013                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8014                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8015                ],
8016                cx,
8017            );
8018            view.handle_input(&Input("{".to_string()), cx);
8019            view.handle_input(&Input("{".to_string()), cx);
8020            view.handle_input(&Input("{".to_string()), cx);
8021            assert_eq!(
8022                view.text(cx),
8023                "
8024                {{{}}}
8025                {{{}}}
8026                /
8027
8028                "
8029                .unindent()
8030            );
8031
8032            view.move_right(&MoveRight, cx);
8033            view.handle_input(&Input("}".to_string()), cx);
8034            view.handle_input(&Input("}".to_string()), cx);
8035            view.handle_input(&Input("}".to_string()), cx);
8036            assert_eq!(
8037                view.text(cx),
8038                "
8039                {{{}}}}
8040                {{{}}}}
8041                /
8042
8043                "
8044                .unindent()
8045            );
8046
8047            view.undo(&Undo, cx);
8048            view.handle_input(&Input("/".to_string()), cx);
8049            view.handle_input(&Input("*".to_string()), cx);
8050            assert_eq!(
8051                view.text(cx),
8052                "
8053                /* */
8054                /* */
8055                /
8056
8057                "
8058                .unindent()
8059            );
8060
8061            view.undo(&Undo, cx);
8062            view.select_display_ranges(
8063                &[
8064                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
8065                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
8066                ],
8067                cx,
8068            );
8069            view.handle_input(&Input("*".to_string()), cx);
8070            assert_eq!(
8071                view.text(cx),
8072                "
8073                a
8074
8075                /*
8076                *
8077                "
8078                .unindent()
8079            );
8080        });
8081    }
8082
8083    #[gpui::test]
8084    async fn test_snippets(cx: &mut gpui::TestAppContext) {
8085        let settings = cx.read(Settings::test);
8086
8087        let text = "
8088            a. b
8089            a. b
8090            a. b
8091        "
8092        .unindent();
8093        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
8094        let (_, editor) = cx.add_window(|cx| build_editor(buffer, settings, cx));
8095
8096        editor.update(cx, |editor, cx| {
8097            let buffer = &editor.snapshot(cx).buffer_snapshot;
8098            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
8099            let insertion_ranges = [
8100                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
8101                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
8102                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
8103            ];
8104
8105            editor
8106                .insert_snippet(&insertion_ranges, snippet, cx)
8107                .unwrap();
8108            assert_eq!(
8109                editor.text(cx),
8110                "
8111                    a.f(one, two, three) b
8112                    a.f(one, two, three) b
8113                    a.f(one, two, three) b
8114                "
8115                .unindent()
8116            );
8117            assert_eq!(
8118                editor.selected_ranges::<Point>(cx),
8119                &[
8120                    Point::new(0, 4)..Point::new(0, 7),
8121                    Point::new(0, 14)..Point::new(0, 19),
8122                    Point::new(1, 4)..Point::new(1, 7),
8123                    Point::new(1, 14)..Point::new(1, 19),
8124                    Point::new(2, 4)..Point::new(2, 7),
8125                    Point::new(2, 14)..Point::new(2, 19),
8126                ]
8127            );
8128
8129            // Can't move earlier than the first tab stop
8130            editor.move_to_prev_snippet_tabstop(cx);
8131            assert_eq!(
8132                editor.selected_ranges::<Point>(cx),
8133                &[
8134                    Point::new(0, 4)..Point::new(0, 7),
8135                    Point::new(0, 14)..Point::new(0, 19),
8136                    Point::new(1, 4)..Point::new(1, 7),
8137                    Point::new(1, 14)..Point::new(1, 19),
8138                    Point::new(2, 4)..Point::new(2, 7),
8139                    Point::new(2, 14)..Point::new(2, 19),
8140                ]
8141            );
8142
8143            assert!(editor.move_to_next_snippet_tabstop(cx));
8144            assert_eq!(
8145                editor.selected_ranges::<Point>(cx),
8146                &[
8147                    Point::new(0, 9)..Point::new(0, 12),
8148                    Point::new(1, 9)..Point::new(1, 12),
8149                    Point::new(2, 9)..Point::new(2, 12)
8150                ]
8151            );
8152
8153            editor.move_to_prev_snippet_tabstop(cx);
8154            assert_eq!(
8155                editor.selected_ranges::<Point>(cx),
8156                &[
8157                    Point::new(0, 4)..Point::new(0, 7),
8158                    Point::new(0, 14)..Point::new(0, 19),
8159                    Point::new(1, 4)..Point::new(1, 7),
8160                    Point::new(1, 14)..Point::new(1, 19),
8161                    Point::new(2, 4)..Point::new(2, 7),
8162                    Point::new(2, 14)..Point::new(2, 19),
8163                ]
8164            );
8165
8166            assert!(editor.move_to_next_snippet_tabstop(cx));
8167            assert!(editor.move_to_next_snippet_tabstop(cx));
8168            assert_eq!(
8169                editor.selected_ranges::<Point>(cx),
8170                &[
8171                    Point::new(0, 20)..Point::new(0, 20),
8172                    Point::new(1, 20)..Point::new(1, 20),
8173                    Point::new(2, 20)..Point::new(2, 20)
8174                ]
8175            );
8176
8177            // As soon as the last tab stop is reached, snippet state is gone
8178            editor.move_to_prev_snippet_tabstop(cx);
8179            assert_eq!(
8180                editor.selected_ranges::<Point>(cx),
8181                &[
8182                    Point::new(0, 20)..Point::new(0, 20),
8183                    Point::new(1, 20)..Point::new(1, 20),
8184                    Point::new(2, 20)..Point::new(2, 20)
8185                ]
8186            );
8187        });
8188    }
8189
8190    #[gpui::test]
8191    async fn test_completion(cx: &mut gpui::TestAppContext) {
8192        let settings = cx.read(Settings::test);
8193        let (language_server, mut fake) = cx.update(|cx| {
8194            lsp::LanguageServer::fake_with_capabilities(
8195                lsp::ServerCapabilities {
8196                    completion_provider: Some(lsp::CompletionOptions {
8197                        trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
8198                        ..Default::default()
8199                    }),
8200                    ..Default::default()
8201                },
8202                cx,
8203            )
8204        });
8205
8206        let text = "
8207            one
8208            two
8209            three
8210        "
8211        .unindent();
8212
8213        let fs = FakeFs::new(cx.background().clone());
8214        fs.insert_file("/file", text).await;
8215
8216        let project = Project::test(fs, cx);
8217
8218        let (worktree, relative_path) = project
8219            .update(cx, |project, cx| {
8220                project.find_or_create_local_worktree("/file", true, cx)
8221            })
8222            .await
8223            .unwrap();
8224        let project_path = ProjectPath {
8225            worktree_id: worktree.read_with(cx, |worktree, _| worktree.id()),
8226            path: relative_path.into(),
8227        };
8228        let buffer = project
8229            .update(cx, |project, cx| project.open_buffer(project_path, cx))
8230            .await
8231            .unwrap();
8232        buffer.update(cx, |buffer, cx| {
8233            buffer.set_language_server(Some(language_server), cx);
8234        });
8235
8236        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8237        buffer.next_notification(&cx).await;
8238
8239        let (_, editor) = cx.add_window(|cx| build_editor(buffer, settings, cx));
8240
8241        editor.update(cx, |editor, cx| {
8242            editor.project = Some(project);
8243            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
8244            editor.handle_input(&Input(".".to_string()), cx);
8245        });
8246
8247        handle_completion_request(
8248            &mut fake,
8249            "/file",
8250            Point::new(0, 4),
8251            vec![
8252                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
8253                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
8254            ],
8255        )
8256        .await;
8257        editor
8258            .condition(&cx, |editor, _| editor.context_menu_visible())
8259            .await;
8260
8261        let apply_additional_edits = editor.update(cx, |editor, cx| {
8262            editor.move_down(&MoveDown, cx);
8263            let apply_additional_edits = editor
8264                .confirm_completion(&ConfirmCompletion(None), cx)
8265                .unwrap();
8266            assert_eq!(
8267                editor.text(cx),
8268                "
8269                    one.second_completion
8270                    two
8271                    three
8272                "
8273                .unindent()
8274            );
8275            apply_additional_edits
8276        });
8277
8278        handle_resolve_completion_request(
8279            &mut fake,
8280            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
8281        )
8282        .await;
8283        apply_additional_edits.await.unwrap();
8284        assert_eq!(
8285            editor.read_with(cx, |editor, cx| editor.text(cx)),
8286            "
8287                one.second_completion
8288                two
8289                three
8290                additional edit
8291            "
8292            .unindent()
8293        );
8294
8295        editor.update(cx, |editor, cx| {
8296            editor.select_ranges(
8297                [
8298                    Point::new(1, 3)..Point::new(1, 3),
8299                    Point::new(2, 5)..Point::new(2, 5),
8300                ],
8301                None,
8302                cx,
8303            );
8304
8305            editor.handle_input(&Input(" ".to_string()), cx);
8306            assert!(editor.context_menu.is_none());
8307            editor.handle_input(&Input("s".to_string()), cx);
8308            assert!(editor.context_menu.is_none());
8309        });
8310
8311        handle_completion_request(
8312            &mut fake,
8313            "/file",
8314            Point::new(2, 7),
8315            vec![
8316                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
8317                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
8318                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
8319            ],
8320        )
8321        .await;
8322        editor
8323            .condition(&cx, |editor, _| editor.context_menu_visible())
8324            .await;
8325
8326        editor.update(cx, |editor, cx| {
8327            editor.handle_input(&Input("i".to_string()), cx);
8328        });
8329
8330        handle_completion_request(
8331            &mut fake,
8332            "/file",
8333            Point::new(2, 8),
8334            vec![
8335                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
8336                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
8337                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
8338            ],
8339        )
8340        .await;
8341        editor
8342            .condition(&cx, |editor, _| editor.context_menu_visible())
8343            .await;
8344
8345        let apply_additional_edits = editor.update(cx, |editor, cx| {
8346            let apply_additional_edits = editor
8347                .confirm_completion(&ConfirmCompletion(None), cx)
8348                .unwrap();
8349            assert_eq!(
8350                editor.text(cx),
8351                "
8352                    one.second_completion
8353                    two sixth_completion
8354                    three sixth_completion
8355                    additional edit
8356                "
8357                .unindent()
8358            );
8359            apply_additional_edits
8360        });
8361        handle_resolve_completion_request(&mut fake, None).await;
8362        apply_additional_edits.await.unwrap();
8363
8364        async fn handle_completion_request(
8365            fake: &mut FakeLanguageServer,
8366            path: &'static str,
8367            position: Point,
8368            completions: Vec<(Range<Point>, &'static str)>,
8369        ) {
8370            fake.handle_request::<lsp::request::Completion, _>(move |params, _| {
8371                assert_eq!(
8372                    params.text_document_position.text_document.uri,
8373                    lsp::Url::from_file_path(path).unwrap()
8374                );
8375                assert_eq!(
8376                    params.text_document_position.position,
8377                    lsp::Position::new(position.row, position.column)
8378                );
8379                Some(lsp::CompletionResponse::Array(
8380                    completions
8381                        .iter()
8382                        .map(|(range, new_text)| lsp::CompletionItem {
8383                            label: new_text.to_string(),
8384                            text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
8385                                range: lsp::Range::new(
8386                                    lsp::Position::new(range.start.row, range.start.column),
8387                                    lsp::Position::new(range.start.row, range.start.column),
8388                                ),
8389                                new_text: new_text.to_string(),
8390                            })),
8391                            ..Default::default()
8392                        })
8393                        .collect(),
8394                ))
8395            })
8396            .next()
8397            .await;
8398        }
8399
8400        async fn handle_resolve_completion_request(
8401            fake: &mut FakeLanguageServer,
8402            edit: Option<(Range<Point>, &'static str)>,
8403        ) {
8404            fake.handle_request::<lsp::request::ResolveCompletionItem, _>(move |_, _| {
8405                lsp::CompletionItem {
8406                    additional_text_edits: edit.clone().map(|(range, new_text)| {
8407                        vec![lsp::TextEdit::new(
8408                            lsp::Range::new(
8409                                lsp::Position::new(range.start.row, range.start.column),
8410                                lsp::Position::new(range.end.row, range.end.column),
8411                            ),
8412                            new_text.to_string(),
8413                        )]
8414                    }),
8415                    ..Default::default()
8416                }
8417            })
8418            .next()
8419            .await;
8420        }
8421    }
8422
8423    #[gpui::test]
8424    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
8425        let settings = cx.read(Settings::test);
8426        let language = Arc::new(Language::new(
8427            LanguageConfig {
8428                line_comment: Some("// ".to_string()),
8429                ..Default::default()
8430            },
8431            Some(tree_sitter_rust::language()),
8432        ));
8433
8434        let text = "
8435            fn a() {
8436                //b();
8437                // c();
8438                //  d();
8439            }
8440        "
8441        .unindent();
8442
8443        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8444        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8445        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
8446
8447        view.update(cx, |editor, cx| {
8448            // If multiple selections intersect a line, the line is only
8449            // toggled once.
8450            editor.select_display_ranges(
8451                &[
8452                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
8453                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
8454                ],
8455                cx,
8456            );
8457            editor.toggle_comments(&ToggleComments, cx);
8458            assert_eq!(
8459                editor.text(cx),
8460                "
8461                    fn a() {
8462                        b();
8463                        c();
8464                         d();
8465                    }
8466                "
8467                .unindent()
8468            );
8469
8470            // The comment prefix is inserted at the same column for every line
8471            // in a selection.
8472            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
8473            editor.toggle_comments(&ToggleComments, cx);
8474            assert_eq!(
8475                editor.text(cx),
8476                "
8477                    fn a() {
8478                        // b();
8479                        // c();
8480                        //  d();
8481                    }
8482                "
8483                .unindent()
8484            );
8485
8486            // If a selection ends at the beginning of a line, that line is not toggled.
8487            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
8488            editor.toggle_comments(&ToggleComments, cx);
8489            assert_eq!(
8490                editor.text(cx),
8491                "
8492                        fn a() {
8493                            // b();
8494                            c();
8495                            //  d();
8496                        }
8497                    "
8498                .unindent()
8499            );
8500        });
8501    }
8502
8503    #[gpui::test]
8504    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
8505        let settings = Settings::test(cx);
8506        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
8507        let multibuffer = cx.add_model(|cx| {
8508            let mut multibuffer = MultiBuffer::new(0);
8509            multibuffer.push_excerpts(
8510                buffer.clone(),
8511                [
8512                    Point::new(0, 0)..Point::new(0, 4),
8513                    Point::new(1, 0)..Point::new(1, 4),
8514                ],
8515                cx,
8516            );
8517            multibuffer
8518        });
8519
8520        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
8521
8522        let (_, view) = cx.add_window(Default::default(), |cx| {
8523            build_editor(multibuffer, settings, cx)
8524        });
8525        view.update(cx, |view, cx| {
8526            assert_eq!(view.text(cx), "aaaa\nbbbb");
8527            view.select_ranges(
8528                [
8529                    Point::new(0, 0)..Point::new(0, 0),
8530                    Point::new(1, 0)..Point::new(1, 0),
8531                ],
8532                None,
8533                cx,
8534            );
8535
8536            view.handle_input(&Input("X".to_string()), cx);
8537            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
8538            assert_eq!(
8539                view.selected_ranges(cx),
8540                [
8541                    Point::new(0, 1)..Point::new(0, 1),
8542                    Point::new(1, 1)..Point::new(1, 1),
8543                ]
8544            )
8545        });
8546    }
8547
8548    #[gpui::test]
8549    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
8550        let settings = Settings::test(cx);
8551        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
8552        let multibuffer = cx.add_model(|cx| {
8553            let mut multibuffer = MultiBuffer::new(0);
8554            multibuffer.push_excerpts(
8555                buffer,
8556                [
8557                    Point::new(0, 0)..Point::new(1, 4),
8558                    Point::new(1, 0)..Point::new(2, 4),
8559                ],
8560                cx,
8561            );
8562            multibuffer
8563        });
8564
8565        assert_eq!(
8566            multibuffer.read(cx).read(cx).text(),
8567            "aaaa\nbbbb\nbbbb\ncccc"
8568        );
8569
8570        let (_, view) = cx.add_window(Default::default(), |cx| {
8571            build_editor(multibuffer, settings, cx)
8572        });
8573        view.update(cx, |view, cx| {
8574            view.select_ranges(
8575                [
8576                    Point::new(1, 1)..Point::new(1, 1),
8577                    Point::new(2, 3)..Point::new(2, 3),
8578                ],
8579                None,
8580                cx,
8581            );
8582
8583            view.handle_input(&Input("X".to_string()), cx);
8584            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
8585            assert_eq!(
8586                view.selected_ranges(cx),
8587                [
8588                    Point::new(1, 2)..Point::new(1, 2),
8589                    Point::new(2, 5)..Point::new(2, 5),
8590                ]
8591            );
8592
8593            view.newline(&Newline, cx);
8594            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
8595            assert_eq!(
8596                view.selected_ranges(cx),
8597                [
8598                    Point::new(2, 0)..Point::new(2, 0),
8599                    Point::new(6, 0)..Point::new(6, 0),
8600                ]
8601            );
8602        });
8603    }
8604
8605    #[gpui::test]
8606    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
8607        let settings = Settings::test(cx);
8608        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
8609        let mut excerpt1_id = None;
8610        let multibuffer = cx.add_model(|cx| {
8611            let mut multibuffer = MultiBuffer::new(0);
8612            excerpt1_id = multibuffer
8613                .push_excerpts(
8614                    buffer.clone(),
8615                    [
8616                        Point::new(0, 0)..Point::new(1, 4),
8617                        Point::new(1, 0)..Point::new(2, 4),
8618                    ],
8619                    cx,
8620                )
8621                .into_iter()
8622                .next();
8623            multibuffer
8624        });
8625        assert_eq!(
8626            multibuffer.read(cx).read(cx).text(),
8627            "aaaa\nbbbb\nbbbb\ncccc"
8628        );
8629        let (_, editor) = cx.add_window(Default::default(), |cx| {
8630            let mut editor = build_editor(multibuffer.clone(), settings, cx);
8631            editor.select_ranges(
8632                [
8633                    Point::new(1, 3)..Point::new(1, 3),
8634                    Point::new(2, 1)..Point::new(2, 1),
8635                ],
8636                None,
8637                cx,
8638            );
8639            editor
8640        });
8641
8642        // Refreshing selections is a no-op when excerpts haven't changed.
8643        editor.update(cx, |editor, cx| {
8644            editor.refresh_selections(cx);
8645            assert_eq!(
8646                editor.selected_ranges(cx),
8647                [
8648                    Point::new(1, 3)..Point::new(1, 3),
8649                    Point::new(2, 1)..Point::new(2, 1),
8650                ]
8651            );
8652        });
8653
8654        multibuffer.update(cx, |multibuffer, cx| {
8655            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
8656        });
8657        editor.update(cx, |editor, cx| {
8658            // Removing an excerpt causes the first selection to become degenerate.
8659            assert_eq!(
8660                editor.selected_ranges(cx),
8661                [
8662                    Point::new(0, 0)..Point::new(0, 0),
8663                    Point::new(0, 1)..Point::new(0, 1)
8664                ]
8665            );
8666
8667            // Refreshing selections will relocate the first selection to the original buffer
8668            // location.
8669            editor.refresh_selections(cx);
8670            assert_eq!(
8671                editor.selected_ranges(cx),
8672                [
8673                    Point::new(0, 1)..Point::new(0, 1),
8674                    Point::new(0, 3)..Point::new(0, 3)
8675                ]
8676            );
8677        });
8678    }
8679
8680    #[gpui::test]
8681    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
8682        let settings = cx.read(Settings::test);
8683        let language = Arc::new(Language::new(
8684            LanguageConfig {
8685                brackets: vec![
8686                    BracketPair {
8687                        start: "{".to_string(),
8688                        end: "}".to_string(),
8689                        close: true,
8690                        newline: true,
8691                    },
8692                    BracketPair {
8693                        start: "/* ".to_string(),
8694                        end: " */".to_string(),
8695                        close: true,
8696                        newline: true,
8697                    },
8698                ],
8699                ..Default::default()
8700            },
8701            Some(tree_sitter_rust::language()),
8702        ));
8703
8704        let text = concat!(
8705            "{   }\n",     // Suppress rustfmt
8706            "  x\n",       //
8707            "  /*   */\n", //
8708            "x\n",         //
8709            "{{} }\n",     //
8710        );
8711
8712        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8713        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8714        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
8715        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8716            .await;
8717
8718        view.update(cx, |view, cx| {
8719            view.select_display_ranges(
8720                &[
8721                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
8722                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
8723                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
8724                ],
8725                cx,
8726            );
8727            view.newline(&Newline, cx);
8728
8729            assert_eq!(
8730                view.buffer().read(cx).read(cx).text(),
8731                concat!(
8732                    "{ \n",    // Suppress rustfmt
8733                    "\n",      //
8734                    "}\n",     //
8735                    "  x\n",   //
8736                    "  /* \n", //
8737                    "  \n",    //
8738                    "  */\n",  //
8739                    "x\n",     //
8740                    "{{} \n",  //
8741                    "}\n",     //
8742                )
8743            );
8744        });
8745    }
8746
8747    #[gpui::test]
8748    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
8749        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
8750        let settings = Settings::test(&cx);
8751        let (_, editor) = cx.add_window(Default::default(), |cx| {
8752            build_editor(buffer.clone(), settings, cx)
8753        });
8754
8755        editor.update(cx, |editor, cx| {
8756            struct Type1;
8757            struct Type2;
8758
8759            let buffer = buffer.read(cx).snapshot(cx);
8760
8761            let anchor_range = |range: Range<Point>| {
8762                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
8763            };
8764
8765            editor.highlight_ranges::<Type1>(
8766                vec![
8767                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
8768                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
8769                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
8770                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
8771                ],
8772                Color::red(),
8773                cx,
8774            );
8775            editor.highlight_ranges::<Type2>(
8776                vec![
8777                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
8778                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
8779                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
8780                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
8781                ],
8782                Color::green(),
8783                cx,
8784            );
8785
8786            let snapshot = editor.snapshot(cx);
8787            let mut highlighted_ranges = editor.highlighted_ranges_in_range(
8788                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
8789                &snapshot,
8790            );
8791            // Enforce a consistent ordering based on color without relying on the ordering of the
8792            // highlight's `TypeId` which is non-deterministic.
8793            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
8794            assert_eq!(
8795                highlighted_ranges,
8796                &[
8797                    (
8798                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
8799                        Color::green(),
8800                    ),
8801                    (
8802                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
8803                        Color::green(),
8804                    ),
8805                    (
8806                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
8807                        Color::red(),
8808                    ),
8809                    (
8810                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
8811                        Color::red(),
8812                    ),
8813                ]
8814            );
8815            assert_eq!(
8816                editor.highlighted_ranges_in_range(
8817                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
8818                    &snapshot,
8819                ),
8820                &[(
8821                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
8822                    Color::red(),
8823                )]
8824            );
8825        });
8826    }
8827
8828    #[test]
8829    fn test_combine_syntax_and_fuzzy_match_highlights() {
8830        let string = "abcdefghijklmnop";
8831        let default = HighlightStyle::default();
8832        let syntax_ranges = [
8833            (
8834                0..3,
8835                HighlightStyle {
8836                    color: Color::red(),
8837                    ..default
8838                },
8839            ),
8840            (
8841                4..8,
8842                HighlightStyle {
8843                    color: Color::green(),
8844                    ..default
8845                },
8846            ),
8847        ];
8848        let match_indices = [4, 6, 7, 8];
8849        assert_eq!(
8850            combine_syntax_and_fuzzy_match_highlights(
8851                &string,
8852                default,
8853                syntax_ranges.into_iter(),
8854                &match_indices,
8855            ),
8856            &[
8857                (
8858                    0..3,
8859                    HighlightStyle {
8860                        color: Color::red(),
8861                        ..default
8862                    },
8863                ),
8864                (
8865                    4..5,
8866                    HighlightStyle {
8867                        color: Color::green(),
8868                        font_properties: *fonts::Properties::default().weight(fonts::Weight::BOLD),
8869                        ..default
8870                    },
8871                ),
8872                (
8873                    5..6,
8874                    HighlightStyle {
8875                        color: Color::green(),
8876                        ..default
8877                    },
8878                ),
8879                (
8880                    6..8,
8881                    HighlightStyle {
8882                        color: Color::green(),
8883                        font_properties: *fonts::Properties::default().weight(fonts::Weight::BOLD),
8884                        ..default
8885                    },
8886                ),
8887                (
8888                    8..9,
8889                    HighlightStyle {
8890                        font_properties: *fonts::Properties::default().weight(fonts::Weight::BOLD),
8891                        ..default
8892                    },
8893                ),
8894            ]
8895        );
8896    }
8897
8898    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
8899        let point = DisplayPoint::new(row as u32, column as u32);
8900        point..point
8901    }
8902
8903    fn build_editor(
8904        buffer: ModelHandle<MultiBuffer>,
8905        settings: Settings,
8906        cx: &mut ViewContext<Editor>,
8907    ) -> Editor {
8908        let settings = watch::channel_with(settings);
8909        Editor::new(EditorMode::Full, buffer, None, settings.1, None, cx)
8910    }
8911}
8912
8913trait RangeExt<T> {
8914    fn sorted(&self) -> Range<T>;
8915    fn to_inclusive(&self) -> RangeInclusive<T>;
8916}
8917
8918impl<T: Ord + Clone> RangeExt<T> for Range<T> {
8919    fn sorted(&self) -> Self {
8920        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
8921    }
8922
8923    fn to_inclusive(&self) -> RangeInclusive<T> {
8924        self.start.clone()..=self.end.clone()
8925    }
8926}