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