lib.rs

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