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