editor.rs

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