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