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