editor.rs

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