editor.rs

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