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