lib.rs

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