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