editor.rs

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