editor.rs

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