editor.rs

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