editor.rs

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