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;
  12pub use display_map::DisplayPoint;
  13use display_map::*;
  14pub use element::*;
  15use gpui::{
  16    action,
  17    elements::Text,
  18    geometry::vector::{vec2f, Vector2F},
  19    keymap::Binding,
  20    text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
  21    MutableAppContext, RenderContext, View, ViewContext, WeakViewHandle,
  22};
  23use items::BufferItemHandle;
  24use language::{
  25    BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point, Selection, SelectionGoal,
  26    SelectionSetId,
  27};
  28use multi_buffer::{
  29    Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot,
  30    SelectionSet, ToOffset, ToPoint,
  31};
  32pub use multi_buffer::MultiBuffer;
  33use serde::{Deserialize, Serialize};
  34use smallvec::SmallVec;
  35use smol::Timer;
  36use std::{
  37    cell::RefCell,
  38    cmp,
  39    collections::HashMap,
  40    iter, mem,
  41    ops::{Deref, Range, RangeInclusive, Sub},
  42    rc::Rc,
  43    sync::Arc,
  44    time::Duration,
  45};
  46use sum_tree::Bias;
  47use text::rope::TextDimension;
  48use theme::{DiagnosticStyle, EditorStyle};
  49use util::post_inc;
  50use workspace::{EntryOpener, Workspace};
  51
  52const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  53const MAX_LINE_LEN: usize = 1024;
  54
  55action!(Cancel);
  56action!(Backspace);
  57action!(Delete);
  58action!(Input, String);
  59action!(Newline);
  60action!(Tab);
  61action!(Outdent);
  62action!(DeleteLine);
  63action!(DeleteToPreviousWordBoundary);
  64action!(DeleteToNextWordBoundary);
  65action!(DeleteToBeginningOfLine);
  66action!(DeleteToEndOfLine);
  67action!(CutToEndOfLine);
  68action!(DuplicateLine);
  69action!(MoveLineUp);
  70action!(MoveLineDown);
  71action!(Cut);
  72action!(Copy);
  73action!(Paste);
  74action!(Undo);
  75action!(Redo);
  76action!(MoveUp);
  77action!(MoveDown);
  78action!(MoveLeft);
  79action!(MoveRight);
  80action!(MoveToPreviousWordBoundary);
  81action!(MoveToNextWordBoundary);
  82action!(MoveToBeginningOfLine);
  83action!(MoveToEndOfLine);
  84action!(MoveToBeginning);
  85action!(MoveToEnd);
  86action!(SelectUp);
  87action!(SelectDown);
  88action!(SelectLeft);
  89action!(SelectRight);
  90action!(SelectToPreviousWordBoundary);
  91action!(SelectToNextWordBoundary);
  92action!(SelectToBeginningOfLine, bool);
  93action!(SelectToEndOfLine);
  94action!(SelectToBeginning);
  95action!(SelectToEnd);
  96action!(SelectAll);
  97action!(SelectLine);
  98action!(SplitSelectionIntoLines);
  99action!(AddSelectionAbove);
 100action!(AddSelectionBelow);
 101action!(SelectNext, bool);
 102action!(ToggleComments);
 103action!(SelectLargerSyntaxNode);
 104action!(SelectSmallerSyntaxNode);
 105action!(MoveToEnclosingBracket);
 106action!(ShowNextDiagnostic);
 107action!(PageUp);
 108action!(PageDown);
 109action!(Fold);
 110action!(Unfold);
 111action!(FoldSelectedRanges);
 112action!(Scroll, Vector2F);
 113action!(Select, SelectPhase);
 114
 115pub fn init(cx: &mut MutableAppContext, entry_openers: &mut Vec<Box<dyn EntryOpener>>) {
 116    entry_openers.push(Box::new(items::BufferOpener));
 117    cx.add_bindings(vec![
 118        Binding::new("escape", Cancel, Some("Editor")),
 119        Binding::new("backspace", Backspace, Some("Editor")),
 120        Binding::new("ctrl-h", Backspace, Some("Editor")),
 121        Binding::new("delete", Delete, Some("Editor")),
 122        Binding::new("ctrl-d", Delete, Some("Editor")),
 123        Binding::new("enter", Newline, Some("Editor && mode == full")),
 124        Binding::new(
 125            "alt-enter",
 126            Input("\n".into()),
 127            Some("Editor && mode == auto_height"),
 128        ),
 129        Binding::new("tab", Tab, Some("Editor")),
 130        Binding::new("shift-tab", Outdent, Some("Editor")),
 131        Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")),
 132        Binding::new(
 133            "alt-backspace",
 134            DeleteToPreviousWordBoundary,
 135            Some("Editor"),
 136        ),
 137        Binding::new("alt-h", DeleteToPreviousWordBoundary, Some("Editor")),
 138        Binding::new("alt-delete", DeleteToNextWordBoundary, Some("Editor")),
 139        Binding::new("alt-d", DeleteToNextWordBoundary, Some("Editor")),
 140        Binding::new("cmd-backspace", DeleteToBeginningOfLine, Some("Editor")),
 141        Binding::new("cmd-delete", DeleteToEndOfLine, Some("Editor")),
 142        Binding::new("ctrl-k", CutToEndOfLine, Some("Editor")),
 143        Binding::new("cmd-shift-D", DuplicateLine, Some("Editor")),
 144        Binding::new("ctrl-cmd-up", MoveLineUp, Some("Editor")),
 145        Binding::new("ctrl-cmd-down", MoveLineDown, Some("Editor")),
 146        Binding::new("cmd-x", Cut, Some("Editor")),
 147        Binding::new("cmd-c", Copy, Some("Editor")),
 148        Binding::new("cmd-v", Paste, Some("Editor")),
 149        Binding::new("cmd-z", Undo, Some("Editor")),
 150        Binding::new("cmd-shift-Z", Redo, Some("Editor")),
 151        Binding::new("up", MoveUp, Some("Editor")),
 152        Binding::new("down", MoveDown, Some("Editor")),
 153        Binding::new("left", MoveLeft, Some("Editor")),
 154        Binding::new("right", MoveRight, Some("Editor")),
 155        Binding::new("ctrl-p", MoveUp, Some("Editor")),
 156        Binding::new("ctrl-n", MoveDown, Some("Editor")),
 157        Binding::new("ctrl-b", MoveLeft, Some("Editor")),
 158        Binding::new("ctrl-f", MoveRight, Some("Editor")),
 159        Binding::new("alt-left", MoveToPreviousWordBoundary, Some("Editor")),
 160        Binding::new("alt-b", MoveToPreviousWordBoundary, Some("Editor")),
 161        Binding::new("alt-right", MoveToNextWordBoundary, Some("Editor")),
 162        Binding::new("alt-f", MoveToNextWordBoundary, Some("Editor")),
 163        Binding::new("cmd-left", MoveToBeginningOfLine, Some("Editor")),
 164        Binding::new("ctrl-a", MoveToBeginningOfLine, Some("Editor")),
 165        Binding::new("cmd-right", MoveToEndOfLine, Some("Editor")),
 166        Binding::new("ctrl-e", MoveToEndOfLine, Some("Editor")),
 167        Binding::new("cmd-up", MoveToBeginning, Some("Editor")),
 168        Binding::new("cmd-down", MoveToEnd, Some("Editor")),
 169        Binding::new("shift-up", SelectUp, Some("Editor")),
 170        Binding::new("ctrl-shift-P", SelectUp, Some("Editor")),
 171        Binding::new("shift-down", SelectDown, Some("Editor")),
 172        Binding::new("ctrl-shift-N", SelectDown, Some("Editor")),
 173        Binding::new("shift-left", SelectLeft, Some("Editor")),
 174        Binding::new("ctrl-shift-B", SelectLeft, Some("Editor")),
 175        Binding::new("shift-right", SelectRight, Some("Editor")),
 176        Binding::new("ctrl-shift-F", SelectRight, Some("Editor")),
 177        Binding::new(
 178            "alt-shift-left",
 179            SelectToPreviousWordBoundary,
 180            Some("Editor"),
 181        ),
 182        Binding::new("alt-shift-B", SelectToPreviousWordBoundary, Some("Editor")),
 183        Binding::new("alt-shift-right", SelectToNextWordBoundary, Some("Editor")),
 184        Binding::new("alt-shift-F", SelectToNextWordBoundary, Some("Editor")),
 185        Binding::new(
 186            "cmd-shift-left",
 187            SelectToBeginningOfLine(true),
 188            Some("Editor"),
 189        ),
 190        Binding::new(
 191            "ctrl-shift-A",
 192            SelectToBeginningOfLine(true),
 193            Some("Editor"),
 194        ),
 195        Binding::new("cmd-shift-right", SelectToEndOfLine, Some("Editor")),
 196        Binding::new("ctrl-shift-E", SelectToEndOfLine, Some("Editor")),
 197        Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")),
 198        Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")),
 199        Binding::new("cmd-a", SelectAll, Some("Editor")),
 200        Binding::new("cmd-l", SelectLine, Some("Editor")),
 201        Binding::new("cmd-shift-L", SplitSelectionIntoLines, Some("Editor")),
 202        Binding::new("cmd-alt-up", AddSelectionAbove, Some("Editor")),
 203        Binding::new("cmd-ctrl-p", AddSelectionAbove, Some("Editor")),
 204        Binding::new("cmd-alt-down", AddSelectionBelow, Some("Editor")),
 205        Binding::new("cmd-ctrl-n", AddSelectionBelow, Some("Editor")),
 206        Binding::new("cmd-d", SelectNext(false), Some("Editor")),
 207        Binding::new("cmd-k cmd-d", SelectNext(true), Some("Editor")),
 208        Binding::new("cmd-/", ToggleComments, Some("Editor")),
 209        Binding::new("alt-up", SelectLargerSyntaxNode, Some("Editor")),
 210        Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")),
 211        Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")),
 212        Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")),
 213        Binding::new("f8", ShowNextDiagnostic, Some("Editor")),
 214        Binding::new("ctrl-m", MoveToEnclosingBracket, Some("Editor")),
 215        Binding::new("pageup", PageUp, Some("Editor")),
 216        Binding::new("pagedown", PageDown, Some("Editor")),
 217        Binding::new("alt-cmd-[", Fold, Some("Editor")),
 218        Binding::new("alt-cmd-]", Unfold, Some("Editor")),
 219        Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")),
 220    ]);
 221
 222    cx.add_action(Editor::open_new);
 223    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
 224    cx.add_action(Editor::select);
 225    cx.add_action(Editor::cancel);
 226    cx.add_action(Editor::handle_input);
 227    cx.add_action(Editor::newline);
 228    cx.add_action(Editor::backspace);
 229    cx.add_action(Editor::delete);
 230    cx.add_action(Editor::tab);
 231    cx.add_action(Editor::outdent);
 232    cx.add_action(Editor::delete_line);
 233    cx.add_action(Editor::delete_to_previous_word_boundary);
 234    cx.add_action(Editor::delete_to_next_word_boundary);
 235    cx.add_action(Editor::delete_to_beginning_of_line);
 236    cx.add_action(Editor::delete_to_end_of_line);
 237    cx.add_action(Editor::cut_to_end_of_line);
 238    cx.add_action(Editor::duplicate_line);
 239    cx.add_action(Editor::move_line_up);
 240    cx.add_action(Editor::move_line_down);
 241    cx.add_action(Editor::cut);
 242    cx.add_action(Editor::copy);
 243    cx.add_action(Editor::paste);
 244    cx.add_action(Editor::undo);
 245    cx.add_action(Editor::redo);
 246    cx.add_action(Editor::move_up);
 247    cx.add_action(Editor::move_down);
 248    cx.add_action(Editor::move_left);
 249    cx.add_action(Editor::move_right);
 250    cx.add_action(Editor::move_to_previous_word_boundary);
 251    cx.add_action(Editor::move_to_next_word_boundary);
 252    cx.add_action(Editor::move_to_beginning_of_line);
 253    cx.add_action(Editor::move_to_end_of_line);
 254    cx.add_action(Editor::move_to_beginning);
 255    cx.add_action(Editor::move_to_end);
 256    cx.add_action(Editor::select_up);
 257    cx.add_action(Editor::select_down);
 258    cx.add_action(Editor::select_left);
 259    cx.add_action(Editor::select_right);
 260    cx.add_action(Editor::select_to_previous_word_boundary);
 261    cx.add_action(Editor::select_to_next_word_boundary);
 262    cx.add_action(Editor::select_to_beginning_of_line);
 263    cx.add_action(Editor::select_to_end_of_line);
 264    cx.add_action(Editor::select_to_beginning);
 265    cx.add_action(Editor::select_to_end);
 266    cx.add_action(Editor::select_all);
 267    cx.add_action(Editor::select_line);
 268    cx.add_action(Editor::split_selection_into_lines);
 269    cx.add_action(Editor::add_selection_above);
 270    cx.add_action(Editor::add_selection_below);
 271    cx.add_action(Editor::select_next);
 272    cx.add_action(Editor::toggle_comments);
 273    cx.add_action(Editor::select_larger_syntax_node);
 274    cx.add_action(Editor::select_smaller_syntax_node);
 275    cx.add_action(Editor::move_to_enclosing_bracket);
 276    cx.add_action(Editor::show_next_diagnostic);
 277    cx.add_action(Editor::page_up);
 278    cx.add_action(Editor::page_down);
 279    cx.add_action(Editor::fold);
 280    cx.add_action(Editor::unfold);
 281    cx.add_action(Editor::fold_selected_ranges);
 282}
 283
 284trait SelectionExt {
 285    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 286    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 287    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 288    fn spanned_rows(
 289        &self,
 290        include_end_if_at_line_start: bool,
 291        map: &DisplaySnapshot,
 292    ) -> SpannedRows;
 293}
 294
 295struct SpannedRows {
 296    buffer_rows: Range<u32>,
 297    display_rows: Range<u32>,
 298}
 299
 300#[derive(Clone, Debug)]
 301pub enum SelectPhase {
 302    Begin {
 303        position: DisplayPoint,
 304        add: bool,
 305        click_count: usize,
 306    },
 307    BeginColumnar {
 308        position: DisplayPoint,
 309        overshoot: u32,
 310    },
 311    Extend {
 312        position: DisplayPoint,
 313        click_count: usize,
 314    },
 315    Update {
 316        position: DisplayPoint,
 317        overshoot: u32,
 318        scroll_position: Vector2F,
 319    },
 320    End,
 321}
 322
 323#[derive(Clone, Debug)]
 324enum SelectMode {
 325    Character,
 326    Word(Range<Anchor>),
 327    Line(Range<Anchor>),
 328    All,
 329}
 330
 331#[derive(PartialEq, Eq)]
 332pub enum Autoscroll {
 333    Fit,
 334    Center,
 335    Newest,
 336}
 337
 338#[derive(Copy, Clone, PartialEq, Eq)]
 339pub enum EditorMode {
 340    SingleLine,
 341    AutoHeight { max_lines: usize },
 342    Full,
 343}
 344
 345#[derive(Clone)]
 346pub struct EditorSettings {
 347    pub tab_size: usize,
 348    pub soft_wrap: SoftWrap,
 349    pub style: EditorStyle,
 350}
 351
 352#[derive(Clone)]
 353pub enum SoftWrap {
 354    None,
 355    EditorWidth,
 356    Column(u32),
 357}
 358
 359pub struct Editor {
 360    handle: WeakViewHandle<Self>,
 361    buffer: ModelHandle<MultiBuffer>,
 362    display_map: ModelHandle<DisplayMap>,
 363    selection_set_id: SelectionSetId,
 364    pending_selection: Option<PendingSelection>,
 365    columnar_selection_tail: Option<Anchor>,
 366    next_selection_id: usize,
 367    add_selections_state: Option<AddSelectionsState>,
 368    select_next_state: Option<SelectNextState>,
 369    autoclose_stack: Vec<BracketPairState>,
 370    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 371    active_diagnostics: Option<ActiveDiagnosticGroup>,
 372    scroll_position: Vector2F,
 373    scroll_top_anchor: Anchor,
 374    autoscroll_request: Option<Autoscroll>,
 375    build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
 376    focused: bool,
 377    show_local_cursors: bool,
 378    blink_epoch: usize,
 379    blinking_paused: bool,
 380    mode: EditorMode,
 381    placeholder_text: Option<Arc<str>>,
 382    highlighted_row: Option<u32>,
 383}
 384
 385pub struct EditorSnapshot {
 386    pub mode: EditorMode,
 387    pub display_snapshot: DisplaySnapshot,
 388    pub placeholder_text: Option<Arc<str>>,
 389    is_focused: bool,
 390    scroll_position: Vector2F,
 391    scroll_top_anchor: Anchor,
 392}
 393
 394struct PendingSelection {
 395    selection: Selection<Anchor>,
 396    mode: SelectMode,
 397}
 398
 399struct AddSelectionsState {
 400    above: bool,
 401    stack: Vec<usize>,
 402}
 403
 404struct SelectNextState {
 405    query: AhoCorasick,
 406    wordwise: bool,
 407    done: bool,
 408}
 409
 410#[derive(Debug)]
 411struct BracketPairState {
 412    ranges: Vec<Range<Anchor>>,
 413    pair: BracketPair,
 414}
 415
 416#[derive(Debug)]
 417struct ActiveDiagnosticGroup {
 418    primary_range: Range<Anchor>,
 419    primary_message: String,
 420    blocks: HashMap<BlockId, Diagnostic>,
 421    is_valid: bool,
 422}
 423
 424#[derive(Serialize, Deserialize)]
 425struct ClipboardSelection {
 426    len: usize,
 427    is_entire_line: bool,
 428}
 429
 430impl Editor {
 431    pub fn single_line(
 432        build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
 433        cx: &mut ViewContext<Self>,
 434    ) -> Self {
 435        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 436        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 437        let mut view = Self::for_buffer(buffer, build_settings, cx);
 438        view.mode = EditorMode::SingleLine;
 439        view
 440    }
 441
 442    pub fn auto_height(
 443        max_lines: usize,
 444        build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
 445        cx: &mut ViewContext<Self>,
 446    ) -> Self {
 447        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 448        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 449        let mut view = Self::for_buffer(buffer, build_settings, cx);
 450        view.mode = EditorMode::AutoHeight { max_lines };
 451        view
 452    }
 453
 454    pub fn for_buffer(
 455        buffer: ModelHandle<MultiBuffer>,
 456        build_settings: impl 'static + Fn(&AppContext) -> EditorSettings,
 457        cx: &mut ViewContext<Self>,
 458    ) -> Self {
 459        Self::new(buffer, Rc::new(RefCell::new(build_settings)), cx)
 460    }
 461
 462    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 463        let mut clone = Self::new(self.buffer.clone(), self.build_settings.clone(), cx);
 464        clone.scroll_position = self.scroll_position;
 465        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
 466        clone
 467    }
 468
 469    pub fn new(
 470        buffer: ModelHandle<MultiBuffer>,
 471        build_settings: Rc<RefCell<dyn Fn(&AppContext) -> EditorSettings>>,
 472        cx: &mut ViewContext<Self>,
 473    ) -> Self {
 474        let settings = build_settings.borrow_mut()(cx);
 475        let display_map = cx.add_model(|cx| {
 476            DisplayMap::new(
 477                buffer.clone(),
 478                settings.tab_size,
 479                settings.style.text.font_id,
 480                settings.style.text.font_size,
 481                None,
 482                cx,
 483            )
 484        });
 485        cx.observe(&buffer, Self::on_buffer_changed).detach();
 486        cx.subscribe(&buffer, Self::on_buffer_event).detach();
 487        cx.observe(&display_map, Self::on_display_map_changed)
 488            .detach();
 489
 490        let mut next_selection_id = 0;
 491        let selection_set_id = buffer.update(cx, |buffer, cx| {
 492            buffer.add_selection_set(
 493                &[Selection {
 494                    id: post_inc(&mut next_selection_id),
 495                    start: 0,
 496                    end: 0,
 497                    reversed: false,
 498                    goal: SelectionGoal::None,
 499                }],
 500                cx,
 501            )
 502        });
 503        Self {
 504            handle: cx.weak_handle(),
 505            buffer,
 506            display_map,
 507            selection_set_id,
 508            pending_selection: None,
 509            columnar_selection_tail: None,
 510            next_selection_id,
 511            add_selections_state: None,
 512            select_next_state: None,
 513            autoclose_stack: Default::default(),
 514            select_larger_syntax_node_stack: Vec::new(),
 515            active_diagnostics: None,
 516            build_settings,
 517            scroll_position: Vector2F::zero(),
 518            scroll_top_anchor: Anchor::min(),
 519            autoscroll_request: None,
 520            focused: false,
 521            show_local_cursors: false,
 522            blink_epoch: 0,
 523            blinking_paused: false,
 524            mode: EditorMode::Full,
 525            placeholder_text: None,
 526            highlighted_row: None,
 527        }
 528    }
 529
 530    pub fn open_new(
 531        workspace: &mut Workspace,
 532        _: &workspace::OpenNew,
 533        cx: &mut ViewContext<Workspace>,
 534    ) {
 535        let buffer = cx.add_model(|cx| {
 536            Buffer::new(0, "", cx).with_language(Some(language::PLAIN_TEXT.clone()), None, cx)
 537        });
 538        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 539        workspace.add_item(BufferItemHandle(buffer), cx);
 540    }
 541
 542    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 543        self.buffer.read(cx).replica_id()
 544    }
 545
 546    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
 547        &self.buffer
 548    }
 549
 550    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
 551        EditorSnapshot {
 552            mode: self.mode,
 553            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 554            scroll_position: self.scroll_position,
 555            scroll_top_anchor: self.scroll_top_anchor.clone(),
 556            placeholder_text: self.placeholder_text.clone(),
 557            is_focused: self
 558                .handle
 559                .upgrade(cx)
 560                .map_or(false, |handle| handle.is_focused(cx)),
 561        }
 562    }
 563
 564    pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
 565        self.buffer.read(cx).language(cx)
 566    }
 567
 568    pub fn set_placeholder_text(
 569        &mut self,
 570        placeholder_text: impl Into<Arc<str>>,
 571        cx: &mut ViewContext<Self>,
 572    ) {
 573        self.placeholder_text = Some(placeholder_text.into());
 574        cx.notify();
 575    }
 576
 577    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
 578        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 579        let scroll_top_buffer_offset =
 580            DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
 581        self.scroll_top_anchor = map
 582            .buffer_snapshot
 583            .anchor_at(scroll_top_buffer_offset, Bias::Right);
 584        self.scroll_position = vec2f(
 585            scroll_position.x(),
 586            scroll_position.y() - self.scroll_top_anchor.to_display_point(&map).row() as f32,
 587        );
 588
 589        debug_assert_eq!(
 590            compute_scroll_position(&map, self.scroll_position, &self.scroll_top_anchor),
 591            scroll_position
 592        );
 593
 594        cx.notify();
 595    }
 596
 597    pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
 598        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 599        compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
 600    }
 601
 602    pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
 603        if max < self.scroll_position.x() {
 604            self.scroll_position.set_x(max);
 605            true
 606        } else {
 607            false
 608        }
 609    }
 610
 611    pub fn autoscroll_vertically(
 612        &mut self,
 613        viewport_height: f32,
 614        line_height: f32,
 615        cx: &mut ViewContext<Self>,
 616    ) -> bool {
 617        let visible_lines = viewport_height / line_height;
 618        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 619        let mut scroll_position =
 620            compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
 621        let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 622            (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
 623        } else {
 624            display_map.max_point().row().saturating_sub(1) as f32
 625        };
 626        if scroll_position.y() > max_scroll_top {
 627            scroll_position.set_y(max_scroll_top);
 628            self.set_scroll_position(scroll_position, cx);
 629        }
 630
 631        let autoscroll = if let Some(autoscroll) = self.autoscroll_request.take() {
 632            autoscroll
 633        } else {
 634            return false;
 635        };
 636
 637        let first_cursor_top;
 638        let last_cursor_bottom;
 639        if autoscroll == Autoscroll::Newest {
 640            let newest_selection = self.newest_selection::<Point>(cx);
 641            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
 642            last_cursor_bottom = first_cursor_top + 1.;
 643        } else {
 644            let selections = self.selections::<Point>(cx);
 645            first_cursor_top = selections
 646                .first()
 647                .unwrap()
 648                .head()
 649                .to_display_point(&display_map)
 650                .row() as f32;
 651            last_cursor_bottom = selections
 652                .last()
 653                .unwrap()
 654                .head()
 655                .to_display_point(&display_map)
 656                .row() as f32
 657                + 1.0;
 658        }
 659
 660        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 661            0.
 662        } else {
 663            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
 664        };
 665        if margin < 0.0 {
 666            return false;
 667        }
 668
 669        match autoscroll {
 670            Autoscroll::Fit | Autoscroll::Newest => {
 671                let margin = margin.min(3.0);
 672                let target_top = (first_cursor_top - margin).max(0.0);
 673                let target_bottom = last_cursor_bottom + margin;
 674                let start_row = scroll_position.y();
 675                let end_row = start_row + visible_lines;
 676
 677                if target_top < start_row {
 678                    scroll_position.set_y(target_top);
 679                    self.set_scroll_position(scroll_position, cx);
 680                } else if target_bottom >= end_row {
 681                    scroll_position.set_y(target_bottom - visible_lines);
 682                    self.set_scroll_position(scroll_position, cx);
 683                }
 684            }
 685            Autoscroll::Center => {
 686                scroll_position.set_y((first_cursor_top - margin).max(0.0));
 687                self.set_scroll_position(scroll_position, cx);
 688            }
 689        }
 690
 691        true
 692    }
 693
 694    pub fn autoscroll_horizontally(
 695        &mut self,
 696        start_row: u32,
 697        viewport_width: f32,
 698        scroll_width: f32,
 699        max_glyph_width: f32,
 700        layouts: &[text_layout::Line],
 701        cx: &mut ViewContext<Self>,
 702    ) -> bool {
 703        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 704        let selections = self.selections::<Point>(cx);
 705        let mut target_left = std::f32::INFINITY;
 706        let mut target_right = 0.0_f32;
 707        for selection in selections {
 708            let head = selection.head().to_display_point(&display_map);
 709            if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
 710                let start_column = head.column().saturating_sub(3);
 711                let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
 712                target_left = target_left.min(
 713                    layouts[(head.row() - start_row) as usize].x_for_index(start_column as usize),
 714                );
 715                target_right = target_right.max(
 716                    layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 717                        + max_glyph_width,
 718                );
 719            }
 720        }
 721        target_right = target_right.min(scroll_width);
 722
 723        if target_right - target_left > viewport_width {
 724            return false;
 725        }
 726
 727        let scroll_left = self.scroll_position.x() * max_glyph_width;
 728        let scroll_right = scroll_left + viewport_width;
 729
 730        if target_left < scroll_left {
 731            self.scroll_position.set_x(target_left / max_glyph_width);
 732            true
 733        } else if target_right > scroll_right {
 734            self.scroll_position
 735                .set_x((target_right - viewport_width) / max_glyph_width);
 736            true
 737        } else {
 738            false
 739        }
 740    }
 741
 742    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
 743        match phase {
 744            SelectPhase::Begin {
 745                position,
 746                add,
 747                click_count,
 748            } => self.begin_selection(*position, *add, *click_count, cx),
 749            SelectPhase::BeginColumnar {
 750                position,
 751                overshoot,
 752            } => self.begin_columnar_selection(*position, *overshoot, cx),
 753            SelectPhase::Extend {
 754                position,
 755                click_count,
 756            } => self.extend_selection(*position, *click_count, cx),
 757            SelectPhase::Update {
 758                position,
 759                overshoot,
 760                scroll_position,
 761            } => self.update_selection(*position, *overshoot, *scroll_position, cx),
 762            SelectPhase::End => self.end_selection(cx),
 763        }
 764    }
 765
 766    fn extend_selection(
 767        &mut self,
 768        position: DisplayPoint,
 769        click_count: usize,
 770        cx: &mut ViewContext<Self>,
 771    ) {
 772        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 773        let tail = self.newest_selection::<usize>(cx).tail();
 774        self.begin_selection(position, false, click_count, cx);
 775
 776        let position = position.to_offset(&display_map, Bias::Left);
 777        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 778        let pending = self.pending_selection.as_mut().unwrap();
 779
 780        if position >= tail {
 781            pending.selection.start = tail_anchor.clone();
 782        } else {
 783            pending.selection.end = tail_anchor.clone();
 784            pending.selection.reversed = true;
 785        }
 786
 787        match &mut pending.mode {
 788            SelectMode::Word(range) | SelectMode::Line(range) => {
 789                *range = tail_anchor.clone()..tail_anchor
 790            }
 791            _ => {}
 792        }
 793    }
 794
 795    fn begin_selection(
 796        &mut self,
 797        position: DisplayPoint,
 798        add: bool,
 799        click_count: usize,
 800        cx: &mut ViewContext<Self>,
 801    ) {
 802        if !self.focused {
 803            cx.focus_self();
 804            cx.emit(Event::Activate);
 805        }
 806
 807        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 808        let buffer = &display_map.buffer_snapshot;
 809        let start;
 810        let end;
 811        let mode;
 812        match click_count {
 813            1 => {
 814                start = buffer.anchor_before(position.to_point(&display_map));
 815                end = start.clone();
 816                mode = SelectMode::Character;
 817            }
 818            2 => {
 819                let range = movement::surrounding_word(&display_map, position);
 820                start = buffer.anchor_before(range.start.to_point(&display_map));
 821                end = buffer.anchor_before(range.end.to_point(&display_map));
 822                mode = SelectMode::Word(start.clone()..end.clone());
 823            }
 824            3 => {
 825                let position = display_map.clip_point(position, Bias::Left);
 826                let line_start = movement::line_beginning(&display_map, position, false);
 827                let mut next_line_start = line_start.clone();
 828                *next_line_start.row_mut() += 1;
 829                *next_line_start.column_mut() = 0;
 830                next_line_start = display_map.clip_point(next_line_start, Bias::Right);
 831
 832                start = buffer.anchor_before(line_start.to_point(&display_map));
 833                end = buffer.anchor_before(next_line_start.to_point(&display_map));
 834                mode = SelectMode::Line(start.clone()..end.clone());
 835            }
 836            _ => {
 837                start = buffer.anchor_before(0);
 838                end = buffer.anchor_before(buffer.len());
 839                mode = SelectMode::All;
 840            }
 841        }
 842
 843        let selection = Selection {
 844            id: post_inc(&mut self.next_selection_id),
 845            start,
 846            end,
 847            reversed: false,
 848            goal: SelectionGoal::None,
 849        };
 850
 851        if !add {
 852            self.update_selections::<usize>(Vec::new(), None, cx);
 853        } else if click_count > 1 {
 854            // Remove the newest selection since it was only added as part of this multi-click.
 855            let newest_selection = self.newest_selection::<usize>(cx);
 856            let mut selections = self.selections(cx);
 857            selections.retain(|selection| selection.id != newest_selection.id);
 858            self.update_selections::<usize>(selections, None, cx)
 859        }
 860
 861        self.pending_selection = Some(PendingSelection { selection, mode });
 862
 863        cx.notify();
 864    }
 865
 866    fn begin_columnar_selection(
 867        &mut self,
 868        position: DisplayPoint,
 869        overshoot: u32,
 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 tail = self.newest_selection::<Point>(cx).tail();
 879        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 880
 881        self.select_columns(
 882            tail.to_display_point(&display_map),
 883            position,
 884            overshoot,
 885            &display_map,
 886            cx,
 887        );
 888    }
 889
 890    fn update_selection(
 891        &mut self,
 892        position: DisplayPoint,
 893        overshoot: u32,
 894        scroll_position: Vector2F,
 895        cx: &mut ViewContext<Self>,
 896    ) {
 897        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 898
 899        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 900            let tail = tail.to_display_point(&display_map);
 901            self.select_columns(tail, position, overshoot, &display_map, cx);
 902        } else if let Some(PendingSelection { selection, mode }) = self.pending_selection.as_mut() {
 903            let buffer = self.buffer.read(cx).snapshot(cx);
 904            let head;
 905            let tail;
 906            match mode {
 907                SelectMode::Character => {
 908                    head = position.to_point(&display_map);
 909                    tail = selection.tail().to_point(&buffer);
 910                }
 911                SelectMode::Word(original_range) => {
 912                    let original_display_range = original_range.start.to_display_point(&display_map)
 913                        ..original_range.end.to_display_point(&display_map);
 914                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 915                        ..original_display_range.end.to_point(&display_map);
 916                    if movement::is_inside_word(&display_map, position)
 917                        || original_display_range.contains(&position)
 918                    {
 919                        let word_range = movement::surrounding_word(&display_map, position);
 920                        if word_range.start < original_display_range.start {
 921                            head = word_range.start.to_point(&display_map);
 922                        } else {
 923                            head = word_range.end.to_point(&display_map);
 924                        }
 925                    } else {
 926                        head = position.to_point(&display_map);
 927                    }
 928
 929                    if head <= original_buffer_range.start {
 930                        tail = original_buffer_range.end;
 931                    } else {
 932                        tail = original_buffer_range.start;
 933                    }
 934                }
 935                SelectMode::Line(original_range) => {
 936                    let original_display_range = original_range.start.to_display_point(&display_map)
 937                        ..original_range.end.to_display_point(&display_map);
 938                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 939                        ..original_display_range.end.to_point(&display_map);
 940                    let line_start = movement::line_beginning(&display_map, position, false);
 941                    let mut next_line_start = line_start.clone();
 942                    *next_line_start.row_mut() += 1;
 943                    *next_line_start.column_mut() = 0;
 944                    next_line_start = display_map.clip_point(next_line_start, Bias::Right);
 945
 946                    if line_start < original_display_range.start {
 947                        head = line_start.to_point(&display_map);
 948                    } else {
 949                        head = next_line_start.to_point(&display_map);
 950                    }
 951
 952                    if head <= original_buffer_range.start {
 953                        tail = original_buffer_range.end;
 954                    } else {
 955                        tail = original_buffer_range.start;
 956                    }
 957                }
 958                SelectMode::All => {
 959                    return;
 960                }
 961            };
 962
 963            if head < tail {
 964                selection.start = buffer.anchor_before(head);
 965                selection.end = buffer.anchor_before(tail);
 966                selection.reversed = true;
 967            } else {
 968                selection.start = buffer.anchor_before(tail);
 969                selection.end = buffer.anchor_before(head);
 970                selection.reversed = false;
 971            }
 972        } else {
 973            log::error!("update_selection dispatched with no pending selection");
 974            return;
 975        }
 976
 977        self.set_scroll_position(scroll_position, cx);
 978        cx.notify();
 979    }
 980
 981    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 982        self.columnar_selection_tail.take();
 983        if self.pending_selection.is_some() {
 984            let selections = self.selections::<usize>(cx);
 985            self.update_selections(selections, None, cx);
 986        }
 987    }
 988
 989    fn select_columns(
 990        &mut self,
 991        tail: DisplayPoint,
 992        head: DisplayPoint,
 993        overshoot: u32,
 994        display_map: &DisplaySnapshot,
 995        cx: &mut ViewContext<Self>,
 996    ) {
 997        let start_row = cmp::min(tail.row(), head.row());
 998        let end_row = cmp::max(tail.row(), head.row());
 999        let start_column = cmp::min(tail.column(), head.column() + overshoot);
1000        let end_column = cmp::max(tail.column(), head.column() + overshoot);
1001        let reversed = start_column < tail.column();
1002
1003        let selections = (start_row..=end_row)
1004            .filter_map(|row| {
1005                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1006                    let start = display_map
1007                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1008                        .to_point(&display_map);
1009                    let end = display_map
1010                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1011                        .to_point(&display_map);
1012                    Some(Selection {
1013                        id: post_inc(&mut self.next_selection_id),
1014                        start,
1015                        end,
1016                        reversed,
1017                        goal: SelectionGoal::None,
1018                    })
1019                } else {
1020                    None
1021                }
1022            })
1023            .collect::<Vec<_>>();
1024
1025        self.update_selections(selections, None, cx);
1026        cx.notify();
1027    }
1028
1029    pub fn is_selecting(&self) -> bool {
1030        self.pending_selection.is_some() || self.columnar_selection_tail.is_some()
1031    }
1032
1033    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1034        if self.active_diagnostics.is_some() {
1035            self.dismiss_diagnostics(cx);
1036        } else if let Some(PendingSelection { selection, .. }) = self.pending_selection.take() {
1037            let buffer = self.buffer.read(cx).snapshot(cx);
1038            let selection = Selection {
1039                id: selection.id,
1040                start: selection.start.to_point(&buffer),
1041                end: selection.end.to_point(&buffer),
1042                reversed: selection.reversed,
1043                goal: selection.goal,
1044            };
1045            if self.selections::<Point>(cx).is_empty() {
1046                self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
1047            }
1048        } else {
1049            let buffer = self.buffer.read(cx).snapshot(cx);
1050            let mut oldest_selection = self.oldest_selection::<usize>(&buffer, cx);
1051            if self.selection_count(cx) == 1 {
1052                oldest_selection.start = oldest_selection.head().clone();
1053                oldest_selection.end = oldest_selection.head().clone();
1054            }
1055            self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx);
1056        }
1057    }
1058
1059    pub fn select_ranges<I, T>(
1060        &mut self,
1061        ranges: I,
1062        autoscroll: Option<Autoscroll>,
1063        cx: &mut ViewContext<Self>,
1064    ) where
1065        I: IntoIterator<Item = Range<T>>,
1066        T: ToOffset,
1067    {
1068        let buffer = self.buffer.read(cx).snapshot(cx);
1069        let selections = ranges
1070            .into_iter()
1071            .map(|range| {
1072                let mut start = range.start.to_offset(&buffer);
1073                let mut end = range.end.to_offset(&buffer);
1074                let reversed = if start > end {
1075                    mem::swap(&mut start, &mut end);
1076                    true
1077                } else {
1078                    false
1079                };
1080                Selection {
1081                    id: post_inc(&mut self.next_selection_id),
1082                    start,
1083                    end,
1084                    reversed,
1085                    goal: SelectionGoal::None,
1086                }
1087            })
1088            .collect();
1089        self.update_selections(selections, autoscroll, cx);
1090    }
1091
1092    #[cfg(test)]
1093    fn select_display_ranges<'a, T>(
1094        &mut self,
1095        ranges: T,
1096        cx: &mut ViewContext<Self>,
1097    ) -> anyhow::Result<()>
1098    where
1099        T: IntoIterator<Item = &'a Range<DisplayPoint>>,
1100    {
1101        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1102        let selections = ranges
1103            .into_iter()
1104            .map(|range| {
1105                let mut start = range.start;
1106                let mut end = range.end;
1107                let reversed = if start > end {
1108                    mem::swap(&mut start, &mut end);
1109                    true
1110                } else {
1111                    false
1112                };
1113                Selection {
1114                    id: post_inc(&mut self.next_selection_id),
1115                    start: start.to_point(&display_map),
1116                    end: end.to_point(&display_map),
1117                    reversed,
1118                    goal: SelectionGoal::None,
1119                }
1120            })
1121            .collect();
1122        self.update_selections(selections, None, cx);
1123        Ok(())
1124    }
1125
1126    pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
1127        let text = action.0.as_ref();
1128        if !self.skip_autoclose_end(text, cx) {
1129            self.start_transaction(cx);
1130            self.insert(text, cx);
1131            self.autoclose_pairs(cx);
1132            self.end_transaction(cx);
1133        }
1134    }
1135
1136    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
1137        self.start_transaction(cx);
1138        let mut old_selections = SmallVec::<[_; 32]>::new();
1139        {
1140            let selections = self.selections::<Point>(cx);
1141            let buffer = self.buffer.read(cx).snapshot(cx);
1142            for selection in selections.iter() {
1143                let start_point = selection.start;
1144                let indent = buffer
1145                    .indent_column_for_line(start_point.row)
1146                    .min(start_point.column);
1147                let start = selection.start.to_offset(&buffer);
1148                let end = selection.end.to_offset(&buffer);
1149
1150                let mut insert_extra_newline = false;
1151                if let Some(language) = buffer.language() {
1152                    let leading_whitespace_len = buffer
1153                        .reversed_chars_at(start)
1154                        .take_while(|c| c.is_whitespace() && *c != '\n')
1155                        .map(|c| c.len_utf8())
1156                        .sum::<usize>();
1157
1158                    let trailing_whitespace_len = buffer
1159                        .chars_at(end)
1160                        .take_while(|c| c.is_whitespace() && *c != '\n')
1161                        .map(|c| c.len_utf8())
1162                        .sum::<usize>();
1163
1164                    insert_extra_newline = language.brackets().iter().any(|pair| {
1165                        let pair_start = pair.start.trim_end();
1166                        let pair_end = pair.end.trim_start();
1167
1168                        pair.newline
1169                            && buffer.contains_str_at(end + trailing_whitespace_len, pair_end)
1170                            && buffer.contains_str_at(
1171                                (start - leading_whitespace_len).saturating_sub(pair_start.len()),
1172                                pair_start,
1173                            )
1174                    });
1175                }
1176
1177                old_selections.push((selection.id, start..end, indent, insert_extra_newline));
1178            }
1179        }
1180
1181        let mut new_selections = Vec::with_capacity(old_selections.len());
1182        self.buffer.update(cx, |buffer, cx| {
1183            let mut delta = 0_isize;
1184            let mut pending_edit: Option<PendingEdit> = None;
1185            for (_, range, indent, insert_extra_newline) in &old_selections {
1186                if pending_edit.as_ref().map_or(false, |pending| {
1187                    pending.indent != *indent
1188                        || pending.insert_extra_newline != *insert_extra_newline
1189                }) {
1190                    let pending = pending_edit.take().unwrap();
1191                    let mut new_text = String::with_capacity(1 + pending.indent as usize);
1192                    new_text.push('\n');
1193                    new_text.extend(iter::repeat(' ').take(pending.indent as usize));
1194                    if pending.insert_extra_newline {
1195                        new_text = new_text.repeat(2);
1196                    }
1197                    buffer.edit_with_autoindent(pending.ranges, new_text, cx);
1198                    delta += pending.delta;
1199                }
1200
1201                let start = (range.start as isize + delta) as usize;
1202                let end = (range.end as isize + delta) as usize;
1203                let mut text_len = *indent as usize + 1;
1204                if *insert_extra_newline {
1205                    text_len *= 2;
1206                }
1207
1208                let pending = pending_edit.get_or_insert_with(Default::default);
1209                pending.delta += text_len as isize - (end - start) as isize;
1210                pending.indent = *indent;
1211                pending.insert_extra_newline = *insert_extra_newline;
1212                pending.ranges.push(start..end);
1213            }
1214
1215            let pending = pending_edit.unwrap();
1216            let mut new_text = String::with_capacity(1 + pending.indent as usize);
1217            new_text.push('\n');
1218            new_text.extend(iter::repeat(' ').take(pending.indent as usize));
1219            if pending.insert_extra_newline {
1220                new_text = new_text.repeat(2);
1221            }
1222            buffer.edit_with_autoindent(pending.ranges, new_text, cx);
1223
1224            let mut delta = 0_isize;
1225            new_selections.extend(old_selections.into_iter().map(
1226                |(id, range, indent, insert_extra_newline)| {
1227                    let start = (range.start as isize + delta) as usize;
1228                    let end = (range.end as isize + delta) as usize;
1229                    let text_before_cursor_len = indent as usize + 1;
1230                    let cursor = start + text_before_cursor_len;
1231                    let text_len = if insert_extra_newline {
1232                        text_before_cursor_len * 2
1233                    } else {
1234                        text_before_cursor_len
1235                    };
1236                    delta += text_len as isize - (end - start) as isize;
1237                    Selection {
1238                        id,
1239                        start: cursor,
1240                        end: cursor,
1241                        reversed: false,
1242                        goal: SelectionGoal::None,
1243                    }
1244                },
1245            ))
1246        });
1247
1248        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
1249        self.end_transaction(cx);
1250
1251        #[derive(Default)]
1252        struct PendingEdit {
1253            indent: u32,
1254            insert_extra_newline: bool,
1255            delta: isize,
1256            ranges: SmallVec<[Range<usize>; 32]>,
1257        }
1258    }
1259
1260    fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1261        self.start_transaction(cx);
1262        let old_selections = self.selections::<usize>(cx);
1263        let mut new_selections = Vec::new();
1264        self.buffer.update(cx, |buffer, cx| {
1265            let edit_ranges = old_selections.iter().map(|s| s.start..s.end);
1266            buffer.edit_with_autoindent(edit_ranges, text, cx);
1267            let text_len = text.len() as isize;
1268            let mut delta = 0_isize;
1269            new_selections = old_selections
1270                .into_iter()
1271                .map(|selection| {
1272                    let start = selection.start as isize;
1273                    let end = selection.end as isize;
1274                    let cursor = (start + delta + text_len) as usize;
1275                    let deleted_count = end - start;
1276                    delta += text_len - deleted_count;
1277                    Selection {
1278                        id: selection.id,
1279                        start: cursor,
1280                        end: cursor,
1281                        reversed: false,
1282                        goal: SelectionGoal::None,
1283                    }
1284                })
1285                .collect();
1286        });
1287
1288        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
1289        self.end_transaction(cx);
1290    }
1291
1292    fn autoclose_pairs(&mut self, cx: &mut ViewContext<Self>) {
1293        let selections = self.selections::<usize>(cx);
1294        let new_autoclose_pair = self.buffer.update(cx, |buffer, cx| {
1295            let snapshot = buffer.snapshot(cx);
1296            let autoclose_pair = snapshot.language().and_then(|language| {
1297                let first_selection_start = selections.first().unwrap().start;
1298                let pair = language.brackets().iter().find(|pair| {
1299                    snapshot.contains_str_at(
1300                        first_selection_start.saturating_sub(pair.start.len()),
1301                        &pair.start,
1302                    )
1303                });
1304                pair.and_then(|pair| {
1305                    let should_autoclose = selections[1..].iter().all(|selection| {
1306                        snapshot.contains_str_at(
1307                            selection.start.saturating_sub(pair.start.len()),
1308                            &pair.start,
1309                        )
1310                    });
1311
1312                    if should_autoclose {
1313                        Some(pair.clone())
1314                    } else {
1315                        None
1316                    }
1317                })
1318            });
1319
1320            autoclose_pair.and_then(|pair| {
1321                let selection_ranges = selections
1322                    .iter()
1323                    .map(|selection| {
1324                        let start = selection.start.to_offset(&snapshot);
1325                        start..start
1326                    })
1327                    .collect::<SmallVec<[_; 32]>>();
1328
1329                buffer.edit(selection_ranges, &pair.end, cx);
1330                let snapshot = buffer.snapshot(cx);
1331
1332                if pair.end.len() == 1 {
1333                    let mut delta = 0;
1334                    Some(BracketPairState {
1335                        ranges: selections
1336                            .iter()
1337                            .map(move |selection| {
1338                                let offset = selection.start + delta;
1339                                delta += 1;
1340                                snapshot.anchor_before(offset)..snapshot.anchor_after(offset)
1341                            })
1342                            .collect(),
1343                        pair,
1344                    })
1345                } else {
1346                    None
1347                }
1348            })
1349        });
1350        self.autoclose_stack.extend(new_autoclose_pair);
1351    }
1352
1353    fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
1354        let old_selections = self.selections::<usize>(cx);
1355        let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() {
1356            autoclose_pair
1357        } else {
1358            return false;
1359        };
1360        if text != autoclose_pair.pair.end {
1361            return false;
1362        }
1363
1364        debug_assert_eq!(old_selections.len(), autoclose_pair.ranges.len());
1365
1366        let buffer = self.buffer.read(cx).snapshot(cx);
1367        if old_selections
1368            .iter()
1369            .zip(autoclose_pair.ranges.iter().map(|r| r.to_offset(&buffer)))
1370            .all(|(selection, autoclose_range)| {
1371                let autoclose_range_end = autoclose_range.end.to_offset(&buffer);
1372                selection.is_empty() && selection.start == autoclose_range_end
1373            })
1374        {
1375            let new_selections = old_selections
1376                .into_iter()
1377                .map(|selection| {
1378                    let cursor = selection.start + 1;
1379                    Selection {
1380                        id: selection.id,
1381                        start: cursor,
1382                        end: cursor,
1383                        reversed: false,
1384                        goal: SelectionGoal::None,
1385                    }
1386                })
1387                .collect();
1388            self.autoclose_stack.pop();
1389            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
1390            true
1391        } else {
1392            false
1393        }
1394    }
1395
1396    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
1397        self.start_transaction(cx);
1398        self.select_all(&SelectAll, cx);
1399        self.insert("", cx);
1400        self.end_transaction(cx);
1401    }
1402
1403    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
1404        self.start_transaction(cx);
1405        let mut selections = self.selections::<Point>(cx);
1406        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1407        for selection in &mut selections {
1408            if selection.is_empty() {
1409                let head = selection.head().to_display_point(&display_map);
1410                let cursor = movement::left(&display_map, head)
1411                    .unwrap()
1412                    .to_point(&display_map);
1413                selection.set_head(cursor);
1414                selection.goal = SelectionGoal::None;
1415            }
1416        }
1417        self.update_selections(selections, Some(Autoscroll::Fit), cx);
1418        self.insert("", cx);
1419        self.end_transaction(cx);
1420    }
1421
1422    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
1423        self.start_transaction(cx);
1424        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1425        let mut selections = self.selections::<Point>(cx);
1426        for selection in &mut selections {
1427            if selection.is_empty() {
1428                let head = selection.head().to_display_point(&display_map);
1429                let cursor = movement::right(&display_map, head)
1430                    .unwrap()
1431                    .to_point(&display_map);
1432                selection.set_head(cursor);
1433                selection.goal = SelectionGoal::None;
1434            }
1435        }
1436        self.update_selections(selections, Some(Autoscroll::Fit), cx);
1437        self.insert(&"", cx);
1438        self.end_transaction(cx);
1439    }
1440
1441    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
1442        self.start_transaction(cx);
1443        let tab_size = self.build_settings.borrow()(cx).tab_size;
1444        let mut selections = self.selections::<Point>(cx);
1445        let mut last_indent = None;
1446        self.buffer.update(cx, |buffer, cx| {
1447            for selection in &mut selections {
1448                if selection.is_empty() {
1449                    let char_column = buffer
1450                        .read(cx)
1451                        .text_for_range(Point::new(selection.start.row, 0)..selection.start)
1452                        .flat_map(str::chars)
1453                        .count();
1454                    let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
1455                    buffer.edit(
1456                        [selection.start..selection.start],
1457                        " ".repeat(chars_to_next_tab_stop),
1458                        cx,
1459                    );
1460                    selection.start.column += chars_to_next_tab_stop as u32;
1461                    selection.end = selection.start;
1462                } else {
1463                    let mut start_row = selection.start.row;
1464                    let mut end_row = selection.end.row + 1;
1465
1466                    // If a selection ends at the beginning of a line, don't indent
1467                    // that last line.
1468                    if selection.end.column == 0 {
1469                        end_row -= 1;
1470                    }
1471
1472                    // Avoid re-indenting a row that has already been indented by a
1473                    // previous selection, but still update this selection's column
1474                    // to reflect that indentation.
1475                    if let Some((last_indent_row, last_indent_len)) = last_indent {
1476                        if last_indent_row == selection.start.row {
1477                            selection.start.column += last_indent_len;
1478                            start_row += 1;
1479                        }
1480                        if last_indent_row == selection.end.row {
1481                            selection.end.column += last_indent_len;
1482                        }
1483                    }
1484
1485                    for row in start_row..end_row {
1486                        let indent_column = buffer.read(cx).indent_column_for_line(row) as usize;
1487                        let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
1488                        let row_start = Point::new(row, 0);
1489                        buffer.edit(
1490                            [row_start..row_start],
1491                            " ".repeat(columns_to_next_tab_stop),
1492                            cx,
1493                        );
1494
1495                        // Update this selection's endpoints to reflect the indentation.
1496                        if row == selection.start.row {
1497                            selection.start.column += columns_to_next_tab_stop as u32;
1498                        }
1499                        if row == selection.end.row {
1500                            selection.end.column += columns_to_next_tab_stop as u32;
1501                        }
1502
1503                        last_indent = Some((row, columns_to_next_tab_stop as u32));
1504                    }
1505                }
1506            }
1507        });
1508
1509        self.update_selections(selections, Some(Autoscroll::Fit), cx);
1510        self.end_transaction(cx);
1511    }
1512
1513    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
1514        self.start_transaction(cx);
1515        let tab_size = self.build_settings.borrow()(cx).tab_size;
1516        let selections = self.selections::<Point>(cx);
1517        let mut deletion_ranges = Vec::new();
1518        let mut last_outdent = None;
1519        {
1520            let buffer = self.buffer.read(cx).read(cx);
1521            for selection in &selections {
1522                let mut start_row = selection.start.row;
1523                let mut end_row = selection.end.row + 1;
1524
1525                // If a selection ends at the beginning of a line, don't indent
1526                // that last line.
1527                if selection.end.column == 0 {
1528                    end_row -= 1;
1529                }
1530
1531                // Avoid re-outdenting a row that has already been outdented by a
1532                // previous selection.
1533                if let Some(last_row) = last_outdent {
1534                    if last_row == selection.start.row {
1535                        start_row += 1;
1536                    }
1537                }
1538
1539                for row in start_row..end_row {
1540                    let column = buffer.indent_column_for_line(row) as usize;
1541                    if column > 0 {
1542                        let mut deletion_len = (column % tab_size) as u32;
1543                        if deletion_len == 0 {
1544                            deletion_len = tab_size as u32;
1545                        }
1546                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
1547                        last_outdent = Some(row);
1548                    }
1549                }
1550            }
1551        }
1552        self.buffer.update(cx, |buffer, cx| {
1553            buffer.edit(deletion_ranges, "", cx);
1554        });
1555
1556        self.update_selections(self.selections::<usize>(cx), Some(Autoscroll::Fit), cx);
1557        self.end_transaction(cx);
1558    }
1559
1560    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
1561        self.start_transaction(cx);
1562
1563        let selections = self.selections::<Point>(cx);
1564        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1565        let buffer = self.buffer.read(cx).snapshot(cx);
1566
1567        let mut row_delta = 0;
1568        let mut new_cursors = Vec::new();
1569        let mut edit_ranges = Vec::new();
1570        let mut selections = selections.iter().peekable();
1571        while let Some(selection) = selections.next() {
1572            let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
1573            let goal_display_column = selection.head().to_display_point(&display_map).column();
1574
1575            // Accumulate contiguous regions of rows that we want to delete.
1576            while let Some(next_selection) = selections.peek() {
1577                let next_rows = next_selection.spanned_rows(false, &display_map).buffer_rows;
1578                if next_rows.start <= rows.end {
1579                    rows.end = next_rows.end;
1580                    selections.next().unwrap();
1581                } else {
1582                    break;
1583                }
1584            }
1585
1586            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
1587            let edit_end;
1588            let cursor_buffer_row;
1589            if buffer.max_point().row >= rows.end {
1590                // If there's a line after the range, delete the \n from the end of the row range
1591                // and position the cursor on the next line.
1592                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
1593                cursor_buffer_row = rows.start;
1594            } else {
1595                // If there isn't a line after the range, delete the \n from the line before the
1596                // start of the row range and position the cursor there.
1597                edit_start = edit_start.saturating_sub(1);
1598                edit_end = buffer.len();
1599                cursor_buffer_row = rows.start.saturating_sub(1);
1600            }
1601
1602            let mut cursor =
1603                Point::new(cursor_buffer_row - row_delta, 0).to_display_point(&display_map);
1604            *cursor.column_mut() =
1605                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
1606            row_delta += rows.len() as u32;
1607
1608            new_cursors.push((selection.id, cursor.to_point(&display_map)));
1609            edit_ranges.push(edit_start..edit_end);
1610        }
1611
1612        new_cursors.sort_unstable_by_key(|(_, point)| point.clone());
1613        let new_selections = new_cursors
1614            .into_iter()
1615            .map(|(id, cursor)| Selection {
1616                id,
1617                start: cursor,
1618                end: cursor,
1619                reversed: false,
1620                goal: SelectionGoal::None,
1621            })
1622            .collect();
1623        self.buffer
1624            .update(cx, |buffer, cx| buffer.edit(edit_ranges, "", cx));
1625        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
1626        self.end_transaction(cx);
1627    }
1628
1629    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
1630        self.start_transaction(cx);
1631
1632        let mut selections = self.selections::<Point>(cx);
1633        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1634        let buffer = &display_map.buffer_snapshot;
1635
1636        let mut edits = Vec::new();
1637        let mut selections_iter = selections.iter().peekable();
1638        while let Some(selection) = selections_iter.next() {
1639            // Avoid duplicating the same lines twice.
1640            let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
1641
1642            while let Some(next_selection) = selections_iter.peek() {
1643                let next_rows = next_selection.spanned_rows(false, &display_map).buffer_rows;
1644                if next_rows.start <= rows.end - 1 {
1645                    rows.end = next_rows.end;
1646                    selections_iter.next().unwrap();
1647                } else {
1648                    break;
1649                }
1650            }
1651
1652            // Copy the text from the selected row region and splice it at the start of the region.
1653            let start = Point::new(rows.start, 0);
1654            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
1655            let text = buffer
1656                .text_for_range(start..end)
1657                .chain(Some("\n"))
1658                .collect::<String>();
1659            edits.push((start, text, rows.len() as u32));
1660        }
1661
1662        let mut edits_iter = edits.iter().peekable();
1663        let mut row_delta = 0;
1664        for selection in selections.iter_mut() {
1665            while let Some((point, _, line_count)) = edits_iter.peek() {
1666                if *point <= selection.start {
1667                    row_delta += line_count;
1668                    edits_iter.next();
1669                } else {
1670                    break;
1671                }
1672            }
1673            selection.start.row += row_delta;
1674            selection.end.row += row_delta;
1675        }
1676
1677        self.buffer.update(cx, |buffer, cx| {
1678            for (point, text, _) in edits.into_iter().rev() {
1679                buffer.edit(Some(point..point), text, cx);
1680            }
1681        });
1682
1683        self.update_selections(selections, Some(Autoscroll::Fit), cx);
1684        self.end_transaction(cx);
1685    }
1686
1687    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
1688        self.start_transaction(cx);
1689
1690        let selections = self.selections::<Point>(cx);
1691        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1692        let buffer = self.buffer.read(cx).snapshot(cx);
1693
1694        let mut edits = Vec::new();
1695        let mut new_selection_ranges = Vec::new();
1696        let mut old_folds = Vec::new();
1697        let mut new_folds = Vec::new();
1698
1699        let mut selections = selections.iter().peekable();
1700        let mut contiguous_selections = Vec::new();
1701        while let Some(selection) = selections.next() {
1702            // Accumulate contiguous regions of rows that we want to move.
1703            contiguous_selections.push(selection.point_range(&buffer));
1704            let SpannedRows {
1705                mut buffer_rows,
1706                mut display_rows,
1707            } = selection.spanned_rows(false, &display_map);
1708
1709            while let Some(next_selection) = selections.peek() {
1710                let SpannedRows {
1711                    buffer_rows: next_buffer_rows,
1712                    display_rows: next_display_rows,
1713                } = next_selection.spanned_rows(false, &display_map);
1714                if next_buffer_rows.start <= buffer_rows.end {
1715                    buffer_rows.end = next_buffer_rows.end;
1716                    display_rows.end = next_display_rows.end;
1717                    contiguous_selections.push(next_selection.point_range(&buffer));
1718                    selections.next().unwrap();
1719                } else {
1720                    break;
1721                }
1722            }
1723
1724            // Cut the text from the selected rows and paste it at the start of the previous line.
1725            if display_rows.start != 0 {
1726                let start = Point::new(buffer_rows.start, 0).to_offset(&buffer);
1727                let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
1728                    .to_offset(&buffer);
1729
1730                let prev_row_display_start = DisplayPoint::new(display_rows.start - 1, 0);
1731                let prev_row_buffer_start = display_map.prev_row_boundary(prev_row_display_start).1;
1732                let prev_row_buffer_start_offset = prev_row_buffer_start.to_offset(&buffer);
1733
1734                let mut text = String::new();
1735                text.extend(buffer.text_for_range(start..end));
1736                text.push('\n');
1737                edits.push((
1738                    prev_row_buffer_start_offset..prev_row_buffer_start_offset,
1739                    text,
1740                ));
1741                edits.push((start - 1..end, String::new()));
1742
1743                let row_delta = buffer_rows.start - prev_row_buffer_start.row;
1744
1745                // Move selections up.
1746                for range in &mut contiguous_selections {
1747                    range.start.row -= row_delta;
1748                    range.end.row -= row_delta;
1749                }
1750
1751                // Move folds up.
1752                old_folds.push(start..end);
1753                for fold in display_map.folds_in_range(start..end) {
1754                    let mut start = fold.start.to_point(&buffer);
1755                    let mut end = fold.end.to_point(&buffer);
1756                    start.row -= row_delta;
1757                    end.row -= row_delta;
1758                    new_folds.push(start..end);
1759                }
1760            }
1761
1762            new_selection_ranges.extend(contiguous_selections.drain(..));
1763        }
1764
1765        self.unfold_ranges(old_folds, cx);
1766        self.buffer.update(cx, |buffer, cx| {
1767            for (range, text) in edits.into_iter().rev() {
1768                buffer.edit(Some(range), text, cx);
1769            }
1770        });
1771        self.fold_ranges(new_folds, cx);
1772        self.select_ranges(new_selection_ranges, Some(Autoscroll::Fit), cx);
1773
1774        self.end_transaction(cx);
1775    }
1776
1777    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
1778        self.start_transaction(cx);
1779
1780        let selections = self.selections::<Point>(cx);
1781        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1782        let buffer = self.buffer.read(cx).snapshot(cx);
1783
1784        let mut edits = Vec::new();
1785        let mut new_selection_ranges = Vec::new();
1786        let mut old_folds = Vec::new();
1787        let mut new_folds = Vec::new();
1788
1789        let mut selections = selections.iter().peekable();
1790        let mut contiguous_selections = Vec::new();
1791        while let Some(selection) = selections.next() {
1792            // Accumulate contiguous regions of rows that we want to move.
1793            contiguous_selections.push(selection.point_range(&buffer));
1794            let SpannedRows {
1795                mut buffer_rows,
1796                mut display_rows,
1797            } = selection.spanned_rows(false, &display_map);
1798            while let Some(next_selection) = selections.peek() {
1799                let SpannedRows {
1800                    buffer_rows: next_buffer_rows,
1801                    display_rows: next_display_rows,
1802                } = next_selection.spanned_rows(false, &display_map);
1803                if next_buffer_rows.start <= buffer_rows.end {
1804                    buffer_rows.end = next_buffer_rows.end;
1805                    display_rows.end = next_display_rows.end;
1806                    contiguous_selections.push(next_selection.point_range(&buffer));
1807                    selections.next().unwrap();
1808                } else {
1809                    break;
1810                }
1811            }
1812
1813            // Cut the text from the selected rows and paste it at the end of the next line.
1814            if display_rows.end <= display_map.max_point().row() {
1815                let start = Point::new(buffer_rows.start, 0).to_offset(&buffer);
1816                let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
1817                    .to_offset(&buffer);
1818
1819                let next_row_display_end =
1820                    DisplayPoint::new(display_rows.end, display_map.line_len(display_rows.end));
1821                let next_row_buffer_end = display_map.next_row_boundary(next_row_display_end).1;
1822                let next_row_buffer_end_offset = next_row_buffer_end.to_offset(&buffer);
1823
1824                let mut text = String::new();
1825                text.push('\n');
1826                text.extend(buffer.text_for_range(start..end));
1827                edits.push((start..end + 1, String::new()));
1828                edits.push((next_row_buffer_end_offset..next_row_buffer_end_offset, text));
1829
1830                let row_delta = next_row_buffer_end.row - buffer_rows.end + 1;
1831
1832                // Move selections down.
1833                for range in &mut contiguous_selections {
1834                    range.start.row += row_delta;
1835                    range.end.row += row_delta;
1836                }
1837
1838                // Move folds down.
1839                old_folds.push(start..end);
1840                for fold in display_map.folds_in_range(start..end) {
1841                    let mut start = fold.start.to_point(&buffer);
1842                    let mut end = fold.end.to_point(&buffer);
1843                    start.row += row_delta;
1844                    end.row += row_delta;
1845                    new_folds.push(start..end);
1846                }
1847            }
1848
1849            new_selection_ranges.extend(contiguous_selections.drain(..));
1850        }
1851
1852        self.unfold_ranges(old_folds, cx);
1853        self.buffer.update(cx, |buffer, cx| {
1854            for (range, text) in edits.into_iter().rev() {
1855                buffer.edit(Some(range), text, cx);
1856            }
1857        });
1858        self.fold_ranges(new_folds, cx);
1859        self.select_ranges(new_selection_ranges, Some(Autoscroll::Fit), cx);
1860
1861        self.end_transaction(cx);
1862    }
1863
1864    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
1865        self.start_transaction(cx);
1866        let mut text = String::new();
1867        let mut selections = self.selections::<Point>(cx);
1868        let mut clipboard_selections = Vec::with_capacity(selections.len());
1869        {
1870            let buffer = self.buffer.read(cx).read(cx);
1871            let max_point = buffer.max_point();
1872            for selection in &mut selections {
1873                let is_entire_line = selection.is_empty();
1874                if is_entire_line {
1875                    selection.start = Point::new(selection.start.row, 0);
1876                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
1877                }
1878                let mut len = 0;
1879                for chunk in buffer.text_for_range(selection.start..selection.end) {
1880                    text.push_str(chunk);
1881                    len += chunk.len();
1882                }
1883                clipboard_selections.push(ClipboardSelection {
1884                    len,
1885                    is_entire_line,
1886                });
1887            }
1888        }
1889        self.update_selections(selections, Some(Autoscroll::Fit), cx);
1890        self.insert("", cx);
1891        self.end_transaction(cx);
1892
1893        cx.as_mut()
1894            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1895    }
1896
1897    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
1898        let selections = self.selections::<Point>(cx);
1899        let mut text = String::new();
1900        let mut clipboard_selections = Vec::with_capacity(selections.len());
1901        {
1902            let buffer = self.buffer.read(cx).read(cx);
1903            let max_point = buffer.max_point();
1904            for selection in selections.iter() {
1905                let mut start = selection.start;
1906                let mut end = selection.end;
1907                let is_entire_line = selection.is_empty();
1908                if is_entire_line {
1909                    start = Point::new(start.row, 0);
1910                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
1911                }
1912                let mut len = 0;
1913                for chunk in buffer.text_for_range(start..end) {
1914                    text.push_str(chunk);
1915                    len += chunk.len();
1916                }
1917                clipboard_selections.push(ClipboardSelection {
1918                    len,
1919                    is_entire_line,
1920                });
1921            }
1922        }
1923
1924        cx.as_mut()
1925            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1926    }
1927
1928    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
1929        if let Some(item) = cx.as_mut().read_from_clipboard() {
1930            let clipboard_text = item.text();
1931            if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
1932                let mut selections = self.selections::<usize>(cx);
1933                let all_selections_were_entire_line =
1934                    clipboard_selections.iter().all(|s| s.is_entire_line);
1935                if clipboard_selections.len() != selections.len() {
1936                    clipboard_selections.clear();
1937                }
1938
1939                let mut delta = 0_isize;
1940                let mut start_offset = 0;
1941                for (i, selection) in selections.iter_mut().enumerate() {
1942                    let to_insert;
1943                    let entire_line;
1944                    if let Some(clipboard_selection) = clipboard_selections.get(i) {
1945                        let end_offset = start_offset + clipboard_selection.len;
1946                        to_insert = &clipboard_text[start_offset..end_offset];
1947                        entire_line = clipboard_selection.is_entire_line;
1948                        start_offset = end_offset
1949                    } else {
1950                        to_insert = clipboard_text.as_str();
1951                        entire_line = all_selections_were_entire_line;
1952                    }
1953
1954                    selection.start = (selection.start as isize + delta) as usize;
1955                    selection.end = (selection.end as isize + delta) as usize;
1956
1957                    self.buffer.update(cx, |buffer, cx| {
1958                        // If the corresponding selection was empty when this slice of the
1959                        // clipboard text was written, then the entire line containing the
1960                        // selection was copied. If this selection is also currently empty,
1961                        // then paste the line before the current line of the buffer.
1962                        let range = if selection.is_empty() && entire_line {
1963                            let column = selection.start.to_point(&buffer.read(cx)).column as usize;
1964                            let line_start = selection.start - column;
1965                            line_start..line_start
1966                        } else {
1967                            selection.start..selection.end
1968                        };
1969
1970                        delta += to_insert.len() as isize - range.len() as isize;
1971                        buffer.edit([range], to_insert, cx);
1972                        selection.start += to_insert.len();
1973                        selection.end = selection.start;
1974                    });
1975                }
1976                self.update_selections(selections, Some(Autoscroll::Fit), cx);
1977            } else {
1978                self.insert(clipboard_text, cx);
1979            }
1980        }
1981    }
1982
1983    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
1984        self.buffer.update(cx, |buffer, cx| buffer.undo(cx));
1985        self.request_autoscroll(Autoscroll::Fit, cx);
1986    }
1987
1988    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
1989        self.buffer.update(cx, |buffer, cx| buffer.redo(cx));
1990        self.request_autoscroll(Autoscroll::Fit, cx);
1991    }
1992
1993    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
1994        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1995        let mut selections = self.selections::<Point>(cx);
1996        for selection in &mut selections {
1997            let start = selection.start.to_display_point(&display_map);
1998            let end = selection.end.to_display_point(&display_map);
1999
2000            if start != end {
2001                selection.end = selection.start.clone();
2002            } else {
2003                let cursor = movement::left(&display_map, start)
2004                    .unwrap()
2005                    .to_point(&display_map);
2006                selection.start = cursor.clone();
2007                selection.end = cursor;
2008            }
2009            selection.reversed = false;
2010            selection.goal = SelectionGoal::None;
2011        }
2012        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2013    }
2014
2015    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
2016        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2017        let mut selections = self.selections::<Point>(cx);
2018        for selection in &mut selections {
2019            let head = selection.head().to_display_point(&display_map);
2020            let cursor = movement::left(&display_map, head)
2021                .unwrap()
2022                .to_point(&display_map);
2023            selection.set_head(cursor);
2024            selection.goal = SelectionGoal::None;
2025        }
2026        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2027    }
2028
2029    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
2030        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2031        let mut selections = self.selections::<Point>(cx);
2032        for selection in &mut selections {
2033            let start = selection.start.to_display_point(&display_map);
2034            let end = selection.end.to_display_point(&display_map);
2035
2036            if start != end {
2037                selection.start = selection.end.clone();
2038            } else {
2039                let cursor = movement::right(&display_map, end)
2040                    .unwrap()
2041                    .to_point(&display_map);
2042                selection.start = cursor;
2043                selection.end = cursor;
2044            }
2045            selection.reversed = false;
2046            selection.goal = SelectionGoal::None;
2047        }
2048        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2049    }
2050
2051    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
2052        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2053        let mut selections = self.selections::<Point>(cx);
2054        for selection in &mut selections {
2055            let head = selection.head().to_display_point(&display_map);
2056            let cursor = movement::right(&display_map, head)
2057                .unwrap()
2058                .to_point(&display_map);
2059            selection.set_head(cursor);
2060            selection.goal = SelectionGoal::None;
2061        }
2062        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2063    }
2064
2065    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
2066        if matches!(self.mode, EditorMode::SingleLine) {
2067            cx.propagate_action();
2068            return;
2069        }
2070
2071        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2072        let mut selections = self.selections::<Point>(cx);
2073        for selection in &mut selections {
2074            let start = selection.start.to_display_point(&display_map);
2075            let end = selection.end.to_display_point(&display_map);
2076            if start != end {
2077                selection.goal = SelectionGoal::None;
2078            }
2079
2080            let (start, goal) = movement::up(&display_map, start, selection.goal).unwrap();
2081            let cursor = start.to_point(&display_map);
2082            selection.start = cursor;
2083            selection.end = cursor;
2084            selection.goal = goal;
2085            selection.reversed = false;
2086        }
2087        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2088    }
2089
2090    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
2091        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2092        let mut selections = self.selections::<Point>(cx);
2093        for selection in &mut selections {
2094            let head = selection.head().to_display_point(&display_map);
2095            let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap();
2096            let cursor = head.to_point(&display_map);
2097            selection.set_head(cursor);
2098            selection.goal = goal;
2099        }
2100        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2101    }
2102
2103    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
2104        if matches!(self.mode, EditorMode::SingleLine) {
2105            cx.propagate_action();
2106            return;
2107        }
2108
2109        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2110        let mut selections = self.selections::<Point>(cx);
2111        for selection in &mut selections {
2112            let start = selection.start.to_display_point(&display_map);
2113            let end = selection.end.to_display_point(&display_map);
2114            if start != end {
2115                selection.goal = SelectionGoal::None;
2116            }
2117
2118            let (start, goal) = movement::down(&display_map, end, selection.goal).unwrap();
2119            let cursor = start.to_point(&display_map);
2120            selection.start = cursor;
2121            selection.end = cursor;
2122            selection.goal = goal;
2123            selection.reversed = false;
2124        }
2125        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2126    }
2127
2128    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
2129        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2130        let mut selections = self.selections::<Point>(cx);
2131        for selection in &mut selections {
2132            let head = selection.head().to_display_point(&display_map);
2133            let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap();
2134            let cursor = head.to_point(&display_map);
2135            selection.set_head(cursor);
2136            selection.goal = goal;
2137        }
2138        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2139    }
2140
2141    pub fn move_to_previous_word_boundary(
2142        &mut self,
2143        _: &MoveToPreviousWordBoundary,
2144        cx: &mut ViewContext<Self>,
2145    ) {
2146        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2147        let mut selections = self.selections::<Point>(cx);
2148        for selection in &mut selections {
2149            let head = selection.head().to_display_point(&display_map);
2150            let cursor = movement::prev_word_boundary(&display_map, head).to_point(&display_map);
2151            selection.start = cursor.clone();
2152            selection.end = cursor;
2153            selection.reversed = false;
2154            selection.goal = SelectionGoal::None;
2155        }
2156        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2157    }
2158
2159    pub fn select_to_previous_word_boundary(
2160        &mut self,
2161        _: &SelectToPreviousWordBoundary,
2162        cx: &mut ViewContext<Self>,
2163    ) {
2164        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2165        let mut selections = self.selections::<Point>(cx);
2166        for selection in &mut selections {
2167            let head = selection.head().to_display_point(&display_map);
2168            let cursor = movement::prev_word_boundary(&display_map, head).to_point(&display_map);
2169            selection.set_head(cursor);
2170            selection.goal = SelectionGoal::None;
2171        }
2172        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2173    }
2174
2175    pub fn delete_to_previous_word_boundary(
2176        &mut self,
2177        _: &DeleteToPreviousWordBoundary,
2178        cx: &mut ViewContext<Self>,
2179    ) {
2180        self.start_transaction(cx);
2181        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2182        let mut selections = self.selections::<Point>(cx);
2183        for selection in &mut selections {
2184            if selection.is_empty() {
2185                let head = selection.head().to_display_point(&display_map);
2186                let cursor =
2187                    movement::prev_word_boundary(&display_map, head).to_point(&display_map);
2188                selection.set_head(cursor);
2189                selection.goal = SelectionGoal::None;
2190            }
2191        }
2192        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2193        self.insert("", cx);
2194        self.end_transaction(cx);
2195    }
2196
2197    pub fn move_to_next_word_boundary(
2198        &mut self,
2199        _: &MoveToNextWordBoundary,
2200        cx: &mut ViewContext<Self>,
2201    ) {
2202        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2203        let mut selections = self.selections::<Point>(cx);
2204        for selection in &mut selections {
2205            let head = selection.head().to_display_point(&display_map);
2206            let cursor = movement::next_word_boundary(&display_map, head).to_point(&display_map);
2207            selection.start = cursor;
2208            selection.end = cursor;
2209            selection.reversed = false;
2210            selection.goal = SelectionGoal::None;
2211        }
2212        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2213    }
2214
2215    pub fn select_to_next_word_boundary(
2216        &mut self,
2217        _: &SelectToNextWordBoundary,
2218        cx: &mut ViewContext<Self>,
2219    ) {
2220        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2221        let mut selections = self.selections::<Point>(cx);
2222        for selection in &mut selections {
2223            let head = selection.head().to_display_point(&display_map);
2224            let cursor = movement::next_word_boundary(&display_map, head).to_point(&display_map);
2225            selection.set_head(cursor);
2226            selection.goal = SelectionGoal::None;
2227        }
2228        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2229    }
2230
2231    pub fn delete_to_next_word_boundary(
2232        &mut self,
2233        _: &DeleteToNextWordBoundary,
2234        cx: &mut ViewContext<Self>,
2235    ) {
2236        self.start_transaction(cx);
2237        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2238        let mut selections = self.selections::<Point>(cx);
2239        for selection in &mut selections {
2240            if selection.is_empty() {
2241                let head = selection.head().to_display_point(&display_map);
2242                let cursor =
2243                    movement::next_word_boundary(&display_map, head).to_point(&display_map);
2244                selection.set_head(cursor);
2245                selection.goal = SelectionGoal::None;
2246            }
2247        }
2248        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2249        self.insert("", cx);
2250        self.end_transaction(cx);
2251    }
2252
2253    pub fn move_to_beginning_of_line(
2254        &mut self,
2255        _: &MoveToBeginningOfLine,
2256        cx: &mut ViewContext<Self>,
2257    ) {
2258        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2259        let mut selections = self.selections::<Point>(cx);
2260        for selection in &mut selections {
2261            let head = selection.head().to_display_point(&display_map);
2262            let new_head = movement::line_beginning(&display_map, head, true);
2263            let cursor = new_head.to_point(&display_map);
2264            selection.start = cursor;
2265            selection.end = cursor;
2266            selection.reversed = false;
2267            selection.goal = SelectionGoal::None;
2268        }
2269        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2270    }
2271
2272    pub fn select_to_beginning_of_line(
2273        &mut self,
2274        SelectToBeginningOfLine(toggle_indent): &SelectToBeginningOfLine,
2275        cx: &mut ViewContext<Self>,
2276    ) {
2277        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2278        let mut selections = self.selections::<Point>(cx);
2279        for selection in &mut selections {
2280            let head = selection.head().to_display_point(&display_map);
2281            let new_head = movement::line_beginning(&display_map, head, *toggle_indent);
2282            selection.set_head(new_head.to_point(&display_map));
2283            selection.goal = SelectionGoal::None;
2284        }
2285        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2286    }
2287
2288    pub fn delete_to_beginning_of_line(
2289        &mut self,
2290        _: &DeleteToBeginningOfLine,
2291        cx: &mut ViewContext<Self>,
2292    ) {
2293        self.start_transaction(cx);
2294        self.select_to_beginning_of_line(&SelectToBeginningOfLine(false), cx);
2295        self.backspace(&Backspace, cx);
2296        self.end_transaction(cx);
2297    }
2298
2299    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
2300        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2301        let mut selections = self.selections::<Point>(cx);
2302        {
2303            for selection in &mut selections {
2304                let head = selection.head().to_display_point(&display_map);
2305                let new_head = movement::line_end(&display_map, head);
2306                let anchor = new_head.to_point(&display_map);
2307                selection.start = anchor.clone();
2308                selection.end = anchor;
2309                selection.reversed = false;
2310                selection.goal = SelectionGoal::None;
2311            }
2312        }
2313        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2314    }
2315
2316    pub fn select_to_end_of_line(&mut self, _: &SelectToEndOfLine, cx: &mut ViewContext<Self>) {
2317        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2318        let mut selections = self.selections::<Point>(cx);
2319        for selection in &mut selections {
2320            let head = selection.head().to_display_point(&display_map);
2321            let new_head = movement::line_end(&display_map, head);
2322            selection.set_head(new_head.to_point(&display_map));
2323            selection.goal = SelectionGoal::None;
2324        }
2325        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2326    }
2327
2328    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
2329        self.start_transaction(cx);
2330        self.select_to_end_of_line(&SelectToEndOfLine, cx);
2331        self.delete(&Delete, cx);
2332        self.end_transaction(cx);
2333    }
2334
2335    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
2336        self.start_transaction(cx);
2337        self.select_to_end_of_line(&SelectToEndOfLine, cx);
2338        self.cut(&Cut, cx);
2339        self.end_transaction(cx);
2340    }
2341
2342    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
2343        let selection = Selection {
2344            id: post_inc(&mut self.next_selection_id),
2345            start: 0,
2346            end: 0,
2347            reversed: false,
2348            goal: SelectionGoal::None,
2349        };
2350        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
2351    }
2352
2353    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
2354        let mut selection = self.selections::<Point>(cx).last().unwrap().clone();
2355        selection.set_head(Point::zero());
2356        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
2357    }
2358
2359    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
2360        let cursor = self.buffer.read(cx).read(cx).len();
2361        let selection = Selection {
2362            id: post_inc(&mut self.next_selection_id),
2363            start: cursor,
2364            end: cursor,
2365            reversed: false,
2366            goal: SelectionGoal::None,
2367        };
2368        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
2369    }
2370
2371    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
2372        let mut selection = self.selections::<usize>(cx).first().unwrap().clone();
2373        selection.set_head(self.buffer.read(cx).read(cx).len());
2374        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
2375    }
2376
2377    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
2378        let selection = Selection {
2379            id: post_inc(&mut self.next_selection_id),
2380            start: 0,
2381            end: self.buffer.read(cx).read(cx).len(),
2382            reversed: false,
2383            goal: SelectionGoal::None,
2384        };
2385        self.update_selections(vec![selection], None, cx);
2386    }
2387
2388    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
2389        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2390        let mut selections = self.selections::<Point>(cx);
2391        let max_point = display_map.buffer_snapshot.max_point();
2392        for selection in &mut selections {
2393            let rows = selection.spanned_rows(true, &display_map).buffer_rows;
2394            selection.start = Point::new(rows.start, 0);
2395            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
2396            selection.reversed = false;
2397        }
2398        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2399    }
2400
2401    pub fn split_selection_into_lines(
2402        &mut self,
2403        _: &SplitSelectionIntoLines,
2404        cx: &mut ViewContext<Self>,
2405    ) {
2406        let mut to_unfold = Vec::new();
2407        let mut new_selections = Vec::new();
2408        {
2409            let selections = self.selections::<Point>(cx);
2410            let buffer = self.buffer.read(cx).read(cx);
2411            for selection in selections {
2412                for row in selection.start.row..selection.end.row {
2413                    let cursor = Point::new(row, buffer.line_len(row));
2414                    new_selections.push(Selection {
2415                        id: post_inc(&mut self.next_selection_id),
2416                        start: cursor,
2417                        end: cursor,
2418                        reversed: false,
2419                        goal: SelectionGoal::None,
2420                    });
2421                }
2422                new_selections.push(Selection {
2423                    id: selection.id,
2424                    start: selection.end,
2425                    end: selection.end,
2426                    reversed: false,
2427                    goal: SelectionGoal::None,
2428                });
2429                to_unfold.push(selection.start..selection.end);
2430            }
2431        }
2432        self.unfold_ranges(to_unfold, cx);
2433        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
2434    }
2435
2436    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
2437        self.add_selection(true, cx);
2438    }
2439
2440    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
2441        self.add_selection(false, cx);
2442    }
2443
2444    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
2445        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2446        let mut selections = self.selections::<Point>(cx);
2447        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
2448            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
2449            let range = oldest_selection.display_range(&display_map).sorted();
2450            let columns = cmp::min(range.start.column(), range.end.column())
2451                ..cmp::max(range.start.column(), range.end.column());
2452
2453            selections.clear();
2454            let mut stack = Vec::new();
2455            for row in range.start.row()..=range.end.row() {
2456                if let Some(selection) = self.build_columnar_selection(
2457                    &display_map,
2458                    row,
2459                    &columns,
2460                    oldest_selection.reversed,
2461                ) {
2462                    stack.push(selection.id);
2463                    selections.push(selection);
2464                }
2465            }
2466
2467            if above {
2468                stack.reverse();
2469            }
2470
2471            AddSelectionsState { above, stack }
2472        });
2473
2474        let last_added_selection = *state.stack.last().unwrap();
2475        let mut new_selections = Vec::new();
2476        if above == state.above {
2477            let end_row = if above {
2478                0
2479            } else {
2480                display_map.max_point().row()
2481            };
2482
2483            'outer: for selection in selections {
2484                if selection.id == last_added_selection {
2485                    let range = selection.display_range(&display_map).sorted();
2486                    debug_assert_eq!(range.start.row(), range.end.row());
2487                    let mut row = range.start.row();
2488                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
2489                    {
2490                        start..end
2491                    } else {
2492                        cmp::min(range.start.column(), range.end.column())
2493                            ..cmp::max(range.start.column(), range.end.column())
2494                    };
2495
2496                    while row != end_row {
2497                        if above {
2498                            row -= 1;
2499                        } else {
2500                            row += 1;
2501                        }
2502
2503                        if let Some(new_selection) = self.build_columnar_selection(
2504                            &display_map,
2505                            row,
2506                            &columns,
2507                            selection.reversed,
2508                        ) {
2509                            state.stack.push(new_selection.id);
2510                            if above {
2511                                new_selections.push(new_selection);
2512                                new_selections.push(selection);
2513                            } else {
2514                                new_selections.push(selection);
2515                                new_selections.push(new_selection);
2516                            }
2517
2518                            continue 'outer;
2519                        }
2520                    }
2521                }
2522
2523                new_selections.push(selection);
2524            }
2525        } else {
2526            new_selections = selections;
2527            new_selections.retain(|s| s.id != last_added_selection);
2528            state.stack.pop();
2529        }
2530
2531        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
2532        if state.stack.len() > 1 {
2533            self.add_selections_state = Some(state);
2534        }
2535    }
2536
2537    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
2538        let replace_newest = action.0;
2539        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2540        let buffer = &display_map.buffer_snapshot;
2541        let mut selections = self.selections::<usize>(cx);
2542        if let Some(mut select_next_state) = self.select_next_state.take() {
2543            let query = &select_next_state.query;
2544            if !select_next_state.done {
2545                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
2546                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
2547                let mut next_selected_range = None;
2548
2549                let bytes_after_last_selection =
2550                    buffer.bytes_in_range(last_selection.end..buffer.len());
2551                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
2552                let query_matches = query
2553                    .stream_find_iter(bytes_after_last_selection)
2554                    .map(|result| (last_selection.end, result))
2555                    .chain(
2556                        query
2557                            .stream_find_iter(bytes_before_first_selection)
2558                            .map(|result| (0, result)),
2559                    );
2560                for (start_offset, query_match) in query_matches {
2561                    let query_match = query_match.unwrap(); // can only fail due to I/O
2562                    let offset_range =
2563                        start_offset + query_match.start()..start_offset + query_match.end();
2564                    let display_range = offset_range.start.to_display_point(&display_map)
2565                        ..offset_range.end.to_display_point(&display_map);
2566
2567                    if !select_next_state.wordwise
2568                        || (!movement::is_inside_word(&display_map, display_range.start)
2569                            && !movement::is_inside_word(&display_map, display_range.end))
2570                    {
2571                        next_selected_range = Some(offset_range);
2572                        break;
2573                    }
2574                }
2575
2576                if let Some(next_selected_range) = next_selected_range {
2577                    if replace_newest {
2578                        if let Some(newest_id) =
2579                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
2580                        {
2581                            selections.retain(|s| s.id != newest_id);
2582                        }
2583                    }
2584                    selections.push(Selection {
2585                        id: post_inc(&mut self.next_selection_id),
2586                        start: next_selected_range.start,
2587                        end: next_selected_range.end,
2588                        reversed: false,
2589                        goal: SelectionGoal::None,
2590                    });
2591                    selections.sort_unstable_by_key(|s| s.start);
2592                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
2593                } else {
2594                    select_next_state.done = true;
2595                }
2596            }
2597
2598            self.select_next_state = Some(select_next_state);
2599        } else if selections.len() == 1 {
2600            let selection = selections.last_mut().unwrap();
2601            if selection.start == selection.end {
2602                let word_range = movement::surrounding_word(
2603                    &display_map,
2604                    selection.start.to_display_point(&display_map),
2605                );
2606                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
2607                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
2608                selection.goal = SelectionGoal::None;
2609                selection.reversed = false;
2610
2611                let query = buffer
2612                    .text_for_range(selection.start..selection.end)
2613                    .collect::<String>();
2614                let select_state = SelectNextState {
2615                    query: AhoCorasick::new_auto_configured(&[query]),
2616                    wordwise: true,
2617                    done: false,
2618                };
2619                self.update_selections(selections, Some(Autoscroll::Newest), cx);
2620                self.select_next_state = Some(select_state);
2621            } else {
2622                let query = buffer
2623                    .text_for_range(selection.start..selection.end)
2624                    .collect::<String>();
2625                self.select_next_state = Some(SelectNextState {
2626                    query: AhoCorasick::new_auto_configured(&[query]),
2627                    wordwise: false,
2628                    done: false,
2629                });
2630                self.select_next(action, cx);
2631            }
2632        }
2633    }
2634
2635    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
2636        // Get the line comment prefix. Split its trailing whitespace into a separate string,
2637        // as that portion won't be used for detecting if a line is a comment.
2638        let full_comment_prefix =
2639            if let Some(prefix) = self.language(cx).and_then(|l| l.line_comment_prefix()) {
2640                prefix.to_string()
2641            } else {
2642                return;
2643            };
2644        let comment_prefix = full_comment_prefix.trim_end_matches(' ');
2645        let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
2646
2647        self.start_transaction(cx);
2648        let mut selections = self.selections::<Point>(cx);
2649        let mut all_selection_lines_are_comments = true;
2650        let mut edit_ranges = Vec::new();
2651        let mut last_toggled_row = None;
2652        self.buffer.update(cx, |buffer, cx| {
2653            for selection in &mut selections {
2654                edit_ranges.clear();
2655                let snapshot = buffer.snapshot(cx);
2656
2657                let end_row =
2658                    if selection.end.row > selection.start.row && selection.end.column == 0 {
2659                        selection.end.row
2660                    } else {
2661                        selection.end.row + 1
2662                    };
2663
2664                for row in selection.start.row..end_row {
2665                    // If multiple selections contain a given row, avoid processing that
2666                    // row more than once.
2667                    if last_toggled_row == Some(row) {
2668                        continue;
2669                    } else {
2670                        last_toggled_row = Some(row);
2671                    }
2672
2673                    if snapshot.is_line_blank(row) {
2674                        continue;
2675                    }
2676
2677                    let start = Point::new(row, snapshot.indent_column_for_line(row));
2678                    let mut line_bytes = snapshot
2679                        .bytes_in_range(start..snapshot.max_point())
2680                        .flatten()
2681                        .copied();
2682
2683                    // If this line currently begins with the line comment prefix, then record
2684                    // the range containing the prefix.
2685                    if all_selection_lines_are_comments
2686                        && line_bytes
2687                            .by_ref()
2688                            .take(comment_prefix.len())
2689                            .eq(comment_prefix.bytes())
2690                    {
2691                        // Include any whitespace that matches the comment prefix.
2692                        let matching_whitespace_len = line_bytes
2693                            .zip(comment_prefix_whitespace.bytes())
2694                            .take_while(|(a, b)| a == b)
2695                            .count() as u32;
2696                        let end = Point::new(
2697                            row,
2698                            start.column + comment_prefix.len() as u32 + matching_whitespace_len,
2699                        );
2700                        edit_ranges.push(start..end);
2701                    }
2702                    // If this line does not begin with the line comment prefix, then record
2703                    // the position where the prefix should be inserted.
2704                    else {
2705                        all_selection_lines_are_comments = false;
2706                        edit_ranges.push(start..start);
2707                    }
2708                }
2709
2710                if !edit_ranges.is_empty() {
2711                    if all_selection_lines_are_comments {
2712                        buffer.edit(edit_ranges.iter().cloned(), "", cx);
2713                    } else {
2714                        let min_column = edit_ranges.iter().map(|r| r.start.column).min().unwrap();
2715                        let edit_ranges = edit_ranges.iter().map(|range| {
2716                            let position = Point::new(range.start.row, min_column);
2717                            position..position
2718                        });
2719                        buffer.edit(edit_ranges, &full_comment_prefix, cx);
2720                    }
2721                }
2722            }
2723        });
2724
2725        self.update_selections(self.selections::<usize>(cx), Some(Autoscroll::Fit), cx);
2726        self.end_transaction(cx);
2727    }
2728
2729    pub fn select_larger_syntax_node(
2730        &mut self,
2731        _: &SelectLargerSyntaxNode,
2732        cx: &mut ViewContext<Self>,
2733    ) {
2734        let old_selections = self.selections::<usize>(cx).into_boxed_slice();
2735        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2736        let buffer = self.buffer.read(cx).snapshot(cx);
2737
2738        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2739        let mut selected_larger_node = false;
2740        let mut new_selections = old_selections
2741            .iter()
2742            .map(|selection| {
2743                let old_range = selection.start..selection.end;
2744                let mut new_range = old_range.clone();
2745                while let Some(containing_range) =
2746                    buffer.range_for_syntax_ancestor(new_range.clone())
2747                {
2748                    new_range = containing_range;
2749                    if !display_map.intersects_fold(new_range.start)
2750                        && !display_map.intersects_fold(new_range.end)
2751                    {
2752                        break;
2753                    }
2754                }
2755
2756                selected_larger_node |= new_range != old_range;
2757                Selection {
2758                    id: selection.id,
2759                    start: new_range.start,
2760                    end: new_range.end,
2761                    goal: SelectionGoal::None,
2762                    reversed: selection.reversed,
2763                }
2764            })
2765            .collect::<Vec<_>>();
2766
2767        if selected_larger_node {
2768            stack.push(old_selections);
2769            new_selections.sort_unstable_by_key(|selection| selection.start);
2770            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
2771        }
2772        self.select_larger_syntax_node_stack = stack;
2773    }
2774
2775    pub fn select_smaller_syntax_node(
2776        &mut self,
2777        _: &SelectSmallerSyntaxNode,
2778        cx: &mut ViewContext<Self>,
2779    ) {
2780        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
2781        if let Some(selections) = stack.pop() {
2782            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
2783        }
2784        self.select_larger_syntax_node_stack = stack;
2785    }
2786
2787    pub fn move_to_enclosing_bracket(
2788        &mut self,
2789        _: &MoveToEnclosingBracket,
2790        cx: &mut ViewContext<Self>,
2791    ) {
2792        let mut selections = self.selections::<usize>(cx);
2793        let buffer = self.buffer.read(cx).snapshot(cx);
2794        for selection in &mut selections {
2795            if let Some((open_range, close_range)) =
2796                buffer.enclosing_bracket_ranges(selection.start..selection.end)
2797            {
2798                let close_range = close_range.to_inclusive();
2799                let destination = if close_range.contains(&selection.start)
2800                    && close_range.contains(&selection.end)
2801                {
2802                    open_range.end
2803                } else {
2804                    *close_range.start()
2805                };
2806                selection.start = destination;
2807                selection.end = destination;
2808            }
2809        }
2810
2811        self.update_selections(selections, Some(Autoscroll::Fit), cx);
2812    }
2813
2814    pub fn show_next_diagnostic(&mut self, _: &ShowNextDiagnostic, cx: &mut ViewContext<Self>) {
2815        let buffer = self.buffer.read(cx).snapshot(cx);
2816        let selection = self.newest_selection::<usize>(cx);
2817        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
2818            active_diagnostics
2819                .primary_range
2820                .to_offset(&buffer)
2821                .to_inclusive()
2822        });
2823        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
2824            if active_primary_range.contains(&selection.head()) {
2825                *active_primary_range.end()
2826            } else {
2827                selection.head()
2828            }
2829        } else {
2830            selection.head()
2831        };
2832
2833        loop {
2834            let next_group = buffer
2835                .diagnostics_in_range::<_, usize>(search_start..buffer.len())
2836                .find_map(|entry| {
2837                    if entry.diagnostic.is_primary
2838                        && !entry.range.is_empty()
2839                        && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
2840                    {
2841                        Some((entry.range, entry.diagnostic.group_id))
2842                    } else {
2843                        None
2844                    }
2845                });
2846
2847            if let Some((primary_range, group_id)) = next_group {
2848                self.activate_diagnostics(group_id, cx);
2849                self.update_selections(
2850                    vec![Selection {
2851                        id: selection.id,
2852                        start: primary_range.start,
2853                        end: primary_range.start,
2854                        reversed: false,
2855                        goal: SelectionGoal::None,
2856                    }],
2857                    Some(Autoscroll::Center),
2858                    cx,
2859                );
2860                break;
2861            } else if search_start == 0 {
2862                break;
2863            } else {
2864                // Cycle around to the start of the buffer.
2865                search_start = 0;
2866            }
2867        }
2868    }
2869
2870    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
2871        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
2872            let buffer = self.buffer.read(cx).snapshot(cx);
2873            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
2874            let is_valid = buffer
2875                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone())
2876                .any(|entry| {
2877                    entry.diagnostic.is_primary
2878                        && !entry.range.is_empty()
2879                        && entry.range.start == primary_range_start
2880                        && entry.diagnostic.message == active_diagnostics.primary_message
2881                });
2882
2883            if is_valid != active_diagnostics.is_valid {
2884                active_diagnostics.is_valid = is_valid;
2885                let mut new_styles = HashMap::new();
2886                for (block_id, diagnostic) in &active_diagnostics.blocks {
2887                    let build_settings = self.build_settings.clone();
2888                    let diagnostic = diagnostic.clone();
2889                    new_styles.insert(*block_id, move |cx: &BlockContext| {
2890                        let diagnostic = diagnostic.clone();
2891                        let settings = build_settings.borrow()(cx.cx);
2892                        render_diagnostic(diagnostic, &settings.style, is_valid, cx.anchor_x)
2893                    });
2894                }
2895                self.display_map
2896                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
2897            }
2898        }
2899    }
2900
2901    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
2902        self.dismiss_diagnostics(cx);
2903        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
2904            let buffer = self.buffer.read(cx).snapshot(cx);
2905
2906            let mut primary_range = None;
2907            let mut primary_message = None;
2908            let mut group_end = Point::zero();
2909            let diagnostic_group = buffer
2910                .diagnostic_group::<Point>(group_id)
2911                .map(|entry| {
2912                    if entry.range.end > group_end {
2913                        group_end = entry.range.end;
2914                    }
2915                    if entry.diagnostic.is_primary {
2916                        primary_range = Some(entry.range.clone());
2917                        primary_message = Some(entry.diagnostic.message.clone());
2918                    }
2919                    entry
2920                })
2921                .collect::<Vec<_>>();
2922            let primary_range = primary_range.unwrap();
2923            let primary_message = primary_message.unwrap();
2924            let primary_range =
2925                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
2926
2927            let blocks = display_map
2928                .insert_blocks(
2929                    diagnostic_group.iter().map(|entry| {
2930                        let build_settings = self.build_settings.clone();
2931                        let diagnostic = entry.diagnostic.clone();
2932                        let message_height = diagnostic.message.lines().count() as u8;
2933
2934                        BlockProperties {
2935                            position: entry.range.start,
2936                            height: message_height,
2937                            render: Arc::new(move |cx| {
2938                                let settings = build_settings.borrow()(cx.cx);
2939                                let diagnostic = diagnostic.clone();
2940                                render_diagnostic(diagnostic, &settings.style, true, cx.anchor_x)
2941                            }),
2942                            disposition: BlockDisposition::Below,
2943                        }
2944                    }),
2945                    cx,
2946                )
2947                .into_iter()
2948                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
2949                .collect();
2950
2951            Some(ActiveDiagnosticGroup {
2952                primary_range,
2953                primary_message,
2954                blocks,
2955                is_valid: true,
2956            })
2957        });
2958    }
2959
2960    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
2961        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
2962            self.display_map.update(cx, |display_map, cx| {
2963                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
2964            });
2965            cx.notify();
2966        }
2967    }
2968
2969    fn build_columnar_selection(
2970        &mut self,
2971        display_map: &DisplaySnapshot,
2972        row: u32,
2973        columns: &Range<u32>,
2974        reversed: bool,
2975    ) -> Option<Selection<Point>> {
2976        let is_empty = columns.start == columns.end;
2977        let line_len = display_map.line_len(row);
2978        if columns.start < line_len || (is_empty && columns.start == line_len) {
2979            let start = DisplayPoint::new(row, columns.start);
2980            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
2981            Some(Selection {
2982                id: post_inc(&mut self.next_selection_id),
2983                start: start.to_point(display_map),
2984                end: end.to_point(display_map),
2985                reversed,
2986                goal: SelectionGoal::ColumnRange {
2987                    start: columns.start,
2988                    end: columns.end,
2989                },
2990            })
2991        } else {
2992            None
2993        }
2994    }
2995
2996    pub fn active_selection_sets<'a>(
2997        &'a self,
2998        cx: &'a AppContext,
2999    ) -> impl 'a + Iterator<Item = SelectionSetId> {
3000        let buffer = self.buffer.read(cx);
3001        let replica_id = buffer.replica_id();
3002        buffer
3003            .selection_sets(cx)
3004            .filter(move |(set_id, set)| {
3005                set.active && (set_id.replica_id != replica_id || **set_id == self.selection_set_id)
3006            })
3007            .map(|(set_id, _)| *set_id)
3008    }
3009
3010    pub fn intersecting_selections<'a>(
3011        &'a self,
3012        set_id: SelectionSetId,
3013        range: Range<DisplayPoint>,
3014        cx: &'a mut MutableAppContext,
3015    ) -> Vec<Selection<DisplayPoint>> {
3016        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3017        let buffer = self.buffer.read(cx);
3018
3019        let pending_selection = if set_id == self.selection_set_id {
3020            self.pending_selection.as_ref().and_then(|pending| {
3021                let selection_start = pending.selection.start.to_display_point(&display_map);
3022                let selection_end = pending.selection.end.to_display_point(&display_map);
3023                if selection_start <= range.end || selection_end <= range.end {
3024                    Some(Selection {
3025                        id: pending.selection.id,
3026                        start: selection_start,
3027                        end: selection_end,
3028                        reversed: pending.selection.reversed,
3029                        goal: pending.selection.goal,
3030                    })
3031                } else {
3032                    None
3033                }
3034            })
3035        } else {
3036            None
3037        };
3038
3039        let range = (range.start.to_offset(&display_map, Bias::Left), Bias::Left)
3040            ..(range.end.to_offset(&display_map, Bias::Left), Bias::Right);
3041        buffer
3042            .selection_set(set_id, cx)
3043            .unwrap()
3044            .intersecting_selections::<Point, _>(range, &buffer.read(cx))
3045            .map(move |s| Selection {
3046                id: s.id,
3047                start: s.start.to_display_point(&display_map),
3048                end: s.end.to_display_point(&display_map),
3049                reversed: s.reversed,
3050                goal: s.goal,
3051            })
3052            .chain(pending_selection)
3053            .collect()
3054    }
3055
3056    pub fn selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
3057    where
3058        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
3059    {
3060        let buffer = self.buffer.read(cx).snapshot(cx);
3061        let mut selections = self.selection_set(cx).selections::<D>(&buffer).peekable();
3062        let mut pending_selection = self.pending_selection(cx);
3063
3064        iter::from_fn(move || {
3065            if let Some(pending) = pending_selection.as_mut() {
3066                while let Some(next_selection) = selections.peek() {
3067                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
3068                        let next_selection = selections.next().unwrap();
3069                        if next_selection.start < pending.start {
3070                            pending.start = next_selection.start;
3071                        }
3072                        if next_selection.end > pending.end {
3073                            pending.end = next_selection.end;
3074                        }
3075                    } else if next_selection.end < pending.start {
3076                        return selections.next();
3077                    } else {
3078                        break;
3079                    }
3080                }
3081
3082                pending_selection.take()
3083            } else {
3084                selections.next()
3085            }
3086        })
3087        .collect()
3088    }
3089
3090    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
3091        &self,
3092        cx: &AppContext,
3093    ) -> Option<Selection<D>> {
3094        let buffer = self.buffer.read(cx).read(cx);
3095        self.pending_selection.as_ref().map(|pending| Selection {
3096            id: pending.selection.id,
3097            start: pending.selection.start.summary::<D>(&buffer),
3098            end: pending.selection.end.summary::<D>(&buffer),
3099            reversed: pending.selection.reversed,
3100            goal: pending.selection.goal,
3101        })
3102    }
3103
3104    fn selection_count<'a>(&self, cx: &'a AppContext) -> usize {
3105        let mut selection_count = self.selection_set(cx).len();
3106        if self.pending_selection.is_some() {
3107            selection_count += 1;
3108        }
3109        selection_count
3110    }
3111
3112    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
3113        &self,
3114        snapshot: &MultiBufferSnapshot,
3115        cx: &AppContext,
3116    ) -> Selection<D> {
3117        self.selection_set(cx)
3118            .oldest_selection(snapshot)
3119            .or_else(|| self.pending_selection(cx))
3120            .unwrap()
3121    }
3122
3123    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
3124        &self,
3125        cx: &AppContext,
3126    ) -> Selection<D> {
3127        self.pending_selection(cx)
3128            .or_else(|| {
3129                self.selection_set(cx)
3130                    .newest_selection(&self.buffer.read(cx).read(cx))
3131            })
3132            .unwrap()
3133    }
3134
3135    fn selection_set<'a>(&self, cx: &'a AppContext) -> &'a SelectionSet {
3136        self.buffer
3137            .read(cx)
3138            .selection_set(self.selection_set_id, cx)
3139            .unwrap()
3140    }
3141
3142    pub fn update_selections<T>(
3143        &mut self,
3144        mut selections: Vec<Selection<T>>,
3145        autoscroll: Option<Autoscroll>,
3146        cx: &mut ViewContext<Self>,
3147    ) where
3148        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
3149    {
3150        // Merge overlapping selections.
3151        let buffer = self.buffer.read(cx).snapshot(cx);
3152        let mut i = 1;
3153        while i < selections.len() {
3154            if selections[i - 1].end >= selections[i].start {
3155                let removed = selections.remove(i);
3156                if removed.start < selections[i - 1].start {
3157                    selections[i - 1].start = removed.start;
3158                }
3159                if removed.end > selections[i - 1].end {
3160                    selections[i - 1].end = removed.end;
3161                }
3162            } else {
3163                i += 1;
3164            }
3165        }
3166
3167        self.pending_selection = None;
3168        self.add_selections_state = None;
3169        self.select_next_state = None;
3170        self.select_larger_syntax_node_stack.clear();
3171        while let Some(autoclose_pair) = self.autoclose_stack.last() {
3172            let all_selections_inside_autoclose_ranges =
3173                if selections.len() == autoclose_pair.ranges.len() {
3174                    selections
3175                        .iter()
3176                        .zip(autoclose_pair.ranges.iter().map(|r| r.to_point(&buffer)))
3177                        .all(|(selection, autoclose_range)| {
3178                            let head = selection.head().to_point(&buffer);
3179                            autoclose_range.start <= head && autoclose_range.end >= head
3180                        })
3181                } else {
3182                    false
3183                };
3184
3185            if all_selections_inside_autoclose_ranges {
3186                break;
3187            } else {
3188                self.autoclose_stack.pop();
3189            }
3190        }
3191
3192        if let Some(autoscroll) = autoscroll {
3193            self.request_autoscroll(autoscroll, cx);
3194        }
3195        self.pause_cursor_blinking(cx);
3196
3197        self.buffer.update(cx, |buffer, cx| {
3198            buffer
3199                .update_selection_set(self.selection_set_id, &selections, cx)
3200                .unwrap();
3201        });
3202    }
3203
3204    fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
3205        self.autoscroll_request = Some(autoscroll);
3206        cx.notify();
3207    }
3208
3209    fn start_transaction(&mut self, cx: &mut ViewContext<Self>) {
3210        self.end_selection(cx);
3211        self.buffer.update(cx, |buffer, cx| {
3212            buffer
3213                .start_transaction([self.selection_set_id], cx)
3214                .unwrap()
3215        });
3216    }
3217
3218    fn end_transaction(&self, cx: &mut ViewContext<Self>) {
3219        self.buffer.update(cx, |buffer, cx| {
3220            buffer.end_transaction([self.selection_set_id], cx).unwrap()
3221        });
3222    }
3223
3224    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
3225        log::info!("Editor::page_up");
3226    }
3227
3228    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
3229        log::info!("Editor::page_down");
3230    }
3231
3232    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
3233        let mut fold_ranges = Vec::new();
3234
3235        let selections = self.selections::<Point>(cx);
3236        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3237        for selection in selections {
3238            let range = selection.display_range(&display_map).sorted();
3239            let buffer_start_row = range.start.to_point(&display_map).row;
3240
3241            for row in (0..=range.end.row()).rev() {
3242                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
3243                    let fold_range = self.foldable_range_for_line(&display_map, row);
3244                    if fold_range.end.row >= buffer_start_row {
3245                        fold_ranges.push(fold_range);
3246                        if row <= range.start.row() {
3247                            break;
3248                        }
3249                    }
3250                }
3251            }
3252        }
3253
3254        self.fold_ranges(fold_ranges, cx);
3255    }
3256
3257    pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext<Self>) {
3258        let selections = self.selections::<Point>(cx);
3259        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3260        let buffer = &display_map.buffer_snapshot;
3261        let ranges = selections
3262            .iter()
3263            .map(|s| {
3264                let range = s.display_range(&display_map).sorted();
3265                let mut start = range.start.to_point(&display_map);
3266                let mut end = range.end.to_point(&display_map);
3267                start.column = 0;
3268                end.column = buffer.line_len(end.row);
3269                start..end
3270            })
3271            .collect::<Vec<_>>();
3272        self.unfold_ranges(ranges, cx);
3273    }
3274
3275    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
3276        let max_point = display_map.max_point();
3277        if display_row >= max_point.row() {
3278            false
3279        } else {
3280            let (start_indent, is_blank) = display_map.line_indent(display_row);
3281            if is_blank {
3282                false
3283            } else {
3284                for display_row in display_row + 1..=max_point.row() {
3285                    let (indent, is_blank) = display_map.line_indent(display_row);
3286                    if !is_blank {
3287                        return indent > start_indent;
3288                    }
3289                }
3290                false
3291            }
3292        }
3293    }
3294
3295    fn foldable_range_for_line(
3296        &self,
3297        display_map: &DisplaySnapshot,
3298        start_row: u32,
3299    ) -> Range<Point> {
3300        let max_point = display_map.max_point();
3301
3302        let (start_indent, _) = display_map.line_indent(start_row);
3303        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
3304        let mut end = None;
3305        for row in start_row + 1..=max_point.row() {
3306            let (indent, is_blank) = display_map.line_indent(row);
3307            if !is_blank && indent <= start_indent {
3308                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
3309                break;
3310            }
3311        }
3312
3313        let end = end.unwrap_or(max_point);
3314        return start.to_point(display_map)..end.to_point(display_map);
3315    }
3316
3317    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
3318        let selections = self.selections::<Point>(cx);
3319        let ranges = selections.into_iter().map(|s| s.start..s.end);
3320        self.fold_ranges(ranges, cx);
3321    }
3322
3323    fn fold_ranges<T: ToOffset>(
3324        &mut self,
3325        ranges: impl IntoIterator<Item = Range<T>>,
3326        cx: &mut ViewContext<Self>,
3327    ) {
3328        let mut ranges = ranges.into_iter().peekable();
3329        if ranges.peek().is_some() {
3330            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
3331            self.request_autoscroll(Autoscroll::Fit, cx);
3332            cx.notify();
3333        }
3334    }
3335
3336    fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
3337        if !ranges.is_empty() {
3338            self.display_map
3339                .update(cx, |map, cx| map.unfold(ranges, cx));
3340            self.request_autoscroll(Autoscroll::Fit, cx);
3341            cx.notify();
3342        }
3343    }
3344
3345    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
3346        self.display_map
3347            .update(cx, |map, cx| map.snapshot(cx))
3348            .longest_row()
3349    }
3350
3351    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
3352        self.display_map
3353            .update(cx, |map, cx| map.snapshot(cx))
3354            .max_point()
3355    }
3356
3357    pub fn text(&self, cx: &AppContext) -> String {
3358        self.buffer.read(cx).read(cx).text()
3359    }
3360
3361    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
3362        self.display_map
3363            .update(cx, |map, cx| map.snapshot(cx))
3364            .text()
3365    }
3366
3367    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
3368        self.display_map
3369            .update(cx, |map, cx| map.set_wrap_width(width, cx))
3370    }
3371
3372    pub fn set_highlighted_row(&mut self, row: Option<u32>) {
3373        self.highlighted_row = row;
3374    }
3375
3376    pub fn highlighted_row(&mut self) -> Option<u32> {
3377        self.highlighted_row
3378    }
3379
3380    fn next_blink_epoch(&mut self) -> usize {
3381        self.blink_epoch += 1;
3382        self.blink_epoch
3383    }
3384
3385    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
3386        self.show_local_cursors = true;
3387        cx.notify();
3388
3389        let epoch = self.next_blink_epoch();
3390        cx.spawn(|this, mut cx| {
3391            let this = this.downgrade();
3392            async move {
3393                Timer::after(CURSOR_BLINK_INTERVAL).await;
3394                if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
3395                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
3396                }
3397            }
3398        })
3399        .detach();
3400    }
3401
3402    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
3403        if epoch == self.blink_epoch {
3404            self.blinking_paused = false;
3405            self.blink_cursors(epoch, cx);
3406        }
3407    }
3408
3409    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
3410        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
3411            self.show_local_cursors = !self.show_local_cursors;
3412            cx.notify();
3413
3414            let epoch = self.next_blink_epoch();
3415            cx.spawn(|this, mut cx| {
3416                let this = this.downgrade();
3417                async move {
3418                    Timer::after(CURSOR_BLINK_INTERVAL).await;
3419                    if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
3420                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
3421                    }
3422                }
3423            })
3424            .detach();
3425        }
3426    }
3427
3428    pub fn show_local_cursors(&self) -> bool {
3429        self.show_local_cursors
3430    }
3431
3432    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
3433        self.refresh_active_diagnostics(cx);
3434        cx.notify();
3435    }
3436
3437    fn on_buffer_event(
3438        &mut self,
3439        _: ModelHandle<MultiBuffer>,
3440        event: &language::Event,
3441        cx: &mut ViewContext<Self>,
3442    ) {
3443        match event {
3444            language::Event::Edited => cx.emit(Event::Edited),
3445            language::Event::Dirtied => cx.emit(Event::Dirtied),
3446            language::Event::Saved => cx.emit(Event::Saved),
3447            language::Event::FileHandleChanged => cx.emit(Event::FileHandleChanged),
3448            language::Event::Reloaded => cx.emit(Event::FileHandleChanged),
3449            language::Event::Closed => cx.emit(Event::Closed),
3450            _ => {}
3451        }
3452    }
3453
3454    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
3455        cx.notify();
3456    }
3457}
3458
3459impl EditorSnapshot {
3460    pub fn is_focused(&self) -> bool {
3461        self.is_focused
3462    }
3463
3464    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
3465        self.placeholder_text.as_ref()
3466    }
3467
3468    pub fn scroll_position(&self) -> Vector2F {
3469        compute_scroll_position(
3470            &self.display_snapshot,
3471            self.scroll_position,
3472            &self.scroll_top_anchor,
3473        )
3474    }
3475}
3476
3477impl Deref for EditorSnapshot {
3478    type Target = DisplaySnapshot;
3479
3480    fn deref(&self) -> &Self::Target {
3481        &self.display_snapshot
3482    }
3483}
3484
3485impl EditorSettings {
3486    #[cfg(any(test, feature = "test-support"))]
3487    pub fn test(cx: &AppContext) -> Self {
3488        Self {
3489            tab_size: 4,
3490            soft_wrap: SoftWrap::None,
3491            style: {
3492                let font_cache: &gpui::FontCache = cx.font_cache();
3493                let font_family_name = Arc::from("Monaco");
3494                let font_properties = Default::default();
3495                let font_family_id = font_cache.load_family(&[&font_family_name]).unwrap();
3496                let font_id = font_cache
3497                    .select_font(font_family_id, &font_properties)
3498                    .unwrap();
3499                EditorStyle {
3500                    text: gpui::fonts::TextStyle {
3501                        font_family_name,
3502                        font_family_id,
3503                        font_id,
3504                        font_size: 14.,
3505                        color: gpui::color::Color::from_u32(0xff0000ff),
3506                        font_properties,
3507                        underline: None,
3508                    },
3509                    placeholder_text: None,
3510                    background: Default::default(),
3511                    gutter_background: Default::default(),
3512                    active_line_background: Default::default(),
3513                    highlighted_line_background: Default::default(),
3514                    line_number: Default::default(),
3515                    line_number_active: Default::default(),
3516                    selection: Default::default(),
3517                    guest_selections: Default::default(),
3518                    syntax: Default::default(),
3519                    error_diagnostic: Default::default(),
3520                    invalid_error_diagnostic: Default::default(),
3521                    warning_diagnostic: Default::default(),
3522                    invalid_warning_diagnostic: Default::default(),
3523                    information_diagnostic: Default::default(),
3524                    invalid_information_diagnostic: Default::default(),
3525                    hint_diagnostic: Default::default(),
3526                    invalid_hint_diagnostic: Default::default(),
3527                }
3528            },
3529        }
3530    }
3531}
3532
3533fn compute_scroll_position(
3534    snapshot: &DisplaySnapshot,
3535    mut scroll_position: Vector2F,
3536    scroll_top_anchor: &Anchor,
3537) -> Vector2F {
3538    let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
3539    scroll_position.set_y(scroll_top + scroll_position.y());
3540    scroll_position
3541}
3542
3543pub enum Event {
3544    Activate,
3545    Edited,
3546    Blurred,
3547    Dirtied,
3548    Saved,
3549    FileHandleChanged,
3550    Closed,
3551}
3552
3553impl Entity for Editor {
3554    type Event = Event;
3555
3556    fn release(&mut self, cx: &mut MutableAppContext) {
3557        self.buffer.update(cx, |buffer, cx| {
3558            buffer
3559                .remove_selection_set(self.selection_set_id, cx)
3560                .unwrap();
3561        });
3562    }
3563}
3564
3565impl View for Editor {
3566    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
3567        let settings = self.build_settings.borrow_mut()(cx);
3568        self.display_map.update(cx, |map, cx| {
3569            map.set_font(
3570                settings.style.text.font_id,
3571                settings.style.text.font_size,
3572                cx,
3573            )
3574        });
3575        EditorElement::new(self.handle.clone(), settings).boxed()
3576    }
3577
3578    fn ui_name() -> &'static str {
3579        "Editor"
3580    }
3581
3582    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
3583        self.focused = true;
3584        self.blink_cursors(self.blink_epoch, cx);
3585        self.buffer.update(cx, |buffer, cx| {
3586            buffer
3587                .set_active_selection_set(Some(self.selection_set_id), cx)
3588                .unwrap();
3589        });
3590    }
3591
3592    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
3593        self.focused = false;
3594        self.show_local_cursors = false;
3595        self.buffer.update(cx, |buffer, cx| {
3596            buffer.set_active_selection_set(None, cx).unwrap();
3597        });
3598        cx.emit(Event::Blurred);
3599        cx.notify();
3600    }
3601
3602    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
3603        let mut cx = Self::default_keymap_context();
3604        let mode = match self.mode {
3605            EditorMode::SingleLine => "single_line",
3606            EditorMode::AutoHeight { .. } => "auto_height",
3607            EditorMode::Full => "full",
3608        };
3609        cx.map.insert("mode".into(), mode.into());
3610        cx
3611    }
3612}
3613
3614impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
3615    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
3616        let start = self.start.to_point(buffer);
3617        let end = self.end.to_point(buffer);
3618        if self.reversed {
3619            end..start
3620        } else {
3621            start..end
3622        }
3623    }
3624
3625    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
3626        let start = self.start.to_offset(buffer);
3627        let end = self.end.to_offset(buffer);
3628        if self.reversed {
3629            end..start
3630        } else {
3631            start..end
3632        }
3633    }
3634
3635    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
3636        let start = self
3637            .start
3638            .to_point(&map.buffer_snapshot)
3639            .to_display_point(map);
3640        let end = self
3641            .end
3642            .to_point(&map.buffer_snapshot)
3643            .to_display_point(map);
3644        if self.reversed {
3645            end..start
3646        } else {
3647            start..end
3648        }
3649    }
3650
3651    fn spanned_rows(
3652        &self,
3653        include_end_if_at_line_start: bool,
3654        map: &DisplaySnapshot,
3655    ) -> SpannedRows {
3656        let display_start = self
3657            .start
3658            .to_point(&map.buffer_snapshot)
3659            .to_display_point(map);
3660        let mut display_end = self
3661            .end
3662            .to_point(&map.buffer_snapshot)
3663            .to_display_point(map);
3664        if !include_end_if_at_line_start
3665            && display_end.row() != map.max_point().row()
3666            && display_start.row() != display_end.row()
3667            && display_end.column() == 0
3668        {
3669            *display_end.row_mut() -= 1;
3670        }
3671
3672        let (display_start, buffer_start) = map.prev_row_boundary(display_start);
3673        let (display_end, buffer_end) = map.next_row_boundary(display_end);
3674
3675        SpannedRows {
3676            buffer_rows: buffer_start.row..buffer_end.row + 1,
3677            display_rows: display_start.row()..display_end.row() + 1,
3678        }
3679    }
3680}
3681
3682fn render_diagnostic(
3683    diagnostic: Diagnostic,
3684    style: &EditorStyle,
3685    valid: bool,
3686    anchor_x: f32,
3687) -> ElementBox {
3688    let mut text_style = style.text.clone();
3689    text_style.color = diagnostic_style(diagnostic.severity, valid, &style).text;
3690    Text::new(diagnostic.message, text_style)
3691        .contained()
3692        .with_margin_left(anchor_x)
3693        .boxed()
3694}
3695
3696pub fn diagnostic_style(
3697    severity: DiagnosticSeverity,
3698    valid: bool,
3699    style: &EditorStyle,
3700) -> DiagnosticStyle {
3701    match (severity, valid) {
3702        (DiagnosticSeverity::ERROR, true) => style.error_diagnostic,
3703        (DiagnosticSeverity::ERROR, false) => style.invalid_error_diagnostic,
3704        (DiagnosticSeverity::WARNING, true) => style.warning_diagnostic,
3705        (DiagnosticSeverity::WARNING, false) => style.invalid_warning_diagnostic,
3706        (DiagnosticSeverity::INFORMATION, true) => style.information_diagnostic,
3707        (DiagnosticSeverity::INFORMATION, false) => style.invalid_information_diagnostic,
3708        (DiagnosticSeverity::HINT, true) => style.hint_diagnostic,
3709        (DiagnosticSeverity::HINT, false) => style.invalid_hint_diagnostic,
3710        _ => Default::default(),
3711    }
3712}
3713
3714#[cfg(test)]
3715mod tests {
3716    use super::*;
3717    use language::LanguageConfig;
3718    use text::Point;
3719    use unindent::Unindent;
3720    use util::test::sample_text;
3721
3722    #[gpui::test]
3723    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
3724        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
3725        let settings = EditorSettings::test(cx);
3726        let (_, editor) =
3727            cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3728
3729        editor.update(cx, |view, cx| {
3730            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
3731        });
3732
3733        assert_eq!(
3734            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3735            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
3736        );
3737
3738        editor.update(cx, |view, cx| {
3739            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
3740        });
3741
3742        assert_eq!(
3743            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3744            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3745        );
3746
3747        editor.update(cx, |view, cx| {
3748            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
3749        });
3750
3751        assert_eq!(
3752            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3753            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
3754        );
3755
3756        editor.update(cx, |view, cx| {
3757            view.end_selection(cx);
3758            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
3759        });
3760
3761        assert_eq!(
3762            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3763            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
3764        );
3765
3766        editor.update(cx, |view, cx| {
3767            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
3768            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
3769        });
3770
3771        assert_eq!(
3772            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3773            [
3774                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
3775                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
3776            ]
3777        );
3778
3779        editor.update(cx, |view, cx| {
3780            view.end_selection(cx);
3781        });
3782
3783        assert_eq!(
3784            editor.update(cx, |view, cx| view.selection_ranges(cx)),
3785            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
3786        );
3787    }
3788
3789    #[gpui::test]
3790    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
3791        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
3792        let settings = EditorSettings::test(cx);
3793        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3794
3795        view.update(cx, |view, cx| {
3796            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
3797            assert_eq!(
3798                view.selection_ranges(cx),
3799                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
3800            );
3801        });
3802
3803        view.update(cx, |view, cx| {
3804            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
3805            assert_eq!(
3806                view.selection_ranges(cx),
3807                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3808            );
3809        });
3810
3811        view.update(cx, |view, cx| {
3812            view.cancel(&Cancel, cx);
3813            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
3814            assert_eq!(
3815                view.selection_ranges(cx),
3816                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
3817            );
3818        });
3819    }
3820
3821    #[gpui::test]
3822    fn test_cancel(cx: &mut gpui::MutableAppContext) {
3823        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
3824        let settings = EditorSettings::test(cx);
3825        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
3826
3827        view.update(cx, |view, cx| {
3828            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
3829            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
3830            view.end_selection(cx);
3831
3832            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
3833            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
3834            view.end_selection(cx);
3835            assert_eq!(
3836                view.selection_ranges(cx),
3837                [
3838                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3839                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
3840                ]
3841            );
3842        });
3843
3844        view.update(cx, |view, cx| {
3845            view.cancel(&Cancel, cx);
3846            assert_eq!(
3847                view.selection_ranges(cx),
3848                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
3849            );
3850        });
3851
3852        view.update(cx, |view, cx| {
3853            view.cancel(&Cancel, cx);
3854            assert_eq!(
3855                view.selection_ranges(cx),
3856                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
3857            );
3858        });
3859    }
3860
3861    #[gpui::test]
3862    fn test_fold(cx: &mut gpui::MutableAppContext) {
3863        let buffer = MultiBuffer::build_simple(
3864            &"
3865                impl Foo {
3866                    // Hello!
3867
3868                    fn a() {
3869                        1
3870                    }
3871
3872                    fn b() {
3873                        2
3874                    }
3875
3876                    fn c() {
3877                        3
3878                    }
3879                }
3880            "
3881            .unindent(),
3882            cx,
3883        );
3884        let settings = EditorSettings::test(&cx);
3885        let (_, view) = cx.add_window(Default::default(), |cx| {
3886            build_editor(buffer.clone(), settings, cx)
3887        });
3888
3889        view.update(cx, |view, cx| {
3890            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx)
3891                .unwrap();
3892            view.fold(&Fold, cx);
3893            assert_eq!(
3894                view.display_text(cx),
3895                "
3896                    impl Foo {
3897                        // Hello!
3898
3899                        fn a() {
3900                            1
3901                        }
3902
3903                        fn b() {…
3904                        }
3905
3906                        fn c() {…
3907                        }
3908                    }
3909                "
3910                .unindent(),
3911            );
3912
3913            view.fold(&Fold, cx);
3914            assert_eq!(
3915                view.display_text(cx),
3916                "
3917                    impl Foo {…
3918                    }
3919                "
3920                .unindent(),
3921            );
3922
3923            view.unfold(&Unfold, cx);
3924            assert_eq!(
3925                view.display_text(cx),
3926                "
3927                    impl Foo {
3928                        // Hello!
3929
3930                        fn a() {
3931                            1
3932                        }
3933
3934                        fn b() {…
3935                        }
3936
3937                        fn c() {…
3938                        }
3939                    }
3940                "
3941                .unindent(),
3942            );
3943
3944            view.unfold(&Unfold, cx);
3945            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
3946        });
3947    }
3948
3949    #[gpui::test]
3950    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
3951        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
3952        let settings = EditorSettings::test(&cx);
3953        let (_, view) = cx.add_window(Default::default(), |cx| {
3954            build_editor(buffer.clone(), settings, cx)
3955        });
3956
3957        buffer.update(cx, |buffer, cx| {
3958            buffer.edit(
3959                vec![
3960                    Point::new(1, 0)..Point::new(1, 0),
3961                    Point::new(1, 1)..Point::new(1, 1),
3962                ],
3963                "\t",
3964                cx,
3965            );
3966        });
3967
3968        view.update(cx, |view, cx| {
3969            assert_eq!(
3970                view.selection_ranges(cx),
3971                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3972            );
3973
3974            view.move_down(&MoveDown, cx);
3975            assert_eq!(
3976                view.selection_ranges(cx),
3977                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3978            );
3979
3980            view.move_right(&MoveRight, cx);
3981            assert_eq!(
3982                view.selection_ranges(cx),
3983                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
3984            );
3985
3986            view.move_left(&MoveLeft, cx);
3987            assert_eq!(
3988                view.selection_ranges(cx),
3989                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
3990            );
3991
3992            view.move_up(&MoveUp, cx);
3993            assert_eq!(
3994                view.selection_ranges(cx),
3995                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
3996            );
3997
3998            view.move_to_end(&MoveToEnd, cx);
3999            assert_eq!(
4000                view.selection_ranges(cx),
4001                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
4002            );
4003
4004            view.move_to_beginning(&MoveToBeginning, cx);
4005            assert_eq!(
4006                view.selection_ranges(cx),
4007                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
4008            );
4009
4010            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx)
4011                .unwrap();
4012            view.select_to_beginning(&SelectToBeginning, cx);
4013            assert_eq!(
4014                view.selection_ranges(cx),
4015                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
4016            );
4017
4018            view.select_to_end(&SelectToEnd, cx);
4019            assert_eq!(
4020                view.selection_ranges(cx),
4021                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
4022            );
4023        });
4024    }
4025
4026    #[gpui::test]
4027    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
4028        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
4029        let settings = EditorSettings::test(&cx);
4030        let (_, view) = cx.add_window(Default::default(), |cx| {
4031            build_editor(buffer.clone(), settings, cx)
4032        });
4033
4034        assert_eq!('ⓐ'.len_utf8(), 3);
4035        assert_eq!('α'.len_utf8(), 2);
4036
4037        view.update(cx, |view, cx| {
4038            view.fold_ranges(
4039                vec![
4040                    Point::new(0, 6)..Point::new(0, 12),
4041                    Point::new(1, 2)..Point::new(1, 4),
4042                    Point::new(2, 4)..Point::new(2, 8),
4043                ],
4044                cx,
4045            );
4046            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
4047
4048            view.move_right(&MoveRight, cx);
4049            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "".len())]);
4050            view.move_right(&MoveRight, cx);
4051            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
4052            view.move_right(&MoveRight, cx);
4053            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
4054
4055            view.move_down(&MoveDown, cx);
4056            assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…".len())]);
4057            view.move_left(&MoveLeft, cx);
4058            assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab".len())]);
4059            view.move_left(&MoveLeft, cx);
4060            assert_eq!(view.selection_ranges(cx), &[empty_range(1, "a".len())]);
4061
4062            view.move_down(&MoveDown, cx);
4063            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "α".len())]);
4064            view.move_right(&MoveRight, cx);
4065            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ".len())]);
4066            view.move_right(&MoveRight, cx);
4067            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…".len())]);
4068            view.move_right(&MoveRight, cx);
4069            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβ…ε".len())]);
4070
4071            view.move_up(&MoveUp, cx);
4072            assert_eq!(view.selection_ranges(cx), &[empty_range(1, "ab…e".len())]);
4073            view.move_up(&MoveUp, cx);
4074            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…ⓔ".len())]);
4075            view.move_left(&MoveLeft, cx);
4076            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ…".len())]);
4077            view.move_left(&MoveLeft, cx);
4078            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "ⓐⓑ".len())]);
4079            view.move_left(&MoveLeft, cx);
4080            assert_eq!(view.selection_ranges(cx), &[empty_range(0, "".len())]);
4081        });
4082    }
4083
4084    #[gpui::test]
4085    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
4086        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
4087        let settings = EditorSettings::test(&cx);
4088        let (_, view) = cx.add_window(Default::default(), |cx| {
4089            build_editor(buffer.clone(), settings, cx)
4090        });
4091        view.update(cx, |view, cx| {
4092            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx)
4093                .unwrap();
4094
4095            view.move_down(&MoveDown, cx);
4096            assert_eq!(view.selection_ranges(cx), &[empty_range(1, "abcd".len())]);
4097
4098            view.move_down(&MoveDown, cx);
4099            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
4100
4101            view.move_down(&MoveDown, cx);
4102            assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
4103
4104            view.move_down(&MoveDown, cx);
4105            assert_eq!(view.selection_ranges(cx), &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]);
4106
4107            view.move_up(&MoveUp, cx);
4108            assert_eq!(view.selection_ranges(cx), &[empty_range(3, "abcd".len())]);
4109
4110            view.move_up(&MoveUp, cx);
4111            assert_eq!(view.selection_ranges(cx), &[empty_range(2, "αβγ".len())]);
4112        });
4113    }
4114
4115    #[gpui::test]
4116    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
4117        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
4118        let settings = EditorSettings::test(&cx);
4119        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4120        view.update(cx, |view, cx| {
4121            view.select_display_ranges(
4122                &[
4123                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4124                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
4125                ],
4126                cx,
4127            )
4128            .unwrap();
4129        });
4130
4131        view.update(cx, |view, cx| {
4132            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
4133            assert_eq!(
4134                view.selection_ranges(cx),
4135                &[
4136                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4137                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
4138                ]
4139            );
4140        });
4141
4142        view.update(cx, |view, cx| {
4143            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
4144            assert_eq!(
4145                view.selection_ranges(cx),
4146                &[
4147                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4148                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4149                ]
4150            );
4151        });
4152
4153        view.update(cx, |view, cx| {
4154            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
4155            assert_eq!(
4156                view.selection_ranges(cx),
4157                &[
4158                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4159                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
4160                ]
4161            );
4162        });
4163
4164        view.update(cx, |view, cx| {
4165            view.move_to_end_of_line(&MoveToEndOfLine, cx);
4166            assert_eq!(
4167                view.selection_ranges(cx),
4168                &[
4169                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4170                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
4171                ]
4172            );
4173        });
4174
4175        // Moving to the end of line again is a no-op.
4176        view.update(cx, |view, cx| {
4177            view.move_to_end_of_line(&MoveToEndOfLine, cx);
4178            assert_eq!(
4179                view.selection_ranges(cx),
4180                &[
4181                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4182                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
4183                ]
4184            );
4185        });
4186
4187        view.update(cx, |view, cx| {
4188            view.move_left(&MoveLeft, cx);
4189            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
4190            assert_eq!(
4191                view.selection_ranges(cx),
4192                &[
4193                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
4194                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
4195                ]
4196            );
4197        });
4198
4199        view.update(cx, |view, cx| {
4200            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
4201            assert_eq!(
4202                view.selection_ranges(cx),
4203                &[
4204                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
4205                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
4206                ]
4207            );
4208        });
4209
4210        view.update(cx, |view, cx| {
4211            view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx);
4212            assert_eq!(
4213                view.selection_ranges(cx),
4214                &[
4215                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
4216                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
4217                ]
4218            );
4219        });
4220
4221        view.update(cx, |view, cx| {
4222            view.select_to_end_of_line(&SelectToEndOfLine, cx);
4223            assert_eq!(
4224                view.selection_ranges(cx),
4225                &[
4226                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
4227                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
4228                ]
4229            );
4230        });
4231
4232        view.update(cx, |view, cx| {
4233            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
4234            assert_eq!(view.display_text(cx), "ab\n  de");
4235            assert_eq!(
4236                view.selection_ranges(cx),
4237                &[
4238                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4239                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
4240                ]
4241            );
4242        });
4243
4244        view.update(cx, |view, cx| {
4245            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
4246            assert_eq!(view.display_text(cx), "\n");
4247            assert_eq!(
4248                view.selection_ranges(cx),
4249                &[
4250                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4251                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4252                ]
4253            );
4254        });
4255    }
4256
4257    #[gpui::test]
4258    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
4259        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
4260        let settings = EditorSettings::test(&cx);
4261        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4262        view.update(cx, |view, cx| {
4263            view.select_display_ranges(
4264                &[
4265                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
4266                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
4267                ],
4268                cx,
4269            )
4270            .unwrap();
4271        });
4272
4273        view.update(cx, |view, cx| {
4274            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4275            assert_eq!(
4276                view.selection_ranges(cx),
4277                &[
4278                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
4279                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
4280                ]
4281            );
4282        });
4283
4284        view.update(cx, |view, cx| {
4285            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4286            assert_eq!(
4287                view.selection_ranges(cx),
4288                &[
4289                    DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
4290                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
4291                ]
4292            );
4293        });
4294
4295        view.update(cx, |view, cx| {
4296            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4297            assert_eq!(
4298                view.selection_ranges(cx),
4299                &[
4300                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
4301                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
4302                ]
4303            );
4304        });
4305
4306        view.update(cx, |view, cx| {
4307            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4308            assert_eq!(
4309                view.selection_ranges(cx),
4310                &[
4311                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4312                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4313                ]
4314            );
4315        });
4316
4317        view.update(cx, |view, cx| {
4318            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4319            assert_eq!(
4320                view.selection_ranges(cx),
4321                &[
4322                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4323                    DisplayPoint::new(0, 23)..DisplayPoint::new(0, 23),
4324                ]
4325            );
4326        });
4327
4328        view.update(cx, |view, cx| {
4329            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4330            assert_eq!(
4331                view.selection_ranges(cx),
4332                &[
4333                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4334                    DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
4335                ]
4336            );
4337        });
4338
4339        view.update(cx, |view, cx| {
4340            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4341            assert_eq!(
4342                view.selection_ranges(cx),
4343                &[
4344                    DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
4345                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4346                ]
4347            );
4348        });
4349
4350        view.update(cx, |view, cx| {
4351            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4352            assert_eq!(
4353                view.selection_ranges(cx),
4354                &[
4355                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
4356                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
4357                ]
4358            );
4359        });
4360
4361        view.update(cx, |view, cx| {
4362            view.move_right(&MoveRight, cx);
4363            view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
4364            assert_eq!(
4365                view.selection_ranges(cx),
4366                &[
4367                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
4368                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
4369                ]
4370            );
4371        });
4372
4373        view.update(cx, |view, cx| {
4374            view.select_to_previous_word_boundary(&SelectToPreviousWordBoundary, cx);
4375            assert_eq!(
4376                view.selection_ranges(cx),
4377                &[
4378                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 7),
4379                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 2),
4380                ]
4381            );
4382        });
4383
4384        view.update(cx, |view, cx| {
4385            view.select_to_next_word_boundary(&SelectToNextWordBoundary, cx);
4386            assert_eq!(
4387                view.selection_ranges(cx),
4388                &[
4389                    DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
4390                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 3),
4391                ]
4392            );
4393        });
4394    }
4395
4396    #[gpui::test]
4397    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
4398        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
4399        let settings = EditorSettings::test(&cx);
4400        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4401
4402        view.update(cx, |view, cx| {
4403            view.set_wrap_width(Some(140.), cx);
4404            assert_eq!(
4405                view.display_text(cx),
4406                "use one::{\n    two::three::\n    four::five\n};"
4407            );
4408
4409            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx)
4410                .unwrap();
4411
4412            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4413            assert_eq!(
4414                view.selection_ranges(cx),
4415                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
4416            );
4417
4418            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4419            assert_eq!(
4420                view.selection_ranges(cx),
4421                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
4422            );
4423
4424            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4425            assert_eq!(
4426                view.selection_ranges(cx),
4427                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
4428            );
4429
4430            view.move_to_next_word_boundary(&MoveToNextWordBoundary, cx);
4431            assert_eq!(
4432                view.selection_ranges(cx),
4433                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
4434            );
4435
4436            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4437            assert_eq!(
4438                view.selection_ranges(cx),
4439                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
4440            );
4441
4442            view.move_to_previous_word_boundary(&MoveToPreviousWordBoundary, cx);
4443            assert_eq!(
4444                view.selection_ranges(cx),
4445                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
4446            );
4447        });
4448    }
4449
4450    #[gpui::test]
4451    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
4452        let buffer = MultiBuffer::build_simple("one two three four", cx);
4453        let settings = EditorSettings::test(&cx);
4454        let (_, view) = cx.add_window(Default::default(), |cx| {
4455            build_editor(buffer.clone(), settings, cx)
4456        });
4457
4458        view.update(cx, |view, cx| {
4459            view.select_display_ranges(
4460                &[
4461                    // an empty selection - the preceding word fragment is deleted
4462                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4463                    // characters selected - they are deleted
4464                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
4465                ],
4466                cx,
4467            )
4468            .unwrap();
4469            view.delete_to_previous_word_boundary(&DeleteToPreviousWordBoundary, cx);
4470        });
4471
4472        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
4473
4474        view.update(cx, |view, cx| {
4475            view.select_display_ranges(
4476                &[
4477                    // an empty selection - the following word fragment is deleted
4478                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
4479                    // characters selected - they are deleted
4480                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
4481                ],
4482                cx,
4483            )
4484            .unwrap();
4485            view.delete_to_next_word_boundary(&DeleteToNextWordBoundary, cx);
4486        });
4487
4488        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
4489    }
4490
4491    #[gpui::test]
4492    fn test_newline(cx: &mut gpui::MutableAppContext) {
4493        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
4494        let settings = EditorSettings::test(&cx);
4495        let (_, view) = cx.add_window(Default::default(), |cx| {
4496            build_editor(buffer.clone(), settings, cx)
4497        });
4498
4499        view.update(cx, |view, cx| {
4500            view.select_display_ranges(
4501                &[
4502                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4503                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
4504                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
4505                ],
4506                cx,
4507            )
4508            .unwrap();
4509
4510            view.newline(&Newline, cx);
4511            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
4512        });
4513    }
4514
4515    #[gpui::test]
4516    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
4517        let buffer = MultiBuffer::build_simple("  one two\nthree\n four", cx);
4518        let settings = EditorSettings::test(&cx);
4519        let (_, view) = cx.add_window(Default::default(), |cx| {
4520            build_editor(buffer.clone(), settings, cx)
4521        });
4522
4523        view.update(cx, |view, cx| {
4524            // two selections on the same line
4525            view.select_display_ranges(
4526                &[
4527                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 5),
4528                    DisplayPoint::new(0, 6)..DisplayPoint::new(0, 9),
4529                ],
4530                cx,
4531            )
4532            .unwrap();
4533
4534            // indent from mid-tabstop to full tabstop
4535            view.tab(&Tab, cx);
4536            assert_eq!(view.text(cx), "    one two\nthree\n four");
4537            assert_eq!(
4538                view.selection_ranges(cx),
4539                &[
4540                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
4541                    DisplayPoint::new(0, 8)..DisplayPoint::new(0, 11),
4542                ]
4543            );
4544
4545            // outdent from 1 tabstop to 0 tabstops
4546            view.outdent(&Outdent, cx);
4547            assert_eq!(view.text(cx), "one two\nthree\n four");
4548            assert_eq!(
4549                view.selection_ranges(cx),
4550                &[
4551                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 3),
4552                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 7),
4553                ]
4554            );
4555
4556            // select across line ending
4557            view.select_display_ranges(&[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)], cx)
4558                .unwrap();
4559
4560            // indent and outdent affect only the preceding line
4561            view.tab(&Tab, cx);
4562            assert_eq!(view.text(cx), "one two\n    three\n four");
4563            assert_eq!(
4564                view.selection_ranges(cx),
4565                &[DisplayPoint::new(1, 5)..DisplayPoint::new(2, 0)]
4566            );
4567            view.outdent(&Outdent, cx);
4568            assert_eq!(view.text(cx), "one two\nthree\n four");
4569            assert_eq!(
4570                view.selection_ranges(cx),
4571                &[DisplayPoint::new(1, 1)..DisplayPoint::new(2, 0)]
4572            );
4573        });
4574    }
4575
4576    #[gpui::test]
4577    fn test_backspace(cx: &mut gpui::MutableAppContext) {
4578        let buffer =
4579            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
4580        let settings = EditorSettings::test(&cx);
4581        let (_, view) = cx.add_window(Default::default(), |cx| {
4582            build_editor(buffer.clone(), settings, cx)
4583        });
4584
4585        view.update(cx, |view, cx| {
4586            view.select_display_ranges(
4587                &[
4588                    // an empty selection - the preceding character is deleted
4589                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4590                    // one character selected - it is deleted
4591                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4592                    // a line suffix selected - it is deleted
4593                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
4594                ],
4595                cx,
4596            )
4597            .unwrap();
4598            view.backspace(&Backspace, cx);
4599        });
4600
4601        assert_eq!(
4602            buffer.read(cx).read(cx).text(),
4603            "oe two three\nfou five six\nseven ten\n"
4604        );
4605    }
4606
4607    #[gpui::test]
4608    fn test_delete(cx: &mut gpui::MutableAppContext) {
4609        let buffer =
4610            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
4611        let settings = EditorSettings::test(&cx);
4612        let (_, view) = cx.add_window(Default::default(), |cx| {
4613            build_editor(buffer.clone(), settings, cx)
4614        });
4615
4616        view.update(cx, |view, cx| {
4617            view.select_display_ranges(
4618                &[
4619                    // an empty selection - the following character is deleted
4620                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4621                    // one character selected - it is deleted
4622                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
4623                    // a line suffix selected - it is deleted
4624                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
4625                ],
4626                cx,
4627            )
4628            .unwrap();
4629            view.delete(&Delete, cx);
4630        });
4631
4632        assert_eq!(
4633            buffer.read(cx).read(cx).text(),
4634            "on two three\nfou five six\nseven ten\n"
4635        );
4636    }
4637
4638    #[gpui::test]
4639    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
4640        let settings = EditorSettings::test(&cx);
4641        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
4642        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4643        view.update(cx, |view, cx| {
4644            view.select_display_ranges(
4645                &[
4646                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4647                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4648                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4649                ],
4650                cx,
4651            )
4652            .unwrap();
4653            view.delete_line(&DeleteLine, cx);
4654            assert_eq!(view.display_text(cx), "ghi");
4655            assert_eq!(
4656                view.selection_ranges(cx),
4657                vec![
4658                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
4659                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
4660                ]
4661            );
4662        });
4663
4664        let settings = EditorSettings::test(&cx);
4665        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
4666        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4667        view.update(cx, |view, cx| {
4668            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx)
4669                .unwrap();
4670            view.delete_line(&DeleteLine, cx);
4671            assert_eq!(view.display_text(cx), "ghi\n");
4672            assert_eq!(
4673                view.selection_ranges(cx),
4674                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
4675            );
4676        });
4677    }
4678
4679    #[gpui::test]
4680    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
4681        let settings = EditorSettings::test(&cx);
4682        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
4683        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4684        view.update(cx, |view, cx| {
4685            view.select_display_ranges(
4686                &[
4687                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4688                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4689                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4690                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4691                ],
4692                cx,
4693            )
4694            .unwrap();
4695            view.duplicate_line(&DuplicateLine, cx);
4696            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
4697            assert_eq!(
4698                view.selection_ranges(cx),
4699                vec![
4700                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
4701                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
4702                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4703                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
4704                ]
4705            );
4706        });
4707
4708        let settings = EditorSettings::test(&cx);
4709        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
4710        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4711        view.update(cx, |view, cx| {
4712            view.select_display_ranges(
4713                &[
4714                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
4715                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
4716                ],
4717                cx,
4718            )
4719            .unwrap();
4720            view.duplicate_line(&DuplicateLine, cx);
4721            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
4722            assert_eq!(
4723                view.selection_ranges(cx),
4724                vec![
4725                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
4726                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
4727                ]
4728            );
4729        });
4730    }
4731
4732    #[gpui::test]
4733    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
4734        let settings = EditorSettings::test(&cx);
4735        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
4736        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4737        view.update(cx, |view, cx| {
4738            view.fold_ranges(
4739                vec![
4740                    Point::new(0, 2)..Point::new(1, 2),
4741                    Point::new(2, 3)..Point::new(4, 1),
4742                    Point::new(7, 0)..Point::new(8, 4),
4743                ],
4744                cx,
4745            );
4746            view.select_display_ranges(
4747                &[
4748                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4749                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4750                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4751                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
4752                ],
4753                cx,
4754            )
4755            .unwrap();
4756            assert_eq!(
4757                view.display_text(cx),
4758                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
4759            );
4760
4761            view.move_line_up(&MoveLineUp, cx);
4762            assert_eq!(
4763                view.display_text(cx),
4764                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
4765            );
4766            assert_eq!(
4767                view.selection_ranges(cx),
4768                vec![
4769                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4770                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4771                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
4772                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
4773                ]
4774            );
4775        });
4776
4777        view.update(cx, |view, cx| {
4778            view.move_line_down(&MoveLineDown, cx);
4779            assert_eq!(
4780                view.display_text(cx),
4781                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
4782            );
4783            assert_eq!(
4784                view.selection_ranges(cx),
4785                vec![
4786                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4787                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4788                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4789                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
4790                ]
4791            );
4792        });
4793
4794        view.update(cx, |view, cx| {
4795            view.move_line_down(&MoveLineDown, cx);
4796            assert_eq!(
4797                view.display_text(cx),
4798                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
4799            );
4800            assert_eq!(
4801                view.selection_ranges(cx),
4802                vec![
4803                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4804                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
4805                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
4806                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
4807                ]
4808            );
4809        });
4810
4811        view.update(cx, |view, cx| {
4812            view.move_line_up(&MoveLineUp, cx);
4813            assert_eq!(
4814                view.display_text(cx),
4815                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
4816            );
4817            assert_eq!(
4818                view.selection_ranges(cx),
4819                vec![
4820                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4821                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4822                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
4823                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
4824                ]
4825            );
4826        });
4827    }
4828
4829    #[gpui::test]
4830    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
4831        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
4832        let settings = EditorSettings::test(&cx);
4833        let view = cx
4834            .add_window(Default::default(), |cx| {
4835                build_editor(buffer.clone(), settings, cx)
4836            })
4837            .1;
4838
4839        // Cut with three selections. Clipboard text is divided into three slices.
4840        view.update(cx, |view, cx| {
4841            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
4842            view.cut(&Cut, cx);
4843            assert_eq!(view.display_text(cx), "two four six ");
4844        });
4845
4846        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
4847        view.update(cx, |view, cx| {
4848            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
4849            view.paste(&Paste, cx);
4850            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
4851            assert_eq!(
4852                view.selection_ranges(cx),
4853                &[
4854                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
4855                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
4856                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
4857                ]
4858            );
4859        });
4860
4861        // Paste again but with only two cursors. Since the number of cursors doesn't
4862        // match the number of slices in the clipboard, the entire clipboard text
4863        // is pasted at each cursor.
4864        view.update(cx, |view, cx| {
4865            view.select_ranges(vec![0..0, 31..31], None, cx);
4866            view.handle_input(&Input("( ".into()), cx);
4867            view.paste(&Paste, cx);
4868            view.handle_input(&Input(") ".into()), cx);
4869            assert_eq!(
4870                view.display_text(cx),
4871                "( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4872            );
4873        });
4874
4875        view.update(cx, |view, cx| {
4876            view.select_ranges(vec![0..0], None, cx);
4877            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
4878            assert_eq!(
4879                view.display_text(cx),
4880                "123\n4567\n89\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4881            );
4882        });
4883
4884        // Cut with three selections, one of which is full-line.
4885        view.update(cx, |view, cx| {
4886            view.select_display_ranges(
4887                &[
4888                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
4889                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4890                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
4891                ],
4892                cx,
4893            )
4894            .unwrap();
4895            view.cut(&Cut, cx);
4896            assert_eq!(
4897                view.display_text(cx),
4898                "13\n9\n( one✅ three five ) two one✅ four three six five ( one✅ three five ) "
4899            );
4900        });
4901
4902        // Paste with three selections, noticing how the copied selection that was full-line
4903        // gets inserted before the second cursor.
4904        view.update(cx, |view, cx| {
4905            view.select_display_ranges(
4906                &[
4907                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4908                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4909                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
4910                ],
4911                cx,
4912            )
4913            .unwrap();
4914            view.paste(&Paste, cx);
4915            assert_eq!(
4916                view.display_text(cx),
4917                "123\n4567\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
4918            );
4919            assert_eq!(
4920                view.selection_ranges(cx),
4921                &[
4922                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4923                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4924                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
4925                ]
4926            );
4927        });
4928
4929        // Copy with a single cursor only, which writes the whole line into the clipboard.
4930        view.update(cx, |view, cx| {
4931            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx)
4932                .unwrap();
4933            view.copy(&Copy, cx);
4934        });
4935
4936        // Paste with three selections, noticing how the copied full-line selection is inserted
4937        // before the empty selections but replaces the selection that is non-empty.
4938        view.update(cx, |view, cx| {
4939            view.select_display_ranges(
4940                &[
4941                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
4942                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
4943                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
4944                ],
4945                cx,
4946            )
4947            .unwrap();
4948            view.paste(&Paste, cx);
4949            assert_eq!(
4950                view.display_text(cx),
4951                "123\n123\n123\n67\n123\n9\n( 8ne✅ three five ) two one✅ four three six five ( one✅ three five ) "
4952            );
4953            assert_eq!(
4954                view.selection_ranges(cx),
4955                &[
4956                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
4957                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
4958                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
4959                ]
4960            );
4961        });
4962    }
4963
4964    #[gpui::test]
4965    fn test_select_all(cx: &mut gpui::MutableAppContext) {
4966        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
4967        let settings = EditorSettings::test(&cx);
4968        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4969        view.update(cx, |view, cx| {
4970            view.select_all(&SelectAll, cx);
4971            assert_eq!(
4972                view.selection_ranges(cx),
4973                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
4974            );
4975        });
4976    }
4977
4978    #[gpui::test]
4979    fn test_select_line(cx: &mut gpui::MutableAppContext) {
4980        let settings = EditorSettings::test(&cx);
4981        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
4982        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
4983        view.update(cx, |view, cx| {
4984            view.select_display_ranges(
4985                &[
4986                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
4987                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
4988                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
4989                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
4990                ],
4991                cx,
4992            )
4993            .unwrap();
4994            view.select_line(&SelectLine, cx);
4995            assert_eq!(
4996                view.selection_ranges(cx),
4997                vec![
4998                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
4999                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
5000                ]
5001            );
5002        });
5003
5004        view.update(cx, |view, cx| {
5005            view.select_line(&SelectLine, cx);
5006            assert_eq!(
5007                view.selection_ranges(cx),
5008                vec![
5009                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
5010                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
5011                ]
5012            );
5013        });
5014
5015        view.update(cx, |view, cx| {
5016            view.select_line(&SelectLine, cx);
5017            assert_eq!(
5018                view.selection_ranges(cx),
5019                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
5020            );
5021        });
5022    }
5023
5024    #[gpui::test]
5025    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
5026        let settings = EditorSettings::test(&cx);
5027        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
5028        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
5029        view.update(cx, |view, cx| {
5030            view.fold_ranges(
5031                vec![
5032                    Point::new(0, 2)..Point::new(1, 2),
5033                    Point::new(2, 3)..Point::new(4, 1),
5034                    Point::new(7, 0)..Point::new(8, 4),
5035                ],
5036                cx,
5037            );
5038            view.select_display_ranges(
5039                &[
5040                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
5041                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
5042                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
5043                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
5044                ],
5045                cx,
5046            )
5047            .unwrap();
5048            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
5049        });
5050
5051        view.update(cx, |view, cx| {
5052            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
5053            assert_eq!(
5054                view.display_text(cx),
5055                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
5056            );
5057            assert_eq!(
5058                view.selection_ranges(cx),
5059                [
5060                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
5061                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
5062                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
5063                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
5064                ]
5065            );
5066        });
5067
5068        view.update(cx, |view, cx| {
5069            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx)
5070                .unwrap();
5071            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
5072            assert_eq!(
5073                view.display_text(cx),
5074                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
5075            );
5076            assert_eq!(
5077                view.selection_ranges(cx),
5078                [
5079                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
5080                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
5081                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
5082                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
5083                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
5084                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
5085                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
5086                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
5087                ]
5088            );
5089        });
5090    }
5091
5092    #[gpui::test]
5093    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
5094        let settings = EditorSettings::test(&cx);
5095        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
5096        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
5097
5098        view.update(cx, |view, cx| {
5099            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx)
5100                .unwrap();
5101        });
5102        view.update(cx, |view, cx| {
5103            view.add_selection_above(&AddSelectionAbove, cx);
5104            assert_eq!(
5105                view.selection_ranges(cx),
5106                vec![
5107                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
5108                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
5109                ]
5110            );
5111        });
5112
5113        view.update(cx, |view, cx| {
5114            view.add_selection_above(&AddSelectionAbove, cx);
5115            assert_eq!(
5116                view.selection_ranges(cx),
5117                vec![
5118                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
5119                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
5120                ]
5121            );
5122        });
5123
5124        view.update(cx, |view, cx| {
5125            view.add_selection_below(&AddSelectionBelow, cx);
5126            assert_eq!(
5127                view.selection_ranges(cx),
5128                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
5129            );
5130        });
5131
5132        view.update(cx, |view, cx| {
5133            view.add_selection_below(&AddSelectionBelow, cx);
5134            assert_eq!(
5135                view.selection_ranges(cx),
5136                vec![
5137                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
5138                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
5139                ]
5140            );
5141        });
5142
5143        view.update(cx, |view, cx| {
5144            view.add_selection_below(&AddSelectionBelow, cx);
5145            assert_eq!(
5146                view.selection_ranges(cx),
5147                vec![
5148                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
5149                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
5150                ]
5151            );
5152        });
5153
5154        view.update(cx, |view, cx| {
5155            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx)
5156                .unwrap();
5157        });
5158        view.update(cx, |view, cx| {
5159            view.add_selection_below(&AddSelectionBelow, cx);
5160            assert_eq!(
5161                view.selection_ranges(cx),
5162                vec![
5163                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
5164                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
5165                ]
5166            );
5167        });
5168
5169        view.update(cx, |view, cx| {
5170            view.add_selection_below(&AddSelectionBelow, cx);
5171            assert_eq!(
5172                view.selection_ranges(cx),
5173                vec![
5174                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
5175                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
5176                ]
5177            );
5178        });
5179
5180        view.update(cx, |view, cx| {
5181            view.add_selection_above(&AddSelectionAbove, cx);
5182            assert_eq!(
5183                view.selection_ranges(cx),
5184                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
5185            );
5186        });
5187
5188        view.update(cx, |view, cx| {
5189            view.add_selection_above(&AddSelectionAbove, cx);
5190            assert_eq!(
5191                view.selection_ranges(cx),
5192                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
5193            );
5194        });
5195
5196        view.update(cx, |view, cx| {
5197            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx)
5198                .unwrap();
5199            view.add_selection_below(&AddSelectionBelow, cx);
5200            assert_eq!(
5201                view.selection_ranges(cx),
5202                vec![
5203                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
5204                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
5205                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
5206                ]
5207            );
5208        });
5209
5210        view.update(cx, |view, cx| {
5211            view.add_selection_below(&AddSelectionBelow, cx);
5212            assert_eq!(
5213                view.selection_ranges(cx),
5214                vec![
5215                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
5216                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
5217                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
5218                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
5219                ]
5220            );
5221        });
5222
5223        view.update(cx, |view, cx| {
5224            view.add_selection_above(&AddSelectionAbove, cx);
5225            assert_eq!(
5226                view.selection_ranges(cx),
5227                vec![
5228                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
5229                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
5230                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
5231                ]
5232            );
5233        });
5234
5235        view.update(cx, |view, cx| {
5236            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx)
5237                .unwrap();
5238        });
5239        view.update(cx, |view, cx| {
5240            view.add_selection_above(&AddSelectionAbove, cx);
5241            assert_eq!(
5242                view.selection_ranges(cx),
5243                vec![
5244                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
5245                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
5246                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
5247                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
5248                ]
5249            );
5250        });
5251
5252        view.update(cx, |view, cx| {
5253            view.add_selection_below(&AddSelectionBelow, cx);
5254            assert_eq!(
5255                view.selection_ranges(cx),
5256                vec![
5257                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
5258                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
5259                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
5260                ]
5261            );
5262        });
5263    }
5264
5265    #[gpui::test]
5266    async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) {
5267        let settings = cx.read(EditorSettings::test);
5268        let language = Some(Arc::new(Language::new(
5269            LanguageConfig::default(),
5270            Some(tree_sitter_rust::language()),
5271        )));
5272
5273        let text = r#"
5274            use mod1::mod2::{mod3, mod4};
5275
5276            fn fn_1(param1: bool, param2: &str) {
5277                let var1 = "text";
5278            }
5279        "#
5280        .unindent();
5281
5282        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
5283        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5284        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
5285        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
5286            .await;
5287
5288        view.update(&mut cx, |view, cx| {
5289            view.select_display_ranges(
5290                &[
5291                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
5292                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
5293                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
5294                ],
5295                cx,
5296            )
5297            .unwrap();
5298            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
5299        });
5300        assert_eq!(
5301            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5302            &[
5303                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
5304                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
5305                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
5306            ]
5307        );
5308
5309        view.update(&mut cx, |view, cx| {
5310            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
5311        });
5312        assert_eq!(
5313            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5314            &[
5315                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
5316                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
5317            ]
5318        );
5319
5320        view.update(&mut cx, |view, cx| {
5321            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
5322        });
5323        assert_eq!(
5324            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5325            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
5326        );
5327
5328        // Trying to expand the selected syntax node one more time has no effect.
5329        view.update(&mut cx, |view, cx| {
5330            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
5331        });
5332        assert_eq!(
5333            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5334            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
5335        );
5336
5337        view.update(&mut cx, |view, cx| {
5338            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
5339        });
5340        assert_eq!(
5341            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5342            &[
5343                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
5344                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
5345            ]
5346        );
5347
5348        view.update(&mut cx, |view, cx| {
5349            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
5350        });
5351        assert_eq!(
5352            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5353            &[
5354                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
5355                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
5356                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
5357            ]
5358        );
5359
5360        view.update(&mut cx, |view, cx| {
5361            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
5362        });
5363        assert_eq!(
5364            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5365            &[
5366                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
5367                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
5368                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
5369            ]
5370        );
5371
5372        // Trying to shrink the selected syntax node one more time has no effect.
5373        view.update(&mut cx, |view, cx| {
5374            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
5375        });
5376        assert_eq!(
5377            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5378            &[
5379                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
5380                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
5381                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
5382            ]
5383        );
5384
5385        // Ensure that we keep expanding the selection if the larger selection starts or ends within
5386        // a fold.
5387        view.update(&mut cx, |view, cx| {
5388            view.fold_ranges(
5389                vec![
5390                    Point::new(0, 21)..Point::new(0, 24),
5391                    Point::new(3, 20)..Point::new(3, 22),
5392                ],
5393                cx,
5394            );
5395            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
5396        });
5397        assert_eq!(
5398            view.update(&mut cx, |view, cx| view.selection_ranges(cx)),
5399            &[
5400                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
5401                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
5402                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
5403            ]
5404        );
5405    }
5406
5407    #[gpui::test]
5408    async fn test_autoclose_pairs(mut cx: gpui::TestAppContext) {
5409        let settings = cx.read(EditorSettings::test);
5410        let language = Some(Arc::new(Language::new(
5411            LanguageConfig {
5412                brackets: vec![
5413                    BracketPair {
5414                        start: "{".to_string(),
5415                        end: "}".to_string(),
5416                        close: true,
5417                        newline: true,
5418                    },
5419                    BracketPair {
5420                        start: "/*".to_string(),
5421                        end: " */".to_string(),
5422                        close: true,
5423                        newline: true,
5424                    },
5425                ],
5426                ..Default::default()
5427            },
5428            Some(tree_sitter_rust::language()),
5429        )));
5430
5431        let text = r#"
5432            a
5433
5434            /
5435
5436        "#
5437        .unindent();
5438
5439        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
5440        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5441        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
5442        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
5443            .await;
5444
5445        view.update(&mut cx, |view, cx| {
5446            view.select_display_ranges(
5447                &[
5448                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
5449                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
5450                ],
5451                cx,
5452            )
5453            .unwrap();
5454            view.handle_input(&Input("{".to_string()), cx);
5455            view.handle_input(&Input("{".to_string()), cx);
5456            view.handle_input(&Input("{".to_string()), cx);
5457            assert_eq!(
5458                view.text(cx),
5459                "
5460                {{{}}}
5461                {{{}}}
5462                /
5463
5464                "
5465                .unindent()
5466            );
5467
5468            view.move_right(&MoveRight, cx);
5469            view.handle_input(&Input("}".to_string()), cx);
5470            view.handle_input(&Input("}".to_string()), cx);
5471            view.handle_input(&Input("}".to_string()), cx);
5472            assert_eq!(
5473                view.text(cx),
5474                "
5475                {{{}}}}
5476                {{{}}}}
5477                /
5478
5479                "
5480                .unindent()
5481            );
5482
5483            view.undo(&Undo, cx);
5484            view.handle_input(&Input("/".to_string()), cx);
5485            view.handle_input(&Input("*".to_string()), cx);
5486            assert_eq!(
5487                view.text(cx),
5488                "
5489                /* */
5490                /* */
5491                /
5492
5493                "
5494                .unindent()
5495            );
5496
5497            view.undo(&Undo, cx);
5498            view.select_display_ranges(
5499                &[
5500                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
5501                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
5502                ],
5503                cx,
5504            )
5505            .unwrap();
5506            view.handle_input(&Input("*".to_string()), cx);
5507            assert_eq!(
5508                view.text(cx),
5509                "
5510                a
5511
5512                /*
5513                *
5514                "
5515                .unindent()
5516            );
5517        });
5518    }
5519
5520    #[gpui::test]
5521    async fn test_toggle_comment(mut cx: gpui::TestAppContext) {
5522        let settings = cx.read(EditorSettings::test);
5523        let language = Some(Arc::new(Language::new(
5524            LanguageConfig {
5525                line_comment: Some("// ".to_string()),
5526                ..Default::default()
5527            },
5528            Some(tree_sitter_rust::language()),
5529        )));
5530
5531        let text = "
5532            fn a() {
5533                //b();
5534                // c();
5535                //  d();
5536            }
5537        "
5538        .unindent();
5539
5540        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
5541        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5542        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
5543
5544        view.update(&mut cx, |editor, cx| {
5545            // If multiple selections intersect a line, the line is only
5546            // toggled once.
5547            editor
5548                .select_display_ranges(
5549                    &[
5550                        DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
5551                        DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
5552                    ],
5553                    cx,
5554                )
5555                .unwrap();
5556            editor.toggle_comments(&ToggleComments, cx);
5557            assert_eq!(
5558                editor.text(cx),
5559                "
5560                    fn a() {
5561                        b();
5562                        c();
5563                         d();
5564                    }
5565                "
5566                .unindent()
5567            );
5568
5569            // The comment prefix is inserted at the same column for every line
5570            // in a selection.
5571            editor
5572                .select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx)
5573                .unwrap();
5574            editor.toggle_comments(&ToggleComments, cx);
5575            assert_eq!(
5576                editor.text(cx),
5577                "
5578                    fn a() {
5579                        // b();
5580                        // c();
5581                        //  d();
5582                    }
5583                "
5584                .unindent()
5585            );
5586
5587            // If a selection ends at the beginning of a line, that line is not toggled.
5588            editor
5589                .select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx)
5590                .unwrap();
5591            editor.toggle_comments(&ToggleComments, cx);
5592            assert_eq!(
5593                editor.text(cx),
5594                "
5595                        fn a() {
5596                            // b();
5597                            c();
5598                            //  d();
5599                        }
5600                    "
5601                .unindent()
5602            );
5603        });
5604    }
5605
5606    #[gpui::test]
5607    async fn test_extra_newline_insertion(mut cx: gpui::TestAppContext) {
5608        let settings = cx.read(EditorSettings::test);
5609        let language = Some(Arc::new(Language::new(
5610            LanguageConfig {
5611                brackets: vec![
5612                    BracketPair {
5613                        start: "{".to_string(),
5614                        end: "}".to_string(),
5615                        close: true,
5616                        newline: true,
5617                    },
5618                    BracketPair {
5619                        start: "/* ".to_string(),
5620                        end: " */".to_string(),
5621                        close: true,
5622                        newline: true,
5623                    },
5624                ],
5625                ..Default::default()
5626            },
5627            Some(tree_sitter_rust::language()),
5628        )));
5629
5630        let text = concat!(
5631            "{   }\n",     // Suppress rustfmt
5632            "  x\n",       //
5633            "  /*   */\n", //
5634            "x\n",         //
5635            "{{} }\n",     //
5636        );
5637
5638        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, None, cx));
5639        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
5640        let (_, view) = cx.add_window(|cx| build_editor(buffer, settings, cx));
5641        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
5642            .await;
5643
5644        view.update(&mut cx, |view, cx| {
5645            view.select_display_ranges(
5646                &[
5647                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
5648                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
5649                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
5650                ],
5651                cx,
5652            )
5653            .unwrap();
5654            view.newline(&Newline, cx);
5655
5656            assert_eq!(
5657                view.buffer().read(cx).read(cx).text(),
5658                concat!(
5659                    "{ \n",    // Suppress rustfmt
5660                    "\n",      //
5661                    "}\n",     //
5662                    "  x\n",   //
5663                    "  /* \n", //
5664                    "  \n",    //
5665                    "  */\n",  //
5666                    "x\n",     //
5667                    "{{} \n",  //
5668                    "}\n",     //
5669                )
5670            );
5671        });
5672    }
5673
5674    impl Editor {
5675        fn selection_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
5676            self.intersecting_selections(
5677                self.selection_set_id,
5678                DisplayPoint::zero()..self.max_point(cx),
5679                cx,
5680            )
5681            .into_iter()
5682            .map(|s| {
5683                if s.reversed {
5684                    s.end..s.start
5685                } else {
5686                    s.start..s.end
5687                }
5688            })
5689            .collect()
5690        }
5691    }
5692
5693    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
5694        let point = DisplayPoint::new(row as u32, column as u32);
5695        point..point
5696    }
5697
5698    fn build_editor(
5699        buffer: ModelHandle<MultiBuffer>,
5700        settings: EditorSettings,
5701        cx: &mut ViewContext<Editor>,
5702    ) -> Editor {
5703        Editor::for_buffer(buffer, move |_| settings.clone(), cx)
5704    }
5705}
5706
5707trait RangeExt<T> {
5708    fn sorted(&self) -> Range<T>;
5709    fn to_inclusive(&self) -> RangeInclusive<T>;
5710}
5711
5712impl<T: Ord + Clone> RangeExt<T> for Range<T> {
5713    fn sorted(&self) -> Self {
5714        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
5715    }
5716
5717    fn to_inclusive(&self) -> RangeInclusive<T> {
5718        self.start.clone()..=self.end.clone()
5719    }
5720}