editor.rs

   1pub mod display_map;
   2mod element;
   3pub mod items;
   4pub mod movement;
   5mod multi_buffer;
   6pub mod selections_collection;
   7
   8#[cfg(any(test, feature = "test-support"))]
   9pub mod test;
  10
  11use aho_corasick::AhoCorasick;
  12use anyhow::Result;
  13use clock::ReplicaId;
  14use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  15pub use display_map::DisplayPoint;
  16use display_map::*;
  17pub use element::*;
  18use fuzzy::{StringMatch, StringMatchCandidate};
  19use gpui::{
  20    actions,
  21    color::Color,
  22    elements::*,
  23    executor,
  24    fonts::{self, HighlightStyle, TextStyle},
  25    geometry::vector::{vec2f, Vector2F},
  26    impl_actions, impl_internal_actions,
  27    platform::CursorStyle,
  28    text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
  29    ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
  30    WeakViewHandle,
  31};
  32pub use language::{char_kind, CharKind};
  33use language::{
  34    BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticSeverity,
  35    Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
  36};
  37use multi_buffer::MultiBufferChunks;
  38pub use multi_buffer::{
  39    Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
  40};
  41use ordered_float::OrderedFloat;
  42use project::{HoverContents, Project, ProjectTransaction};
  43use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  44use serde::{Deserialize, Serialize};
  45use settings::Settings;
  46use smallvec::SmallVec;
  47use smol::Timer;
  48use snippet::Snippet;
  49use std::{
  50    any::TypeId,
  51    borrow::Cow,
  52    cmp::{self, Ordering, Reverse},
  53    iter, mem,
  54    ops::{Deref, DerefMut, Range, RangeInclusive},
  55    sync::Arc,
  56    time::{Duration, Instant},
  57};
  58pub use sum_tree::Bias;
  59use theme::{DiagnosticStyle, Theme};
  60use util::{post_inc, ResultExt, TryFutureExt};
  61use workspace::{ItemNavHistory, Workspace};
  62
  63const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  64const MAX_LINE_LEN: usize = 1024;
  65const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  66const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  67
  68#[derive(Clone, Deserialize, PartialEq)]
  69pub struct SelectNext {
  70    #[serde(default)]
  71    pub replace_newest: bool,
  72}
  73
  74#[derive(Clone, PartialEq)]
  75pub struct GoToDiagnostic(pub Direction);
  76
  77#[derive(Clone, PartialEq)]
  78pub struct Scroll(pub Vector2F);
  79
  80#[derive(Clone, PartialEq)]
  81pub struct Select(pub SelectPhase);
  82
  83#[derive(Clone)]
  84pub struct ShowHover(DisplayPoint);
  85
  86#[derive(Clone)]
  87pub struct HideHover;
  88
  89#[derive(Clone)]
  90pub struct Hover {
  91    point: Option<DisplayPoint>,
  92    // visible: bool,
  93    // TODO(isaac): remove overshoot
  94    // overshoot: DisplayPoint,
  95}
  96
  97#[derive(Clone, Deserialize, PartialEq)]
  98pub struct Input(pub String);
  99
 100#[derive(Clone, Deserialize, PartialEq)]
 101pub struct SelectToBeginningOfLine {
 102    #[serde(default)]
 103    stop_at_soft_wraps: bool,
 104}
 105
 106#[derive(Clone, Deserialize, PartialEq)]
 107pub struct SelectToEndOfLine {
 108    #[serde(default)]
 109    stop_at_soft_wraps: bool,
 110}
 111
 112#[derive(Clone, Deserialize, PartialEq)]
 113pub struct ToggleCodeActions {
 114    #[serde(default)]
 115    pub deployed_from_indicator: bool,
 116}
 117
 118#[derive(Clone, Default, Deserialize, PartialEq)]
 119pub struct ConfirmCompletion {
 120    #[serde(default)]
 121    pub item_ix: Option<usize>,
 122}
 123
 124#[derive(Clone, Default, Deserialize, PartialEq)]
 125pub struct ConfirmCodeAction {
 126    #[serde(default)]
 127    pub item_ix: Option<usize>,
 128}
 129
 130#[derive(Clone, Default)]
 131pub struct GoToDefinitionAt {
 132    pub location: Option<DisplayPoint>,
 133}
 134
 135actions!(
 136    editor,
 137    [
 138        Cancel,
 139        Backspace,
 140        Delete,
 141        Newline,
 142        GoToNextDiagnostic,
 143        GoToPrevDiagnostic,
 144        Indent,
 145        Outdent,
 146        DeleteLine,
 147        DeleteToPreviousWordStart,
 148        DeleteToPreviousSubwordStart,
 149        DeleteToNextWordEnd,
 150        DeleteToNextSubwordEnd,
 151        DeleteToBeginningOfLine,
 152        DeleteToEndOfLine,
 153        CutToEndOfLine,
 154        DuplicateLine,
 155        MoveLineUp,
 156        MoveLineDown,
 157        Transpose,
 158        Cut,
 159        Copy,
 160        Paste,
 161        Undo,
 162        Redo,
 163        MoveUp,
 164        MoveDown,
 165        MoveLeft,
 166        MoveRight,
 167        MoveToPreviousWordStart,
 168        MoveToPreviousSubwordStart,
 169        MoveToNextWordEnd,
 170        MoveToNextSubwordEnd,
 171        MoveToBeginningOfLine,
 172        MoveToEndOfLine,
 173        MoveToBeginning,
 174        MoveToEnd,
 175        SelectUp,
 176        SelectDown,
 177        SelectLeft,
 178        SelectRight,
 179        SelectToPreviousWordStart,
 180        SelectToPreviousSubwordStart,
 181        SelectToNextWordEnd,
 182        SelectToNextSubwordEnd,
 183        SelectToBeginning,
 184        SelectToEnd,
 185        SelectAll,
 186        SelectLine,
 187        SplitSelectionIntoLines,
 188        AddSelectionAbove,
 189        AddSelectionBelow,
 190        Tab,
 191        TabPrev,
 192        ToggleComments,
 193        SelectLargerSyntaxNode,
 194        SelectSmallerSyntaxNode,
 195        GoToDefinition,
 196        MoveToEnclosingBracket,
 197        UndoSelection,
 198        RedoSelection,
 199        FindAllReferences,
 200        Rename,
 201        ConfirmRename,
 202        PageUp,
 203        PageDown,
 204        Fold,
 205        UnfoldLines,
 206        FoldSelectedRanges,
 207        ShowCompletions,
 208        OpenExcerpts,
 209        RestartLanguageServer,
 210    ]
 211);
 212
 213impl_actions!(
 214    editor,
 215    [
 216        Input,
 217        SelectNext,
 218        SelectToBeginningOfLine,
 219        SelectToEndOfLine,
 220        ToggleCodeActions,
 221        ConfirmCompletion,
 222        ConfirmCodeAction,
 223    ]
 224);
 225
 226impl_internal_actions!(editor, [Scroll, Select, Hover, ShowHover, HideHover, GoToDefinitionAt]);
 227
 228enum DocumentHighlightRead {}
 229enum DocumentHighlightWrite {}
 230
 231#[derive(Copy, Clone, PartialEq, Eq)]
 232pub enum Direction {
 233    Prev,
 234    Next,
 235}
 236
 237pub fn init(cx: &mut MutableAppContext) {
 238    cx.add_action(Editor::new_file);
 239    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
 240    cx.add_action(Editor::select);
 241    cx.add_action(Editor::cancel);
 242    cx.add_action(Editor::handle_input);
 243    cx.add_action(Editor::newline);
 244    cx.add_action(Editor::backspace);
 245    cx.add_action(Editor::delete);
 246    cx.add_action(Editor::tab);
 247    cx.add_action(Editor::tab_prev);
 248    cx.add_action(Editor::indent);
 249    cx.add_action(Editor::outdent);
 250    cx.add_action(Editor::delete_line);
 251    cx.add_action(Editor::delete_to_previous_word_start);
 252    cx.add_action(Editor::delete_to_previous_subword_start);
 253    cx.add_action(Editor::delete_to_next_word_end);
 254    cx.add_action(Editor::delete_to_next_subword_end);
 255    cx.add_action(Editor::delete_to_beginning_of_line);
 256    cx.add_action(Editor::delete_to_end_of_line);
 257    cx.add_action(Editor::cut_to_end_of_line);
 258    cx.add_action(Editor::duplicate_line);
 259    cx.add_action(Editor::move_line_up);
 260    cx.add_action(Editor::move_line_down);
 261    cx.add_action(Editor::transpose);
 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_start);
 272    cx.add_action(Editor::move_to_previous_subword_start);
 273    cx.add_action(Editor::move_to_next_word_end);
 274    cx.add_action(Editor::move_to_next_subword_end);
 275    cx.add_action(Editor::move_to_beginning_of_line);
 276    cx.add_action(Editor::move_to_end_of_line);
 277    cx.add_action(Editor::move_to_beginning);
 278    cx.add_action(Editor::move_to_end);
 279    cx.add_action(Editor::select_up);
 280    cx.add_action(Editor::select_down);
 281    cx.add_action(Editor::select_left);
 282    cx.add_action(Editor::select_right);
 283    cx.add_action(Editor::select_to_previous_word_start);
 284    cx.add_action(Editor::select_to_previous_subword_start);
 285    cx.add_action(Editor::select_to_next_word_end);
 286    cx.add_action(Editor::select_to_next_subword_end);
 287    cx.add_action(Editor::select_to_beginning_of_line);
 288    cx.add_action(Editor::select_to_end_of_line);
 289    cx.add_action(Editor::select_to_beginning);
 290    cx.add_action(Editor::select_to_end);
 291    cx.add_action(Editor::select_all);
 292    cx.add_action(Editor::select_line);
 293    cx.add_action(Editor::split_selection_into_lines);
 294    cx.add_action(Editor::add_selection_above);
 295    cx.add_action(Editor::add_selection_below);
 296    cx.add_action(Editor::select_next);
 297    cx.add_action(Editor::toggle_comments);
 298    cx.add_action(Editor::select_larger_syntax_node);
 299    cx.add_action(Editor::select_smaller_syntax_node);
 300    cx.add_action(Editor::move_to_enclosing_bracket);
 301    cx.add_action(Editor::undo_selection);
 302    cx.add_action(Editor::redo_selection);
 303    cx.add_action(Editor::go_to_next_diagnostic);
 304    cx.add_action(Editor::go_to_prev_diagnostic);
 305    cx.add_action(Editor::go_to_definition);
 306    cx.add_action(Editor::page_up);
 307    cx.add_action(Editor::page_down);
 308    cx.add_action(Editor::fold);
 309    cx.add_action(Editor::unfold_lines);
 310    cx.add_action(Editor::fold_selected_ranges);
 311    cx.add_action(Editor::show_completions);
 312    cx.add_action(Editor::toggle_code_actions);
 313    cx.add_action(Editor::hover);
 314    cx.add_action(Editor::show_hover);
 315    cx.add_action(Editor::hide_hover);
 316    cx.add_action(Editor::open_excerpts);
 317    cx.add_action(Editor::restart_language_server);
 318    cx.add_async_action(Editor::confirm_completion);
 319    cx.add_async_action(Editor::confirm_code_action);
 320    cx.add_async_action(Editor::rename);
 321    cx.add_async_action(Editor::confirm_rename);
 322    cx.add_async_action(Editor::find_all_references);
 323
 324    workspace::register_project_item::<Editor>(cx);
 325    workspace::register_followable_item::<Editor>(cx);
 326}
 327
 328trait InvalidationRegion {
 329    fn ranges(&self) -> &[Range<Anchor>];
 330}
 331
 332#[derive(Clone, Debug, PartialEq)]
 333pub enum SelectPhase {
 334    Begin {
 335        position: DisplayPoint,
 336        add: bool,
 337        click_count: usize,
 338    },
 339    BeginColumnar {
 340        position: DisplayPoint,
 341        overshoot: u32,
 342    },
 343    Extend {
 344        position: DisplayPoint,
 345        click_count: usize,
 346    },
 347    Update {
 348        position: DisplayPoint,
 349        overshoot: u32,
 350        scroll_position: Vector2F,
 351    },
 352    End,
 353}
 354
 355#[derive(Clone, Debug)]
 356pub enum SelectMode {
 357    Character,
 358    Word(Range<Anchor>),
 359    Line(Range<Anchor>),
 360    All,
 361}
 362
 363#[derive(PartialEq, Eq)]
 364pub enum Autoscroll {
 365    Fit,
 366    Center,
 367    Newest,
 368}
 369
 370#[derive(Copy, Clone, PartialEq, Eq)]
 371pub enum EditorMode {
 372    SingleLine,
 373    AutoHeight { max_lines: usize },
 374    Full,
 375}
 376
 377#[derive(Clone)]
 378pub enum SoftWrap {
 379    None,
 380    EditorWidth,
 381    Column(u32),
 382}
 383
 384#[derive(Clone)]
 385pub struct EditorStyle {
 386    pub text: TextStyle,
 387    pub placeholder_text: Option<TextStyle>,
 388    pub theme: theme::Editor,
 389}
 390
 391type CompletionId = usize;
 392
 393pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor;
 394
 395type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 396
 397pub struct Editor {
 398    handle: WeakViewHandle<Self>,
 399    buffer: ModelHandle<MultiBuffer>,
 400    display_map: ModelHandle<DisplayMap>,
 401    pub selections: SelectionsCollection,
 402    columnar_selection_tail: Option<Anchor>,
 403    add_selections_state: Option<AddSelectionsState>,
 404    select_next_state: Option<SelectNextState>,
 405    selection_history: SelectionHistory,
 406    autoclose_stack: InvalidationStack<BracketPairState>,
 407    snippet_stack: InvalidationStack<SnippetState>,
 408    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 409    active_diagnostics: Option<ActiveDiagnosticGroup>,
 410    scroll_position: Vector2F,
 411    scroll_top_anchor: Anchor,
 412    autoscroll_request: Option<(Autoscroll, bool)>,
 413    soft_wrap_mode_override: Option<settings::SoftWrap>,
 414    get_field_editor_theme: Option<GetFieldEditorTheme>,
 415    override_text_style: Option<Box<OverrideTextStyle>>,
 416    project: Option<ModelHandle<Project>>,
 417    focused: bool,
 418    show_local_cursors: bool,
 419    show_local_selections: bool,
 420    blink_epoch: usize,
 421    blinking_paused: bool,
 422    mode: EditorMode,
 423    vertical_scroll_margin: f32,
 424    placeholder_text: Option<Arc<str>>,
 425    highlighted_rows: Option<Range<u32>>,
 426    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 427    nav_history: Option<ItemNavHistory>,
 428    context_menu: Option<ContextMenu>,
 429    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 430    next_completion_id: CompletionId,
 431    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 432    code_actions_task: Option<Task<()>>,
 433    hover_task: Option<Task<Option<()>>>,
 434    document_highlights_task: Option<Task<()>>,
 435    pending_rename: Option<RenameState>,
 436    searchable: bool,
 437    cursor_shape: CursorShape,
 438    keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
 439    input_enabled: bool,
 440    leader_replica_id: Option<u16>,
 441    hover_popover: HoverState,
 442}
 443
 444/// Keeps track of the state of the [`HoverPopover`].
 445/// Times out the initial delay and the grace period.
 446pub struct HoverState {
 447    popover: Option<HoverPopover>,
 448    last_hover: std::time::Instant,
 449    start_grace: std::time::Instant,
 450}
 451
 452impl HoverState {
 453    /// Takes whether the cursor is currently hovering over a symbol,
 454    /// and returns a tuple containing whether there was a recent hover,
 455    /// and whether the hover is still in the grace period.
 456    pub fn determine_state(&mut self, hovering: bool) -> (bool, bool) {
 457        // NOTE: 200ms and 100ms are sane defaults, but it might be
 458        //       nice to make these values configurable.
 459        let recent_hover = self.last_hover.elapsed() < std::time::Duration::from_millis(200);
 460        if !hovering {
 461            self.last_hover = std::time::Instant::now();
 462        }
 463
 464        let in_grace = self.start_grace.elapsed() < std::time::Duration::from_millis(100);
 465        if hovering && !recent_hover {
 466            self.start_grace = std::time::Instant::now();
 467        }
 468
 469        return (recent_hover, in_grace);
 470    }
 471}
 472
 473pub struct EditorSnapshot {
 474    pub mode: EditorMode,
 475    pub display_snapshot: DisplaySnapshot,
 476    pub placeholder_text: Option<Arc<str>>,
 477    is_focused: bool,
 478    scroll_position: Vector2F,
 479    scroll_top_anchor: Anchor,
 480}
 481
 482#[derive(Clone, Debug)]
 483struct SelectionHistoryEntry {
 484    selections: Arc<[Selection<Anchor>]>,
 485    select_next_state: Option<SelectNextState>,
 486    add_selections_state: Option<AddSelectionsState>,
 487}
 488
 489enum SelectionHistoryMode {
 490    Normal,
 491    Undoing,
 492    Redoing,
 493}
 494
 495impl Default for SelectionHistoryMode {
 496    fn default() -> Self {
 497        Self::Normal
 498    }
 499}
 500
 501#[derive(Default)]
 502struct SelectionHistory {
 503    selections_by_transaction:
 504        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 505    mode: SelectionHistoryMode,
 506    undo_stack: VecDeque<SelectionHistoryEntry>,
 507    redo_stack: VecDeque<SelectionHistoryEntry>,
 508}
 509
 510impl SelectionHistory {
 511    fn insert_transaction(
 512        &mut self,
 513        transaction_id: TransactionId,
 514        selections: Arc<[Selection<Anchor>]>,
 515    ) {
 516        self.selections_by_transaction
 517            .insert(transaction_id, (selections, None));
 518    }
 519
 520    fn transaction(
 521        &self,
 522        transaction_id: TransactionId,
 523    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 524        self.selections_by_transaction.get(&transaction_id)
 525    }
 526
 527    fn transaction_mut(
 528        &mut self,
 529        transaction_id: TransactionId,
 530    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 531        self.selections_by_transaction.get_mut(&transaction_id)
 532    }
 533
 534    fn push(&mut self, entry: SelectionHistoryEntry) {
 535        if !entry.selections.is_empty() {
 536            match self.mode {
 537                SelectionHistoryMode::Normal => {
 538                    self.push_undo(entry);
 539                    self.redo_stack.clear();
 540                }
 541                SelectionHistoryMode::Undoing => self.push_redo(entry),
 542                SelectionHistoryMode::Redoing => self.push_undo(entry),
 543            }
 544        }
 545    }
 546
 547    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 548        if self
 549            .undo_stack
 550            .back()
 551            .map_or(true, |e| e.selections != entry.selections)
 552        {
 553            self.undo_stack.push_back(entry);
 554            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 555                self.undo_stack.pop_front();
 556            }
 557        }
 558    }
 559
 560    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 561        if self
 562            .redo_stack
 563            .back()
 564            .map_or(true, |e| e.selections != entry.selections)
 565        {
 566            self.redo_stack.push_back(entry);
 567            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 568                self.redo_stack.pop_front();
 569            }
 570        }
 571    }
 572}
 573
 574#[derive(Clone, Debug)]
 575struct AddSelectionsState {
 576    above: bool,
 577    stack: Vec<usize>,
 578}
 579
 580#[derive(Clone, Debug)]
 581struct SelectNextState {
 582    query: AhoCorasick,
 583    wordwise: bool,
 584    done: bool,
 585}
 586
 587struct BracketPairState {
 588    ranges: Vec<Range<Anchor>>,
 589    pair: BracketPair,
 590}
 591
 592#[derive(Debug)]
 593struct SnippetState {
 594    ranges: Vec<Vec<Range<Anchor>>>,
 595    active_index: usize,
 596}
 597
 598pub struct RenameState {
 599    pub range: Range<Anchor>,
 600    pub old_name: Arc<str>,
 601    pub editor: ViewHandle<Editor>,
 602    block_id: BlockId,
 603}
 604
 605struct InvalidationStack<T>(Vec<T>);
 606
 607enum ContextMenu {
 608    Completions(CompletionsMenu),
 609    CodeActions(CodeActionsMenu),
 610}
 611
 612impl ContextMenu {
 613    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 614        if self.visible() {
 615            match self {
 616                ContextMenu::Completions(menu) => menu.select_prev(cx),
 617                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 618            }
 619            true
 620        } else {
 621            false
 622        }
 623    }
 624
 625    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 626        if self.visible() {
 627            match self {
 628                ContextMenu::Completions(menu) => menu.select_next(cx),
 629                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 630            }
 631            true
 632        } else {
 633            false
 634        }
 635    }
 636
 637    fn visible(&self) -> bool {
 638        match self {
 639            ContextMenu::Completions(menu) => menu.visible(),
 640            ContextMenu::CodeActions(menu) => menu.visible(),
 641        }
 642    }
 643
 644    fn render(
 645        &self,
 646        cursor_position: DisplayPoint,
 647        style: EditorStyle,
 648        cx: &mut RenderContext<Editor>,
 649    ) -> (DisplayPoint, ElementBox) {
 650        match self {
 651            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 652            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 653            ContextMenu::Hover(popover) => (cursor_position, popover.render(style)),
 654        }
 655    }
 656}
 657
 658struct CompletionsMenu {
 659    id: CompletionId,
 660    initial_position: Anchor,
 661    buffer: ModelHandle<Buffer>,
 662    completions: Arc<[Completion]>,
 663    match_candidates: Vec<StringMatchCandidate>,
 664    matches: Arc<[StringMatch]>,
 665    selected_item: usize,
 666    list: UniformListState,
 667}
 668
 669impl CompletionsMenu {
 670    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 671        if self.selected_item > 0 {
 672            self.selected_item -= 1;
 673            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 674        }
 675        cx.notify();
 676    }
 677
 678    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 679        if self.selected_item + 1 < self.matches.len() {
 680            self.selected_item += 1;
 681            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 682        }
 683        cx.notify();
 684    }
 685
 686    fn visible(&self) -> bool {
 687        !self.matches.is_empty()
 688    }
 689
 690    fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
 691        enum CompletionTag {}
 692
 693        let completions = self.completions.clone();
 694        let matches = self.matches.clone();
 695        let selected_item = self.selected_item;
 696        let container_style = style.autocomplete.container;
 697        UniformList::new(
 698            self.list.clone(),
 699            matches.len(),
 700            cx,
 701            move |_, range, items, cx| {
 702                let start_ix = range.start;
 703                for (ix, mat) in matches[range].iter().enumerate() {
 704                    let completion = &completions[mat.candidate_id];
 705                    let item_ix = start_ix + ix;
 706                    items.push(
 707                        MouseEventHandler::new::<CompletionTag, _, _>(
 708                            mat.candidate_id,
 709                            cx,
 710                            |state, _| {
 711                                let item_style = if item_ix == selected_item {
 712                                    style.autocomplete.selected_item
 713                                } else if state.hovered {
 714                                    style.autocomplete.hovered_item
 715                                } else {
 716                                    style.autocomplete.item
 717                                };
 718
 719                                Text::new(completion.label.text.clone(), style.text.clone())
 720                                    .with_soft_wrap(false)
 721                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 722                                        &completion.label.text,
 723                                        style.text.color.into(),
 724                                        styled_runs_for_code_label(
 725                                            &completion.label,
 726                                            &style.syntax,
 727                                        ),
 728                                        &mat.positions,
 729                                    ))
 730                                    .contained()
 731                                    .with_style(item_style)
 732                                    .boxed()
 733                            },
 734                        )
 735                        .with_cursor_style(CursorStyle::PointingHand)
 736                        .on_mouse_down(move |_, cx| {
 737                            cx.dispatch_action(ConfirmCompletion {
 738                                item_ix: Some(item_ix),
 739                            });
 740                        })
 741                        .boxed(),
 742                    );
 743                }
 744            },
 745        )
 746        .with_width_from_item(
 747            self.matches
 748                .iter()
 749                .enumerate()
 750                .max_by_key(|(_, mat)| {
 751                    self.completions[mat.candidate_id]
 752                        .label
 753                        .text
 754                        .chars()
 755                        .count()
 756                })
 757                .map(|(ix, _)| ix),
 758        )
 759        .contained()
 760        .with_style(container_style)
 761        .boxed()
 762    }
 763
 764    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 765        let mut matches = if let Some(query) = query {
 766            fuzzy::match_strings(
 767                &self.match_candidates,
 768                query,
 769                false,
 770                100,
 771                &Default::default(),
 772                executor,
 773            )
 774            .await
 775        } else {
 776            self.match_candidates
 777                .iter()
 778                .enumerate()
 779                .map(|(candidate_id, candidate)| StringMatch {
 780                    candidate_id,
 781                    score: Default::default(),
 782                    positions: Default::default(),
 783                    string: candidate.string.clone(),
 784                })
 785                .collect()
 786        };
 787        matches.sort_unstable_by_key(|mat| {
 788            (
 789                Reverse(OrderedFloat(mat.score)),
 790                self.completions[mat.candidate_id].sort_key(),
 791            )
 792        });
 793
 794        for mat in &mut matches {
 795            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 796            for position in &mut mat.positions {
 797                *position += filter_start;
 798            }
 799        }
 800
 801        self.matches = matches.into();
 802    }
 803}
 804
 805#[derive(Clone)]
 806struct CodeActionsMenu {
 807    actions: Arc<[CodeAction]>,
 808    buffer: ModelHandle<Buffer>,
 809    selected_item: usize,
 810    list: UniformListState,
 811    deployed_from_indicator: bool,
 812}
 813
 814impl CodeActionsMenu {
 815    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 816        if self.selected_item > 0 {
 817            self.selected_item -= 1;
 818            cx.notify()
 819        }
 820    }
 821
 822    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 823        if self.selected_item + 1 < self.actions.len() {
 824            self.selected_item += 1;
 825            cx.notify()
 826        }
 827    }
 828
 829    fn visible(&self) -> bool {
 830        !self.actions.is_empty()
 831    }
 832
 833    fn render(
 834        &self,
 835        mut cursor_position: DisplayPoint,
 836        style: EditorStyle,
 837        cx: &mut RenderContext<Editor>,
 838    ) -> (DisplayPoint, ElementBox) {
 839        enum ActionTag {}
 840
 841        let container_style = style.autocomplete.container;
 842        let actions = self.actions.clone();
 843        let selected_item = self.selected_item;
 844        let element = UniformList::new(
 845            self.list.clone(),
 846            actions.len(),
 847            cx,
 848            move |_, range, items, cx| {
 849                let start_ix = range.start;
 850                for (ix, action) in actions[range].iter().enumerate() {
 851                    let item_ix = start_ix + ix;
 852                    items.push(
 853                        MouseEventHandler::new::<ActionTag, _, _>(item_ix, cx, |state, _| {
 854                            let item_style = if item_ix == selected_item {
 855                                style.autocomplete.selected_item
 856                            } else if state.hovered {
 857                                style.autocomplete.hovered_item
 858                            } else {
 859                                style.autocomplete.item
 860                            };
 861
 862                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 863                                .with_soft_wrap(false)
 864                                .contained()
 865                                .with_style(item_style)
 866                                .boxed()
 867                        })
 868                        .with_cursor_style(CursorStyle::PointingHand)
 869                        .on_mouse_down(move |_, cx| {
 870                            cx.dispatch_action(ConfirmCodeAction {
 871                                item_ix: Some(item_ix),
 872                            });
 873                        })
 874                        .boxed(),
 875                    );
 876                }
 877            },
 878        )
 879        .with_width_from_item(
 880            self.actions
 881                .iter()
 882                .enumerate()
 883                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 884                .map(|(ix, _)| ix),
 885        )
 886        .contained()
 887        .with_style(container_style)
 888        .boxed();
 889
 890        if self.deployed_from_indicator {
 891            *cursor_position.column_mut() = 0;
 892        }
 893
 894        (cursor_position, element)
 895    }
 896}
 897
 898struct HoverPopover {
 899    pub point: DisplayPoint,
 900    pub contents: Vec<HoverContents>,
 901}
 902
 903impl HoverPopover {
 904    fn render(&self, style: EditorStyle) -> (DisplayPoint, ElementBox) {
 905        let contents = self.contents.first().unwrap();
 906        (
 907            self.point,
 908            Text::new(contents.text.clone(), style.text.clone())
 909                .with_soft_wrap(false)
 910                .with_highlights(
 911                    contents
 912                        .runs
 913                        .iter()
 914                        .filter_map(|(range, id)| {
 915                            id.style(style.theme.syntax.as_ref())
 916                                .map(|style| (range.clone(), style))
 917                        })
 918                        .collect(),
 919                )
 920                .contained()
 921                .with_style(style.hover_popover)
 922                .boxed(),
 923        )
 924    }
 925}
 926
 927#[derive(Debug)]
 928struct ActiveDiagnosticGroup {
 929    primary_range: Range<Anchor>,
 930    primary_message: String,
 931    blocks: HashMap<BlockId, Diagnostic>,
 932    is_valid: bool,
 933}
 934
 935#[derive(Serialize, Deserialize)]
 936pub struct ClipboardSelection {
 937    pub len: usize,
 938    pub is_entire_line: bool,
 939}
 940
 941#[derive(Debug)]
 942pub struct NavigationData {
 943    // Matching offsets for anchor and scroll_top_anchor allows us to recreate the anchor if the buffer
 944    // has since been closed
 945    cursor_anchor: Anchor,
 946    cursor_position: Point,
 947    scroll_position: Vector2F,
 948    scroll_top_anchor: Anchor,
 949    scroll_top_row: u32,
 950}
 951
 952pub struct EditorCreated(pub ViewHandle<Editor>);
 953
 954impl Editor {
 955    pub fn single_line(
 956        field_editor_style: Option<GetFieldEditorTheme>,
 957        cx: &mut ViewContext<Self>,
 958    ) -> Self {
 959        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 960        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 961        Self::new(
 962            EditorMode::SingleLine,
 963            buffer,
 964            None,
 965            field_editor_style,
 966            None,
 967            cx,
 968        )
 969    }
 970
 971    pub fn auto_height(
 972        max_lines: usize,
 973        field_editor_style: Option<GetFieldEditorTheme>,
 974        cx: &mut ViewContext<Self>,
 975    ) -> Self {
 976        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 977        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 978        Self::new(
 979            EditorMode::AutoHeight { max_lines },
 980            buffer,
 981            None,
 982            field_editor_style,
 983            None,
 984            cx,
 985        )
 986    }
 987
 988    pub fn for_buffer(
 989        buffer: ModelHandle<Buffer>,
 990        project: Option<ModelHandle<Project>>,
 991        cx: &mut ViewContext<Self>,
 992    ) -> Self {
 993        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 994        Self::new(EditorMode::Full, buffer, project, None, None, cx)
 995    }
 996
 997    pub fn for_multibuffer(
 998        buffer: ModelHandle<MultiBuffer>,
 999        project: Option<ModelHandle<Project>>,
1000        cx: &mut ViewContext<Self>,
1001    ) -> Self {
1002        Self::new(EditorMode::Full, buffer, project, None, None, cx)
1003    }
1004
1005    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1006        let mut clone = Self::new(
1007            self.mode,
1008            self.buffer.clone(),
1009            self.project.clone(),
1010            self.get_field_editor_theme,
1011            Some(self.selections.clone()),
1012            cx,
1013        );
1014        clone.scroll_position = self.scroll_position;
1015        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
1016        clone.searchable = self.searchable;
1017        clone
1018    }
1019
1020    fn new(
1021        mode: EditorMode,
1022        buffer: ModelHandle<MultiBuffer>,
1023        project: Option<ModelHandle<Project>>,
1024        get_field_editor_theme: Option<GetFieldEditorTheme>,
1025        selections: Option<SelectionsCollection>,
1026        cx: &mut ViewContext<Self>,
1027    ) -> Self {
1028        let display_map = cx.add_model(|cx| {
1029            let settings = cx.global::<Settings>();
1030            let style = build_style(&*settings, get_field_editor_theme, None, cx);
1031            DisplayMap::new(
1032                buffer.clone(),
1033                style.text.font_id,
1034                style.text.font_size,
1035                None,
1036                2,
1037                1,
1038                cx,
1039            )
1040        });
1041        cx.observe(&buffer, Self::on_buffer_changed).detach();
1042        cx.subscribe(&buffer, Self::on_buffer_event).detach();
1043        cx.observe(&display_map, Self::on_display_map_changed)
1044            .detach();
1045
1046        let selections = selections
1047            .unwrap_or_else(|| SelectionsCollection::new(display_map.clone(), buffer.clone()));
1048
1049        let mut this = Self {
1050            handle: cx.weak_handle(),
1051            buffer,
1052            display_map,
1053            selections,
1054            columnar_selection_tail: None,
1055            add_selections_state: None,
1056            select_next_state: None,
1057            selection_history: Default::default(),
1058            autoclose_stack: Default::default(),
1059            snippet_stack: Default::default(),
1060            select_larger_syntax_node_stack: Vec::new(),
1061            active_diagnostics: None,
1062            soft_wrap_mode_override: None,
1063            get_field_editor_theme,
1064            project,
1065            scroll_position: Vector2F::zero(),
1066            scroll_top_anchor: Anchor::min(),
1067            autoscroll_request: None,
1068            focused: false,
1069            show_local_cursors: false,
1070            show_local_selections: true,
1071            blink_epoch: 0,
1072            blinking_paused: false,
1073            mode,
1074            vertical_scroll_margin: 3.0,
1075            placeholder_text: None,
1076            highlighted_rows: None,
1077            background_highlights: Default::default(),
1078            nav_history: None,
1079            context_menu: None,
1080            completion_tasks: Default::default(),
1081            next_completion_id: 0,
1082            available_code_actions: Default::default(),
1083            code_actions_task: Default::default(),
1084            hover_task: Default::default(),
1085            document_highlights_task: Default::default(),
1086            pending_rename: Default::default(),
1087            searchable: true,
1088            override_text_style: None,
1089            cursor_shape: Default::default(),
1090            keymap_context_layers: Default::default(),
1091            input_enabled: true,
1092            leader_replica_id: None,
1093            hover_popover: HoverState {
1094                popover: None,
1095                last_hover: std::time::Instant::now(),
1096                start_grace: std::time::Instant::now(),
1097            },
1098        };
1099        this.end_selection(cx);
1100
1101        let editor_created_event = EditorCreated(cx.handle());
1102        cx.emit_global(editor_created_event);
1103
1104        this
1105    }
1106
1107    pub fn new_file(
1108        workspace: &mut Workspace,
1109        _: &workspace::NewFile,
1110        cx: &mut ViewContext<Workspace>,
1111    ) {
1112        let project = workspace.project().clone();
1113        if project.read(cx).is_remote() {
1114            cx.propagate_action();
1115        } else if let Some(buffer) = project
1116            .update(cx, |project, cx| project.create_buffer("", None, cx))
1117            .log_err()
1118        {
1119            workspace.add_item(
1120                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1121                cx,
1122            );
1123        }
1124    }
1125
1126    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1127        self.buffer.read(cx).replica_id()
1128    }
1129
1130    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1131        self.leader_replica_id
1132    }
1133
1134    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1135        &self.buffer
1136    }
1137
1138    pub fn title(&self, cx: &AppContext) -> String {
1139        self.buffer().read(cx).title(cx)
1140    }
1141
1142    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
1143        EditorSnapshot {
1144            mode: self.mode,
1145            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1146            scroll_position: self.scroll_position,
1147            scroll_top_anchor: self.scroll_top_anchor.clone(),
1148            placeholder_text: self.placeholder_text.clone(),
1149            is_focused: self
1150                .handle
1151                .upgrade(cx)
1152                .map_or(false, |handle| handle.is_focused(cx)),
1153        }
1154    }
1155
1156    pub fn language_at<'a, T: ToOffset>(
1157        &self,
1158        point: T,
1159        cx: &'a AppContext,
1160    ) -> Option<&'a Arc<Language>> {
1161        self.buffer.read(cx).language_at(point, cx)
1162    }
1163
1164    fn style(&self, cx: &AppContext) -> EditorStyle {
1165        build_style(
1166            cx.global::<Settings>(),
1167            self.get_field_editor_theme,
1168            self.override_text_style.as_deref(),
1169            cx,
1170        )
1171    }
1172
1173    pub fn mode(&self) -> EditorMode {
1174        self.mode
1175    }
1176
1177    pub fn set_placeholder_text(
1178        &mut self,
1179        placeholder_text: impl Into<Arc<str>>,
1180        cx: &mut ViewContext<Self>,
1181    ) {
1182        self.placeholder_text = Some(placeholder_text.into());
1183        cx.notify();
1184    }
1185
1186    pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
1187        self.vertical_scroll_margin = margin_rows as f32;
1188        cx.notify();
1189    }
1190
1191    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
1192        self.set_scroll_position_internal(scroll_position, true, cx);
1193    }
1194
1195    fn set_scroll_position_internal(
1196        &mut self,
1197        scroll_position: Vector2F,
1198        local: bool,
1199        cx: &mut ViewContext<Self>,
1200    ) {
1201        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1202
1203        if scroll_position.y() == 0. {
1204            self.scroll_top_anchor = Anchor::min();
1205            self.scroll_position = scroll_position;
1206        } else {
1207            let scroll_top_buffer_offset =
1208                DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
1209            let anchor = map
1210                .buffer_snapshot
1211                .anchor_at(scroll_top_buffer_offset, Bias::Right);
1212            self.scroll_position = vec2f(
1213                scroll_position.x(),
1214                scroll_position.y() - anchor.to_display_point(&map).row() as f32,
1215            );
1216            self.scroll_top_anchor = anchor;
1217        }
1218
1219        self.autoscroll_request.take();
1220        cx.emit(Event::ScrollPositionChanged { local });
1221        cx.notify();
1222    }
1223
1224    fn set_scroll_top_anchor(
1225        &mut self,
1226        anchor: Anchor,
1227        position: Vector2F,
1228        cx: &mut ViewContext<Self>,
1229    ) {
1230        self.scroll_top_anchor = anchor;
1231        self.scroll_position = position;
1232        cx.emit(Event::ScrollPositionChanged { local: false });
1233        cx.notify();
1234    }
1235
1236    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1237        self.cursor_shape = cursor_shape;
1238        cx.notify();
1239    }
1240
1241    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1242        if self.display_map.read(cx).clip_at_line_ends != clip {
1243            self.display_map
1244                .update(cx, |map, _| map.clip_at_line_ends = clip);
1245        }
1246    }
1247
1248    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: gpui::keymap::Context) {
1249        self.keymap_context_layers
1250            .insert(TypeId::of::<Tag>(), context);
1251    }
1252
1253    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
1254        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1255    }
1256
1257    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1258        self.input_enabled = input_enabled;
1259    }
1260
1261    pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
1262        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1263        compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
1264    }
1265
1266    pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
1267        if max < self.scroll_position.x() {
1268            self.scroll_position.set_x(max);
1269            true
1270        } else {
1271            false
1272        }
1273    }
1274
1275    pub fn autoscroll_vertically(
1276        &mut self,
1277        viewport_height: f32,
1278        line_height: f32,
1279        cx: &mut ViewContext<Self>,
1280    ) -> bool {
1281        let visible_lines = viewport_height / line_height;
1282        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1283        let mut scroll_position =
1284            compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
1285        let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
1286            (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
1287        } else {
1288            display_map.max_point().row().saturating_sub(1) as f32
1289        };
1290        if scroll_position.y() > max_scroll_top {
1291            scroll_position.set_y(max_scroll_top);
1292            self.set_scroll_position(scroll_position, cx);
1293        }
1294
1295        let (autoscroll, local) = if let Some(autoscroll) = self.autoscroll_request.take() {
1296            autoscroll
1297        } else {
1298            return false;
1299        };
1300
1301        let first_cursor_top;
1302        let last_cursor_bottom;
1303        if let Some(highlighted_rows) = &self.highlighted_rows {
1304            first_cursor_top = highlighted_rows.start as f32;
1305            last_cursor_bottom = first_cursor_top + 1.;
1306        } else if autoscroll == Autoscroll::Newest {
1307            let newest_selection = self.selections.newest::<Point>(cx);
1308            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
1309            last_cursor_bottom = first_cursor_top + 1.;
1310        } else {
1311            let selections = self.selections.all::<Point>(cx);
1312            first_cursor_top = selections
1313                .first()
1314                .unwrap()
1315                .head()
1316                .to_display_point(&display_map)
1317                .row() as f32;
1318            last_cursor_bottom = selections
1319                .last()
1320                .unwrap()
1321                .head()
1322                .to_display_point(&display_map)
1323                .row() as f32
1324                + 1.0;
1325        }
1326
1327        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
1328            0.
1329        } else {
1330            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
1331        };
1332        if margin < 0.0 {
1333            return false;
1334        }
1335
1336        match autoscroll {
1337            Autoscroll::Fit | Autoscroll::Newest => {
1338                let margin = margin.min(self.vertical_scroll_margin);
1339                let target_top = (first_cursor_top - margin).max(0.0);
1340                let target_bottom = last_cursor_bottom + margin;
1341                let start_row = scroll_position.y();
1342                let end_row = start_row + visible_lines;
1343
1344                if target_top < start_row {
1345                    scroll_position.set_y(target_top);
1346                    self.set_scroll_position_internal(scroll_position, local, cx);
1347                } else if target_bottom >= end_row {
1348                    scroll_position.set_y(target_bottom - visible_lines);
1349                    self.set_scroll_position_internal(scroll_position, local, cx);
1350                }
1351            }
1352            Autoscroll::Center => {
1353                scroll_position.set_y((first_cursor_top - margin).max(0.0));
1354                self.set_scroll_position_internal(scroll_position, local, cx);
1355            }
1356        }
1357
1358        true
1359    }
1360
1361    pub fn autoscroll_horizontally(
1362        &mut self,
1363        start_row: u32,
1364        viewport_width: f32,
1365        scroll_width: f32,
1366        max_glyph_width: f32,
1367        layouts: &[text_layout::Line],
1368        cx: &mut ViewContext<Self>,
1369    ) -> bool {
1370        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1371        let selections = self.selections.all::<Point>(cx);
1372
1373        let mut target_left;
1374        let mut target_right;
1375
1376        if self.highlighted_rows.is_some() {
1377            target_left = 0.0_f32;
1378            target_right = 0.0_f32;
1379        } else {
1380            target_left = std::f32::INFINITY;
1381            target_right = 0.0_f32;
1382            for selection in selections {
1383                let head = selection.head().to_display_point(&display_map);
1384                if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
1385                    let start_column = head.column().saturating_sub(3);
1386                    let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
1387                    target_left = target_left.min(
1388                        layouts[(head.row() - start_row) as usize]
1389                            .x_for_index(start_column as usize),
1390                    );
1391                    target_right = target_right.max(
1392                        layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
1393                            + max_glyph_width,
1394                    );
1395                }
1396            }
1397        }
1398
1399        target_right = target_right.min(scroll_width);
1400
1401        if target_right - target_left > viewport_width {
1402            return false;
1403        }
1404
1405        let scroll_left = self.scroll_position.x() * max_glyph_width;
1406        let scroll_right = scroll_left + viewport_width;
1407
1408        if target_left < scroll_left {
1409            self.scroll_position.set_x(target_left / max_glyph_width);
1410            true
1411        } else if target_right > scroll_right {
1412            self.scroll_position
1413                .set_x((target_right - viewport_width) / max_glyph_width);
1414            true
1415        } else {
1416            false
1417        }
1418    }
1419
1420    fn selections_did_change(
1421        &mut self,
1422        local: bool,
1423        old_cursor_position: &Anchor,
1424        cx: &mut ViewContext<Self>,
1425    ) {
1426        if self.focused && self.leader_replica_id.is_none() {
1427            self.buffer.update(cx, |buffer, cx| {
1428                buffer.set_active_selections(
1429                    &self.selections.disjoint_anchors(),
1430                    self.selections.line_mode,
1431                    cx,
1432                )
1433            });
1434        }
1435
1436        let display_map = self
1437            .display_map
1438            .update(cx, |display_map, cx| display_map.snapshot(cx));
1439        let buffer = &display_map.buffer_snapshot;
1440        self.add_selections_state = None;
1441        self.select_next_state = None;
1442        self.select_larger_syntax_node_stack.clear();
1443        self.autoclose_stack
1444            .invalidate(&self.selections.disjoint_anchors(), buffer);
1445        self.snippet_stack
1446            .invalidate(&self.selections.disjoint_anchors(), buffer);
1447        self.take_rename(false, cx);
1448
1449        let new_cursor_position = self.selections.newest_anchor().head();
1450
1451        self.push_to_nav_history(
1452            old_cursor_position.clone(),
1453            Some(new_cursor_position.to_point(buffer)),
1454            cx,
1455        );
1456
1457        if local {
1458            let new_cursor_position = self.selections.newest_anchor().head();
1459            let completion_menu = match self.context_menu.as_mut() {
1460                Some(ContextMenu::Completions(menu)) => Some(menu),
1461                _ => {
1462                    self.context_menu.take();
1463                    None
1464                }
1465            };
1466
1467            if let Some(completion_menu) = completion_menu {
1468                let cursor_position = new_cursor_position.to_offset(buffer);
1469                let (word_range, kind) =
1470                    buffer.surrounding_word(completion_menu.initial_position.clone());
1471                if kind == Some(CharKind::Word)
1472                    && word_range.to_inclusive().contains(&cursor_position)
1473                {
1474                    let query = Self::completion_query(buffer, cursor_position);
1475                    cx.background()
1476                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1477                    self.show_completions(&ShowCompletions, cx);
1478                } else {
1479                    self.hide_context_menu(cx);
1480                }
1481            }
1482
1483            if old_cursor_position.to_display_point(&display_map).row()
1484                != new_cursor_position.to_display_point(&display_map).row()
1485            {
1486                self.available_code_actions.take();
1487            }
1488            self.refresh_code_actions(cx);
1489            self.refresh_document_highlights(cx);
1490        }
1491
1492        self.pause_cursor_blinking(cx);
1493        cx.emit(Event::SelectionsChanged { local });
1494        cx.notify();
1495    }
1496
1497    pub fn change_selections<R>(
1498        &mut self,
1499        autoscroll: Option<Autoscroll>,
1500        cx: &mut ViewContext<Self>,
1501        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1502    ) -> R {
1503        let old_cursor_position = self.selections.newest_anchor().head();
1504        self.push_to_selection_history();
1505
1506        let (changed, result) = self.selections.change_with(cx, change);
1507
1508        if changed {
1509            if let Some(autoscroll) = autoscroll {
1510                self.request_autoscroll(autoscroll, cx);
1511            }
1512            self.selections_did_change(true, &old_cursor_position, cx);
1513        }
1514
1515        result
1516    }
1517
1518    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1519    where
1520        I: IntoIterator<Item = (Range<S>, T)>,
1521        S: ToOffset,
1522        T: Into<Arc<str>>,
1523    {
1524        self.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
1525    }
1526
1527    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1528    where
1529        I: IntoIterator<Item = (Range<S>, T)>,
1530        S: ToOffset,
1531        T: Into<Arc<str>>,
1532    {
1533        self.buffer
1534            .update(cx, |buffer, cx| buffer.edit_with_autoindent(edits, cx));
1535    }
1536
1537    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
1538        self.hide_context_menu(cx);
1539
1540        match phase {
1541            SelectPhase::Begin {
1542                position,
1543                add,
1544                click_count,
1545            } => self.begin_selection(*position, *add, *click_count, cx),
1546            SelectPhase::BeginColumnar {
1547                position,
1548                overshoot,
1549            } => self.begin_columnar_selection(*position, *overshoot, cx),
1550            SelectPhase::Extend {
1551                position,
1552                click_count,
1553            } => self.extend_selection(*position, *click_count, cx),
1554            SelectPhase::Update {
1555                position,
1556                overshoot,
1557                scroll_position,
1558            } => self.update_selection(*position, *overshoot, *scroll_position, cx),
1559            SelectPhase::End => self.end_selection(cx),
1560        }
1561    }
1562
1563    fn extend_selection(
1564        &mut self,
1565        position: DisplayPoint,
1566        click_count: usize,
1567        cx: &mut ViewContext<Self>,
1568    ) {
1569        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1570        let tail = self.selections.newest::<usize>(cx).tail();
1571        self.begin_selection(position, false, click_count, cx);
1572
1573        let position = position.to_offset(&display_map, Bias::Left);
1574        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1575
1576        let mut pending_selection = self
1577            .selections
1578            .pending_anchor()
1579            .expect("extend_selection not called with pending selection");
1580        if position >= tail {
1581            pending_selection.start = tail_anchor.clone();
1582        } else {
1583            pending_selection.end = tail_anchor.clone();
1584            pending_selection.reversed = true;
1585        }
1586
1587        let mut pending_mode = self.selections.pending_mode().unwrap();
1588        match &mut pending_mode {
1589            SelectMode::Word(range) | SelectMode::Line(range) => {
1590                *range = tail_anchor.clone()..tail_anchor
1591            }
1592            _ => {}
1593        }
1594
1595        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
1596            s.set_pending(pending_selection, pending_mode)
1597        });
1598    }
1599
1600    fn begin_selection(
1601        &mut self,
1602        position: DisplayPoint,
1603        add: bool,
1604        click_count: usize,
1605        cx: &mut ViewContext<Self>,
1606    ) {
1607        if !self.focused {
1608            cx.focus_self();
1609            cx.emit(Event::Activate);
1610        }
1611
1612        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1613        let buffer = &display_map.buffer_snapshot;
1614        let newest_selection = self.selections.newest_anchor().clone();
1615        let position = display_map.clip_point(position, Bias::Left);
1616
1617        let start;
1618        let end;
1619        let mode;
1620        match click_count {
1621            1 => {
1622                start = buffer.anchor_before(position.to_point(&display_map));
1623                end = start.clone();
1624                mode = SelectMode::Character;
1625            }
1626            2 => {
1627                let range = movement::surrounding_word(&display_map, position);
1628                start = buffer.anchor_before(range.start.to_point(&display_map));
1629                end = buffer.anchor_before(range.end.to_point(&display_map));
1630                mode = SelectMode::Word(start.clone()..end.clone());
1631            }
1632            3 => {
1633                let position = display_map
1634                    .clip_point(position, Bias::Left)
1635                    .to_point(&display_map);
1636                let line_start = display_map.prev_line_boundary(position).0;
1637                let next_line_start = buffer.clip_point(
1638                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1639                    Bias::Left,
1640                );
1641                start = buffer.anchor_before(line_start);
1642                end = buffer.anchor_before(next_line_start);
1643                mode = SelectMode::Line(start.clone()..end.clone());
1644            }
1645            _ => {
1646                start = buffer.anchor_before(0);
1647                end = buffer.anchor_before(buffer.len());
1648                mode = SelectMode::All;
1649            }
1650        }
1651
1652        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
1653            if !add {
1654                s.clear_disjoint();
1655            } else if click_count > 1 {
1656                s.delete(newest_selection.id)
1657            }
1658
1659            s.set_pending_range(start..end, mode);
1660        });
1661    }
1662
1663    fn begin_columnar_selection(
1664        &mut self,
1665        position: DisplayPoint,
1666        overshoot: u32,
1667        cx: &mut ViewContext<Self>,
1668    ) {
1669        if !self.focused {
1670            cx.focus_self();
1671            cx.emit(Event::Activate);
1672        }
1673
1674        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1675        let tail = self.selections.newest::<Point>(cx).tail();
1676        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1677
1678        self.select_columns(
1679            tail.to_display_point(&display_map),
1680            position,
1681            overshoot,
1682            &display_map,
1683            cx,
1684        );
1685    }
1686
1687    fn update_selection(
1688        &mut self,
1689        position: DisplayPoint,
1690        overshoot: u32,
1691        scroll_position: Vector2F,
1692        cx: &mut ViewContext<Self>,
1693    ) {
1694        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1695
1696        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1697            let tail = tail.to_display_point(&display_map);
1698            self.select_columns(tail, position, overshoot, &display_map, cx);
1699        } else if let Some(mut pending) = self.selections.pending_anchor().clone() {
1700            let buffer = self.buffer.read(cx).snapshot(cx);
1701            let head;
1702            let tail;
1703            let mode = self.selections.pending_mode().unwrap();
1704            match &mode {
1705                SelectMode::Character => {
1706                    head = position.to_point(&display_map);
1707                    tail = pending.tail().to_point(&buffer);
1708                }
1709                SelectMode::Word(original_range) => {
1710                    let original_display_range = original_range.start.to_display_point(&display_map)
1711                        ..original_range.end.to_display_point(&display_map);
1712                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1713                        ..original_display_range.end.to_point(&display_map);
1714                    if movement::is_inside_word(&display_map, position)
1715                        || original_display_range.contains(&position)
1716                    {
1717                        let word_range = movement::surrounding_word(&display_map, position);
1718                        if word_range.start < original_display_range.start {
1719                            head = word_range.start.to_point(&display_map);
1720                        } else {
1721                            head = word_range.end.to_point(&display_map);
1722                        }
1723                    } else {
1724                        head = position.to_point(&display_map);
1725                    }
1726
1727                    if head <= original_buffer_range.start {
1728                        tail = original_buffer_range.end;
1729                    } else {
1730                        tail = original_buffer_range.start;
1731                    }
1732                }
1733                SelectMode::Line(original_range) => {
1734                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1735
1736                    let position = display_map
1737                        .clip_point(position, Bias::Left)
1738                        .to_point(&display_map);
1739                    let line_start = display_map.prev_line_boundary(position).0;
1740                    let next_line_start = buffer.clip_point(
1741                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1742                        Bias::Left,
1743                    );
1744
1745                    if line_start < original_range.start {
1746                        head = line_start
1747                    } else {
1748                        head = next_line_start
1749                    }
1750
1751                    if head <= original_range.start {
1752                        tail = original_range.end;
1753                    } else {
1754                        tail = original_range.start;
1755                    }
1756                }
1757                SelectMode::All => {
1758                    return;
1759                }
1760            };
1761
1762            if head < tail {
1763                pending.start = buffer.anchor_before(head);
1764                pending.end = buffer.anchor_before(tail);
1765                pending.reversed = true;
1766            } else {
1767                pending.start = buffer.anchor_before(tail);
1768                pending.end = buffer.anchor_before(head);
1769                pending.reversed = false;
1770            }
1771
1772            self.change_selections(None, cx, |s| {
1773                s.set_pending(pending, mode);
1774            });
1775        } else {
1776            log::error!("update_selection dispatched with no pending selection");
1777            return;
1778        }
1779
1780        self.set_scroll_position(scroll_position, cx);
1781        cx.notify();
1782    }
1783
1784    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1785        self.columnar_selection_tail.take();
1786        if self.selections.pending_anchor().is_some() {
1787            let selections = self.selections.all::<usize>(cx);
1788            self.change_selections(None, cx, |s| {
1789                s.select(selections);
1790                s.clear_pending();
1791            });
1792        }
1793    }
1794
1795    fn select_columns(
1796        &mut self,
1797        tail: DisplayPoint,
1798        head: DisplayPoint,
1799        overshoot: u32,
1800        display_map: &DisplaySnapshot,
1801        cx: &mut ViewContext<Self>,
1802    ) {
1803        let start_row = cmp::min(tail.row(), head.row());
1804        let end_row = cmp::max(tail.row(), head.row());
1805        let start_column = cmp::min(tail.column(), head.column() + overshoot);
1806        let end_column = cmp::max(tail.column(), head.column() + overshoot);
1807        let reversed = start_column < tail.column();
1808
1809        let selection_ranges = (start_row..=end_row)
1810            .filter_map(|row| {
1811                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1812                    let start = display_map
1813                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1814                        .to_point(&display_map);
1815                    let end = display_map
1816                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1817                        .to_point(&display_map);
1818                    if reversed {
1819                        Some(end..start)
1820                    } else {
1821                        Some(start..end)
1822                    }
1823                } else {
1824                    None
1825                }
1826            })
1827            .collect::<Vec<_>>();
1828
1829        self.change_selections(None, cx, |s| {
1830            s.select_ranges(selection_ranges);
1831        });
1832        cx.notify();
1833    }
1834
1835    pub fn is_selecting(&self) -> bool {
1836        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1837    }
1838
1839    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1840        if self.take_rename(false, cx).is_some() {
1841            return;
1842        }
1843
1844        if self.hide_context_menu(cx).is_some() {
1845            return;
1846        }
1847
1848        if self.snippet_stack.pop().is_some() {
1849            return;
1850        }
1851
1852        if self.mode == EditorMode::Full {
1853            if self.active_diagnostics.is_some() {
1854                self.dismiss_diagnostics(cx);
1855                return;
1856            }
1857
1858            if self.change_selections(Some(Autoscroll::Fit), cx, |s| s.try_cancel()) {
1859                return;
1860            }
1861        }
1862
1863        cx.propagate_action();
1864    }
1865
1866    pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
1867        if !self.input_enabled {
1868            cx.propagate_action();
1869            return;
1870        }
1871
1872        let text = action.0.as_ref();
1873        if !self.skip_autoclose_end(text, cx) {
1874            self.transact(cx, |this, cx| {
1875                if !this.surround_with_bracket_pair(text, cx) {
1876                    this.insert(text, cx);
1877                    this.autoclose_bracket_pairs(cx);
1878                }
1879            });
1880            self.trigger_completion_on_input(text, cx);
1881        }
1882    }
1883
1884    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
1885        self.transact(cx, |this, cx| {
1886            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
1887                let selections = this.selections.all::<usize>(cx);
1888
1889                let buffer = this.buffer.read(cx).snapshot(cx);
1890                selections
1891                    .iter()
1892                    .map(|selection| {
1893                        let start_point = selection.start.to_point(&buffer);
1894                        let indent = buffer
1895                            .indent_column_for_line(start_point.row)
1896                            .min(start_point.column);
1897                        let start = selection.start;
1898                        let end = selection.end;
1899
1900                        let mut insert_extra_newline = false;
1901                        if let Some(language) = buffer.language() {
1902                            let leading_whitespace_len = buffer
1903                                .reversed_chars_at(start)
1904                                .take_while(|c| c.is_whitespace() && *c != '\n')
1905                                .map(|c| c.len_utf8())
1906                                .sum::<usize>();
1907
1908                            let trailing_whitespace_len = buffer
1909                                .chars_at(end)
1910                                .take_while(|c| c.is_whitespace() && *c != '\n')
1911                                .map(|c| c.len_utf8())
1912                                .sum::<usize>();
1913
1914                            insert_extra_newline = language.brackets().iter().any(|pair| {
1915                                let pair_start = pair.start.trim_end();
1916                                let pair_end = pair.end.trim_start();
1917
1918                                pair.newline
1919                                    && buffer
1920                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
1921                                    && buffer.contains_str_at(
1922                                        (start - leading_whitespace_len)
1923                                            .saturating_sub(pair_start.len()),
1924                                        pair_start,
1925                                    )
1926                            });
1927                        }
1928
1929                        let mut new_text = String::with_capacity(1 + indent as usize);
1930                        new_text.push('\n');
1931                        new_text.extend(iter::repeat(' ').take(indent as usize));
1932                        if insert_extra_newline {
1933                            new_text = new_text.repeat(2);
1934                        }
1935
1936                        let anchor = buffer.anchor_after(end);
1937                        let new_selection = selection.map(|_| anchor.clone());
1938                        (
1939                            (start..end, new_text),
1940                            (insert_extra_newline, new_selection),
1941                        )
1942                    })
1943                    .unzip()
1944            };
1945
1946            this.buffer.update(cx, |buffer, cx| {
1947                buffer.edit_with_autoindent(edits, cx);
1948            });
1949            let buffer = this.buffer.read(cx).snapshot(cx);
1950            let new_selections = selection_fixup_info
1951                .into_iter()
1952                .map(|(extra_newline_inserted, new_selection)| {
1953                    let mut cursor = new_selection.end.to_point(&buffer);
1954                    if extra_newline_inserted {
1955                        cursor.row -= 1;
1956                        cursor.column = buffer.line_len(cursor.row);
1957                    }
1958                    new_selection.map(|_| cursor.clone())
1959                })
1960                .collect();
1961
1962            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
1963        });
1964    }
1965
1966    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1967        let text: Arc<str> = text.into();
1968        self.transact(cx, |this, cx| {
1969            let old_selections = this.selections.all_adjusted(cx);
1970            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
1971                let anchors = {
1972                    let snapshot = buffer.read(cx);
1973                    old_selections
1974                        .iter()
1975                        .map(|s| {
1976                            let anchor = snapshot.anchor_after(s.end);
1977                            s.map(|_| anchor.clone())
1978                        })
1979                        .collect::<Vec<_>>()
1980                };
1981                buffer.edit_with_autoindent(
1982                    old_selections
1983                        .iter()
1984                        .map(|s| (s.start..s.end, text.clone())),
1985                    cx,
1986                );
1987                anchors
1988            });
1989
1990            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
1991                s.select_anchors(selection_anchors);
1992            })
1993        });
1994    }
1995
1996    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1997        let selection = self.selections.newest_anchor();
1998        if self
1999            .buffer
2000            .read(cx)
2001            .is_completion_trigger(selection.head(), text, cx)
2002        {
2003            self.show_completions(&ShowCompletions, cx);
2004        } else {
2005            self.hide_context_menu(cx);
2006        }
2007    }
2008
2009    fn surround_with_bracket_pair(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
2010        let snapshot = self.buffer.read(cx).snapshot(cx);
2011        if let Some(pair) = snapshot
2012            .language()
2013            .and_then(|language| language.brackets().iter().find(|b| b.start == text))
2014            .cloned()
2015        {
2016            if self
2017                .selections
2018                .all::<usize>(cx)
2019                .iter()
2020                .any(|selection| selection.is_empty())
2021            {
2022                return false;
2023            }
2024
2025            let mut selections = self.selections.disjoint_anchors().to_vec();
2026            for selection in &mut selections {
2027                selection.end = selection.end.bias_left(&snapshot);
2028            }
2029            drop(snapshot);
2030
2031            self.buffer.update(cx, |buffer, cx| {
2032                let pair_start: Arc<str> = pair.start.clone().into();
2033                let pair_end: Arc<str> = pair.end.clone().into();
2034                buffer.edit(
2035                    selections
2036                        .iter()
2037                        .map(|s| (s.start.clone()..s.start.clone(), pair_start.clone()))
2038                        .chain(
2039                            selections
2040                                .iter()
2041                                .map(|s| (s.end.clone()..s.end.clone(), pair_end.clone())),
2042                        ),
2043                    cx,
2044                );
2045            });
2046
2047            let snapshot = self.buffer.read(cx).read(cx);
2048            for selection in &mut selections {
2049                selection.end = selection.end.bias_right(&snapshot);
2050            }
2051            drop(snapshot);
2052
2053            self.change_selections(None, cx, |s| s.select_anchors(selections));
2054            true
2055        } else {
2056            false
2057        }
2058    }
2059
2060    fn autoclose_bracket_pairs(&mut self, cx: &mut ViewContext<Self>) {
2061        let selections = self.selections.all::<usize>(cx);
2062        let mut bracket_pair_state = None;
2063        let mut new_selections = None;
2064        self.buffer.update(cx, |buffer, cx| {
2065            let mut snapshot = buffer.snapshot(cx);
2066            let left_biased_selections = selections
2067                .iter()
2068                .map(|selection| selection.map(|p| snapshot.anchor_before(p)))
2069                .collect::<Vec<_>>();
2070
2071            let autoclose_pair = snapshot.language().and_then(|language| {
2072                let first_selection_start = selections.first().unwrap().start;
2073                let pair = language.brackets().iter().find(|pair| {
2074                    snapshot.contains_str_at(
2075                        first_selection_start.saturating_sub(pair.start.len()),
2076                        &pair.start,
2077                    )
2078                });
2079                pair.and_then(|pair| {
2080                    let should_autoclose = selections.iter().all(|selection| {
2081                        // Ensure all selections are parked at the end of a pair start.
2082                        if snapshot.contains_str_at(
2083                            selection.start.saturating_sub(pair.start.len()),
2084                            &pair.start,
2085                        ) {
2086                            snapshot
2087                                .chars_at(selection.start)
2088                                .next()
2089                                .map_or(true, |c| language.should_autoclose_before(c))
2090                        } else {
2091                            false
2092                        }
2093                    });
2094
2095                    if should_autoclose {
2096                        Some(pair.clone())
2097                    } else {
2098                        None
2099                    }
2100                })
2101            });
2102
2103            if let Some(pair) = autoclose_pair {
2104                let selection_ranges = selections
2105                    .iter()
2106                    .map(|selection| {
2107                        let start = selection.start.to_offset(&snapshot);
2108                        start..start
2109                    })
2110                    .collect::<SmallVec<[_; 32]>>();
2111
2112                let pair_end: Arc<str> = pair.end.clone().into();
2113                buffer.edit(
2114                    selection_ranges
2115                        .iter()
2116                        .map(|range| (range.clone(), pair_end.clone())),
2117                    cx,
2118                );
2119                snapshot = buffer.snapshot(cx);
2120
2121                new_selections = Some(
2122                    resolve_multiple::<usize, _>(left_biased_selections.iter(), &snapshot)
2123                        .collect::<Vec<_>>(),
2124                );
2125
2126                if pair.end.len() == 1 {
2127                    let mut delta = 0;
2128                    bracket_pair_state = Some(BracketPairState {
2129                        ranges: selections
2130                            .iter()
2131                            .map(move |selection| {
2132                                let offset = selection.start + delta;
2133                                delta += 1;
2134                                snapshot.anchor_before(offset)..snapshot.anchor_after(offset)
2135                            })
2136                            .collect(),
2137                        pair,
2138                    });
2139                }
2140            }
2141        });
2142
2143        if let Some(new_selections) = new_selections {
2144            self.change_selections(None, cx, |s| {
2145                s.select(new_selections);
2146            });
2147        }
2148        if let Some(bracket_pair_state) = bracket_pair_state {
2149            self.autoclose_stack.push(bracket_pair_state);
2150        }
2151    }
2152
2153    fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
2154        let buffer = self.buffer.read(cx).snapshot(cx);
2155        let old_selections = self.selections.all::<usize>(cx);
2156        let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() {
2157            autoclose_pair
2158        } else {
2159            return false;
2160        };
2161        if text != autoclose_pair.pair.end {
2162            return false;
2163        }
2164
2165        debug_assert_eq!(old_selections.len(), autoclose_pair.ranges.len());
2166
2167        if old_selections
2168            .iter()
2169            .zip(autoclose_pair.ranges.iter().map(|r| r.to_offset(&buffer)))
2170            .all(|(selection, autoclose_range)| {
2171                let autoclose_range_end = autoclose_range.end.to_offset(&buffer);
2172                selection.is_empty() && selection.start == autoclose_range_end
2173            })
2174        {
2175            let new_selections = old_selections
2176                .into_iter()
2177                .map(|selection| {
2178                    let cursor = selection.start + 1;
2179                    Selection {
2180                        id: selection.id,
2181                        start: cursor,
2182                        end: cursor,
2183                        reversed: false,
2184                        goal: SelectionGoal::None,
2185                    }
2186                })
2187                .collect();
2188            self.autoclose_stack.pop();
2189            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2190                s.select(new_selections);
2191            });
2192            true
2193        } else {
2194            false
2195        }
2196    }
2197
2198    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2199        let offset = position.to_offset(buffer);
2200        let (word_range, kind) = buffer.surrounding_word(offset);
2201        if offset > word_range.start && kind == Some(CharKind::Word) {
2202            Some(
2203                buffer
2204                    .text_for_range(word_range.start..offset)
2205                    .collect::<String>(),
2206            )
2207        } else {
2208            None
2209        }
2210    }
2211
2212    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2213        if self.pending_rename.is_some() {
2214            return;
2215        }
2216
2217        let project = if let Some(project) = self.project.clone() {
2218            project
2219        } else {
2220            return;
2221        };
2222
2223        let position = self.selections.newest_anchor().head();
2224        let (buffer, buffer_position) = if let Some(output) = self
2225            .buffer
2226            .read(cx)
2227            .text_anchor_for_position(position.clone(), cx)
2228        {
2229            output
2230        } else {
2231            return;
2232        };
2233
2234        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2235        let completions = project.update(cx, |project, cx| {
2236            project.completions(&buffer, buffer_position.clone(), cx)
2237        });
2238
2239        let id = post_inc(&mut self.next_completion_id);
2240        let task = cx.spawn_weak(|this, mut cx| {
2241            async move {
2242                let completions = completions.await?;
2243                if completions.is_empty() {
2244                    return Ok(());
2245                }
2246
2247                let mut menu = CompletionsMenu {
2248                    id,
2249                    initial_position: position,
2250                    match_candidates: completions
2251                        .iter()
2252                        .enumerate()
2253                        .map(|(id, completion)| {
2254                            StringMatchCandidate::new(
2255                                id,
2256                                completion.label.text[completion.label.filter_range.clone()].into(),
2257                            )
2258                        })
2259                        .collect(),
2260                    buffer,
2261                    completions: completions.into(),
2262                    matches: Vec::new().into(),
2263                    selected_item: 0,
2264                    list: Default::default(),
2265                };
2266
2267                menu.filter(query.as_deref(), cx.background()).await;
2268
2269                if let Some(this) = this.upgrade(&cx) {
2270                    this.update(&mut cx, |this, cx| {
2271                        match this.context_menu.as_ref() {
2272                            None => {}
2273                            Some(ContextMenu::Completions(prev_menu)) => {
2274                                if prev_menu.id > menu.id {
2275                                    return;
2276                                }
2277                            }
2278                            _ => return,
2279                        }
2280
2281                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
2282                        if this.focused {
2283                            this.show_context_menu(ContextMenu::Completions(menu), cx);
2284                        }
2285
2286                        cx.notify();
2287                    });
2288                }
2289                Ok::<_, anyhow::Error>(())
2290            }
2291            .log_err()
2292        });
2293        self.completion_tasks.push((id, task));
2294    }
2295
2296    pub fn confirm_completion(
2297        &mut self,
2298        action: &ConfirmCompletion,
2299        cx: &mut ViewContext<Self>,
2300    ) -> Option<Task<Result<()>>> {
2301        use language::ToOffset as _;
2302
2303        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2304            menu
2305        } else {
2306            return None;
2307        };
2308
2309        let mat = completions_menu
2310            .matches
2311            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2312        let buffer_handle = completions_menu.buffer;
2313        let completion = completions_menu.completions.get(mat.candidate_id)?;
2314
2315        let snippet;
2316        let text;
2317        if completion.is_snippet() {
2318            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2319            text = snippet.as_ref().unwrap().text.clone();
2320        } else {
2321            snippet = None;
2322            text = completion.new_text.clone();
2323        };
2324        let selections = self.selections.all::<usize>(cx);
2325        let buffer = buffer_handle.read(cx);
2326        let old_range = completion.old_range.to_offset(&buffer);
2327        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2328
2329        let newest_selection = self.selections.newest_anchor();
2330        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
2331            return None;
2332        }
2333
2334        let lookbehind = newest_selection
2335            .start
2336            .text_anchor
2337            .to_offset(buffer)
2338            .saturating_sub(old_range.start);
2339        let lookahead = old_range
2340            .end
2341            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2342        let mut common_prefix_len = old_text
2343            .bytes()
2344            .zip(text.bytes())
2345            .take_while(|(a, b)| a == b)
2346            .count();
2347
2348        let snapshot = self.buffer.read(cx).snapshot(cx);
2349        let mut ranges = Vec::new();
2350        for selection in &selections {
2351            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2352                let start = selection.start.saturating_sub(lookbehind);
2353                let end = selection.end + lookahead;
2354                ranges.push(start + common_prefix_len..end);
2355            } else {
2356                common_prefix_len = 0;
2357                ranges.clear();
2358                ranges.extend(selections.iter().map(|s| {
2359                    if s.id == newest_selection.id {
2360                        old_range.clone()
2361                    } else {
2362                        s.start..s.end
2363                    }
2364                }));
2365                break;
2366            }
2367        }
2368        let text = &text[common_prefix_len..];
2369
2370        self.transact(cx, |this, cx| {
2371            if let Some(mut snippet) = snippet {
2372                snippet.text = text.to_string();
2373                for tabstop in snippet.tabstops.iter_mut().flatten() {
2374                    tabstop.start -= common_prefix_len as isize;
2375                    tabstop.end -= common_prefix_len as isize;
2376                }
2377
2378                this.insert_snippet(&ranges, snippet, cx).log_err();
2379            } else {
2380                this.buffer.update(cx, |buffer, cx| {
2381                    buffer
2382                        .edit_with_autoindent(ranges.iter().map(|range| (range.clone(), text)), cx);
2383                });
2384            }
2385        });
2386
2387        let project = self.project.clone()?;
2388        let apply_edits = project.update(cx, |project, cx| {
2389            project.apply_additional_edits_for_completion(
2390                buffer_handle,
2391                completion.clone(),
2392                true,
2393                cx,
2394            )
2395        });
2396        Some(cx.foreground().spawn(async move {
2397            apply_edits.await?;
2398            Ok(())
2399        }))
2400    }
2401
2402    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2403        if matches!(
2404            self.context_menu.as_ref(),
2405            Some(ContextMenu::CodeActions(_))
2406        ) {
2407            self.context_menu.take();
2408            cx.notify();
2409            return;
2410        }
2411
2412        let deployed_from_indicator = action.deployed_from_indicator;
2413        let mut task = self.code_actions_task.take();
2414        cx.spawn_weak(|this, mut cx| async move {
2415            while let Some(prev_task) = task {
2416                prev_task.await;
2417                task = this
2418                    .upgrade(&cx)
2419                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
2420            }
2421
2422            if let Some(this) = this.upgrade(&cx) {
2423                this.update(&mut cx, |this, cx| {
2424                    if this.focused {
2425                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
2426                            this.show_context_menu(
2427                                ContextMenu::CodeActions(CodeActionsMenu {
2428                                    buffer,
2429                                    actions,
2430                                    selected_item: Default::default(),
2431                                    list: Default::default(),
2432                                    deployed_from_indicator,
2433                                }),
2434                                cx,
2435                            );
2436                        }
2437                    }
2438                })
2439            }
2440            Ok::<_, anyhow::Error>(())
2441        })
2442        .detach_and_log_err(cx);
2443    }
2444
2445    pub fn confirm_code_action(
2446        workspace: &mut Workspace,
2447        action: &ConfirmCodeAction,
2448        cx: &mut ViewContext<Workspace>,
2449    ) -> Option<Task<Result<()>>> {
2450        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2451        let actions_menu = if let ContextMenu::CodeActions(menu) =
2452            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2453        {
2454            menu
2455        } else {
2456            return None;
2457        };
2458        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2459        let action = actions_menu.actions.get(action_ix)?.clone();
2460        let title = action.lsp_action.title.clone();
2461        let buffer = actions_menu.buffer;
2462
2463        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2464            project.apply_code_action(buffer, action, true, cx)
2465        });
2466        Some(cx.spawn(|workspace, cx| async move {
2467            let project_transaction = apply_code_actions.await?;
2468            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
2469        }))
2470    }
2471
2472    /// The hover action dispatches between `show_hover` or `hide_hover`
2473    /// depending on whether a point to hover over is provided.
2474    fn hover(&mut self, action: &Hover, cx: &mut ViewContext<Self>) {
2475        if let Some(point) = action.point {
2476            self.show_hover(&ShowHover(point), cx);
2477        } else {
2478            self.hide_hover(&HideHover, cx);
2479        }
2480    }
2481
2482    /// Hides the type information popup ASAP.
2483    /// Triggered by the `Hover` action when the cursor is not over a symbol.
2484    fn hide_hover(&mut self, _: &HideHover, cx: &mut ViewContext<Self>) {
2485        let task = cx.spawn_weak(|this, mut cx| {
2486            async move {
2487                if let Some(this) = this.upgrade(&cx) {
2488                    this.update(&mut cx, |this, cx| {
2489                        // consistently keep track of state to make handoff smooth
2490                        let (_recent_hover, _in_grace) = this.hover_popover.determine_state(false);
2491
2492                        // only notify the context once
2493                        if this.hover_popover.popover.is_some() {
2494                            this.hover_popover.popover = None;
2495                            cx.notify();
2496                        }
2497                    });
2498                }
2499                Ok(())
2500            }
2501            .log_err()
2502        });
2503
2504        self.hover_task = Some(task);
2505    }
2506
2507    /// Queries the LSP and shows type info and documentation
2508    /// about the symbol the mouse is currently hovering over.
2509    /// Triggered by the `Hover` action when the cursor may be over a symbol.
2510    fn show_hover(&mut self, action: &ShowHover, cx: &mut ViewContext<Self>) {
2511        if self.pending_rename.is_some() {
2512            return;
2513        }
2514
2515        let project = if let Some(project) = self.project.clone() {
2516            project
2517        } else {
2518            return;
2519        };
2520
2521        // we use the mouse cursor position by default
2522        let mut point = action.0.clone();
2523
2524        let snapshot = self.snapshot(cx);
2525        let (buffer, buffer_position) = if let Some(output) = self
2526            .buffer
2527            .read(cx)
2528            .text_anchor_for_position(point.to_point(&snapshot.display_snapshot), cx)
2529        {
2530            output
2531        } else {
2532            return;
2533        };
2534
2535        let buffer_snapshot = buffer.read(cx).snapshot();
2536
2537        // query the LSP for hover info
2538        let hover = project.update(cx, |project, cx| {
2539            project.hover(&buffer, buffer_position.clone(), cx)
2540        });
2541
2542        let task = cx.spawn_weak(|this, mut cx| {
2543            async move {
2544                // TODO: what to show while LSP is loading?
2545                let mut contents = None;
2546
2547                let hover = match hover.await {
2548                    Ok(hover) => hover,
2549                    Err(_) => None,
2550                };
2551
2552                // determine the contents of the popover
2553                if let Some(hover) = hover {
2554                    if hover.contents.is_empty() {
2555                        contents = None;
2556                    } else {
2557                        contents = Some(hover.contents);
2558
2559                        if let Some(range) = hover.range {
2560                            let offset_range = range.to_offset(&buffer_snapshot);
2561                            if offset_range
2562                                .contains(&point.to_offset(&snapshot.display_snapshot, Bias::Left))
2563                            {
2564                                point = offset_range
2565                                    .start
2566                                    .to_display_point(&snapshot.display_snapshot);
2567                            } else {
2568                                contents = None;
2569                            }
2570                        }
2571                    }
2572                };
2573
2574                let hover_popover = contents.map(|contents| HoverPopover { point, contents });
2575
2576                if let Some(this) = this.upgrade(&cx) {
2577                    this.update(&mut cx, |this, cx| {
2578                        // this was trickier than expected, trying to do a couple things:
2579                        //
2580                        // 1. if you hover over a symbol, there should be a slight delay
2581                        //    before the popover shows
2582                        // 2. if you move to another symbol when the popover is showing,
2583                        //    the popover should switch right away, and you should
2584                        //    not have to wait for it to come up again
2585                        let (recent_hover, in_grace) =
2586                            this.hover_popover.determine_state(hover_popover.is_some());
2587                        let smooth_handoff =
2588                            this.hover_popover.popover.is_some() && hover_popover.is_some();
2589                        let visible =
2590                            this.hover_popover.popover.is_some() || hover_popover.is_some();
2591
2592                        // `smooth_handoff` and `in_grace` determine whether to switch right away.
2593                        // `recent_hover` will activate the handoff after the initial delay.
2594                        if (smooth_handoff || !recent_hover || in_grace) && visible {
2595                            this.hover_popover.popover = hover_popover;
2596                            cx.notify();
2597                        }
2598                    });
2599                }
2600                Ok::<_, anyhow::Error>(())
2601            }
2602            .log_err()
2603        });
2604
2605        self.hover_task = Some(task);
2606    }
2607
2608    async fn open_project_transaction(
2609        this: ViewHandle<Editor>,
2610        workspace: ViewHandle<Workspace>,
2611        transaction: ProjectTransaction,
2612        title: String,
2613        mut cx: AsyncAppContext,
2614    ) -> Result<()> {
2615        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
2616
2617        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2618        entries.sort_unstable_by_key(|(buffer, _)| {
2619            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2620        });
2621
2622        // If the project transaction's edits are all contained within this editor, then
2623        // avoid opening a new editor to display them.
2624
2625        if let Some((buffer, transaction)) = entries.first() {
2626            if entries.len() == 1 {
2627                let excerpt = this.read_with(&cx, |editor, cx| {
2628                    editor
2629                        .buffer()
2630                        .read(cx)
2631                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2632                });
2633                if let Some((excerpted_buffer, excerpt_range)) = excerpt {
2634                    if excerpted_buffer == *buffer {
2635                        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
2636                        let excerpt_range = excerpt_range.to_offset(&snapshot);
2637                        if snapshot
2638                            .edited_ranges_for_transaction(transaction)
2639                            .all(|range| {
2640                                excerpt_range.start <= range.start && excerpt_range.end >= range.end
2641                            })
2642                        {
2643                            return Ok(());
2644                        }
2645                    }
2646                }
2647            }
2648        } else {
2649            return Ok(());
2650        }
2651
2652        let mut ranges_to_highlight = Vec::new();
2653        let excerpt_buffer = cx.add_model(|cx| {
2654            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2655            for (buffer, transaction) in &entries {
2656                let snapshot = buffer.read(cx).snapshot();
2657                ranges_to_highlight.extend(
2658                    multibuffer.push_excerpts_with_context_lines(
2659                        buffer.clone(),
2660                        snapshot
2661                            .edited_ranges_for_transaction::<usize>(transaction)
2662                            .collect(),
2663                        1,
2664                        cx,
2665                    ),
2666                );
2667            }
2668            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
2669            multibuffer
2670        });
2671
2672        workspace.update(&mut cx, |workspace, cx| {
2673            let project = workspace.project().clone();
2674            let editor =
2675                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2676            workspace.add_item(Box::new(editor.clone()), cx);
2677            editor.update(cx, |editor, cx| {
2678                editor.highlight_background::<Self>(
2679                    ranges_to_highlight,
2680                    |theme| theme.editor.highlighted_line_background,
2681                    cx,
2682                );
2683            });
2684        });
2685
2686        Ok(())
2687    }
2688
2689    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2690        let project = self.project.as_ref()?;
2691        let buffer = self.buffer.read(cx);
2692        let newest_selection = self.selections.newest_anchor().clone();
2693        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2694        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2695        if start_buffer != end_buffer {
2696            return None;
2697        }
2698
2699        let actions = project.update(cx, |project, cx| {
2700            project.code_actions(&start_buffer, start..end, cx)
2701        });
2702        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
2703            let actions = actions.await;
2704            if let Some(this) = this.upgrade(&cx) {
2705                this.update(&mut cx, |this, cx| {
2706                    this.available_code_actions = actions.log_err().and_then(|actions| {
2707                        if actions.is_empty() {
2708                            None
2709                        } else {
2710                            Some((start_buffer, actions.into()))
2711                        }
2712                    });
2713                    cx.notify();
2714                })
2715            }
2716        }));
2717        None
2718    }
2719
2720    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2721        if self.pending_rename.is_some() {
2722            return None;
2723        }
2724
2725        let project = self.project.as_ref()?;
2726        let buffer = self.buffer.read(cx);
2727        let newest_selection = self.selections.newest_anchor().clone();
2728        let cursor_position = newest_selection.head();
2729        let (cursor_buffer, cursor_buffer_position) =
2730            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2731        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2732        if cursor_buffer != tail_buffer {
2733            return None;
2734        }
2735
2736        let highlights = project.update(cx, |project, cx| {
2737            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2738        });
2739
2740        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
2741            let highlights = highlights.log_err().await;
2742            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
2743                this.update(&mut cx, |this, cx| {
2744                    if this.pending_rename.is_some() {
2745                        return;
2746                    }
2747
2748                    let buffer_id = cursor_position.buffer_id;
2749                    let buffer = this.buffer.read(cx);
2750                    if !buffer
2751                        .text_anchor_for_position(cursor_position, cx)
2752                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2753                    {
2754                        return;
2755                    }
2756
2757                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2758                    let mut write_ranges = Vec::new();
2759                    let mut read_ranges = Vec::new();
2760                    for highlight in highlights {
2761                        for (excerpt_id, excerpt_range) in
2762                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2763                        {
2764                            let start = highlight
2765                                .range
2766                                .start
2767                                .max(&excerpt_range.start, cursor_buffer_snapshot);
2768                            let end = highlight
2769                                .range
2770                                .end
2771                                .min(&excerpt_range.end, cursor_buffer_snapshot);
2772                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2773                                continue;
2774                            }
2775
2776                            let range = Anchor {
2777                                buffer_id,
2778                                excerpt_id: excerpt_id.clone(),
2779                                text_anchor: start,
2780                            }..Anchor {
2781                                buffer_id,
2782                                excerpt_id,
2783                                text_anchor: end,
2784                            };
2785                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2786                                write_ranges.push(range);
2787                            } else {
2788                                read_ranges.push(range);
2789                            }
2790                        }
2791                    }
2792
2793                    this.highlight_background::<DocumentHighlightRead>(
2794                        read_ranges,
2795                        |theme| theme.editor.document_highlight_read_background,
2796                        cx,
2797                    );
2798                    this.highlight_background::<DocumentHighlightWrite>(
2799                        write_ranges,
2800                        |theme| theme.editor.document_highlight_write_background,
2801                        cx,
2802                    );
2803                    cx.notify();
2804                });
2805            }
2806        }));
2807        None
2808    }
2809
2810    pub fn render_code_actions_indicator(
2811        &self,
2812        style: &EditorStyle,
2813        cx: &mut RenderContext<Self>,
2814    ) -> Option<ElementBox> {
2815        if self.available_code_actions.is_some() {
2816            enum Tag {}
2817            Some(
2818                MouseEventHandler::new::<Tag, _, _>(0, cx, |_, _| {
2819                    Svg::new("icons/zap.svg")
2820                        .with_color(style.code_actions_indicator)
2821                        .boxed()
2822                })
2823                .with_cursor_style(CursorStyle::PointingHand)
2824                .with_padding(Padding::uniform(3.))
2825                .on_mouse_down(|_, cx| {
2826                    cx.dispatch_action(ToggleCodeActions {
2827                        deployed_from_indicator: true,
2828                    });
2829                })
2830                .boxed(),
2831            )
2832        } else {
2833            None
2834        }
2835    }
2836
2837    pub fn context_menu_visible(&self) -> bool {
2838        self.context_menu
2839            .as_ref()
2840            .map_or(false, |menu| menu.visible())
2841    }
2842
2843    pub fn render_context_menu(
2844        &self,
2845        cursor_position: DisplayPoint,
2846        style: EditorStyle,
2847        cx: &mut RenderContext<Editor>,
2848    ) -> Option<(DisplayPoint, ElementBox)> {
2849        self.context_menu
2850            .as_ref()
2851            .map(|menu| menu.render(cursor_position, style))
2852    }
2853
2854    pub fn render_hover_popover(&self, style: EditorStyle) -> Option<(DisplayPoint, ElementBox)> {
2855        self.hover_popover
2856            .popover
2857            .as_ref()
2858            .map(|hover| hover.render(style))
2859    }
2860
2861    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
2862        if !matches!(menu, ContextMenu::Completions(_)) {
2863            self.completion_tasks.clear();
2864        }
2865        self.context_menu = Some(menu);
2866        cx.notify();
2867    }
2868
2869    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
2870        cx.notify();
2871        self.completion_tasks.clear();
2872        self.context_menu.take()
2873    }
2874
2875    pub fn insert_snippet(
2876        &mut self,
2877        insertion_ranges: &[Range<usize>],
2878        snippet: Snippet,
2879        cx: &mut ViewContext<Self>,
2880    ) -> Result<()> {
2881        let tabstops = self.buffer.update(cx, |buffer, cx| {
2882            let snippet_text: Arc<str> = snippet.text.clone().into();
2883            buffer.edit_with_autoindent(
2884                insertion_ranges
2885                    .iter()
2886                    .cloned()
2887                    .map(|range| (range, snippet_text.clone())),
2888                cx,
2889            );
2890
2891            let snapshot = &*buffer.read(cx);
2892            let snippet = &snippet;
2893            snippet
2894                .tabstops
2895                .iter()
2896                .map(|tabstop| {
2897                    let mut tabstop_ranges = tabstop
2898                        .iter()
2899                        .flat_map(|tabstop_range| {
2900                            let mut delta = 0 as isize;
2901                            insertion_ranges.iter().map(move |insertion_range| {
2902                                let insertion_start = insertion_range.start as isize + delta;
2903                                delta +=
2904                                    snippet.text.len() as isize - insertion_range.len() as isize;
2905
2906                                let start = snapshot.anchor_before(
2907                                    (insertion_start + tabstop_range.start) as usize,
2908                                );
2909                                let end = snapshot
2910                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
2911                                start..end
2912                            })
2913                        })
2914                        .collect::<Vec<_>>();
2915                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
2916                    tabstop_ranges
2917                })
2918                .collect::<Vec<_>>()
2919        });
2920
2921        if let Some(tabstop) = tabstops.first() {
2922            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2923                s.select_ranges(tabstop.iter().cloned());
2924            });
2925            self.snippet_stack.push(SnippetState {
2926                active_index: 0,
2927                ranges: tabstops,
2928            });
2929        }
2930
2931        Ok(())
2932    }
2933
2934    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2935        self.move_to_snippet_tabstop(Bias::Right, cx)
2936    }
2937
2938    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2939        self.move_to_snippet_tabstop(Bias::Left, cx)
2940    }
2941
2942    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
2943        if let Some(mut snippet) = self.snippet_stack.pop() {
2944            match bias {
2945                Bias::Left => {
2946                    if snippet.active_index > 0 {
2947                        snippet.active_index -= 1;
2948                    } else {
2949                        self.snippet_stack.push(snippet);
2950                        return false;
2951                    }
2952                }
2953                Bias::Right => {
2954                    if snippet.active_index + 1 < snippet.ranges.len() {
2955                        snippet.active_index += 1;
2956                    } else {
2957                        self.snippet_stack.push(snippet);
2958                        return false;
2959                    }
2960                }
2961            }
2962            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
2963                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2964                    s.select_anchor_ranges(current_ranges.into_iter().cloned())
2965                });
2966                // If snippet state is not at the last tabstop, push it back on the stack
2967                if snippet.active_index + 1 < snippet.ranges.len() {
2968                    self.snippet_stack.push(snippet);
2969                }
2970                return true;
2971            }
2972        }
2973
2974        false
2975    }
2976
2977    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
2978        self.transact(cx, |this, cx| {
2979            this.select_all(&SelectAll, cx);
2980            this.insert("", cx);
2981        });
2982    }
2983
2984    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
2985        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2986        let mut selections = self.selections.all::<Point>(cx);
2987        if !self.selections.line_mode {
2988            for selection in &mut selections {
2989                if selection.is_empty() {
2990                    let old_head = selection.head();
2991                    let mut new_head =
2992                        movement::left(&display_map, old_head.to_display_point(&display_map))
2993                            .to_point(&display_map);
2994                    if let Some((buffer, line_buffer_range)) = display_map
2995                        .buffer_snapshot
2996                        .buffer_line_for_row(old_head.row)
2997                    {
2998                        let indent_column =
2999                            buffer.indent_column_for_line(line_buffer_range.start.row);
3000                        let language_name = buffer.language().map(|language| language.name());
3001                        let indent = cx.global::<Settings>().tab_size(language_name.as_deref());
3002                        if old_head.column <= indent_column && old_head.column > 0 {
3003                            new_head = cmp::min(
3004                                new_head,
3005                                Point::new(old_head.row, ((old_head.column - 1) / indent) * indent),
3006                            );
3007                        }
3008                    }
3009
3010                    selection.set_head(new_head, SelectionGoal::None);
3011                }
3012            }
3013        }
3014
3015        self.transact(cx, |this, cx| {
3016            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3017            this.insert("", cx);
3018        });
3019    }
3020
3021    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3022        self.transact(cx, |this, cx| {
3023            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3024                let line_mode = s.line_mode;
3025                s.move_with(|map, selection| {
3026                    if selection.is_empty() && !line_mode {
3027                        let cursor = movement::right(map, selection.head());
3028                        selection.set_head(cursor, SelectionGoal::None);
3029                    }
3030                })
3031            });
3032            this.insert(&"", cx);
3033        });
3034    }
3035
3036    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3037        if self.move_to_prev_snippet_tabstop(cx) {
3038            return;
3039        }
3040
3041        self.outdent(&Outdent, cx);
3042    }
3043
3044    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3045        if self.move_to_next_snippet_tabstop(cx) {
3046            return;
3047        }
3048
3049        let mut selections = self.selections.all_adjusted(cx);
3050        if selections.iter().all(|s| s.is_empty()) {
3051            self.transact(cx, |this, cx| {
3052                this.buffer.update(cx, |buffer, cx| {
3053                    for selection in &mut selections {
3054                        let language_name =
3055                            buffer.language_at(selection.start, cx).map(|l| l.name());
3056                        let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
3057                        let char_column = buffer
3058                            .read(cx)
3059                            .text_for_range(Point::new(selection.start.row, 0)..selection.start)
3060                            .flat_map(str::chars)
3061                            .count();
3062                        let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3063                        buffer.edit(
3064                            [(
3065                                selection.start..selection.start,
3066                                " ".repeat(chars_to_next_tab_stop as usize),
3067                            )],
3068                            cx,
3069                        );
3070                        selection.start.column += chars_to_next_tab_stop;
3071                        selection.end = selection.start;
3072                    }
3073                });
3074                this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3075                    s.select(selections);
3076                });
3077            });
3078        } else {
3079            self.indent(&Indent, cx);
3080        }
3081    }
3082
3083    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3084        let mut selections = self.selections.all::<Point>(cx);
3085        self.transact(cx, |this, cx| {
3086            let mut last_indent = None;
3087            this.buffer.update(cx, |buffer, cx| {
3088                let snapshot = buffer.snapshot(cx);
3089                for selection in &mut selections {
3090                    let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3091                    let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
3092                    let mut start_row = selection.start.row;
3093                    let mut end_row = selection.end.row + 1;
3094
3095                    // If a selection ends at the beginning of a line, don't indent
3096                    // that last line.
3097                    if selection.end.column == 0 {
3098                        end_row -= 1;
3099                    }
3100
3101                    // Avoid re-indenting a row that has already been indented by a
3102                    // previous selection, but still update this selection's column
3103                    // to reflect that indentation.
3104                    if let Some((last_indent_row, last_indent_len)) = last_indent {
3105                        if last_indent_row == selection.start.row {
3106                            selection.start.column += last_indent_len;
3107                            start_row += 1;
3108                        }
3109                        if last_indent_row == selection.end.row {
3110                            selection.end.column += last_indent_len;
3111                        }
3112                    }
3113
3114                    for row in start_row..end_row {
3115                        let indent_column = snapshot.indent_column_for_line(row);
3116                        let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
3117                        let row_start = Point::new(row, 0);
3118                        buffer.edit(
3119                            [(
3120                                row_start..row_start,
3121                                " ".repeat(columns_to_next_tab_stop as usize),
3122                            )],
3123                            cx,
3124                        );
3125
3126                        // Update this selection's endpoints to reflect the indentation.
3127                        if row == selection.start.row {
3128                            selection.start.column += columns_to_next_tab_stop as u32;
3129                        }
3130                        if row == selection.end.row {
3131                            selection.end.column += columns_to_next_tab_stop as u32;
3132                        }
3133
3134                        last_indent = Some((row, columns_to_next_tab_stop as u32));
3135                    }
3136                }
3137            });
3138
3139            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3140                s.select(selections);
3141            });
3142        });
3143    }
3144
3145    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3146        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3147        let selections = self.selections.all::<Point>(cx);
3148        let mut deletion_ranges = Vec::new();
3149        let mut last_outdent = None;
3150        {
3151            let buffer = self.buffer.read(cx);
3152            let snapshot = buffer.snapshot(cx);
3153            for selection in &selections {
3154                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3155                let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
3156                let mut rows = selection.spanned_rows(false, &display_map);
3157
3158                // Avoid re-outdenting a row that has already been outdented by a
3159                // previous selection.
3160                if let Some(last_row) = last_outdent {
3161                    if last_row == rows.start {
3162                        rows.start += 1;
3163                    }
3164                }
3165
3166                for row in rows {
3167                    let column = snapshot.indent_column_for_line(row);
3168                    if column > 0 {
3169                        let mut deletion_len = column % tab_size;
3170                        if deletion_len == 0 {
3171                            deletion_len = tab_size;
3172                        }
3173                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3174                        last_outdent = Some(row);
3175                    }
3176                }
3177            }
3178        }
3179
3180        self.transact(cx, |this, cx| {
3181            this.buffer.update(cx, |buffer, cx| {
3182                let empty_str: Arc<str> = "".into();
3183                buffer.edit(
3184                    deletion_ranges
3185                        .into_iter()
3186                        .map(|range| (range, empty_str.clone())),
3187                    cx,
3188                );
3189            });
3190            let selections = this.selections.all::<usize>(cx);
3191            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3192        });
3193    }
3194
3195    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3196        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3197        let selections = self.selections.all::<Point>(cx);
3198
3199        let mut new_cursors = Vec::new();
3200        let mut edit_ranges = Vec::new();
3201        let mut selections = selections.iter().peekable();
3202        while let Some(selection) = selections.next() {
3203            let mut rows = selection.spanned_rows(false, &display_map);
3204            let goal_display_column = selection.head().to_display_point(&display_map).column();
3205
3206            // Accumulate contiguous regions of rows that we want to delete.
3207            while let Some(next_selection) = selections.peek() {
3208                let next_rows = next_selection.spanned_rows(false, &display_map);
3209                if next_rows.start <= rows.end {
3210                    rows.end = next_rows.end;
3211                    selections.next().unwrap();
3212                } else {
3213                    break;
3214                }
3215            }
3216
3217            let buffer = &display_map.buffer_snapshot;
3218            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
3219            let edit_end;
3220            let cursor_buffer_row;
3221            if buffer.max_point().row >= rows.end {
3222                // If there's a line after the range, delete the \n from the end of the row range
3223                // and position the cursor on the next line.
3224                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
3225                cursor_buffer_row = rows.end;
3226            } else {
3227                // If there isn't a line after the range, delete the \n from the line before the
3228                // start of the row range and position the cursor there.
3229                edit_start = edit_start.saturating_sub(1);
3230                edit_end = buffer.len();
3231                cursor_buffer_row = rows.start.saturating_sub(1);
3232            }
3233
3234            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3235            *cursor.column_mut() =
3236                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3237
3238            new_cursors.push((
3239                selection.id,
3240                buffer.anchor_after(cursor.to_point(&display_map)),
3241            ));
3242            edit_ranges.push(edit_start..edit_end);
3243        }
3244
3245        self.transact(cx, |this, cx| {
3246            let buffer = this.buffer.update(cx, |buffer, cx| {
3247                let empty_str: Arc<str> = "".into();
3248                buffer.edit(
3249                    edit_ranges
3250                        .into_iter()
3251                        .map(|range| (range, empty_str.clone())),
3252                    cx,
3253                );
3254                buffer.snapshot(cx)
3255            });
3256            let new_selections = new_cursors
3257                .into_iter()
3258                .map(|(id, cursor)| {
3259                    let cursor = cursor.to_point(&buffer);
3260                    Selection {
3261                        id,
3262                        start: cursor,
3263                        end: cursor,
3264                        reversed: false,
3265                        goal: SelectionGoal::None,
3266                    }
3267                })
3268                .collect();
3269
3270            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3271                s.select(new_selections);
3272            });
3273        });
3274    }
3275
3276    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3277        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3278        let buffer = &display_map.buffer_snapshot;
3279        let selections = self.selections.all::<Point>(cx);
3280
3281        let mut edits = Vec::new();
3282        let mut selections_iter = selections.iter().peekable();
3283        while let Some(selection) = selections_iter.next() {
3284            // Avoid duplicating the same lines twice.
3285            let mut rows = selection.spanned_rows(false, &display_map);
3286
3287            while let Some(next_selection) = selections_iter.peek() {
3288                let next_rows = next_selection.spanned_rows(false, &display_map);
3289                if next_rows.start <= rows.end - 1 {
3290                    rows.end = next_rows.end;
3291                    selections_iter.next().unwrap();
3292                } else {
3293                    break;
3294                }
3295            }
3296
3297            // Copy the text from the selected row region and splice it at the start of the region.
3298            let start = Point::new(rows.start, 0);
3299            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3300            let text = buffer
3301                .text_for_range(start..end)
3302                .chain(Some("\n"))
3303                .collect::<String>();
3304            edits.push((start..start, text));
3305        }
3306
3307        self.transact(cx, |this, cx| {
3308            this.buffer.update(cx, |buffer, cx| {
3309                buffer.edit(edits, cx);
3310            });
3311
3312            this.request_autoscroll(Autoscroll::Fit, cx);
3313        });
3314    }
3315
3316    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3317        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3318        let buffer = self.buffer.read(cx).snapshot(cx);
3319
3320        let mut edits = Vec::new();
3321        let mut unfold_ranges = Vec::new();
3322        let mut refold_ranges = Vec::new();
3323
3324        let selections = self.selections.all::<Point>(cx);
3325        let mut selections = selections.iter().peekable();
3326        let mut contiguous_row_selections = Vec::new();
3327        let mut new_selections = Vec::new();
3328
3329        while let Some(selection) = selections.next() {
3330            // Find all the selections that span a contiguous row range
3331            contiguous_row_selections.push(selection.clone());
3332            let start_row = selection.start.row;
3333            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3334                display_map.next_line_boundary(selection.end).0.row + 1
3335            } else {
3336                selection.end.row
3337            };
3338
3339            while let Some(next_selection) = selections.peek() {
3340                if next_selection.start.row <= end_row {
3341                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3342                        display_map.next_line_boundary(next_selection.end).0.row + 1
3343                    } else {
3344                        next_selection.end.row
3345                    };
3346                    contiguous_row_selections.push(selections.next().unwrap().clone());
3347                } else {
3348                    break;
3349                }
3350            }
3351
3352            // Move the text spanned by the row range to be before the line preceding the row range
3353            if start_row > 0 {
3354                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3355                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3356                let insertion_point = display_map
3357                    .prev_line_boundary(Point::new(start_row - 1, 0))
3358                    .0;
3359
3360                // Don't move lines across excerpts
3361                if buffer
3362                    .excerpt_boundaries_in_range((
3363                        Bound::Excluded(insertion_point),
3364                        Bound::Included(range_to_move.end),
3365                    ))
3366                    .next()
3367                    .is_none()
3368                {
3369                    let text = buffer
3370                        .text_for_range(range_to_move.clone())
3371                        .flat_map(|s| s.chars())
3372                        .skip(1)
3373                        .chain(['\n'])
3374                        .collect::<String>();
3375
3376                    edits.push((
3377                        buffer.anchor_after(range_to_move.start)
3378                            ..buffer.anchor_before(range_to_move.end),
3379                        String::new(),
3380                    ));
3381                    let insertion_anchor = buffer.anchor_after(insertion_point);
3382                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3383
3384                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3385
3386                    // Move selections up
3387                    new_selections.extend(contiguous_row_selections.drain(..).map(
3388                        |mut selection| {
3389                            selection.start.row -= row_delta;
3390                            selection.end.row -= row_delta;
3391                            selection
3392                        },
3393                    ));
3394
3395                    // Move folds up
3396                    unfold_ranges.push(range_to_move.clone());
3397                    for fold in display_map.folds_in_range(
3398                        buffer.anchor_before(range_to_move.start)
3399                            ..buffer.anchor_after(range_to_move.end),
3400                    ) {
3401                        let mut start = fold.start.to_point(&buffer);
3402                        let mut end = fold.end.to_point(&buffer);
3403                        start.row -= row_delta;
3404                        end.row -= row_delta;
3405                        refold_ranges.push(start..end);
3406                    }
3407                }
3408            }
3409
3410            // If we didn't move line(s), preserve the existing selections
3411            new_selections.extend(contiguous_row_selections.drain(..));
3412        }
3413
3414        self.transact(cx, |this, cx| {
3415            this.unfold_ranges(unfold_ranges, true, cx);
3416            this.buffer.update(cx, |buffer, cx| {
3417                for (range, text) in edits {
3418                    buffer.edit([(range, text)], cx);
3419                }
3420            });
3421            this.fold_ranges(refold_ranges, cx);
3422            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3423                s.select(new_selections);
3424            })
3425        });
3426    }
3427
3428    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3429        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3430        let buffer = self.buffer.read(cx).snapshot(cx);
3431
3432        let mut edits = Vec::new();
3433        let mut unfold_ranges = Vec::new();
3434        let mut refold_ranges = Vec::new();
3435
3436        let selections = self.selections.all::<Point>(cx);
3437        let mut selections = selections.iter().peekable();
3438        let mut contiguous_row_selections = Vec::new();
3439        let mut new_selections = Vec::new();
3440
3441        while let Some(selection) = selections.next() {
3442            // Find all the selections that span a contiguous row range
3443            contiguous_row_selections.push(selection.clone());
3444            let start_row = selection.start.row;
3445            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3446                display_map.next_line_boundary(selection.end).0.row + 1
3447            } else {
3448                selection.end.row
3449            };
3450
3451            while let Some(next_selection) = selections.peek() {
3452                if next_selection.start.row <= end_row {
3453                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3454                        display_map.next_line_boundary(next_selection.end).0.row + 1
3455                    } else {
3456                        next_selection.end.row
3457                    };
3458                    contiguous_row_selections.push(selections.next().unwrap().clone());
3459                } else {
3460                    break;
3461                }
3462            }
3463
3464            // Move the text spanned by the row range to be after the last line of the row range
3465            if end_row <= buffer.max_point().row {
3466                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3467                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3468
3469                // Don't move lines across excerpt boundaries
3470                if buffer
3471                    .excerpt_boundaries_in_range((
3472                        Bound::Excluded(range_to_move.start),
3473                        Bound::Included(insertion_point),
3474                    ))
3475                    .next()
3476                    .is_none()
3477                {
3478                    let mut text = String::from("\n");
3479                    text.extend(buffer.text_for_range(range_to_move.clone()));
3480                    text.pop(); // Drop trailing newline
3481                    edits.push((
3482                        buffer.anchor_after(range_to_move.start)
3483                            ..buffer.anchor_before(range_to_move.end),
3484                        String::new(),
3485                    ));
3486                    let insertion_anchor = buffer.anchor_after(insertion_point);
3487                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3488
3489                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3490
3491                    // Move selections down
3492                    new_selections.extend(contiguous_row_selections.drain(..).map(
3493                        |mut selection| {
3494                            selection.start.row += row_delta;
3495                            selection.end.row += row_delta;
3496                            selection
3497                        },
3498                    ));
3499
3500                    // Move folds down
3501                    unfold_ranges.push(range_to_move.clone());
3502                    for fold in display_map.folds_in_range(
3503                        buffer.anchor_before(range_to_move.start)
3504                            ..buffer.anchor_after(range_to_move.end),
3505                    ) {
3506                        let mut start = fold.start.to_point(&buffer);
3507                        let mut end = fold.end.to_point(&buffer);
3508                        start.row += row_delta;
3509                        end.row += row_delta;
3510                        refold_ranges.push(start..end);
3511                    }
3512                }
3513            }
3514
3515            // If we didn't move line(s), preserve the existing selections
3516            new_selections.extend(contiguous_row_selections.drain(..));
3517        }
3518
3519        self.transact(cx, |this, cx| {
3520            this.unfold_ranges(unfold_ranges, true, cx);
3521            this.buffer.update(cx, |buffer, cx| {
3522                for (range, text) in edits {
3523                    buffer.edit([(range, text)], cx);
3524                }
3525            });
3526            this.fold_ranges(refold_ranges, cx);
3527            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
3528        });
3529    }
3530
3531    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3532        self.transact(cx, |this, cx| {
3533            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3534                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3535                let line_mode = s.line_mode;
3536                s.move_with(|display_map, selection| {
3537                    if !selection.is_empty() || line_mode {
3538                        return;
3539                    }
3540
3541                    let mut head = selection.head();
3542                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3543                    if head.column() == display_map.line_len(head.row()) {
3544                        transpose_offset = display_map
3545                            .buffer_snapshot
3546                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3547                    }
3548
3549                    if transpose_offset == 0 {
3550                        return;
3551                    }
3552
3553                    *head.column_mut() += 1;
3554                    head = display_map.clip_point(head, Bias::Right);
3555                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3556
3557                    let transpose_start = display_map
3558                        .buffer_snapshot
3559                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3560                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3561                        let transpose_end = display_map
3562                            .buffer_snapshot
3563                            .clip_offset(transpose_offset + 1, Bias::Right);
3564                        if let Some(ch) =
3565                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3566                        {
3567                            edits.push((transpose_start..transpose_offset, String::new()));
3568                            edits.push((transpose_end..transpose_end, ch.to_string()));
3569                        }
3570                    }
3571                });
3572                edits
3573            });
3574            this.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
3575            let selections = this.selections.all::<usize>(cx);
3576            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3577                s.select(selections);
3578            });
3579        });
3580    }
3581
3582    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3583        let mut text = String::new();
3584        let buffer = self.buffer.read(cx).snapshot(cx);
3585        let mut selections = self.selections.all::<Point>(cx);
3586        let mut clipboard_selections = Vec::with_capacity(selections.len());
3587        {
3588            let max_point = buffer.max_point();
3589            for selection in &mut selections {
3590                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3591                if is_entire_line {
3592                    selection.start = Point::new(selection.start.row, 0);
3593                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3594                    selection.goal = SelectionGoal::None;
3595                }
3596                let mut len = 0;
3597                for chunk in buffer.text_for_range(selection.start..selection.end) {
3598                    text.push_str(chunk);
3599                    len += chunk.len();
3600                }
3601                clipboard_selections.push(ClipboardSelection {
3602                    len,
3603                    is_entire_line,
3604                });
3605            }
3606        }
3607
3608        self.transact(cx, |this, cx| {
3609            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3610                s.select(selections);
3611            });
3612            this.insert("", cx);
3613            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3614        });
3615    }
3616
3617    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3618        let selections = self.selections.all::<Point>(cx);
3619        let buffer = self.buffer.read(cx).read(cx);
3620        let mut text = String::new();
3621
3622        let mut clipboard_selections = Vec::with_capacity(selections.len());
3623        {
3624            let max_point = buffer.max_point();
3625            for selection in selections.iter() {
3626                let mut start = selection.start;
3627                let mut end = selection.end;
3628                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3629                if is_entire_line {
3630                    start = Point::new(start.row, 0);
3631                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3632                }
3633                let mut len = 0;
3634                for chunk in buffer.text_for_range(start..end) {
3635                    text.push_str(chunk);
3636                    len += chunk.len();
3637                }
3638                clipboard_selections.push(ClipboardSelection {
3639                    len,
3640                    is_entire_line,
3641                });
3642            }
3643        }
3644
3645        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3646    }
3647
3648    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3649        self.transact(cx, |this, cx| {
3650            if let Some(item) = cx.as_mut().read_from_clipboard() {
3651                let mut clipboard_text = Cow::Borrowed(item.text());
3652                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3653                    let old_selections = this.selections.all::<usize>(cx);
3654                    let all_selections_were_entire_line =
3655                        clipboard_selections.iter().all(|s| s.is_entire_line);
3656                    if clipboard_selections.len() != old_selections.len() {
3657                        let mut newline_separated_text = String::new();
3658                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3659                        let mut ix = 0;
3660                        while let Some(clipboard_selection) = clipboard_selections.next() {
3661                            newline_separated_text
3662                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3663                            ix += clipboard_selection.len;
3664                            if clipboard_selections.peek().is_some() {
3665                                newline_separated_text.push('\n');
3666                            }
3667                        }
3668                        clipboard_text = Cow::Owned(newline_separated_text);
3669                    }
3670
3671                    this.buffer.update(cx, |buffer, cx| {
3672                        let snapshot = buffer.read(cx);
3673                        let mut start_offset = 0;
3674                        let mut edits = Vec::new();
3675                        let line_mode = this.selections.line_mode;
3676                        for (ix, selection) in old_selections.iter().enumerate() {
3677                            let to_insert;
3678                            let entire_line;
3679                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3680                                let end_offset = start_offset + clipboard_selection.len;
3681                                to_insert = &clipboard_text[start_offset..end_offset];
3682                                entire_line = clipboard_selection.is_entire_line;
3683                                start_offset = end_offset;
3684                            } else {
3685                                to_insert = clipboard_text.as_str();
3686                                entire_line = all_selections_were_entire_line;
3687                            }
3688
3689                            // If the corresponding selection was empty when this slice of the
3690                            // clipboard text was written, then the entire line containing the
3691                            // selection was copied. If this selection is also currently empty,
3692                            // then paste the line before the current line of the buffer.
3693                            let range = if selection.is_empty() && !line_mode && entire_line {
3694                                let column = selection.start.to_point(&snapshot).column as usize;
3695                                let line_start = selection.start - column;
3696                                line_start..line_start
3697                            } else {
3698                                selection.range()
3699                            };
3700
3701                            edits.push((range, to_insert));
3702                        }
3703                        drop(snapshot);
3704                        buffer.edit_with_autoindent(edits, cx);
3705                    });
3706
3707                    let selections = this.selections.all::<usize>(cx);
3708                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3709                } else {
3710                    this.insert(&clipboard_text, cx);
3711                }
3712            }
3713        });
3714    }
3715
3716    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3717        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3718            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3719                self.change_selections(None, cx, |s| {
3720                    s.select_anchors(selections.to_vec());
3721                });
3722            }
3723            self.request_autoscroll(Autoscroll::Fit, cx);
3724            cx.emit(Event::Edited);
3725        }
3726    }
3727
3728    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3729        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3730            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3731            {
3732                self.change_selections(None, cx, |s| {
3733                    s.select_anchors(selections.to_vec());
3734                });
3735            }
3736            self.request_autoscroll(Autoscroll::Fit, cx);
3737            cx.emit(Event::Edited);
3738        }
3739    }
3740
3741    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3742        self.buffer
3743            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3744    }
3745
3746    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3747        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3748            let line_mode = s.line_mode;
3749            s.move_with(|map, selection| {
3750                let cursor = if selection.is_empty() && !line_mode {
3751                    movement::left(map, selection.start)
3752                } else {
3753                    selection.start
3754                };
3755                selection.collapse_to(cursor, SelectionGoal::None);
3756            });
3757        })
3758    }
3759
3760    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3761        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3762            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3763        })
3764    }
3765
3766    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3767        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3768            let line_mode = s.line_mode;
3769            s.move_with(|map, selection| {
3770                let cursor = if selection.is_empty() && !line_mode {
3771                    movement::right(map, selection.end)
3772                } else {
3773                    selection.end
3774                };
3775                selection.collapse_to(cursor, SelectionGoal::None)
3776            });
3777        })
3778    }
3779
3780    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3781        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3782            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3783        })
3784    }
3785
3786    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3787        if self.take_rename(true, cx).is_some() {
3788            return;
3789        }
3790
3791        if let Some(context_menu) = self.context_menu.as_mut() {
3792            if context_menu.select_prev(cx) {
3793                return;
3794            }
3795        }
3796
3797        if matches!(self.mode, EditorMode::SingleLine) {
3798            cx.propagate_action();
3799            return;
3800        }
3801
3802        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3803            let line_mode = s.line_mode;
3804            s.move_with(|map, selection| {
3805                if !selection.is_empty() && !line_mode {
3806                    selection.goal = SelectionGoal::None;
3807                }
3808                let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false);
3809                selection.collapse_to(cursor, goal);
3810            });
3811        })
3812    }
3813
3814    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3815        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3816            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3817        })
3818    }
3819
3820    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3821        self.take_rename(true, cx);
3822
3823        if let Some(context_menu) = self.context_menu.as_mut() {
3824            if context_menu.select_next(cx) {
3825                return;
3826            }
3827        }
3828
3829        if matches!(self.mode, EditorMode::SingleLine) {
3830            cx.propagate_action();
3831            return;
3832        }
3833
3834        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3835            let line_mode = s.line_mode;
3836            s.move_with(|map, selection| {
3837                if !selection.is_empty() && !line_mode {
3838                    selection.goal = SelectionGoal::None;
3839                }
3840                let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false);
3841                selection.collapse_to(cursor, goal);
3842            });
3843        });
3844    }
3845
3846    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3847        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3848            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3849        });
3850    }
3851
3852    pub fn move_to_previous_word_start(
3853        &mut self,
3854        _: &MoveToPreviousWordStart,
3855        cx: &mut ViewContext<Self>,
3856    ) {
3857        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3858            s.move_cursors_with(|map, head, _| {
3859                (
3860                    movement::previous_word_start(map, head),
3861                    SelectionGoal::None,
3862                )
3863            });
3864        })
3865    }
3866
3867    pub fn move_to_previous_subword_start(
3868        &mut self,
3869        _: &MoveToPreviousSubwordStart,
3870        cx: &mut ViewContext<Self>,
3871    ) {
3872        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3873            s.move_cursors_with(|map, head, _| {
3874                (
3875                    movement::previous_subword_start(map, head),
3876                    SelectionGoal::None,
3877                )
3878            });
3879        })
3880    }
3881
3882    pub fn select_to_previous_word_start(
3883        &mut self,
3884        _: &SelectToPreviousWordStart,
3885        cx: &mut ViewContext<Self>,
3886    ) {
3887        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3888            s.move_heads_with(|map, head, _| {
3889                (
3890                    movement::previous_word_start(map, head),
3891                    SelectionGoal::None,
3892                )
3893            });
3894        })
3895    }
3896
3897    pub fn select_to_previous_subword_start(
3898        &mut self,
3899        _: &SelectToPreviousSubwordStart,
3900        cx: &mut ViewContext<Self>,
3901    ) {
3902        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3903            s.move_heads_with(|map, head, _| {
3904                (
3905                    movement::previous_subword_start(map, head),
3906                    SelectionGoal::None,
3907                )
3908            });
3909        })
3910    }
3911
3912    pub fn delete_to_previous_word_start(
3913        &mut self,
3914        _: &DeleteToPreviousWordStart,
3915        cx: &mut ViewContext<Self>,
3916    ) {
3917        self.transact(cx, |this, cx| {
3918            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3919                let line_mode = s.line_mode;
3920                s.move_with(|map, selection| {
3921                    if selection.is_empty() && !line_mode {
3922                        let cursor = movement::previous_word_start(map, selection.head());
3923                        selection.set_head(cursor, SelectionGoal::None);
3924                    }
3925                });
3926            });
3927            this.insert("", cx);
3928        });
3929    }
3930
3931    pub fn delete_to_previous_subword_start(
3932        &mut self,
3933        _: &DeleteToPreviousSubwordStart,
3934        cx: &mut ViewContext<Self>,
3935    ) {
3936        self.transact(cx, |this, cx| {
3937            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3938                let line_mode = s.line_mode;
3939                s.move_with(|map, selection| {
3940                    if selection.is_empty() && !line_mode {
3941                        let cursor = movement::previous_subword_start(map, selection.head());
3942                        selection.set_head(cursor, SelectionGoal::None);
3943                    }
3944                });
3945            });
3946            this.insert("", cx);
3947        });
3948    }
3949
3950    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3951        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3952            s.move_cursors_with(|map, head, _| {
3953                (movement::next_word_end(map, head), SelectionGoal::None)
3954            });
3955        })
3956    }
3957
3958    pub fn move_to_next_subword_end(
3959        &mut self,
3960        _: &MoveToNextSubwordEnd,
3961        cx: &mut ViewContext<Self>,
3962    ) {
3963        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3964            s.move_cursors_with(|map, head, _| {
3965                (movement::next_subword_end(map, head), SelectionGoal::None)
3966            });
3967        })
3968    }
3969
3970    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
3971        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3972            s.move_heads_with(|map, head, _| {
3973                (movement::next_word_end(map, head), SelectionGoal::None)
3974            });
3975        })
3976    }
3977
3978    pub fn select_to_next_subword_end(
3979        &mut self,
3980        _: &SelectToNextSubwordEnd,
3981        cx: &mut ViewContext<Self>,
3982    ) {
3983        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3984            s.move_heads_with(|map, head, _| {
3985                (movement::next_subword_end(map, head), SelectionGoal::None)
3986            });
3987        })
3988    }
3989
3990    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
3991        self.transact(cx, |this, cx| {
3992            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3993                let line_mode = s.line_mode;
3994                s.move_with(|map, selection| {
3995                    if selection.is_empty() && !line_mode {
3996                        let cursor = movement::next_word_end(map, selection.head());
3997                        selection.set_head(cursor, SelectionGoal::None);
3998                    }
3999                });
4000            });
4001            this.insert("", cx);
4002        });
4003    }
4004
4005    pub fn delete_to_next_subword_end(
4006        &mut self,
4007        _: &DeleteToNextSubwordEnd,
4008        cx: &mut ViewContext<Self>,
4009    ) {
4010        self.transact(cx, |this, cx| {
4011            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4012                s.move_with(|map, selection| {
4013                    if selection.is_empty() {
4014                        let cursor = movement::next_subword_end(map, selection.head());
4015                        selection.set_head(cursor, SelectionGoal::None);
4016                    }
4017                });
4018            });
4019            this.insert("", cx);
4020        });
4021    }
4022
4023    pub fn move_to_beginning_of_line(
4024        &mut self,
4025        _: &MoveToBeginningOfLine,
4026        cx: &mut ViewContext<Self>,
4027    ) {
4028        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4029            s.move_cursors_with(|map, head, _| {
4030                (
4031                    movement::line_beginning(map, head, true),
4032                    SelectionGoal::None,
4033                )
4034            });
4035        })
4036    }
4037
4038    pub fn select_to_beginning_of_line(
4039        &mut self,
4040        action: &SelectToBeginningOfLine,
4041        cx: &mut ViewContext<Self>,
4042    ) {
4043        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4044            s.move_heads_with(|map, head, _| {
4045                (
4046                    movement::line_beginning(map, head, action.stop_at_soft_wraps),
4047                    SelectionGoal::None,
4048                )
4049            });
4050        });
4051    }
4052
4053    pub fn delete_to_beginning_of_line(
4054        &mut self,
4055        _: &DeleteToBeginningOfLine,
4056        cx: &mut ViewContext<Self>,
4057    ) {
4058        self.transact(cx, |this, cx| {
4059            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4060                s.move_with(|_, selection| {
4061                    selection.reversed = true;
4062                });
4063            });
4064
4065            this.select_to_beginning_of_line(
4066                &SelectToBeginningOfLine {
4067                    stop_at_soft_wraps: false,
4068                },
4069                cx,
4070            );
4071            this.backspace(&Backspace, cx);
4072        });
4073    }
4074
4075    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4076        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4077            s.move_cursors_with(|map, head, _| {
4078                (movement::line_end(map, head, true), SelectionGoal::None)
4079            });
4080        })
4081    }
4082
4083    pub fn select_to_end_of_line(
4084        &mut self,
4085        action: &SelectToEndOfLine,
4086        cx: &mut ViewContext<Self>,
4087    ) {
4088        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4089            s.move_heads_with(|map, head, _| {
4090                (
4091                    movement::line_end(map, head, action.stop_at_soft_wraps),
4092                    SelectionGoal::None,
4093                )
4094            });
4095        })
4096    }
4097
4098    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4099        self.transact(cx, |this, cx| {
4100            this.select_to_end_of_line(
4101                &SelectToEndOfLine {
4102                    stop_at_soft_wraps: false,
4103                },
4104                cx,
4105            );
4106            this.delete(&Delete, cx);
4107        });
4108    }
4109
4110    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4111        self.transact(cx, |this, cx| {
4112            this.select_to_end_of_line(
4113                &SelectToEndOfLine {
4114                    stop_at_soft_wraps: false,
4115                },
4116                cx,
4117            );
4118            this.cut(&Cut, cx);
4119        });
4120    }
4121
4122    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4123        if matches!(self.mode, EditorMode::SingleLine) {
4124            cx.propagate_action();
4125            return;
4126        }
4127
4128        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4129            s.select_ranges(vec![0..0]);
4130        });
4131    }
4132
4133    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4134        let mut selection = self.selections.last::<Point>(cx);
4135        selection.set_head(Point::zero(), SelectionGoal::None);
4136
4137        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4138            s.select(vec![selection]);
4139        });
4140    }
4141
4142    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4143        if matches!(self.mode, EditorMode::SingleLine) {
4144            cx.propagate_action();
4145            return;
4146        }
4147
4148        let cursor = self.buffer.read(cx).read(cx).len();
4149        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4150            s.select_ranges(vec![cursor..cursor])
4151        });
4152    }
4153
4154    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4155        self.nav_history = nav_history;
4156    }
4157
4158    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4159        self.nav_history.as_ref()
4160    }
4161
4162    fn push_to_nav_history(
4163        &self,
4164        position: Anchor,
4165        new_position: Option<Point>,
4166        cx: &mut ViewContext<Self>,
4167    ) {
4168        if let Some(nav_history) = &self.nav_history {
4169            let buffer = self.buffer.read(cx).read(cx);
4170            let point = position.to_point(&buffer);
4171            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
4172            drop(buffer);
4173
4174            if let Some(new_position) = new_position {
4175                let row_delta = (new_position.row as i64 - point.row as i64).abs();
4176                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4177                    return;
4178                }
4179            }
4180
4181            nav_history.push(Some(NavigationData {
4182                cursor_anchor: position,
4183                cursor_position: point,
4184                scroll_position: self.scroll_position,
4185                scroll_top_anchor: self.scroll_top_anchor.clone(),
4186                scroll_top_row,
4187            }));
4188        }
4189    }
4190
4191    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4192        let buffer = self.buffer.read(cx).snapshot(cx);
4193        let mut selection = self.selections.first::<usize>(cx);
4194        selection.set_head(buffer.len(), SelectionGoal::None);
4195        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4196            s.select(vec![selection]);
4197        });
4198    }
4199
4200    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4201        let end = self.buffer.read(cx).read(cx).len();
4202        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4203            s.select_ranges(vec![0..end]);
4204        });
4205    }
4206
4207    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4208        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4209        let mut selections = self.selections.all::<Point>(cx);
4210        let max_point = display_map.buffer_snapshot.max_point();
4211        for selection in &mut selections {
4212            let rows = selection.spanned_rows(true, &display_map);
4213            selection.start = Point::new(rows.start, 0);
4214            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4215            selection.reversed = false;
4216        }
4217        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4218            s.select(selections);
4219        });
4220    }
4221
4222    pub fn split_selection_into_lines(
4223        &mut self,
4224        _: &SplitSelectionIntoLines,
4225        cx: &mut ViewContext<Self>,
4226    ) {
4227        let mut to_unfold = Vec::new();
4228        let mut new_selection_ranges = Vec::new();
4229        {
4230            let selections = self.selections.all::<Point>(cx);
4231            let buffer = self.buffer.read(cx).read(cx);
4232            for selection in selections {
4233                for row in selection.start.row..selection.end.row {
4234                    let cursor = Point::new(row, buffer.line_len(row));
4235                    new_selection_ranges.push(cursor..cursor);
4236                }
4237                new_selection_ranges.push(selection.end..selection.end);
4238                to_unfold.push(selection.start..selection.end);
4239            }
4240        }
4241        self.unfold_ranges(to_unfold, true, cx);
4242        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4243            s.select_ranges(new_selection_ranges);
4244        });
4245    }
4246
4247    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4248        self.add_selection(true, cx);
4249    }
4250
4251    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4252        self.add_selection(false, cx);
4253    }
4254
4255    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4256        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4257        let mut selections = self.selections.all::<Point>(cx);
4258        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4259            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4260            let range = oldest_selection.display_range(&display_map).sorted();
4261            let columns = cmp::min(range.start.column(), range.end.column())
4262                ..cmp::max(range.start.column(), range.end.column());
4263
4264            selections.clear();
4265            let mut stack = Vec::new();
4266            for row in range.start.row()..=range.end.row() {
4267                if let Some(selection) = self.selections.build_columnar_selection(
4268                    &display_map,
4269                    row,
4270                    &columns,
4271                    oldest_selection.reversed,
4272                ) {
4273                    stack.push(selection.id);
4274                    selections.push(selection);
4275                }
4276            }
4277
4278            if above {
4279                stack.reverse();
4280            }
4281
4282            AddSelectionsState { above, stack }
4283        });
4284
4285        let last_added_selection = *state.stack.last().unwrap();
4286        let mut new_selections = Vec::new();
4287        if above == state.above {
4288            let end_row = if above {
4289                0
4290            } else {
4291                display_map.max_point().row()
4292            };
4293
4294            'outer: for selection in selections {
4295                if selection.id == last_added_selection {
4296                    let range = selection.display_range(&display_map).sorted();
4297                    debug_assert_eq!(range.start.row(), range.end.row());
4298                    let mut row = range.start.row();
4299                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4300                    {
4301                        start..end
4302                    } else {
4303                        cmp::min(range.start.column(), range.end.column())
4304                            ..cmp::max(range.start.column(), range.end.column())
4305                    };
4306
4307                    while row != end_row {
4308                        if above {
4309                            row -= 1;
4310                        } else {
4311                            row += 1;
4312                        }
4313
4314                        if let Some(new_selection) = self.selections.build_columnar_selection(
4315                            &display_map,
4316                            row,
4317                            &columns,
4318                            selection.reversed,
4319                        ) {
4320                            state.stack.push(new_selection.id);
4321                            if above {
4322                                new_selections.push(new_selection);
4323                                new_selections.push(selection);
4324                            } else {
4325                                new_selections.push(selection);
4326                                new_selections.push(new_selection);
4327                            }
4328
4329                            continue 'outer;
4330                        }
4331                    }
4332                }
4333
4334                new_selections.push(selection);
4335            }
4336        } else {
4337            new_selections = selections;
4338            new_selections.retain(|s| s.id != last_added_selection);
4339            state.stack.pop();
4340        }
4341
4342        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4343            s.select(new_selections);
4344        });
4345        if state.stack.len() > 1 {
4346            self.add_selections_state = Some(state);
4347        }
4348    }
4349
4350    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4351        self.push_to_selection_history();
4352        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4353        let buffer = &display_map.buffer_snapshot;
4354        let mut selections = self.selections.all::<usize>(cx);
4355        if let Some(mut select_next_state) = self.select_next_state.take() {
4356            let query = &select_next_state.query;
4357            if !select_next_state.done {
4358                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4359                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4360                let mut next_selected_range = None;
4361
4362                let bytes_after_last_selection =
4363                    buffer.bytes_in_range(last_selection.end..buffer.len());
4364                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4365                let query_matches = query
4366                    .stream_find_iter(bytes_after_last_selection)
4367                    .map(|result| (last_selection.end, result))
4368                    .chain(
4369                        query
4370                            .stream_find_iter(bytes_before_first_selection)
4371                            .map(|result| (0, result)),
4372                    );
4373                for (start_offset, query_match) in query_matches {
4374                    let query_match = query_match.unwrap(); // can only fail due to I/O
4375                    let offset_range =
4376                        start_offset + query_match.start()..start_offset + query_match.end();
4377                    let display_range = offset_range.start.to_display_point(&display_map)
4378                        ..offset_range.end.to_display_point(&display_map);
4379
4380                    if !select_next_state.wordwise
4381                        || (!movement::is_inside_word(&display_map, display_range.start)
4382                            && !movement::is_inside_word(&display_map, display_range.end))
4383                    {
4384                        next_selected_range = Some(offset_range);
4385                        break;
4386                    }
4387                }
4388
4389                if let Some(next_selected_range) = next_selected_range {
4390                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4391                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4392                        if action.replace_newest {
4393                            s.delete(s.newest_anchor().id);
4394                        }
4395                        s.insert_range(next_selected_range);
4396                    });
4397                } else {
4398                    select_next_state.done = true;
4399                }
4400            }
4401
4402            self.select_next_state = Some(select_next_state);
4403        } else if selections.len() == 1 {
4404            let selection = selections.last_mut().unwrap();
4405            if selection.start == selection.end {
4406                let word_range = movement::surrounding_word(
4407                    &display_map,
4408                    selection.start.to_display_point(&display_map),
4409                );
4410                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4411                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4412                selection.goal = SelectionGoal::None;
4413                selection.reversed = false;
4414
4415                let query = buffer
4416                    .text_for_range(selection.start..selection.end)
4417                    .collect::<String>();
4418                let select_state = SelectNextState {
4419                    query: AhoCorasick::new_auto_configured(&[query]),
4420                    wordwise: true,
4421                    done: false,
4422                };
4423                self.unfold_ranges([selection.start..selection.end], false, cx);
4424                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4425                    s.select(selections);
4426                });
4427                self.select_next_state = Some(select_state);
4428            } else {
4429                let query = buffer
4430                    .text_for_range(selection.start..selection.end)
4431                    .collect::<String>();
4432                self.select_next_state = Some(SelectNextState {
4433                    query: AhoCorasick::new_auto_configured(&[query]),
4434                    wordwise: false,
4435                    done: false,
4436                });
4437                self.select_next(action, cx);
4438            }
4439        }
4440    }
4441
4442    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4443        self.transact(cx, |this, cx| {
4444            let mut selections = this.selections.all::<Point>(cx);
4445            let mut all_selection_lines_are_comments = true;
4446            let mut edit_ranges = Vec::new();
4447            let mut last_toggled_row = None;
4448            this.buffer.update(cx, |buffer, cx| {
4449                // TODO: Handle selections that cross excerpts
4450                for selection in &mut selections {
4451                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
4452                    // as that portion won't be used for detecting if a line is a comment.
4453                    let full_comment_prefix: Arc<str> = if let Some(prefix) = buffer
4454                        .language_at(selection.start, cx)
4455                        .and_then(|l| l.line_comment_prefix())
4456                    {
4457                        prefix.into()
4458                    } else {
4459                        return;
4460                    };
4461                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4462                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4463                    edit_ranges.clear();
4464                    let snapshot = buffer.snapshot(cx);
4465
4466                    let end_row =
4467                        if selection.end.row > selection.start.row && selection.end.column == 0 {
4468                            selection.end.row
4469                        } else {
4470                            selection.end.row + 1
4471                        };
4472
4473                    for row in selection.start.row..end_row {
4474                        // If multiple selections contain a given row, avoid processing that
4475                        // row more than once.
4476                        if last_toggled_row == Some(row) {
4477                            continue;
4478                        } else {
4479                            last_toggled_row = Some(row);
4480                        }
4481
4482                        if snapshot.is_line_blank(row) {
4483                            continue;
4484                        }
4485
4486                        let start = Point::new(row, snapshot.indent_column_for_line(row));
4487                        let mut line_bytes = snapshot
4488                            .bytes_in_range(start..snapshot.max_point())
4489                            .flatten()
4490                            .copied();
4491
4492                        // If this line currently begins with the line comment prefix, then record
4493                        // the range containing the prefix.
4494                        if all_selection_lines_are_comments
4495                            && line_bytes
4496                                .by_ref()
4497                                .take(comment_prefix.len())
4498                                .eq(comment_prefix.bytes())
4499                        {
4500                            // Include any whitespace that matches the comment prefix.
4501                            let matching_whitespace_len = line_bytes
4502                                .zip(comment_prefix_whitespace.bytes())
4503                                .take_while(|(a, b)| a == b)
4504                                .count()
4505                                as u32;
4506                            let end = Point::new(
4507                                row,
4508                                start.column
4509                                    + comment_prefix.len() as u32
4510                                    + matching_whitespace_len,
4511                            );
4512                            edit_ranges.push(start..end);
4513                        }
4514                        // If this line does not begin with the line comment prefix, then record
4515                        // the position where the prefix should be inserted.
4516                        else {
4517                            all_selection_lines_are_comments = false;
4518                            edit_ranges.push(start..start);
4519                        }
4520                    }
4521
4522                    if !edit_ranges.is_empty() {
4523                        if all_selection_lines_are_comments {
4524                            let empty_str: Arc<str> = "".into();
4525                            buffer.edit(
4526                                edit_ranges
4527                                    .iter()
4528                                    .cloned()
4529                                    .map(|range| (range, empty_str.clone())),
4530                                cx,
4531                            );
4532                        } else {
4533                            let min_column =
4534                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
4535                            let edits = edit_ranges.iter().map(|range| {
4536                                let position = Point::new(range.start.row, min_column);
4537                                (position..position, full_comment_prefix.clone())
4538                            });
4539                            buffer.edit(edits, cx);
4540                        }
4541                    }
4542                }
4543            });
4544
4545            let selections = this.selections.all::<usize>(cx);
4546            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
4547        });
4548    }
4549
4550    pub fn select_larger_syntax_node(
4551        &mut self,
4552        _: &SelectLargerSyntaxNode,
4553        cx: &mut ViewContext<Self>,
4554    ) {
4555        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4556        let buffer = self.buffer.read(cx).snapshot(cx);
4557        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4558
4559        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4560        let mut selected_larger_node = false;
4561        let new_selections = old_selections
4562            .iter()
4563            .map(|selection| {
4564                let old_range = selection.start..selection.end;
4565                let mut new_range = old_range.clone();
4566                while let Some(containing_range) =
4567                    buffer.range_for_syntax_ancestor(new_range.clone())
4568                {
4569                    new_range = containing_range;
4570                    if !display_map.intersects_fold(new_range.start)
4571                        && !display_map.intersects_fold(new_range.end)
4572                    {
4573                        break;
4574                    }
4575                }
4576
4577                selected_larger_node |= new_range != old_range;
4578                Selection {
4579                    id: selection.id,
4580                    start: new_range.start,
4581                    end: new_range.end,
4582                    goal: SelectionGoal::None,
4583                    reversed: selection.reversed,
4584                }
4585            })
4586            .collect::<Vec<_>>();
4587
4588        if selected_larger_node {
4589            stack.push(old_selections);
4590            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4591                s.select(new_selections);
4592            });
4593        }
4594        self.select_larger_syntax_node_stack = stack;
4595    }
4596
4597    pub fn select_smaller_syntax_node(
4598        &mut self,
4599        _: &SelectSmallerSyntaxNode,
4600        cx: &mut ViewContext<Self>,
4601    ) {
4602        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4603        if let Some(selections) = stack.pop() {
4604            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4605                s.select(selections.to_vec());
4606            });
4607        }
4608        self.select_larger_syntax_node_stack = stack;
4609    }
4610
4611    pub fn move_to_enclosing_bracket(
4612        &mut self,
4613        _: &MoveToEnclosingBracket,
4614        cx: &mut ViewContext<Self>,
4615    ) {
4616        let buffer = self.buffer.read(cx).snapshot(cx);
4617        let mut selections = self.selections.all::<usize>(cx);
4618        for selection in &mut selections {
4619            if let Some((open_range, close_range)) =
4620                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4621            {
4622                let close_range = close_range.to_inclusive();
4623                let destination = if close_range.contains(&selection.start)
4624                    && close_range.contains(&selection.end)
4625                {
4626                    open_range.end
4627                } else {
4628                    *close_range.start()
4629                };
4630                selection.start = destination;
4631                selection.end = destination;
4632            }
4633        }
4634
4635        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4636            s.select(selections);
4637        });
4638    }
4639
4640    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4641        self.end_selection(cx);
4642        self.selection_history.mode = SelectionHistoryMode::Undoing;
4643        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4644            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4645            self.select_next_state = entry.select_next_state;
4646            self.add_selections_state = entry.add_selections_state;
4647            self.request_autoscroll(Autoscroll::Newest, cx);
4648        }
4649        self.selection_history.mode = SelectionHistoryMode::Normal;
4650    }
4651
4652    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4653        self.end_selection(cx);
4654        self.selection_history.mode = SelectionHistoryMode::Redoing;
4655        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4656            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4657            self.select_next_state = entry.select_next_state;
4658            self.add_selections_state = entry.add_selections_state;
4659            self.request_autoscroll(Autoscroll::Newest, cx);
4660        }
4661        self.selection_history.mode = SelectionHistoryMode::Normal;
4662    }
4663
4664    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
4665        self.go_to_diagnostic(Direction::Next, cx)
4666    }
4667
4668    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4669        self.go_to_diagnostic(Direction::Prev, cx)
4670    }
4671
4672    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4673        let buffer = self.buffer.read(cx).snapshot(cx);
4674        let selection = self.selections.newest::<usize>(cx);
4675        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4676            active_diagnostics
4677                .primary_range
4678                .to_offset(&buffer)
4679                .to_inclusive()
4680        });
4681        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4682            if active_primary_range.contains(&selection.head()) {
4683                *active_primary_range.end()
4684            } else {
4685                selection.head()
4686            }
4687        } else {
4688            selection.head()
4689        };
4690
4691        loop {
4692            let mut diagnostics = if direction == Direction::Prev {
4693                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4694            } else {
4695                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4696            };
4697            let group = diagnostics.find_map(|entry| {
4698                if entry.diagnostic.is_primary
4699                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4700                    && !entry.range.is_empty()
4701                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4702                {
4703                    Some((entry.range, entry.diagnostic.group_id))
4704                } else {
4705                    None
4706                }
4707            });
4708
4709            if let Some((primary_range, group_id)) = group {
4710                self.activate_diagnostics(group_id, cx);
4711                self.change_selections(Some(Autoscroll::Center), cx, |s| {
4712                    s.select(vec![Selection {
4713                        id: selection.id,
4714                        start: primary_range.start,
4715                        end: primary_range.start,
4716                        reversed: false,
4717                        goal: SelectionGoal::None,
4718                    }]);
4719                });
4720                break;
4721            } else {
4722                // Cycle around to the start of the buffer, potentially moving back to the start of
4723                // the currently active diagnostic.
4724                active_primary_range.take();
4725                if direction == Direction::Prev {
4726                    if search_start == buffer.len() {
4727                        break;
4728                    } else {
4729                        search_start = buffer.len();
4730                    }
4731                } else {
4732                    if search_start == 0 {
4733                        break;
4734                    } else {
4735                        search_start = 0;
4736                    }
4737                }
4738            }
4739        }
4740    }
4741
4742    pub fn go_to_definition(
4743        workspace: &mut Workspace,
4744        _: &GoToDefinition,
4745        cx: &mut ViewContext<Workspace>,
4746    ) {
4747        let active_item = workspace.active_item(cx);
4748        let editor_handle = if let Some(editor) = active_item
4749            .as_ref()
4750            .and_then(|item| item.act_as::<Self>(cx))
4751        {
4752            editor
4753        } else {
4754            return;
4755        };
4756
4757        let editor = editor_handle.read(cx);
4758        let buffer = editor.buffer.read(cx);
4759        let head = editor.selections.newest::<usize>(cx).head();
4760        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
4761            text_anchor
4762        } else {
4763            return;
4764        };
4765
4766        let project = workspace.project().clone();
4767        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
4768        cx.spawn(|workspace, mut cx| async move {
4769            let definitions = definitions.await?;
4770            workspace.update(&mut cx, |workspace, cx| {
4771                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
4772                for definition in definitions {
4773                    let range = definition.range.to_offset(definition.buffer.read(cx));
4774
4775                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
4776                    target_editor_handle.update(cx, |target_editor, cx| {
4777                        // When selecting a definition in a different buffer, disable the nav history
4778                        // to avoid creating a history entry at the previous cursor location.
4779                        if editor_handle != target_editor_handle {
4780                            nav_history.borrow_mut().disable();
4781                        }
4782                        target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
4783                            s.select_ranges([range]);
4784                        });
4785
4786                        nav_history.borrow_mut().enable();
4787                    });
4788                }
4789            });
4790
4791            Ok::<(), anyhow::Error>(())
4792        })
4793        .detach_and_log_err(cx);
4794    }
4795
4796    pub fn find_all_references(
4797        workspace: &mut Workspace,
4798        _: &FindAllReferences,
4799        cx: &mut ViewContext<Workspace>,
4800    ) -> Option<Task<Result<()>>> {
4801        let active_item = workspace.active_item(cx)?;
4802        let editor_handle = active_item.act_as::<Self>(cx)?;
4803
4804        let editor = editor_handle.read(cx);
4805        let buffer = editor.buffer.read(cx);
4806        let head = editor.selections.newest::<usize>(cx).head();
4807        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
4808        let replica_id = editor.replica_id(cx);
4809
4810        let project = workspace.project().clone();
4811        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
4812        Some(cx.spawn(|workspace, mut cx| async move {
4813            let mut locations = references.await?;
4814            if locations.is_empty() {
4815                return Ok(());
4816            }
4817
4818            locations.sort_by_key(|location| location.buffer.id());
4819            let mut locations = locations.into_iter().peekable();
4820            let mut ranges_to_highlight = Vec::new();
4821
4822            let excerpt_buffer = cx.add_model(|cx| {
4823                let mut symbol_name = None;
4824                let mut multibuffer = MultiBuffer::new(replica_id);
4825                while let Some(location) = locations.next() {
4826                    let buffer = location.buffer.read(cx);
4827                    let mut ranges_for_buffer = Vec::new();
4828                    let range = location.range.to_offset(buffer);
4829                    ranges_for_buffer.push(range.clone());
4830                    if symbol_name.is_none() {
4831                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
4832                    }
4833
4834                    while let Some(next_location) = locations.peek() {
4835                        if next_location.buffer == location.buffer {
4836                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
4837                            locations.next();
4838                        } else {
4839                            break;
4840                        }
4841                    }
4842
4843                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
4844                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
4845                        location.buffer.clone(),
4846                        ranges_for_buffer,
4847                        1,
4848                        cx,
4849                    ));
4850                }
4851                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
4852            });
4853
4854            workspace.update(&mut cx, |workspace, cx| {
4855                let editor =
4856                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
4857                editor.update(cx, |editor, cx| {
4858                    editor.highlight_background::<Self>(
4859                        ranges_to_highlight,
4860                        |theme| theme.editor.highlighted_line_background,
4861                        cx,
4862                    );
4863                });
4864                workspace.add_item(Box::new(editor), cx);
4865            });
4866
4867            Ok(())
4868        }))
4869    }
4870
4871    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
4872        use language::ToOffset as _;
4873
4874        let project = self.project.clone()?;
4875        let selection = self.selections.newest_anchor().clone();
4876        let (cursor_buffer, cursor_buffer_position) = self
4877            .buffer
4878            .read(cx)
4879            .text_anchor_for_position(selection.head(), cx)?;
4880        let (tail_buffer, _) = self
4881            .buffer
4882            .read(cx)
4883            .text_anchor_for_position(selection.tail(), cx)?;
4884        if tail_buffer != cursor_buffer {
4885            return None;
4886        }
4887
4888        let snapshot = cursor_buffer.read(cx).snapshot();
4889        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
4890        let prepare_rename = project.update(cx, |project, cx| {
4891            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
4892        });
4893
4894        Some(cx.spawn(|this, mut cx| async move {
4895            let rename_range = if let Some(range) = prepare_rename.await? {
4896                Some(range)
4897            } else {
4898                this.read_with(&cx, |this, cx| {
4899                    let buffer = this.buffer.read(cx).snapshot(cx);
4900                    let mut buffer_highlights = this
4901                        .document_highlights_for_position(selection.head(), &buffer)
4902                        .filter(|highlight| {
4903                            highlight.start.excerpt_id() == selection.head().excerpt_id()
4904                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
4905                        });
4906                    buffer_highlights
4907                        .next()
4908                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
4909                })
4910            };
4911            if let Some(rename_range) = rename_range {
4912                let rename_buffer_range = rename_range.to_offset(&snapshot);
4913                let cursor_offset_in_rename_range =
4914                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
4915
4916                this.update(&mut cx, |this, cx| {
4917                    this.take_rename(false, cx);
4918                    let style = this.style(cx);
4919                    let buffer = this.buffer.read(cx).read(cx);
4920                    let cursor_offset = selection.head().to_offset(&buffer);
4921                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
4922                    let rename_end = rename_start + rename_buffer_range.len();
4923                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
4924                    let mut old_highlight_id = None;
4925                    let old_name: Arc<str> = buffer
4926                        .chunks(rename_start..rename_end, true)
4927                        .map(|chunk| {
4928                            if old_highlight_id.is_none() {
4929                                old_highlight_id = chunk.syntax_highlight_id;
4930                            }
4931                            chunk.text
4932                        })
4933                        .collect::<String>()
4934                        .into();
4935
4936                    drop(buffer);
4937
4938                    // Position the selection in the rename editor so that it matches the current selection.
4939                    this.show_local_selections = false;
4940                    let rename_editor = cx.add_view(|cx| {
4941                        println!("Rename editor created.");
4942                        let mut editor = Editor::single_line(None, cx);
4943                        if let Some(old_highlight_id) = old_highlight_id {
4944                            editor.override_text_style =
4945                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
4946                        }
4947                        editor
4948                            .buffer
4949                            .update(cx, |buffer, cx| buffer.edit([(0..0, old_name.clone())], cx));
4950                        editor.select_all(&SelectAll, cx);
4951                        editor
4952                    });
4953
4954                    let ranges = this
4955                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
4956                        .into_iter()
4957                        .flat_map(|(_, ranges)| ranges)
4958                        .chain(
4959                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
4960                                .into_iter()
4961                                .flat_map(|(_, ranges)| ranges),
4962                        )
4963                        .collect();
4964
4965                    this.highlight_text::<Rename>(
4966                        ranges,
4967                        HighlightStyle {
4968                            fade_out: Some(style.rename_fade),
4969                            ..Default::default()
4970                        },
4971                        cx,
4972                    );
4973                    cx.focus(&rename_editor);
4974                    let block_id = this.insert_blocks(
4975                        [BlockProperties {
4976                            position: range.start.clone(),
4977                            height: 1,
4978                            render: Arc::new({
4979                                let editor = rename_editor.clone();
4980                                move |cx: &mut BlockContext| {
4981                                    ChildView::new(editor.clone())
4982                                        .contained()
4983                                        .with_padding_left(cx.anchor_x)
4984                                        .boxed()
4985                                }
4986                            }),
4987                            disposition: BlockDisposition::Below,
4988                        }],
4989                        cx,
4990                    )[0];
4991                    this.pending_rename = Some(RenameState {
4992                        range,
4993                        old_name,
4994                        editor: rename_editor,
4995                        block_id,
4996                    });
4997                });
4998            }
4999
5000            Ok(())
5001        }))
5002    }
5003
5004    pub fn confirm_rename(
5005        workspace: &mut Workspace,
5006        _: &ConfirmRename,
5007        cx: &mut ViewContext<Workspace>,
5008    ) -> Option<Task<Result<()>>> {
5009        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5010
5011        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5012            let rename = editor.take_rename(false, cx)?;
5013            let buffer = editor.buffer.read(cx);
5014            let (start_buffer, start) =
5015                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5016            let (end_buffer, end) =
5017                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5018            if start_buffer == end_buffer {
5019                let new_name = rename.editor.read(cx).text(cx);
5020                Some((start_buffer, start..end, rename.old_name, new_name))
5021            } else {
5022                None
5023            }
5024        })?;
5025
5026        let rename = workspace.project().clone().update(cx, |project, cx| {
5027            project.perform_rename(
5028                buffer.clone(),
5029                range.start.clone(),
5030                new_name.clone(),
5031                true,
5032                cx,
5033            )
5034        });
5035
5036        Some(cx.spawn(|workspace, mut cx| async move {
5037            let project_transaction = rename.await?;
5038            Self::open_project_transaction(
5039                editor.clone(),
5040                workspace,
5041                project_transaction,
5042                format!("Rename: {}{}", old_name, new_name),
5043                cx.clone(),
5044            )
5045            .await?;
5046
5047            editor.update(&mut cx, |editor, cx| {
5048                editor.refresh_document_highlights(cx);
5049            });
5050            Ok(())
5051        }))
5052    }
5053
5054    fn take_rename(
5055        &mut self,
5056        moving_cursor: bool,
5057        cx: &mut ViewContext<Self>,
5058    ) -> Option<RenameState> {
5059        let rename = self.pending_rename.take()?;
5060        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5061        self.clear_text_highlights::<Rename>(cx);
5062        self.show_local_selections = true;
5063
5064        if moving_cursor {
5065            let rename_editor = rename.editor.read(cx);
5066            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5067
5068            // Update the selection to match the position of the selection inside
5069            // the rename editor.
5070            let snapshot = self.buffer.read(cx).read(cx);
5071            let rename_range = rename.range.to_offset(&snapshot);
5072            let cursor_in_editor = snapshot
5073                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5074                .min(rename_range.end);
5075            drop(snapshot);
5076
5077            self.change_selections(None, cx, |s| {
5078                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5079            });
5080        }
5081
5082        Some(rename)
5083    }
5084
5085    #[cfg(any(test, feature = "test-support"))]
5086    pub fn pending_rename(&self) -> Option<&RenameState> {
5087        self.pending_rename.as_ref()
5088    }
5089
5090    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5091        if let Some(project) = self.project.clone() {
5092            self.buffer.update(cx, |multi_buffer, cx| {
5093                project.update(cx, |project, cx| {
5094                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5095                });
5096            })
5097        }
5098    }
5099
5100    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5101        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5102            let buffer = self.buffer.read(cx).snapshot(cx);
5103            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5104            let is_valid = buffer
5105                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5106                .any(|entry| {
5107                    entry.diagnostic.is_primary
5108                        && !entry.range.is_empty()
5109                        && entry.range.start == primary_range_start
5110                        && entry.diagnostic.message == active_diagnostics.primary_message
5111                });
5112
5113            if is_valid != active_diagnostics.is_valid {
5114                active_diagnostics.is_valid = is_valid;
5115                let mut new_styles = HashMap::default();
5116                for (block_id, diagnostic) in &active_diagnostics.blocks {
5117                    new_styles.insert(
5118                        *block_id,
5119                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5120                    );
5121                }
5122                self.display_map
5123                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5124            }
5125        }
5126    }
5127
5128    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
5129        self.dismiss_diagnostics(cx);
5130        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5131            let buffer = self.buffer.read(cx).snapshot(cx);
5132
5133            let mut primary_range = None;
5134            let mut primary_message = None;
5135            let mut group_end = Point::zero();
5136            let diagnostic_group = buffer
5137                .diagnostic_group::<Point>(group_id)
5138                .map(|entry| {
5139                    if entry.range.end > group_end {
5140                        group_end = entry.range.end;
5141                    }
5142                    if entry.diagnostic.is_primary {
5143                        primary_range = Some(entry.range.clone());
5144                        primary_message = Some(entry.diagnostic.message.clone());
5145                    }
5146                    entry
5147                })
5148                .collect::<Vec<_>>();
5149            let primary_range = primary_range.unwrap();
5150            let primary_message = primary_message.unwrap();
5151            let primary_range =
5152                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5153
5154            let blocks = display_map
5155                .insert_blocks(
5156                    diagnostic_group.iter().map(|entry| {
5157                        let diagnostic = entry.diagnostic.clone();
5158                        let message_height = diagnostic.message.lines().count() as u8;
5159                        BlockProperties {
5160                            position: buffer.anchor_after(entry.range.start),
5161                            height: message_height,
5162                            render: diagnostic_block_renderer(diagnostic, true),
5163                            disposition: BlockDisposition::Below,
5164                        }
5165                    }),
5166                    cx,
5167                )
5168                .into_iter()
5169                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5170                .collect();
5171
5172            Some(ActiveDiagnosticGroup {
5173                primary_range,
5174                primary_message,
5175                blocks,
5176                is_valid: true,
5177            })
5178        });
5179    }
5180
5181    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5182        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5183            self.display_map.update(cx, |display_map, cx| {
5184                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5185            });
5186            cx.notify();
5187        }
5188    }
5189
5190    pub fn set_selections_from_remote(
5191        &mut self,
5192        selections: Vec<Selection<Anchor>>,
5193        cx: &mut ViewContext<Self>,
5194    ) {
5195        let old_cursor_position = self.selections.newest_anchor().head();
5196        self.selections.change_with(cx, |s| {
5197            s.select_anchors(selections);
5198        });
5199        self.selections_did_change(false, &old_cursor_position, cx);
5200    }
5201
5202    fn push_to_selection_history(&mut self) {
5203        self.selection_history.push(SelectionHistoryEntry {
5204            selections: self.selections.disjoint_anchors().clone(),
5205            select_next_state: self.select_next_state.clone(),
5206            add_selections_state: self.add_selections_state.clone(),
5207        });
5208    }
5209
5210    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5211        self.autoscroll_request = Some((autoscroll, true));
5212        cx.notify();
5213    }
5214
5215    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5216        self.autoscroll_request = Some((autoscroll, false));
5217        cx.notify();
5218    }
5219
5220    pub fn transact(
5221        &mut self,
5222        cx: &mut ViewContext<Self>,
5223        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5224    ) {
5225        self.start_transaction_at(Instant::now(), cx);
5226        update(self, cx);
5227        self.end_transaction_at(Instant::now(), cx);
5228    }
5229
5230    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5231        self.end_selection(cx);
5232        if let Some(tx_id) = self
5233            .buffer
5234            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5235        {
5236            self.selection_history
5237                .insert_transaction(tx_id, self.selections.disjoint_anchors().clone());
5238        }
5239    }
5240
5241    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5242        if let Some(tx_id) = self
5243            .buffer
5244            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5245        {
5246            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5247                *end_selections = Some(self.selections.disjoint_anchors().clone());
5248            } else {
5249                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5250            }
5251
5252            cx.emit(Event::Edited);
5253        }
5254    }
5255
5256    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
5257        log::info!("Editor::page_up");
5258    }
5259
5260    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
5261        log::info!("Editor::page_down");
5262    }
5263
5264    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5265        let mut fold_ranges = Vec::new();
5266
5267        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5268        let selections = self.selections.all::<Point>(cx);
5269        for selection in selections {
5270            let range = selection.display_range(&display_map).sorted();
5271            let buffer_start_row = range.start.to_point(&display_map).row;
5272
5273            for row in (0..=range.end.row()).rev() {
5274                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5275                    let fold_range = self.foldable_range_for_line(&display_map, row);
5276                    if fold_range.end.row >= buffer_start_row {
5277                        fold_ranges.push(fold_range);
5278                        if row <= range.start.row() {
5279                            break;
5280                        }
5281                    }
5282                }
5283            }
5284        }
5285
5286        self.fold_ranges(fold_ranges, cx);
5287    }
5288
5289    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5290        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5291        let buffer = &display_map.buffer_snapshot;
5292        let selections = self.selections.all::<Point>(cx);
5293        let ranges = selections
5294            .iter()
5295            .map(|s| {
5296                let range = s.display_range(&display_map).sorted();
5297                let mut start = range.start.to_point(&display_map);
5298                let mut end = range.end.to_point(&display_map);
5299                start.column = 0;
5300                end.column = buffer.line_len(end.row);
5301                start..end
5302            })
5303            .collect::<Vec<_>>();
5304        self.unfold_ranges(ranges, true, cx);
5305    }
5306
5307    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5308        let max_point = display_map.max_point();
5309        if display_row >= max_point.row() {
5310            false
5311        } else {
5312            let (start_indent, is_blank) = display_map.line_indent(display_row);
5313            if is_blank {
5314                false
5315            } else {
5316                for display_row in display_row + 1..=max_point.row() {
5317                    let (indent, is_blank) = display_map.line_indent(display_row);
5318                    if !is_blank {
5319                        return indent > start_indent;
5320                    }
5321                }
5322                false
5323            }
5324        }
5325    }
5326
5327    fn foldable_range_for_line(
5328        &self,
5329        display_map: &DisplaySnapshot,
5330        start_row: u32,
5331    ) -> Range<Point> {
5332        let max_point = display_map.max_point();
5333
5334        let (start_indent, _) = display_map.line_indent(start_row);
5335        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5336        let mut end = None;
5337        for row in start_row + 1..=max_point.row() {
5338            let (indent, is_blank) = display_map.line_indent(row);
5339            if !is_blank && indent <= start_indent {
5340                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5341                break;
5342            }
5343        }
5344
5345        let end = end.unwrap_or(max_point);
5346        return start.to_point(display_map)..end.to_point(display_map);
5347    }
5348
5349    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5350        let selections = self.selections.all::<Point>(cx);
5351        let ranges = selections.into_iter().map(|s| s.start..s.end);
5352        self.fold_ranges(ranges, cx);
5353    }
5354
5355    pub fn fold_ranges<T: ToOffset>(
5356        &mut self,
5357        ranges: impl IntoIterator<Item = Range<T>>,
5358        cx: &mut ViewContext<Self>,
5359    ) {
5360        let mut ranges = ranges.into_iter().peekable();
5361        if ranges.peek().is_some() {
5362            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5363            self.request_autoscroll(Autoscroll::Fit, cx);
5364            cx.notify();
5365        }
5366    }
5367
5368    pub fn unfold_ranges<T: ToOffset>(
5369        &mut self,
5370        ranges: impl IntoIterator<Item = Range<T>>,
5371        inclusive: bool,
5372        cx: &mut ViewContext<Self>,
5373    ) {
5374        let mut ranges = ranges.into_iter().peekable();
5375        if ranges.peek().is_some() {
5376            self.display_map
5377                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5378            self.request_autoscroll(Autoscroll::Fit, cx);
5379            cx.notify();
5380        }
5381    }
5382
5383    pub fn insert_blocks(
5384        &mut self,
5385        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5386        cx: &mut ViewContext<Self>,
5387    ) -> Vec<BlockId> {
5388        let blocks = self
5389            .display_map
5390            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5391        self.request_autoscroll(Autoscroll::Fit, cx);
5392        blocks
5393    }
5394
5395    pub fn replace_blocks(
5396        &mut self,
5397        blocks: HashMap<BlockId, RenderBlock>,
5398        cx: &mut ViewContext<Self>,
5399    ) {
5400        self.display_map
5401            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5402        self.request_autoscroll(Autoscroll::Fit, cx);
5403    }
5404
5405    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5406        self.display_map.update(cx, |display_map, cx| {
5407            display_map.remove_blocks(block_ids, cx)
5408        });
5409    }
5410
5411    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5412        self.display_map
5413            .update(cx, |map, cx| map.snapshot(cx))
5414            .longest_row()
5415    }
5416
5417    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5418        self.display_map
5419            .update(cx, |map, cx| map.snapshot(cx))
5420            .max_point()
5421    }
5422
5423    pub fn text(&self, cx: &AppContext) -> String {
5424        self.buffer.read(cx).read(cx).text()
5425    }
5426
5427    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5428        self.transact(cx, |this, cx| {
5429            this.buffer
5430                .read(cx)
5431                .as_singleton()
5432                .expect("you can only call set_text on editors for singleton buffers")
5433                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5434        });
5435    }
5436
5437    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5438        self.display_map
5439            .update(cx, |map, cx| map.snapshot(cx))
5440            .text()
5441    }
5442
5443    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5444        let language_name = self
5445            .buffer
5446            .read(cx)
5447            .as_singleton()
5448            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5449            .map(|l| l.name());
5450
5451        let settings = cx.global::<Settings>();
5452        let mode = self
5453            .soft_wrap_mode_override
5454            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5455        match mode {
5456            settings::SoftWrap::None => SoftWrap::None,
5457            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5458            settings::SoftWrap::PreferredLineLength => {
5459                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5460            }
5461        }
5462    }
5463
5464    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5465        self.soft_wrap_mode_override = Some(mode);
5466        cx.notify();
5467    }
5468
5469    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5470        self.display_map
5471            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5472    }
5473
5474    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5475        self.highlighted_rows = rows;
5476    }
5477
5478    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5479        self.highlighted_rows.clone()
5480    }
5481
5482    pub fn highlight_background<T: 'static>(
5483        &mut self,
5484        ranges: Vec<Range<Anchor>>,
5485        color_fetcher: fn(&Theme) -> Color,
5486        cx: &mut ViewContext<Self>,
5487    ) {
5488        self.background_highlights
5489            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5490        cx.notify();
5491    }
5492
5493    pub fn clear_background_highlights<T: 'static>(
5494        &mut self,
5495        cx: &mut ViewContext<Self>,
5496    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5497        cx.notify();
5498        self.background_highlights.remove(&TypeId::of::<T>())
5499    }
5500
5501    #[cfg(feature = "test-support")]
5502    pub fn all_background_highlights(
5503        &mut self,
5504        cx: &mut ViewContext<Self>,
5505    ) -> Vec<(Range<DisplayPoint>, Color)> {
5506        let snapshot = self.snapshot(cx);
5507        let buffer = &snapshot.buffer_snapshot;
5508        let start = buffer.anchor_before(0);
5509        let end = buffer.anchor_after(buffer.len());
5510        let theme = cx.global::<Settings>().theme.as_ref();
5511        self.background_highlights_in_range(start..end, &snapshot, theme)
5512    }
5513
5514    fn document_highlights_for_position<'a>(
5515        &'a self,
5516        position: Anchor,
5517        buffer: &'a MultiBufferSnapshot,
5518    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5519        let read_highlights = self
5520            .background_highlights
5521            .get(&TypeId::of::<DocumentHighlightRead>())
5522            .map(|h| &h.1);
5523        let write_highlights = self
5524            .background_highlights
5525            .get(&TypeId::of::<DocumentHighlightRead>())
5526            .map(|h| &h.1);
5527        let left_position = position.bias_left(buffer);
5528        let right_position = position.bias_right(buffer);
5529        read_highlights
5530            .into_iter()
5531            .chain(write_highlights)
5532            .flat_map(move |ranges| {
5533                let start_ix = match ranges.binary_search_by(|probe| {
5534                    let cmp = probe.end.cmp(&left_position, &buffer);
5535                    if cmp.is_ge() {
5536                        Ordering::Greater
5537                    } else {
5538                        Ordering::Less
5539                    }
5540                }) {
5541                    Ok(i) | Err(i) => i,
5542                };
5543
5544                let right_position = right_position.clone();
5545                ranges[start_ix..]
5546                    .iter()
5547                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
5548            })
5549    }
5550
5551    pub fn background_highlights_in_range(
5552        &self,
5553        search_range: Range<Anchor>,
5554        display_snapshot: &DisplaySnapshot,
5555        theme: &Theme,
5556    ) -> Vec<(Range<DisplayPoint>, Color)> {
5557        let mut results = Vec::new();
5558        let buffer = &display_snapshot.buffer_snapshot;
5559        for (color_fetcher, ranges) in self.background_highlights.values() {
5560            let color = color_fetcher(theme);
5561            let start_ix = match ranges.binary_search_by(|probe| {
5562                let cmp = probe.end.cmp(&search_range.start, &buffer);
5563                if cmp.is_gt() {
5564                    Ordering::Greater
5565                } else {
5566                    Ordering::Less
5567                }
5568            }) {
5569                Ok(i) | Err(i) => i,
5570            };
5571            for range in &ranges[start_ix..] {
5572                if range.start.cmp(&search_range.end, &buffer).is_ge() {
5573                    break;
5574                }
5575                let start = range
5576                    .start
5577                    .to_point(buffer)
5578                    .to_display_point(display_snapshot);
5579                let end = range
5580                    .end
5581                    .to_point(buffer)
5582                    .to_display_point(display_snapshot);
5583                results.push((start..end, color))
5584            }
5585        }
5586        results
5587    }
5588
5589    pub fn highlight_text<T: 'static>(
5590        &mut self,
5591        ranges: Vec<Range<Anchor>>,
5592        style: HighlightStyle,
5593        cx: &mut ViewContext<Self>,
5594    ) {
5595        self.display_map.update(cx, |map, _| {
5596            map.highlight_text(TypeId::of::<T>(), ranges, style)
5597        });
5598        cx.notify();
5599    }
5600
5601    pub fn clear_text_highlights<T: 'static>(
5602        &mut self,
5603        cx: &mut ViewContext<Self>,
5604    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5605        cx.notify();
5606        self.display_map
5607            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
5608    }
5609
5610    fn next_blink_epoch(&mut self) -> usize {
5611        self.blink_epoch += 1;
5612        self.blink_epoch
5613    }
5614
5615    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5616        if !self.focused {
5617            return;
5618        }
5619
5620        self.show_local_cursors = true;
5621        cx.notify();
5622
5623        let epoch = self.next_blink_epoch();
5624        cx.spawn(|this, mut cx| {
5625            let this = this.downgrade();
5626            async move {
5627                Timer::after(CURSOR_BLINK_INTERVAL).await;
5628                if let Some(this) = this.upgrade(&cx) {
5629                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5630                }
5631            }
5632        })
5633        .detach();
5634    }
5635
5636    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5637        if epoch == self.blink_epoch {
5638            self.blinking_paused = false;
5639            self.blink_cursors(epoch, cx);
5640        }
5641    }
5642
5643    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5644        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5645            self.show_local_cursors = !self.show_local_cursors;
5646            cx.notify();
5647
5648            let epoch = self.next_blink_epoch();
5649            cx.spawn(|this, mut cx| {
5650                let this = this.downgrade();
5651                async move {
5652                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5653                    if let Some(this) = this.upgrade(&cx) {
5654                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5655                    }
5656                }
5657            })
5658            .detach();
5659        }
5660    }
5661
5662    pub fn show_local_cursors(&self) -> bool {
5663        self.show_local_cursors && self.focused
5664    }
5665
5666    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5667        cx.notify();
5668    }
5669
5670    fn on_buffer_event(
5671        &mut self,
5672        _: ModelHandle<MultiBuffer>,
5673        event: &language::Event,
5674        cx: &mut ViewContext<Self>,
5675    ) {
5676        match event {
5677            language::Event::Edited => {
5678                self.refresh_active_diagnostics(cx);
5679                self.refresh_code_actions(cx);
5680                cx.emit(Event::BufferEdited);
5681            }
5682            language::Event::Reparsed => cx.emit(Event::Reparsed),
5683            language::Event::Dirtied => cx.emit(Event::Dirtied),
5684            language::Event::Saved => cx.emit(Event::Saved),
5685            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5686            language::Event::Reloaded => cx.emit(Event::TitleChanged),
5687            language::Event::Closed => cx.emit(Event::Closed),
5688            language::Event::DiagnosticsUpdated => {
5689                self.refresh_active_diagnostics(cx);
5690            }
5691            _ => {}
5692        }
5693    }
5694
5695    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5696        cx.notify();
5697    }
5698
5699    pub fn set_searchable(&mut self, searchable: bool) {
5700        self.searchable = searchable;
5701    }
5702
5703    pub fn searchable(&self) -> bool {
5704        self.searchable
5705    }
5706
5707    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
5708        let active_item = workspace.active_item(cx);
5709        let editor_handle = if let Some(editor) = active_item
5710            .as_ref()
5711            .and_then(|item| item.act_as::<Self>(cx))
5712        {
5713            editor
5714        } else {
5715            cx.propagate_action();
5716            return;
5717        };
5718
5719        let editor = editor_handle.read(cx);
5720        let buffer = editor.buffer.read(cx);
5721        if buffer.is_singleton() {
5722            cx.propagate_action();
5723            return;
5724        }
5725
5726        let mut new_selections_by_buffer = HashMap::default();
5727        for selection in editor.selections.all::<usize>(cx) {
5728            for (buffer, mut range) in
5729                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
5730            {
5731                if selection.reversed {
5732                    mem::swap(&mut range.start, &mut range.end);
5733                }
5734                new_selections_by_buffer
5735                    .entry(buffer)
5736                    .or_insert(Vec::new())
5737                    .push(range)
5738            }
5739        }
5740
5741        editor_handle.update(cx, |editor, cx| {
5742            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
5743        });
5744        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
5745        nav_history.borrow_mut().disable();
5746
5747        // We defer the pane interaction because we ourselves are a workspace item
5748        // and activating a new item causes the pane to call a method on us reentrantly,
5749        // which panics if we're on the stack.
5750        cx.defer(move |workspace, cx| {
5751            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
5752                let editor = workspace.open_project_item::<Self>(buffer, cx);
5753                editor.update(cx, |editor, cx| {
5754                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
5755                        s.select_ranges(ranges);
5756                    });
5757                });
5758            }
5759
5760            nav_history.borrow_mut().enable();
5761        });
5762    }
5763}
5764
5765impl EditorSnapshot {
5766    pub fn is_focused(&self) -> bool {
5767        self.is_focused
5768    }
5769
5770    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
5771        self.placeholder_text.as_ref()
5772    }
5773
5774    pub fn scroll_position(&self) -> Vector2F {
5775        compute_scroll_position(
5776            &self.display_snapshot,
5777            self.scroll_position,
5778            &self.scroll_top_anchor,
5779        )
5780    }
5781}
5782
5783impl Deref for EditorSnapshot {
5784    type Target = DisplaySnapshot;
5785
5786    fn deref(&self) -> &Self::Target {
5787        &self.display_snapshot
5788    }
5789}
5790
5791fn compute_scroll_position(
5792    snapshot: &DisplaySnapshot,
5793    mut scroll_position: Vector2F,
5794    scroll_top_anchor: &Anchor,
5795) -> Vector2F {
5796    if *scroll_top_anchor != Anchor::min() {
5797        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
5798        scroll_position.set_y(scroll_top + scroll_position.y());
5799    } else {
5800        scroll_position.set_y(0.);
5801    }
5802    scroll_position
5803}
5804
5805#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5806pub enum Event {
5807    Activate,
5808    BufferEdited,
5809    Edited,
5810    Reparsed,
5811    Blurred,
5812    Dirtied,
5813    Saved,
5814    TitleChanged,
5815    SelectionsChanged { local: bool },
5816    ScrollPositionChanged { local: bool },
5817    Closed,
5818}
5819
5820pub struct EditorFocused(pub ViewHandle<Editor>);
5821pub struct EditorBlurred(pub ViewHandle<Editor>);
5822pub struct EditorReleased(pub WeakViewHandle<Editor>);
5823
5824impl Entity for Editor {
5825    type Event = Event;
5826
5827    fn release(&mut self, cx: &mut MutableAppContext) {
5828        cx.emit_global(EditorReleased(self.handle.clone()));
5829    }
5830}
5831
5832impl View for Editor {
5833    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5834        let style = self.style(cx);
5835        self.display_map.update(cx, |map, cx| {
5836            map.set_font(style.text.font_id, style.text.font_size, cx)
5837        });
5838        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
5839    }
5840
5841    fn ui_name() -> &'static str {
5842        "Editor"
5843    }
5844
5845    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
5846        let focused_event = EditorFocused(cx.handle());
5847        cx.emit_global(focused_event);
5848        if let Some(rename) = self.pending_rename.as_ref() {
5849            cx.focus(&rename.editor);
5850        } else {
5851            self.focused = true;
5852            self.blink_cursors(self.blink_epoch, cx);
5853            self.buffer.update(cx, |buffer, cx| {
5854                buffer.finalize_last_transaction(cx);
5855                if self.leader_replica_id.is_none() {
5856                    buffer.set_active_selections(
5857                        &self.selections.disjoint_anchors(),
5858                        self.selections.line_mode,
5859                        cx,
5860                    );
5861                }
5862            });
5863        }
5864    }
5865
5866    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
5867        let blurred_event = EditorBlurred(cx.handle());
5868        cx.emit_global(blurred_event);
5869        self.focused = false;
5870        self.buffer
5871            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
5872        self.hide_context_menu(cx);
5873        cx.emit(Event::Blurred);
5874        cx.notify();
5875    }
5876
5877    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
5878        let mut context = Self::default_keymap_context();
5879        let mode = match self.mode {
5880            EditorMode::SingleLine => "single_line",
5881            EditorMode::AutoHeight { .. } => "auto_height",
5882            EditorMode::Full => "full",
5883        };
5884        context.map.insert("mode".into(), mode.into());
5885        if self.pending_rename.is_some() {
5886            context.set.insert("renaming".into());
5887        }
5888        match self.context_menu.as_ref() {
5889            Some(ContextMenu::Completions(_)) => {
5890                context.set.insert("showing_completions".into());
5891            }
5892            Some(ContextMenu::CodeActions(_)) => {
5893                context.set.insert("showing_code_actions".into());
5894            }
5895            None => {}
5896        }
5897
5898        for layer in self.keymap_context_layers.values() {
5899            context.extend(layer);
5900        }
5901
5902        context
5903    }
5904}
5905
5906fn build_style(
5907    settings: &Settings,
5908    get_field_editor_theme: Option<GetFieldEditorTheme>,
5909    override_text_style: Option<&OverrideTextStyle>,
5910    cx: &AppContext,
5911) -> EditorStyle {
5912    let font_cache = cx.font_cache();
5913
5914    let mut theme = settings.theme.editor.clone();
5915    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
5916        let field_editor_theme = get_field_editor_theme(&settings.theme);
5917        theme.text_color = field_editor_theme.text.color;
5918        theme.selection = field_editor_theme.selection;
5919        theme.background = field_editor_theme
5920            .container
5921            .background_color
5922            .unwrap_or_default();
5923        EditorStyle {
5924            text: field_editor_theme.text,
5925            placeholder_text: field_editor_theme.placeholder_text,
5926            theme,
5927        }
5928    } else {
5929        let font_family_id = settings.buffer_font_family;
5930        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
5931        let font_properties = Default::default();
5932        let font_id = font_cache
5933            .select_font(font_family_id, &font_properties)
5934            .unwrap();
5935        let font_size = settings.buffer_font_size;
5936        EditorStyle {
5937            text: TextStyle {
5938                color: settings.theme.editor.text_color,
5939                font_family_name,
5940                font_family_id,
5941                font_id,
5942                font_size,
5943                font_properties,
5944                underline: Default::default(),
5945            },
5946            placeholder_text: None,
5947            theme,
5948        }
5949    };
5950
5951    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
5952        if let Some(highlighted) = style
5953            .text
5954            .clone()
5955            .highlight(highlight_style, font_cache)
5956            .log_err()
5957        {
5958            style.text = highlighted;
5959        }
5960    }
5961
5962    style
5963}
5964
5965trait SelectionExt {
5966    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
5967    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
5968    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
5969    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
5970        -> Range<u32>;
5971}
5972
5973impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
5974    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
5975        let start = self.start.to_point(buffer);
5976        let end = self.end.to_point(buffer);
5977        if self.reversed {
5978            end..start
5979        } else {
5980            start..end
5981        }
5982    }
5983
5984    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
5985        let start = self.start.to_offset(buffer);
5986        let end = self.end.to_offset(buffer);
5987        if self.reversed {
5988            end..start
5989        } else {
5990            start..end
5991        }
5992    }
5993
5994    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
5995        let start = self
5996            .start
5997            .to_point(&map.buffer_snapshot)
5998            .to_display_point(map);
5999        let end = self
6000            .end
6001            .to_point(&map.buffer_snapshot)
6002            .to_display_point(map);
6003        if self.reversed {
6004            end..start
6005        } else {
6006            start..end
6007        }
6008    }
6009
6010    fn spanned_rows(
6011        &self,
6012        include_end_if_at_line_start: bool,
6013        map: &DisplaySnapshot,
6014    ) -> Range<u32> {
6015        let start = self.start.to_point(&map.buffer_snapshot);
6016        let mut end = self.end.to_point(&map.buffer_snapshot);
6017        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6018            end.row -= 1;
6019        }
6020
6021        let buffer_start = map.prev_line_boundary(start).0;
6022        let buffer_end = map.next_line_boundary(end).0;
6023        buffer_start.row..buffer_end.row + 1
6024    }
6025}
6026
6027impl<T: InvalidationRegion> InvalidationStack<T> {
6028    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6029    where
6030        S: Clone + ToOffset,
6031    {
6032        while let Some(region) = self.last() {
6033            let all_selections_inside_invalidation_ranges =
6034                if selections.len() == region.ranges().len() {
6035                    selections
6036                        .iter()
6037                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
6038                        .all(|(selection, invalidation_range)| {
6039                            let head = selection.head().to_offset(&buffer);
6040                            invalidation_range.start <= head && invalidation_range.end >= head
6041                        })
6042                } else {
6043                    false
6044                };
6045
6046            if all_selections_inside_invalidation_ranges {
6047                break;
6048            } else {
6049                self.pop();
6050            }
6051        }
6052    }
6053}
6054
6055impl<T> Default for InvalidationStack<T> {
6056    fn default() -> Self {
6057        Self(Default::default())
6058    }
6059}
6060
6061impl<T> Deref for InvalidationStack<T> {
6062    type Target = Vec<T>;
6063
6064    fn deref(&self) -> &Self::Target {
6065        &self.0
6066    }
6067}
6068
6069impl<T> DerefMut for InvalidationStack<T> {
6070    fn deref_mut(&mut self) -> &mut Self::Target {
6071        &mut self.0
6072    }
6073}
6074
6075impl InvalidationRegion for BracketPairState {
6076    fn ranges(&self) -> &[Range<Anchor>] {
6077        &self.ranges
6078    }
6079}
6080
6081impl InvalidationRegion for SnippetState {
6082    fn ranges(&self) -> &[Range<Anchor>] {
6083        &self.ranges[self.active_index]
6084    }
6085}
6086
6087impl Deref for EditorStyle {
6088    type Target = theme::Editor;
6089
6090    fn deref(&self) -> &Self::Target {
6091        &self.theme
6092    }
6093}
6094
6095pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6096    let mut highlighted_lines = Vec::new();
6097    for line in diagnostic.message.lines() {
6098        highlighted_lines.push(highlight_diagnostic_message(line));
6099    }
6100
6101    Arc::new(move |cx: &mut BlockContext| {
6102        let settings = cx.global::<Settings>();
6103        let theme = &settings.theme.editor;
6104        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6105        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6106        Flex::column()
6107            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6108                Label::new(
6109                    line.clone(),
6110                    style.message.clone().with_font_size(font_size),
6111                )
6112                .with_highlights(highlights.clone())
6113                .contained()
6114                .with_margin_left(cx.anchor_x)
6115                .boxed()
6116            }))
6117            .aligned()
6118            .left()
6119            .boxed()
6120    })
6121}
6122
6123pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6124    let mut message_without_backticks = String::new();
6125    let mut prev_offset = 0;
6126    let mut inside_block = false;
6127    let mut highlights = Vec::new();
6128    for (match_ix, (offset, _)) in message
6129        .match_indices('`')
6130        .chain([(message.len(), "")])
6131        .enumerate()
6132    {
6133        message_without_backticks.push_str(&message[prev_offset..offset]);
6134        if inside_block {
6135            highlights.extend(prev_offset - match_ix..offset - match_ix);
6136        }
6137
6138        inside_block = !inside_block;
6139        prev_offset = offset + 1;
6140    }
6141
6142    (message_without_backticks, highlights)
6143}
6144
6145pub fn diagnostic_style(
6146    severity: DiagnosticSeverity,
6147    valid: bool,
6148    theme: &theme::Editor,
6149) -> DiagnosticStyle {
6150    match (severity, valid) {
6151        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6152        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6153        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6154        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6155        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6156        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6157        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6158        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6159        _ => theme.invalid_hint_diagnostic.clone(),
6160    }
6161}
6162
6163pub fn combine_syntax_and_fuzzy_match_highlights(
6164    text: &str,
6165    default_style: HighlightStyle,
6166    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6167    match_indices: &[usize],
6168) -> Vec<(Range<usize>, HighlightStyle)> {
6169    let mut result = Vec::new();
6170    let mut match_indices = match_indices.iter().copied().peekable();
6171
6172    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6173    {
6174        syntax_highlight.weight = None;
6175
6176        // Add highlights for any fuzzy match characters before the next
6177        // syntax highlight range.
6178        while let Some(&match_index) = match_indices.peek() {
6179            if match_index >= range.start {
6180                break;
6181            }
6182            match_indices.next();
6183            let end_index = char_ix_after(match_index, text);
6184            let mut match_style = default_style;
6185            match_style.weight = Some(fonts::Weight::BOLD);
6186            result.push((match_index..end_index, match_style));
6187        }
6188
6189        if range.start == usize::MAX {
6190            break;
6191        }
6192
6193        // Add highlights for any fuzzy match characters within the
6194        // syntax highlight range.
6195        let mut offset = range.start;
6196        while let Some(&match_index) = match_indices.peek() {
6197            if match_index >= range.end {
6198                break;
6199            }
6200
6201            match_indices.next();
6202            if match_index > offset {
6203                result.push((offset..match_index, syntax_highlight));
6204            }
6205
6206            let mut end_index = char_ix_after(match_index, text);
6207            while let Some(&next_match_index) = match_indices.peek() {
6208                if next_match_index == end_index && next_match_index < range.end {
6209                    end_index = char_ix_after(next_match_index, text);
6210                    match_indices.next();
6211                } else {
6212                    break;
6213                }
6214            }
6215
6216            let mut match_style = syntax_highlight;
6217            match_style.weight = Some(fonts::Weight::BOLD);
6218            result.push((match_index..end_index, match_style));
6219            offset = end_index;
6220        }
6221
6222        if offset < range.end {
6223            result.push((offset..range.end, syntax_highlight));
6224        }
6225    }
6226
6227    fn char_ix_after(ix: usize, text: &str) -> usize {
6228        ix + text[ix..].chars().next().unwrap().len_utf8()
6229    }
6230
6231    result
6232}
6233
6234pub fn styled_runs_for_code_label<'a>(
6235    label: &'a CodeLabel,
6236    syntax_theme: &'a theme::SyntaxTheme,
6237) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6238    let fade_out = HighlightStyle {
6239        fade_out: Some(0.35),
6240        ..Default::default()
6241    };
6242
6243    let mut prev_end = label.filter_range.end;
6244    label
6245        .runs
6246        .iter()
6247        .enumerate()
6248        .flat_map(move |(ix, (range, highlight_id))| {
6249            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6250                style
6251            } else {
6252                return Default::default();
6253            };
6254            let mut muted_style = style.clone();
6255            muted_style.highlight(fade_out);
6256
6257            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6258            if range.start >= label.filter_range.end {
6259                if range.start > prev_end {
6260                    runs.push((prev_end..range.start, fade_out));
6261                }
6262                runs.push((range.clone(), muted_style));
6263            } else if range.end <= label.filter_range.end {
6264                runs.push((range.clone(), style));
6265            } else {
6266                runs.push((range.start..label.filter_range.end, style));
6267                runs.push((label.filter_range.end..range.end, muted_style));
6268            }
6269            prev_end = cmp::max(prev_end, range.end);
6270
6271            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6272                runs.push((prev_end..label.text.len(), fade_out));
6273            }
6274
6275            runs
6276        })
6277}
6278
6279#[cfg(test)]
6280mod tests {
6281    use crate::test::{
6282        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
6283    };
6284
6285    use super::*;
6286    use gpui::{
6287        geometry::rect::RectF,
6288        platform::{WindowBounds, WindowOptions},
6289    };
6290    use indoc::indoc;
6291    use language::{FakeLspAdapter, LanguageConfig};
6292    use lsp::FakeLanguageServer;
6293    use project::FakeFs;
6294    use settings::LanguageOverride;
6295    use smol::stream::StreamExt;
6296    use std::{cell::RefCell, rc::Rc, time::Instant};
6297    use text::Point;
6298    use unindent::Unindent;
6299    use util::{
6300        assert_set_eq,
6301        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
6302    };
6303    use workspace::{FollowableItem, ItemHandle};
6304
6305    #[gpui::test]
6306    fn test_edit_events(cx: &mut MutableAppContext) {
6307        cx.set_global(Settings::test(cx));
6308        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6309
6310        let events = Rc::new(RefCell::new(Vec::new()));
6311        let (_, editor1) = cx.add_window(Default::default(), {
6312            let events = events.clone();
6313            |cx| {
6314                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6315                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6316                        events.borrow_mut().push(("editor1", *event));
6317                    }
6318                })
6319                .detach();
6320                Editor::for_buffer(buffer.clone(), None, cx)
6321            }
6322        });
6323        let (_, editor2) = cx.add_window(Default::default(), {
6324            let events = events.clone();
6325            |cx| {
6326                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6327                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6328                        events.borrow_mut().push(("editor2", *event));
6329                    }
6330                })
6331                .detach();
6332                Editor::for_buffer(buffer.clone(), None, cx)
6333            }
6334        });
6335        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6336
6337        // Mutating editor 1 will emit an `Edited` event only for that editor.
6338        editor1.update(cx, |editor, cx| editor.insert("X", cx));
6339        assert_eq!(
6340            mem::take(&mut *events.borrow_mut()),
6341            [
6342                ("editor1", Event::Edited),
6343                ("editor1", Event::BufferEdited),
6344                ("editor2", Event::BufferEdited),
6345                ("editor1", Event::Dirtied),
6346                ("editor2", Event::Dirtied)
6347            ]
6348        );
6349
6350        // Mutating editor 2 will emit an `Edited` event only for that editor.
6351        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
6352        assert_eq!(
6353            mem::take(&mut *events.borrow_mut()),
6354            [
6355                ("editor2", Event::Edited),
6356                ("editor1", Event::BufferEdited),
6357                ("editor2", Event::BufferEdited),
6358            ]
6359        );
6360
6361        // Undoing on editor 1 will emit an `Edited` event only for that editor.
6362        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
6363        assert_eq!(
6364            mem::take(&mut *events.borrow_mut()),
6365            [
6366                ("editor1", Event::Edited),
6367                ("editor1", Event::BufferEdited),
6368                ("editor2", Event::BufferEdited),
6369            ]
6370        );
6371
6372        // Redoing on editor 1 will emit an `Edited` event only for that editor.
6373        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
6374        assert_eq!(
6375            mem::take(&mut *events.borrow_mut()),
6376            [
6377                ("editor1", Event::Edited),
6378                ("editor1", Event::BufferEdited),
6379                ("editor2", Event::BufferEdited),
6380            ]
6381        );
6382
6383        // Undoing on editor 2 will emit an `Edited` event only for that editor.
6384        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
6385        assert_eq!(
6386            mem::take(&mut *events.borrow_mut()),
6387            [
6388                ("editor2", Event::Edited),
6389                ("editor1", Event::BufferEdited),
6390                ("editor2", Event::BufferEdited),
6391            ]
6392        );
6393
6394        // Redoing on editor 2 will emit an `Edited` event only for that editor.
6395        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
6396        assert_eq!(
6397            mem::take(&mut *events.borrow_mut()),
6398            [
6399                ("editor2", Event::Edited),
6400                ("editor1", Event::BufferEdited),
6401                ("editor2", Event::BufferEdited),
6402            ]
6403        );
6404
6405        // No event is emitted when the mutation is a no-op.
6406        editor2.update(cx, |editor, cx| {
6407            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
6408
6409            editor.backspace(&Backspace, cx);
6410        });
6411        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6412    }
6413
6414    #[gpui::test]
6415    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
6416        cx.set_global(Settings::test(cx));
6417        let mut now = Instant::now();
6418        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6419        let group_interval = buffer.read(cx).transaction_group_interval();
6420        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
6421        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6422
6423        editor.update(cx, |editor, cx| {
6424            editor.start_transaction_at(now, cx);
6425            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
6426
6427            editor.insert("cd", cx);
6428            editor.end_transaction_at(now, cx);
6429            assert_eq!(editor.text(cx), "12cd56");
6430            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
6431
6432            editor.start_transaction_at(now, cx);
6433            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
6434            editor.insert("e", cx);
6435            editor.end_transaction_at(now, cx);
6436            assert_eq!(editor.text(cx), "12cde6");
6437            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
6438
6439            now += group_interval + Duration::from_millis(1);
6440            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
6441
6442            // Simulate an edit in another editor
6443            buffer.update(cx, |buffer, cx| {
6444                buffer.start_transaction_at(now, cx);
6445                buffer.edit([(0..1, "a")], cx);
6446                buffer.edit([(1..1, "b")], cx);
6447                buffer.end_transaction_at(now, cx);
6448            });
6449
6450            assert_eq!(editor.text(cx), "ab2cde6");
6451            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
6452
6453            // Last transaction happened past the group interval in a different editor.
6454            // Undo it individually and don't restore selections.
6455            editor.undo(&Undo, cx);
6456            assert_eq!(editor.text(cx), "12cde6");
6457            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
6458
6459            // First two transactions happened within the group interval in this editor.
6460            // Undo them together and restore selections.
6461            editor.undo(&Undo, cx);
6462            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
6463            assert_eq!(editor.text(cx), "123456");
6464            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
6465
6466            // Redo the first two transactions together.
6467            editor.redo(&Redo, cx);
6468            assert_eq!(editor.text(cx), "12cde6");
6469            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
6470
6471            // Redo the last transaction on its own.
6472            editor.redo(&Redo, cx);
6473            assert_eq!(editor.text(cx), "ab2cde6");
6474            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
6475
6476            // Test empty transactions.
6477            editor.start_transaction_at(now, cx);
6478            editor.end_transaction_at(now, cx);
6479            editor.undo(&Undo, cx);
6480            assert_eq!(editor.text(cx), "12cde6");
6481        });
6482    }
6483
6484    #[gpui::test]
6485    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
6486        cx.set_global(Settings::test(cx));
6487
6488        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
6489        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6490        editor.update(cx, |view, cx| {
6491            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6492        });
6493        assert_eq!(
6494            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6495            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6496        );
6497
6498        editor.update(cx, |view, cx| {
6499            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6500        });
6501
6502        assert_eq!(
6503            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6504            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6505        );
6506
6507        editor.update(cx, |view, cx| {
6508            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6509        });
6510
6511        assert_eq!(
6512            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6513            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6514        );
6515
6516        editor.update(cx, |view, cx| {
6517            view.end_selection(cx);
6518            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6519        });
6520
6521        assert_eq!(
6522            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6523            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6524        );
6525
6526        editor.update(cx, |view, cx| {
6527            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
6528            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
6529        });
6530
6531        assert_eq!(
6532            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6533            [
6534                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
6535                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
6536            ]
6537        );
6538
6539        editor.update(cx, |view, cx| {
6540            view.end_selection(cx);
6541        });
6542
6543        assert_eq!(
6544            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6545            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
6546        );
6547    }
6548
6549    #[gpui::test]
6550    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
6551        cx.set_global(Settings::test(cx));
6552        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6553        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6554
6555        view.update(cx, |view, cx| {
6556            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6557            assert_eq!(
6558                view.selections.display_ranges(cx),
6559                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6560            );
6561        });
6562
6563        view.update(cx, |view, cx| {
6564            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6565            assert_eq!(
6566                view.selections.display_ranges(cx),
6567                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6568            );
6569        });
6570
6571        view.update(cx, |view, cx| {
6572            view.cancel(&Cancel, cx);
6573            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6574            assert_eq!(
6575                view.selections.display_ranges(cx),
6576                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6577            );
6578        });
6579    }
6580
6581    #[gpui::test]
6582    fn test_clone_with_selections(cx: &mut gpui::MutableAppContext) {
6583        let (text, selection_ranges) = marked_text_ranges(indoc! {"
6584            The qu[ick brown
6585            fox jum]ps over
6586            the lazy dog
6587        "});
6588        cx.set_global(Settings::test(cx));
6589        let buffer = MultiBuffer::build_simple(&text, cx);
6590
6591        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6592
6593        let cloned_editor = view.update(cx, |view, cx| {
6594            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
6595            view.clone(cx)
6596        });
6597
6598        assert_set_eq!(cloned_editor.selections.ranges(cx), selection_ranges);
6599    }
6600
6601    #[gpui::test]
6602    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
6603        cx.set_global(Settings::test(cx));
6604        use workspace::Item;
6605        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
6606        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
6607
6608        cx.add_window(Default::default(), |cx| {
6609            let mut editor = build_editor(buffer.clone(), cx);
6610            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
6611
6612            // Move the cursor a small distance.
6613            // Nothing is added to the navigation history.
6614            editor.change_selections(None, cx, |s| {
6615                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
6616            });
6617            editor.change_selections(None, cx, |s| {
6618                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
6619            });
6620            assert!(nav_history.borrow_mut().pop_backward().is_none());
6621
6622            // Move the cursor a large distance.
6623            // The history can jump back to the previous position.
6624            editor.change_selections(None, cx, |s| {
6625                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
6626            });
6627            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6628            editor.navigate(nav_entry.data.unwrap(), cx);
6629            assert_eq!(nav_entry.item.id(), cx.view_id());
6630            assert_eq!(
6631                editor.selections.display_ranges(cx),
6632                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
6633            );
6634            assert!(nav_history.borrow_mut().pop_backward().is_none());
6635
6636            // Move the cursor a small distance via the mouse.
6637            // Nothing is added to the navigation history.
6638            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
6639            editor.end_selection(cx);
6640            assert_eq!(
6641                editor.selections.display_ranges(cx),
6642                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6643            );
6644            assert!(nav_history.borrow_mut().pop_backward().is_none());
6645
6646            // Move the cursor a large distance via the mouse.
6647            // The history can jump back to the previous position.
6648            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
6649            editor.end_selection(cx);
6650            assert_eq!(
6651                editor.selections.display_ranges(cx),
6652                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
6653            );
6654            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6655            editor.navigate(nav_entry.data.unwrap(), cx);
6656            assert_eq!(nav_entry.item.id(), cx.view_id());
6657            assert_eq!(
6658                editor.selections.display_ranges(cx),
6659                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6660            );
6661            assert!(nav_history.borrow_mut().pop_backward().is_none());
6662
6663            // Set scroll position to check later
6664            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
6665            let original_scroll_position = editor.scroll_position;
6666            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
6667
6668            // Jump to the end of the document and adjust scroll
6669            editor.move_to_end(&MoveToEnd, cx);
6670            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
6671            assert_ne!(editor.scroll_position, original_scroll_position);
6672            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
6673
6674            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6675            editor.navigate(nav_entry.data.unwrap(), cx);
6676            assert_eq!(editor.scroll_position, original_scroll_position);
6677            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
6678
6679            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
6680            let mut invalid_anchor = editor.scroll_top_anchor.clone();
6681            invalid_anchor.text_anchor.buffer_id = Some(999);
6682            let invalid_point = Point::new(9999, 0);
6683            editor.navigate(
6684                Box::new(NavigationData {
6685                    cursor_anchor: invalid_anchor.clone(),
6686                    cursor_position: invalid_point,
6687                    scroll_top_anchor: invalid_anchor.clone(),
6688                    scroll_top_row: invalid_point.row,
6689                    scroll_position: Default::default(),
6690                }),
6691                cx,
6692            );
6693            assert_eq!(
6694                editor.selections.display_ranges(cx),
6695                &[editor.max_point(cx)..editor.max_point(cx)]
6696            );
6697            assert_eq!(
6698                editor.scroll_position(cx),
6699                vec2f(0., editor.max_point(cx).row() as f32)
6700            );
6701
6702            editor
6703        });
6704    }
6705
6706    #[gpui::test]
6707    fn test_cancel(cx: &mut gpui::MutableAppContext) {
6708        cx.set_global(Settings::test(cx));
6709        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6710        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6711
6712        view.update(cx, |view, cx| {
6713            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
6714            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6715            view.end_selection(cx);
6716
6717            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
6718            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
6719            view.end_selection(cx);
6720            assert_eq!(
6721                view.selections.display_ranges(cx),
6722                [
6723                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
6724                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
6725                ]
6726            );
6727        });
6728
6729        view.update(cx, |view, cx| {
6730            view.cancel(&Cancel, cx);
6731            assert_eq!(
6732                view.selections.display_ranges(cx),
6733                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
6734            );
6735        });
6736
6737        view.update(cx, |view, cx| {
6738            view.cancel(&Cancel, cx);
6739            assert_eq!(
6740                view.selections.display_ranges(cx),
6741                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
6742            );
6743        });
6744    }
6745
6746    #[gpui::test]
6747    fn test_fold(cx: &mut gpui::MutableAppContext) {
6748        cx.set_global(Settings::test(cx));
6749        let buffer = MultiBuffer::build_simple(
6750            &"
6751                impl Foo {
6752                    // Hello!
6753
6754                    fn a() {
6755                        1
6756                    }
6757
6758                    fn b() {
6759                        2
6760                    }
6761
6762                    fn c() {
6763                        3
6764                    }
6765                }
6766            "
6767            .unindent(),
6768            cx,
6769        );
6770        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6771
6772        view.update(cx, |view, cx| {
6773            view.change_selections(None, cx, |s| {
6774                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
6775            });
6776            view.fold(&Fold, cx);
6777            assert_eq!(
6778                view.display_text(cx),
6779                "
6780                    impl Foo {
6781                        // Hello!
6782
6783                        fn a() {
6784                            1
6785                        }
6786
6787                        fn b() {…
6788                        }
6789
6790                        fn c() {…
6791                        }
6792                    }
6793                "
6794                .unindent(),
6795            );
6796
6797            view.fold(&Fold, cx);
6798            assert_eq!(
6799                view.display_text(cx),
6800                "
6801                    impl Foo {…
6802                    }
6803                "
6804                .unindent(),
6805            );
6806
6807            view.unfold_lines(&UnfoldLines, cx);
6808            assert_eq!(
6809                view.display_text(cx),
6810                "
6811                    impl Foo {
6812                        // Hello!
6813
6814                        fn a() {
6815                            1
6816                        }
6817
6818                        fn b() {…
6819                        }
6820
6821                        fn c() {…
6822                        }
6823                    }
6824                "
6825                .unindent(),
6826            );
6827
6828            view.unfold_lines(&UnfoldLines, cx);
6829            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
6830        });
6831    }
6832
6833    #[gpui::test]
6834    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
6835        cx.set_global(Settings::test(cx));
6836        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
6837        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6838
6839        buffer.update(cx, |buffer, cx| {
6840            buffer.edit(
6841                vec![
6842                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
6843                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
6844                ],
6845                cx,
6846            );
6847        });
6848
6849        view.update(cx, |view, cx| {
6850            assert_eq!(
6851                view.selections.display_ranges(cx),
6852                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6853            );
6854
6855            view.move_down(&MoveDown, cx);
6856            assert_eq!(
6857                view.selections.display_ranges(cx),
6858                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6859            );
6860
6861            view.move_right(&MoveRight, cx);
6862            assert_eq!(
6863                view.selections.display_ranges(cx),
6864                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
6865            );
6866
6867            view.move_left(&MoveLeft, cx);
6868            assert_eq!(
6869                view.selections.display_ranges(cx),
6870                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6871            );
6872
6873            view.move_up(&MoveUp, cx);
6874            assert_eq!(
6875                view.selections.display_ranges(cx),
6876                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6877            );
6878
6879            view.move_to_end(&MoveToEnd, cx);
6880            assert_eq!(
6881                view.selections.display_ranges(cx),
6882                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
6883            );
6884
6885            view.move_to_beginning(&MoveToBeginning, cx);
6886            assert_eq!(
6887                view.selections.display_ranges(cx),
6888                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6889            );
6890
6891            view.change_selections(None, cx, |s| {
6892                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
6893            });
6894            view.select_to_beginning(&SelectToBeginning, cx);
6895            assert_eq!(
6896                view.selections.display_ranges(cx),
6897                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
6898            );
6899
6900            view.select_to_end(&SelectToEnd, cx);
6901            assert_eq!(
6902                view.selections.display_ranges(cx),
6903                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
6904            );
6905        });
6906    }
6907
6908    #[gpui::test]
6909    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
6910        cx.set_global(Settings::test(cx));
6911        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
6912        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6913
6914        assert_eq!('ⓐ'.len_utf8(), 3);
6915        assert_eq!('α'.len_utf8(), 2);
6916
6917        view.update(cx, |view, cx| {
6918            view.fold_ranges(
6919                vec![
6920                    Point::new(0, 6)..Point::new(0, 12),
6921                    Point::new(1, 2)..Point::new(1, 4),
6922                    Point::new(2, 4)..Point::new(2, 8),
6923                ],
6924                cx,
6925            );
6926            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
6927
6928            view.move_right(&MoveRight, cx);
6929            assert_eq!(
6930                view.selections.display_ranges(cx),
6931                &[empty_range(0, "".len())]
6932            );
6933            view.move_right(&MoveRight, cx);
6934            assert_eq!(
6935                view.selections.display_ranges(cx),
6936                &[empty_range(0, "ⓐⓑ".len())]
6937            );
6938            view.move_right(&MoveRight, cx);
6939            assert_eq!(
6940                view.selections.display_ranges(cx),
6941                &[empty_range(0, "ⓐⓑ…".len())]
6942            );
6943
6944            view.move_down(&MoveDown, cx);
6945            assert_eq!(
6946                view.selections.display_ranges(cx),
6947                &[empty_range(1, "ab…".len())]
6948            );
6949            view.move_left(&MoveLeft, cx);
6950            assert_eq!(
6951                view.selections.display_ranges(cx),
6952                &[empty_range(1, "ab".len())]
6953            );
6954            view.move_left(&MoveLeft, cx);
6955            assert_eq!(
6956                view.selections.display_ranges(cx),
6957                &[empty_range(1, "a".len())]
6958            );
6959
6960            view.move_down(&MoveDown, cx);
6961            assert_eq!(
6962                view.selections.display_ranges(cx),
6963                &[empty_range(2, "α".len())]
6964            );
6965            view.move_right(&MoveRight, cx);
6966            assert_eq!(
6967                view.selections.display_ranges(cx),
6968                &[empty_range(2, "αβ".len())]
6969            );
6970            view.move_right(&MoveRight, cx);
6971            assert_eq!(
6972                view.selections.display_ranges(cx),
6973                &[empty_range(2, "αβ…".len())]
6974            );
6975            view.move_right(&MoveRight, cx);
6976            assert_eq!(
6977                view.selections.display_ranges(cx),
6978                &[empty_range(2, "αβ…ε".len())]
6979            );
6980
6981            view.move_up(&MoveUp, cx);
6982            assert_eq!(
6983                view.selections.display_ranges(cx),
6984                &[empty_range(1, "ab…e".len())]
6985            );
6986            view.move_up(&MoveUp, cx);
6987            assert_eq!(
6988                view.selections.display_ranges(cx),
6989                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
6990            );
6991            view.move_left(&MoveLeft, cx);
6992            assert_eq!(
6993                view.selections.display_ranges(cx),
6994                &[empty_range(0, "ⓐⓑ…".len())]
6995            );
6996            view.move_left(&MoveLeft, cx);
6997            assert_eq!(
6998                view.selections.display_ranges(cx),
6999                &[empty_range(0, "ⓐⓑ".len())]
7000            );
7001            view.move_left(&MoveLeft, cx);
7002            assert_eq!(
7003                view.selections.display_ranges(cx),
7004                &[empty_range(0, "".len())]
7005            );
7006        });
7007    }
7008
7009    #[gpui::test]
7010    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
7011        cx.set_global(Settings::test(cx));
7012        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
7013        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7014        view.update(cx, |view, cx| {
7015            view.change_selections(None, cx, |s| {
7016                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
7017            });
7018            view.move_down(&MoveDown, cx);
7019            assert_eq!(
7020                view.selections.display_ranges(cx),
7021                &[empty_range(1, "abcd".len())]
7022            );
7023
7024            view.move_down(&MoveDown, cx);
7025            assert_eq!(
7026                view.selections.display_ranges(cx),
7027                &[empty_range(2, "αβγ".len())]
7028            );
7029
7030            view.move_down(&MoveDown, cx);
7031            assert_eq!(
7032                view.selections.display_ranges(cx),
7033                &[empty_range(3, "abcd".len())]
7034            );
7035
7036            view.move_down(&MoveDown, cx);
7037            assert_eq!(
7038                view.selections.display_ranges(cx),
7039                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
7040            );
7041
7042            view.move_up(&MoveUp, cx);
7043            assert_eq!(
7044                view.selections.display_ranges(cx),
7045                &[empty_range(3, "abcd".len())]
7046            );
7047
7048            view.move_up(&MoveUp, cx);
7049            assert_eq!(
7050                view.selections.display_ranges(cx),
7051                &[empty_range(2, "αβγ".len())]
7052            );
7053        });
7054    }
7055
7056    #[gpui::test]
7057    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
7058        cx.set_global(Settings::test(cx));
7059        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
7060        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7061        view.update(cx, |view, cx| {
7062            view.change_selections(None, cx, |s| {
7063                s.select_display_ranges([
7064                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7065                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
7066                ]);
7067            });
7068        });
7069
7070        view.update(cx, |view, cx| {
7071            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7072            assert_eq!(
7073                view.selections.display_ranges(cx),
7074                &[
7075                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7076                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7077                ]
7078            );
7079        });
7080
7081        view.update(cx, |view, cx| {
7082            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7083            assert_eq!(
7084                view.selections.display_ranges(cx),
7085                &[
7086                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7087                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7088                ]
7089            );
7090        });
7091
7092        view.update(cx, |view, cx| {
7093            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
7094            assert_eq!(
7095                view.selections.display_ranges(cx),
7096                &[
7097                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7098                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7099                ]
7100            );
7101        });
7102
7103        view.update(cx, |view, cx| {
7104            view.move_to_end_of_line(&MoveToEndOfLine, cx);
7105            assert_eq!(
7106                view.selections.display_ranges(cx),
7107                &[
7108                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7109                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
7110                ]
7111            );
7112        });
7113
7114        // Moving to the end of line again is a no-op.
7115        view.update(cx, |view, cx| {
7116            view.move_to_end_of_line(&MoveToEndOfLine, cx);
7117            assert_eq!(
7118                view.selections.display_ranges(cx),
7119                &[
7120                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7121                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
7122                ]
7123            );
7124        });
7125
7126        view.update(cx, |view, cx| {
7127            view.move_left(&MoveLeft, cx);
7128            view.select_to_beginning_of_line(
7129                &SelectToBeginningOfLine {
7130                    stop_at_soft_wraps: true,
7131                },
7132                cx,
7133            );
7134            assert_eq!(
7135                view.selections.display_ranges(cx),
7136                &[
7137                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7138                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7139                ]
7140            );
7141        });
7142
7143        view.update(cx, |view, cx| {
7144            view.select_to_beginning_of_line(
7145                &SelectToBeginningOfLine {
7146                    stop_at_soft_wraps: true,
7147                },
7148                cx,
7149            );
7150            assert_eq!(
7151                view.selections.display_ranges(cx),
7152                &[
7153                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7154                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
7155                ]
7156            );
7157        });
7158
7159        view.update(cx, |view, cx| {
7160            view.select_to_beginning_of_line(
7161                &SelectToBeginningOfLine {
7162                    stop_at_soft_wraps: true,
7163                },
7164                cx,
7165            );
7166            assert_eq!(
7167                view.selections.display_ranges(cx),
7168                &[
7169                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7170                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7171                ]
7172            );
7173        });
7174
7175        view.update(cx, |view, cx| {
7176            view.select_to_end_of_line(
7177                &SelectToEndOfLine {
7178                    stop_at_soft_wraps: true,
7179                },
7180                cx,
7181            );
7182            assert_eq!(
7183                view.selections.display_ranges(cx),
7184                &[
7185                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
7186                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
7187                ]
7188            );
7189        });
7190
7191        view.update(cx, |view, cx| {
7192            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
7193            assert_eq!(view.display_text(cx), "ab\n  de");
7194            assert_eq!(
7195                view.selections.display_ranges(cx),
7196                &[
7197                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7198                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
7199                ]
7200            );
7201        });
7202
7203        view.update(cx, |view, cx| {
7204            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
7205            assert_eq!(view.display_text(cx), "\n");
7206            assert_eq!(
7207                view.selections.display_ranges(cx),
7208                &[
7209                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7210                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7211                ]
7212            );
7213        });
7214    }
7215
7216    #[gpui::test]
7217    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
7218        cx.set_global(Settings::test(cx));
7219        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
7220        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7221        view.update(cx, |view, cx| {
7222            view.change_selections(None, cx, |s| {
7223                s.select_display_ranges([
7224                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
7225                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
7226                ])
7227            });
7228
7229            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7230            assert_selection_ranges(
7231                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7232                vec![('<', '>'), ('[', ']')],
7233                view,
7234                cx,
7235            );
7236
7237            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7238            assert_selection_ranges(
7239                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
7240                vec![('<', '>'), ('[', ']')],
7241                view,
7242                cx,
7243            );
7244
7245            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7246            assert_selection_ranges(
7247                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
7248                vec![('<', '>'), ('[', ']')],
7249                view,
7250                cx,
7251            );
7252
7253            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7254            assert_selection_ranges(
7255                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
7256                vec![('<', '>'), ('[', ']')],
7257                view,
7258                cx,
7259            );
7260
7261            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7262            assert_selection_ranges(
7263                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
7264                vec![('<', '>'), ('[', ']')],
7265                view,
7266                cx,
7267            );
7268
7269            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7270            assert_selection_ranges(
7271                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
7272                vec![('<', '>'), ('[', ']')],
7273                view,
7274                cx,
7275            );
7276
7277            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7278            assert_selection_ranges(
7279                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
7280                vec![('<', '>'), ('[', ']')],
7281                view,
7282                cx,
7283            );
7284
7285            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7286            assert_selection_ranges(
7287                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7288                vec![('<', '>'), ('[', ']')],
7289                view,
7290                cx,
7291            );
7292
7293            view.move_right(&MoveRight, cx);
7294            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7295            assert_selection_ranges(
7296                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7297                vec![('<', '>'), ('[', ']')],
7298                view,
7299                cx,
7300            );
7301
7302            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7303            assert_selection_ranges(
7304                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
7305                vec![('<', '>'), ('[', ']')],
7306                view,
7307                cx,
7308            );
7309
7310            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
7311            assert_selection_ranges(
7312                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7313                vec![('<', '>'), ('[', ']')],
7314                view,
7315                cx,
7316            );
7317        });
7318    }
7319
7320    #[gpui::test]
7321    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
7322        cx.set_global(Settings::test(cx));
7323        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
7324        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7325
7326        view.update(cx, |view, cx| {
7327            view.set_wrap_width(Some(140.), cx);
7328            assert_eq!(
7329                view.display_text(cx),
7330                "use one::{\n    two::three::\n    four::five\n};"
7331            );
7332
7333            view.change_selections(None, cx, |s| {
7334                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
7335            });
7336
7337            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7338            assert_eq!(
7339                view.selections.display_ranges(cx),
7340                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
7341            );
7342
7343            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7344            assert_eq!(
7345                view.selections.display_ranges(cx),
7346                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7347            );
7348
7349            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7350            assert_eq!(
7351                view.selections.display_ranges(cx),
7352                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7353            );
7354
7355            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7356            assert_eq!(
7357                view.selections.display_ranges(cx),
7358                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
7359            );
7360
7361            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7362            assert_eq!(
7363                view.selections.display_ranges(cx),
7364                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7365            );
7366
7367            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7368            assert_eq!(
7369                view.selections.display_ranges(cx),
7370                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7371            );
7372        });
7373    }
7374
7375    #[gpui::test]
7376    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
7377        cx.set_global(Settings::test(cx));
7378        let (text, ranges) = marked_text_ranges("one [two three] four");
7379        let buffer = MultiBuffer::build_simple(&text, cx);
7380
7381        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7382
7383        editor.update(cx, |editor, cx| {
7384            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
7385            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
7386            assert_eq!(editor.text(cx), " four");
7387        });
7388    }
7389
7390    #[gpui::test]
7391    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
7392        cx.set_global(Settings::test(cx));
7393        let buffer = MultiBuffer::build_simple("one two three four", cx);
7394        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7395
7396        view.update(cx, |view, cx| {
7397            view.change_selections(None, cx, |s| {
7398                s.select_display_ranges([
7399                    // an empty selection - the preceding word fragment is deleted
7400                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7401                    // characters selected - they are deleted
7402                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
7403                ])
7404            });
7405            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
7406        });
7407
7408        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
7409
7410        view.update(cx, |view, cx| {
7411            view.change_selections(None, cx, |s| {
7412                s.select_display_ranges([
7413                    // an empty selection - the following word fragment is deleted
7414                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7415                    // characters selected - they are deleted
7416                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
7417                ])
7418            });
7419            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
7420        });
7421
7422        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
7423    }
7424
7425    #[gpui::test]
7426    fn test_newline(cx: &mut gpui::MutableAppContext) {
7427        cx.set_global(Settings::test(cx));
7428        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
7429        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7430
7431        view.update(cx, |view, cx| {
7432            view.change_selections(None, cx, |s| {
7433                s.select_display_ranges([
7434                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7435                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7436                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
7437                ])
7438            });
7439
7440            view.newline(&Newline, cx);
7441            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
7442        });
7443    }
7444
7445    #[gpui::test]
7446    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
7447        cx.set_global(Settings::test(cx));
7448        let buffer = MultiBuffer::build_simple(
7449            "
7450                a
7451                b(
7452                    X
7453                )
7454                c(
7455                    X
7456                )
7457            "
7458            .unindent()
7459            .as_str(),
7460            cx,
7461        );
7462
7463        let (_, editor) = cx.add_window(Default::default(), |cx| {
7464            let mut editor = build_editor(buffer.clone(), cx);
7465            editor.change_selections(None, cx, |s| {
7466                s.select_ranges([
7467                    Point::new(2, 4)..Point::new(2, 5),
7468                    Point::new(5, 4)..Point::new(5, 5),
7469                ])
7470            });
7471            editor
7472        });
7473
7474        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7475        buffer.update(cx, |buffer, cx| {
7476            buffer.edit(
7477                [
7478                    (Point::new(1, 2)..Point::new(3, 0), ""),
7479                    (Point::new(4, 2)..Point::new(6, 0), ""),
7480                ],
7481                cx,
7482            );
7483            assert_eq!(
7484                buffer.read(cx).text(),
7485                "
7486                    a
7487                    b()
7488                    c()
7489                "
7490                .unindent()
7491            );
7492        });
7493
7494        editor.update(cx, |editor, cx| {
7495            assert_eq!(
7496                editor.selections.ranges(cx),
7497                &[
7498                    Point::new(1, 2)..Point::new(1, 2),
7499                    Point::new(2, 2)..Point::new(2, 2),
7500                ],
7501            );
7502
7503            editor.newline(&Newline, cx);
7504            assert_eq!(
7505                editor.text(cx),
7506                "
7507                    a
7508                    b(
7509                    )
7510                    c(
7511                    )
7512                "
7513                .unindent()
7514            );
7515
7516            // The selections are moved after the inserted newlines
7517            assert_eq!(
7518                editor.selections.ranges(cx),
7519                &[
7520                    Point::new(2, 0)..Point::new(2, 0),
7521                    Point::new(4, 0)..Point::new(4, 0),
7522                ],
7523            );
7524        });
7525    }
7526
7527    #[gpui::test]
7528    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
7529        cx.set_global(Settings::test(cx));
7530        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
7531        let (_, editor) = cx.add_window(Default::default(), |cx| {
7532            let mut editor = build_editor(buffer.clone(), cx);
7533            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
7534            editor
7535        });
7536
7537        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7538        buffer.update(cx, |buffer, cx| {
7539            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
7540            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
7541        });
7542
7543        editor.update(cx, |editor, cx| {
7544            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
7545
7546            editor.insert("Z", cx);
7547            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
7548
7549            // The selections are moved after the inserted characters
7550            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
7551        });
7552    }
7553
7554    #[gpui::test]
7555    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
7556        let mut cx = EditorTestContext::new(cx).await;
7557
7558        cx.set_state(indoc! {"
7559              [one} [two}
7560            three
7561             four"});
7562        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7563        cx.assert_editor_state(indoc! {"
7564                [one} [two}
7565            three
7566             four"});
7567
7568        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7569        cx.assert_editor_state(indoc! {"
7570            [one} [two}
7571            three
7572             four"});
7573
7574        // select across line ending
7575        cx.set_state(indoc! {"
7576            one two
7577            t[hree
7578            } four"});
7579        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7580        cx.assert_editor_state(indoc! {"
7581            one two
7582                t[hree
7583            } four"});
7584
7585        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7586        cx.assert_editor_state(indoc! {"
7587            one two
7588            t[hree
7589            } four"});
7590
7591        // Ensure that indenting/outdenting works when the cursor is at column 0.
7592        cx.set_state(indoc! {"
7593            one two
7594            |three
7595                four"});
7596        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7597        cx.assert_editor_state(indoc! {"
7598            one two
7599                |three
7600                four"});
7601
7602        cx.set_state(indoc! {"
7603            one two
7604            |    three
7605             four"});
7606        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7607        cx.assert_editor_state(indoc! {"
7608            one two
7609            |three
7610             four"});
7611    }
7612
7613    #[gpui::test]
7614    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
7615        cx.set_global(
7616            Settings::test(cx)
7617                .with_overrides(
7618                    "TOML",
7619                    LanguageOverride {
7620                        tab_size: Some(2),
7621                        ..Default::default()
7622                    },
7623                )
7624                .with_overrides(
7625                    "Rust",
7626                    LanguageOverride {
7627                        tab_size: Some(4),
7628                        ..Default::default()
7629                    },
7630                ),
7631        );
7632        let toml_language = Arc::new(Language::new(
7633            LanguageConfig {
7634                name: "TOML".into(),
7635                ..Default::default()
7636            },
7637            None,
7638        ));
7639        let rust_language = Arc::new(Language::new(
7640            LanguageConfig {
7641                name: "Rust".into(),
7642                ..Default::default()
7643            },
7644            None,
7645        ));
7646
7647        let toml_buffer = cx
7648            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
7649        let rust_buffer = cx.add_model(|cx| {
7650            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
7651        });
7652        let multibuffer = cx.add_model(|cx| {
7653            let mut multibuffer = MultiBuffer::new(0);
7654            multibuffer.push_excerpts(
7655                toml_buffer.clone(),
7656                [Point::new(0, 0)..Point::new(2, 0)],
7657                cx,
7658            );
7659            multibuffer.push_excerpts(
7660                rust_buffer.clone(),
7661                [Point::new(0, 0)..Point::new(1, 0)],
7662                cx,
7663            );
7664            multibuffer
7665        });
7666
7667        cx.add_window(Default::default(), |cx| {
7668            let mut editor = build_editor(multibuffer, cx);
7669
7670            assert_eq!(
7671                editor.text(cx),
7672                indoc! {"
7673                    a = 1
7674                    b = 2
7675
7676                    const c: usize = 3;
7677                "}
7678            );
7679
7680            select_ranges(
7681                &mut editor,
7682                indoc! {"
7683                    [a] = 1
7684                    b = 2
7685
7686                    [const c:] usize = 3;
7687                "},
7688                cx,
7689            );
7690
7691            editor.tab(&Tab, cx);
7692            assert_text_with_selections(
7693                &mut editor,
7694                indoc! {"
7695                      [a] = 1
7696                    b = 2
7697
7698                        [const c:] usize = 3;
7699                "},
7700                cx,
7701            );
7702            editor.tab_prev(&TabPrev, cx);
7703            assert_text_with_selections(
7704                &mut editor,
7705                indoc! {"
7706                    [a] = 1
7707                    b = 2
7708
7709                    [const c:] usize = 3;
7710                "},
7711                cx,
7712            );
7713
7714            editor
7715        });
7716    }
7717
7718    #[gpui::test]
7719    async fn test_backspace(cx: &mut gpui::TestAppContext) {
7720        let mut cx = EditorTestContext::new(cx).await;
7721        // Basic backspace
7722        cx.set_state(indoc! {"
7723            on|e two three
7724            fou[r} five six
7725            seven {eight nine
7726            ]ten"});
7727        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7728        cx.assert_editor_state(indoc! {"
7729            o|e two three
7730            fou| five six
7731            seven |ten"});
7732
7733        // Test backspace inside and around indents
7734        cx.set_state(indoc! {"
7735            zero
7736                |one
7737                    |two
7738                | | |  three
7739            |  |  four"});
7740        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7741        cx.assert_editor_state(indoc! {"
7742            zero
7743            |one
7744                |two
7745            |  three|  four"});
7746
7747        // Test backspace with line_mode set to true
7748        cx.update_editor(|e, _| e.selections.line_mode = true);
7749        cx.set_state(indoc! {"
7750            The |quick |brown
7751            fox jumps over
7752            the lazy dog
7753            |The qu[ick b}rown"});
7754        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7755        cx.assert_editor_state(indoc! {"
7756            |fox jumps over
7757            the lazy dog|"});
7758    }
7759
7760    #[gpui::test]
7761    async fn test_delete(cx: &mut gpui::TestAppContext) {
7762        let mut cx = EditorTestContext::new(cx).await;
7763
7764        cx.set_state(indoc! {"
7765            on|e two three
7766            fou[r} five six
7767            seven {eight nine
7768            ]ten"});
7769        cx.update_editor(|e, cx| e.delete(&Delete, cx));
7770        cx.assert_editor_state(indoc! {"
7771            on| two three
7772            fou| five six
7773            seven |ten"});
7774
7775        // Test backspace with line_mode set to true
7776        cx.update_editor(|e, _| e.selections.line_mode = true);
7777        cx.set_state(indoc! {"
7778            The |quick |brown
7779            fox {jum]ps over
7780            the lazy dog
7781            |The qu[ick b}rown"});
7782        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7783        cx.assert_editor_state("|the lazy dog|");
7784    }
7785
7786    #[gpui::test]
7787    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
7788        cx.set_global(Settings::test(cx));
7789        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7790        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7791        view.update(cx, |view, cx| {
7792            view.change_selections(None, cx, |s| {
7793                s.select_display_ranges([
7794                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7795                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7796                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7797                ])
7798            });
7799            view.delete_line(&DeleteLine, cx);
7800            assert_eq!(view.display_text(cx), "ghi");
7801            assert_eq!(
7802                view.selections.display_ranges(cx),
7803                vec![
7804                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7805                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
7806                ]
7807            );
7808        });
7809
7810        cx.set_global(Settings::test(cx));
7811        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7812        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7813        view.update(cx, |view, cx| {
7814            view.change_selections(None, cx, |s| {
7815                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
7816            });
7817            view.delete_line(&DeleteLine, cx);
7818            assert_eq!(view.display_text(cx), "ghi\n");
7819            assert_eq!(
7820                view.selections.display_ranges(cx),
7821                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
7822            );
7823        });
7824    }
7825
7826    #[gpui::test]
7827    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
7828        cx.set_global(Settings::test(cx));
7829        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7830        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7831        view.update(cx, |view, cx| {
7832            view.change_selections(None, cx, |s| {
7833                s.select_display_ranges([
7834                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7835                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7836                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7837                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7838                ])
7839            });
7840            view.duplicate_line(&DuplicateLine, cx);
7841            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
7842            assert_eq!(
7843                view.selections.display_ranges(cx),
7844                vec![
7845                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7846                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7847                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7848                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
7849                ]
7850            );
7851        });
7852
7853        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7854        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7855        view.update(cx, |view, cx| {
7856            view.change_selections(None, cx, |s| {
7857                s.select_display_ranges([
7858                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
7859                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
7860                ])
7861            });
7862            view.duplicate_line(&DuplicateLine, cx);
7863            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
7864            assert_eq!(
7865                view.selections.display_ranges(cx),
7866                vec![
7867                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
7868                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
7869                ]
7870            );
7871        });
7872    }
7873
7874    #[gpui::test]
7875    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
7876        cx.set_global(Settings::test(cx));
7877        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7878        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7879        view.update(cx, |view, cx| {
7880            view.fold_ranges(
7881                vec![
7882                    Point::new(0, 2)..Point::new(1, 2),
7883                    Point::new(2, 3)..Point::new(4, 1),
7884                    Point::new(7, 0)..Point::new(8, 4),
7885                ],
7886                cx,
7887            );
7888            view.change_selections(None, cx, |s| {
7889                s.select_display_ranges([
7890                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7891                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7892                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7893                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
7894                ])
7895            });
7896            assert_eq!(
7897                view.display_text(cx),
7898                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
7899            );
7900
7901            view.move_line_up(&MoveLineUp, cx);
7902            assert_eq!(
7903                view.display_text(cx),
7904                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
7905            );
7906            assert_eq!(
7907                view.selections.display_ranges(cx),
7908                vec![
7909                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7910                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7911                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7912                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7913                ]
7914            );
7915        });
7916
7917        view.update(cx, |view, cx| {
7918            view.move_line_down(&MoveLineDown, cx);
7919            assert_eq!(
7920                view.display_text(cx),
7921                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
7922            );
7923            assert_eq!(
7924                view.selections.display_ranges(cx),
7925                vec![
7926                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7927                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7928                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7929                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7930                ]
7931            );
7932        });
7933
7934        view.update(cx, |view, cx| {
7935            view.move_line_down(&MoveLineDown, cx);
7936            assert_eq!(
7937                view.display_text(cx),
7938                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
7939            );
7940            assert_eq!(
7941                view.selections.display_ranges(cx),
7942                vec![
7943                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7944                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7945                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7946                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7947                ]
7948            );
7949        });
7950
7951        view.update(cx, |view, cx| {
7952            view.move_line_up(&MoveLineUp, cx);
7953            assert_eq!(
7954                view.display_text(cx),
7955                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
7956            );
7957            assert_eq!(
7958                view.selections.display_ranges(cx),
7959                vec![
7960                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7961                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7962                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7963                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7964                ]
7965            );
7966        });
7967    }
7968
7969    #[gpui::test]
7970    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
7971        cx.set_global(Settings::test(cx));
7972        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7973        let snapshot = buffer.read(cx).snapshot(cx);
7974        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7975        editor.update(cx, |editor, cx| {
7976            editor.insert_blocks(
7977                [BlockProperties {
7978                    position: snapshot.anchor_after(Point::new(2, 0)),
7979                    disposition: BlockDisposition::Below,
7980                    height: 1,
7981                    render: Arc::new(|_| Empty::new().boxed()),
7982                }],
7983                cx,
7984            );
7985            editor.change_selections(None, cx, |s| {
7986                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
7987            });
7988            editor.move_line_down(&MoveLineDown, cx);
7989        });
7990    }
7991
7992    #[gpui::test]
7993    fn test_transpose(cx: &mut gpui::MutableAppContext) {
7994        cx.set_global(Settings::test(cx));
7995
7996        cx.add_window(Default::default(), |cx| {
7997            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
7998
7999            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
8000            editor.transpose(&Default::default(), cx);
8001            assert_eq!(editor.text(cx), "bac");
8002            assert_eq!(editor.selections.ranges(cx), [2..2]);
8003
8004            editor.transpose(&Default::default(), cx);
8005            assert_eq!(editor.text(cx), "bca");
8006            assert_eq!(editor.selections.ranges(cx), [3..3]);
8007
8008            editor.transpose(&Default::default(), cx);
8009            assert_eq!(editor.text(cx), "bac");
8010            assert_eq!(editor.selections.ranges(cx), [3..3]);
8011
8012            editor
8013        })
8014        .1;
8015
8016        cx.add_window(Default::default(), |cx| {
8017            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
8018
8019            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
8020            editor.transpose(&Default::default(), cx);
8021            assert_eq!(editor.text(cx), "acb\nde");
8022            assert_eq!(editor.selections.ranges(cx), [3..3]);
8023
8024            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
8025            editor.transpose(&Default::default(), cx);
8026            assert_eq!(editor.text(cx), "acbd\ne");
8027            assert_eq!(editor.selections.ranges(cx), [5..5]);
8028
8029            editor.transpose(&Default::default(), cx);
8030            assert_eq!(editor.text(cx), "acbde\n");
8031            assert_eq!(editor.selections.ranges(cx), [6..6]);
8032
8033            editor.transpose(&Default::default(), cx);
8034            assert_eq!(editor.text(cx), "acbd\ne");
8035            assert_eq!(editor.selections.ranges(cx), [6..6]);
8036
8037            editor
8038        })
8039        .1;
8040
8041        cx.add_window(Default::default(), |cx| {
8042            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
8043
8044            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
8045            editor.transpose(&Default::default(), cx);
8046            assert_eq!(editor.text(cx), "bacd\ne");
8047            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
8048
8049            editor.transpose(&Default::default(), cx);
8050            assert_eq!(editor.text(cx), "bcade\n");
8051            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
8052
8053            editor.transpose(&Default::default(), cx);
8054            assert_eq!(editor.text(cx), "bcda\ne");
8055            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
8056
8057            editor.transpose(&Default::default(), cx);
8058            assert_eq!(editor.text(cx), "bcade\n");
8059            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
8060
8061            editor.transpose(&Default::default(), cx);
8062            assert_eq!(editor.text(cx), "bcaed\n");
8063            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
8064
8065            editor
8066        })
8067        .1;
8068
8069        cx.add_window(Default::default(), |cx| {
8070            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
8071
8072            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
8073            editor.transpose(&Default::default(), cx);
8074            assert_eq!(editor.text(cx), "🏀🍐✋");
8075            assert_eq!(editor.selections.ranges(cx), [8..8]);
8076
8077            editor.transpose(&Default::default(), cx);
8078            assert_eq!(editor.text(cx), "🏀✋🍐");
8079            assert_eq!(editor.selections.ranges(cx), [11..11]);
8080
8081            editor.transpose(&Default::default(), cx);
8082            assert_eq!(editor.text(cx), "🏀🍐✋");
8083            assert_eq!(editor.selections.ranges(cx), [11..11]);
8084
8085            editor
8086        })
8087        .1;
8088    }
8089
8090    #[gpui::test]
8091    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
8092        let mut cx = EditorTestContext::new(cx).await;
8093
8094        cx.set_state("[one✅ }two [three }four [five }six ");
8095        cx.update_editor(|e, cx| e.cut(&Cut, cx));
8096        cx.assert_editor_state("|two |four |six ");
8097
8098        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
8099        cx.set_state("two |four |six |");
8100        cx.update_editor(|e, cx| e.paste(&Paste, cx));
8101        cx.assert_editor_state("two one✅ |four three |six five |");
8102
8103        // Paste again but with only two cursors. Since the number of cursors doesn't
8104        // match the number of slices in the clipboard, the entire clipboard text
8105        // is pasted at each cursor.
8106        cx.set_state("|two one✅ four three six five |");
8107        cx.update_editor(|e, cx| {
8108            e.handle_input(&Input("( ".into()), cx);
8109            e.paste(&Paste, cx);
8110            e.handle_input(&Input(") ".into()), cx);
8111        });
8112        cx.assert_editor_state(indoc! {"
8113            ( one✅ 
8114            three 
8115            five ) |two one✅ four three six five ( one✅ 
8116            three 
8117            five ) |"});
8118
8119        // Cut with three selections, one of which is full-line.
8120        cx.set_state(indoc! {"
8121            1[2}3
8122            4|567
8123            [8}9"});
8124        cx.update_editor(|e, cx| e.cut(&Cut, cx));
8125        cx.assert_editor_state(indoc! {"
8126            1|3
8127            |9"});
8128
8129        // Paste with three selections, noticing how the copied selection that was full-line
8130        // gets inserted before the second cursor.
8131        cx.set_state(indoc! {"
8132            1|3
8133            9|
8134            [o}ne"});
8135        cx.update_editor(|e, cx| e.paste(&Paste, cx));
8136        cx.assert_editor_state(indoc! {"
8137            12|3
8138            4567
8139            9|
8140            8|ne"});
8141
8142        // Copy with a single cursor only, which writes the whole line into the clipboard.
8143        cx.set_state(indoc! {"
8144            The quick brown
8145            fox ju|mps over
8146            the lazy dog"});
8147        cx.update_editor(|e, cx| e.copy(&Copy, cx));
8148        cx.assert_clipboard_content(Some("fox jumps over\n"));
8149
8150        // Paste with three selections, noticing how the copied full-line selection is inserted
8151        // before the empty selections but replaces the selection that is non-empty.
8152        cx.set_state(indoc! {"
8153            T|he quick brown
8154            [fo}x jumps over
8155            t|he lazy dog"});
8156        cx.update_editor(|e, cx| e.paste(&Paste, cx));
8157        cx.assert_editor_state(indoc! {"
8158            fox jumps over
8159            T|he quick brown
8160            fox jumps over
8161            |x jumps over
8162            fox jumps over
8163            t|he lazy dog"});
8164    }
8165
8166    #[gpui::test]
8167    fn test_select_all(cx: &mut gpui::MutableAppContext) {
8168        cx.set_global(Settings::test(cx));
8169        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
8170        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8171        view.update(cx, |view, cx| {
8172            view.select_all(&SelectAll, cx);
8173            assert_eq!(
8174                view.selections.display_ranges(cx),
8175                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
8176            );
8177        });
8178    }
8179
8180    #[gpui::test]
8181    fn test_select_line(cx: &mut gpui::MutableAppContext) {
8182        cx.set_global(Settings::test(cx));
8183        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
8184        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8185        view.update(cx, |view, cx| {
8186            view.change_selections(None, cx, |s| {
8187                s.select_display_ranges([
8188                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8189                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8190                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8191                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
8192                ])
8193            });
8194            view.select_line(&SelectLine, cx);
8195            assert_eq!(
8196                view.selections.display_ranges(cx),
8197                vec![
8198                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
8199                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
8200                ]
8201            );
8202        });
8203
8204        view.update(cx, |view, cx| {
8205            view.select_line(&SelectLine, cx);
8206            assert_eq!(
8207                view.selections.display_ranges(cx),
8208                vec![
8209                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
8210                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
8211                ]
8212            );
8213        });
8214
8215        view.update(cx, |view, cx| {
8216            view.select_line(&SelectLine, cx);
8217            assert_eq!(
8218                view.selections.display_ranges(cx),
8219                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
8220            );
8221        });
8222    }
8223
8224    #[gpui::test]
8225    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
8226        cx.set_global(Settings::test(cx));
8227        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
8228        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8229        view.update(cx, |view, cx| {
8230            view.fold_ranges(
8231                vec![
8232                    Point::new(0, 2)..Point::new(1, 2),
8233                    Point::new(2, 3)..Point::new(4, 1),
8234                    Point::new(7, 0)..Point::new(8, 4),
8235                ],
8236                cx,
8237            );
8238            view.change_selections(None, cx, |s| {
8239                s.select_display_ranges([
8240                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8241                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8242                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8243                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
8244                ])
8245            });
8246            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
8247        });
8248
8249        view.update(cx, |view, cx| {
8250            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8251            assert_eq!(
8252                view.display_text(cx),
8253                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
8254            );
8255            assert_eq!(
8256                view.selections.display_ranges(cx),
8257                [
8258                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
8259                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8260                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
8261                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
8262                ]
8263            );
8264        });
8265
8266        view.update(cx, |view, cx| {
8267            view.change_selections(None, cx, |s| {
8268                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
8269            });
8270            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8271            assert_eq!(
8272                view.display_text(cx),
8273                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
8274            );
8275            assert_eq!(
8276                view.selections.display_ranges(cx),
8277                [
8278                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
8279                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
8280                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
8281                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
8282                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
8283                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
8284                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
8285                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
8286                ]
8287            );
8288        });
8289    }
8290
8291    #[gpui::test]
8292    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
8293        cx.set_global(Settings::test(cx));
8294        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
8295        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8296
8297        view.update(cx, |view, cx| {
8298            view.change_selections(None, cx, |s| {
8299                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
8300            });
8301        });
8302        view.update(cx, |view, cx| {
8303            view.add_selection_above(&AddSelectionAbove, cx);
8304            assert_eq!(
8305                view.selections.display_ranges(cx),
8306                vec![
8307                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8308                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8309                ]
8310            );
8311        });
8312
8313        view.update(cx, |view, cx| {
8314            view.add_selection_above(&AddSelectionAbove, cx);
8315            assert_eq!(
8316                view.selections.display_ranges(cx),
8317                vec![
8318                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8319                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8320                ]
8321            );
8322        });
8323
8324        view.update(cx, |view, cx| {
8325            view.add_selection_below(&AddSelectionBelow, cx);
8326            assert_eq!(
8327                view.selections.display_ranges(cx),
8328                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
8329            );
8330
8331            view.undo_selection(&UndoSelection, cx);
8332            assert_eq!(
8333                view.selections.display_ranges(cx),
8334                vec![
8335                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8336                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8337                ]
8338            );
8339
8340            view.redo_selection(&RedoSelection, cx);
8341            assert_eq!(
8342                view.selections.display_ranges(cx),
8343                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
8344            );
8345        });
8346
8347        view.update(cx, |view, cx| {
8348            view.add_selection_below(&AddSelectionBelow, cx);
8349            assert_eq!(
8350                view.selections.display_ranges(cx),
8351                vec![
8352                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8353                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8354                ]
8355            );
8356        });
8357
8358        view.update(cx, |view, cx| {
8359            view.add_selection_below(&AddSelectionBelow, cx);
8360            assert_eq!(
8361                view.selections.display_ranges(cx),
8362                vec![
8363                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8364                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8365                ]
8366            );
8367        });
8368
8369        view.update(cx, |view, cx| {
8370            view.change_selections(None, cx, |s| {
8371                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
8372            });
8373        });
8374        view.update(cx, |view, cx| {
8375            view.add_selection_below(&AddSelectionBelow, cx);
8376            assert_eq!(
8377                view.selections.display_ranges(cx),
8378                vec![
8379                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8380                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8381                ]
8382            );
8383        });
8384
8385        view.update(cx, |view, cx| {
8386            view.add_selection_below(&AddSelectionBelow, cx);
8387            assert_eq!(
8388                view.selections.display_ranges(cx),
8389                vec![
8390                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8391                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8392                ]
8393            );
8394        });
8395
8396        view.update(cx, |view, cx| {
8397            view.add_selection_above(&AddSelectionAbove, cx);
8398            assert_eq!(
8399                view.selections.display_ranges(cx),
8400                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8401            );
8402        });
8403
8404        view.update(cx, |view, cx| {
8405            view.add_selection_above(&AddSelectionAbove, cx);
8406            assert_eq!(
8407                view.selections.display_ranges(cx),
8408                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8409            );
8410        });
8411
8412        view.update(cx, |view, cx| {
8413            view.change_selections(None, cx, |s| {
8414                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
8415            });
8416            view.add_selection_below(&AddSelectionBelow, cx);
8417            assert_eq!(
8418                view.selections.display_ranges(cx),
8419                vec![
8420                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8421                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8422                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8423                ]
8424            );
8425        });
8426
8427        view.update(cx, |view, cx| {
8428            view.add_selection_below(&AddSelectionBelow, cx);
8429            assert_eq!(
8430                view.selections.display_ranges(cx),
8431                vec![
8432                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8433                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8434                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8435                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
8436                ]
8437            );
8438        });
8439
8440        view.update(cx, |view, cx| {
8441            view.add_selection_above(&AddSelectionAbove, cx);
8442            assert_eq!(
8443                view.selections.display_ranges(cx),
8444                vec![
8445                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8446                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8447                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8448                ]
8449            );
8450        });
8451
8452        view.update(cx, |view, cx| {
8453            view.change_selections(None, cx, |s| {
8454                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
8455            });
8456        });
8457        view.update(cx, |view, cx| {
8458            view.add_selection_above(&AddSelectionAbove, cx);
8459            assert_eq!(
8460                view.selections.display_ranges(cx),
8461                vec![
8462                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
8463                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8464                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8465                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8466                ]
8467            );
8468        });
8469
8470        view.update(cx, |view, cx| {
8471            view.add_selection_below(&AddSelectionBelow, cx);
8472            assert_eq!(
8473                view.selections.display_ranges(cx),
8474                vec![
8475                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8476                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8477                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8478                ]
8479            );
8480        });
8481    }
8482
8483    #[gpui::test]
8484    fn test_select_next(cx: &mut gpui::MutableAppContext) {
8485        cx.set_global(Settings::test(cx));
8486
8487        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
8488        let buffer = MultiBuffer::build_simple(&text, cx);
8489        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8490
8491        view.update(cx, |view, cx| {
8492            view.change_selections(None, cx, |s| {
8493                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
8494            });
8495            view.select_next(
8496                &SelectNext {
8497                    replace_newest: false,
8498                },
8499                cx,
8500            );
8501            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
8502
8503            view.select_next(
8504                &SelectNext {
8505                    replace_newest: false,
8506                },
8507                cx,
8508            );
8509            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
8510
8511            view.undo_selection(&UndoSelection, cx);
8512            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
8513
8514            view.redo_selection(&RedoSelection, cx);
8515            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
8516
8517            view.select_next(
8518                &SelectNext {
8519                    replace_newest: false,
8520                },
8521                cx,
8522            );
8523            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
8524
8525            view.select_next(
8526                &SelectNext {
8527                    replace_newest: false,
8528                },
8529                cx,
8530            );
8531            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
8532        });
8533    }
8534
8535    #[gpui::test]
8536    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
8537        cx.update(|cx| cx.set_global(Settings::test(cx)));
8538        let language = Arc::new(Language::new(
8539            LanguageConfig::default(),
8540            Some(tree_sitter_rust::language()),
8541        ));
8542
8543        let text = r#"
8544            use mod1::mod2::{mod3, mod4};
8545
8546            fn fn_1(param1: bool, param2: &str) {
8547                let var1 = "text";
8548            }
8549        "#
8550        .unindent();
8551
8552        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8553        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8554        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8555        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8556            .await;
8557
8558        view.update(cx, |view, cx| {
8559            view.change_selections(None, cx, |s| {
8560                s.select_display_ranges([
8561                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8562                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8563                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8564                ]);
8565            });
8566            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8567        });
8568        assert_eq!(
8569            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
8570            &[
8571                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8572                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8573                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8574            ]
8575        );
8576
8577        view.update(cx, |view, cx| {
8578            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8579        });
8580        assert_eq!(
8581            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8582            &[
8583                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8584                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8585            ]
8586        );
8587
8588        view.update(cx, |view, cx| {
8589            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8590        });
8591        assert_eq!(
8592            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8593            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8594        );
8595
8596        // Trying to expand the selected syntax node one more time has no effect.
8597        view.update(cx, |view, cx| {
8598            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8599        });
8600        assert_eq!(
8601            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8602            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8603        );
8604
8605        view.update(cx, |view, cx| {
8606            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8607        });
8608        assert_eq!(
8609            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8610            &[
8611                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8612                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8613            ]
8614        );
8615
8616        view.update(cx, |view, cx| {
8617            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8618        });
8619        assert_eq!(
8620            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8621            &[
8622                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8623                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8624                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8625            ]
8626        );
8627
8628        view.update(cx, |view, cx| {
8629            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8630        });
8631        assert_eq!(
8632            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8633            &[
8634                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8635                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8636                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8637            ]
8638        );
8639
8640        // Trying to shrink the selected syntax node one more time has no effect.
8641        view.update(cx, |view, cx| {
8642            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8643        });
8644        assert_eq!(
8645            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8646            &[
8647                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8648                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8649                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8650            ]
8651        );
8652
8653        // Ensure that we keep expanding the selection if the larger selection starts or ends within
8654        // a fold.
8655        view.update(cx, |view, cx| {
8656            view.fold_ranges(
8657                vec![
8658                    Point::new(0, 21)..Point::new(0, 24),
8659                    Point::new(3, 20)..Point::new(3, 22),
8660                ],
8661                cx,
8662            );
8663            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8664        });
8665        assert_eq!(
8666            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8667            &[
8668                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8669                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8670                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
8671            ]
8672        );
8673    }
8674
8675    #[gpui::test]
8676    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
8677        cx.update(|cx| cx.set_global(Settings::test(cx)));
8678        let language = Arc::new(
8679            Language::new(
8680                LanguageConfig {
8681                    brackets: vec![
8682                        BracketPair {
8683                            start: "{".to_string(),
8684                            end: "}".to_string(),
8685                            close: false,
8686                            newline: true,
8687                        },
8688                        BracketPair {
8689                            start: "(".to_string(),
8690                            end: ")".to_string(),
8691                            close: false,
8692                            newline: true,
8693                        },
8694                    ],
8695                    ..Default::default()
8696                },
8697                Some(tree_sitter_rust::language()),
8698            )
8699            .with_indents_query(
8700                r#"
8701                (_ "(" ")" @end) @indent
8702                (_ "{" "}" @end) @indent
8703                "#,
8704            )
8705            .unwrap(),
8706        );
8707
8708        let text = "fn a() {}";
8709
8710        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8711        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8712        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8713        editor
8714            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
8715            .await;
8716
8717        editor.update(cx, |editor, cx| {
8718            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
8719            editor.newline(&Newline, cx);
8720            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
8721            assert_eq!(
8722                editor.selections.ranges(cx),
8723                &[
8724                    Point::new(1, 4)..Point::new(1, 4),
8725                    Point::new(3, 4)..Point::new(3, 4),
8726                    Point::new(5, 0)..Point::new(5, 0)
8727                ]
8728            );
8729        });
8730    }
8731
8732    #[gpui::test]
8733    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
8734        cx.update(|cx| cx.set_global(Settings::test(cx)));
8735        let language = Arc::new(Language::new(
8736            LanguageConfig {
8737                brackets: vec![
8738                    BracketPair {
8739                        start: "{".to_string(),
8740                        end: "}".to_string(),
8741                        close: true,
8742                        newline: true,
8743                    },
8744                    BracketPair {
8745                        start: "/*".to_string(),
8746                        end: " */".to_string(),
8747                        close: true,
8748                        newline: true,
8749                    },
8750                ],
8751                autoclose_before: "})]".to_string(),
8752                ..Default::default()
8753            },
8754            Some(tree_sitter_rust::language()),
8755        ));
8756
8757        let text = r#"
8758            a
8759
8760            /
8761
8762        "#
8763        .unindent();
8764
8765        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8766        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8767        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8768        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8769            .await;
8770
8771        view.update(cx, |view, cx| {
8772            view.change_selections(None, cx, |s| {
8773                s.select_display_ranges([
8774                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8775                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8776                ])
8777            });
8778
8779            view.handle_input(&Input("{".to_string()), cx);
8780            view.handle_input(&Input("{".to_string()), cx);
8781            view.handle_input(&Input("{".to_string()), cx);
8782            assert_eq!(
8783                view.text(cx),
8784                "
8785                {{{}}}
8786                {{{}}}
8787                /
8788
8789                "
8790                .unindent()
8791            );
8792
8793            view.move_right(&MoveRight, cx);
8794            view.handle_input(&Input("}".to_string()), cx);
8795            view.handle_input(&Input("}".to_string()), cx);
8796            view.handle_input(&Input("}".to_string()), cx);
8797            assert_eq!(
8798                view.text(cx),
8799                "
8800                {{{}}}}
8801                {{{}}}}
8802                /
8803
8804                "
8805                .unindent()
8806            );
8807
8808            view.undo(&Undo, cx);
8809            view.handle_input(&Input("/".to_string()), cx);
8810            view.handle_input(&Input("*".to_string()), cx);
8811            assert_eq!(
8812                view.text(cx),
8813                "
8814                /* */
8815                /* */
8816                /
8817
8818                "
8819                .unindent()
8820            );
8821
8822            view.undo(&Undo, cx);
8823            view.change_selections(None, cx, |s| {
8824                s.select_display_ranges([
8825                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
8826                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
8827                ])
8828            });
8829            view.handle_input(&Input("*".to_string()), cx);
8830            assert_eq!(
8831                view.text(cx),
8832                "
8833                a
8834
8835                /*
8836                *
8837                "
8838                .unindent()
8839            );
8840
8841            // Don't autoclose if the next character isn't whitespace and isn't
8842            // listed in the language's "autoclose_before" section.
8843            view.finalize_last_transaction(cx);
8844            view.change_selections(None, cx, |s| {
8845                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
8846            });
8847            view.handle_input(&Input("{".to_string()), cx);
8848            assert_eq!(
8849                view.text(cx),
8850                "
8851                {a
8852
8853                /*
8854                *
8855                "
8856                .unindent()
8857            );
8858
8859            view.undo(&Undo, cx);
8860            view.change_selections(None, cx, |s| {
8861                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
8862            });
8863            view.handle_input(&Input("{".to_string()), cx);
8864            assert_eq!(
8865                view.text(cx),
8866                "
8867                {a}
8868
8869                /*
8870                *
8871                "
8872                .unindent()
8873            );
8874            assert_eq!(
8875                view.selections.display_ranges(cx),
8876                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
8877            );
8878        });
8879    }
8880
8881    #[gpui::test]
8882    async fn test_snippets(cx: &mut gpui::TestAppContext) {
8883        cx.update(|cx| cx.set_global(Settings::test(cx)));
8884
8885        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
8886            a.| b
8887            a.| b
8888            a.| b"});
8889        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
8890        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8891
8892        editor.update(cx, |editor, cx| {
8893            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
8894
8895            editor
8896                .insert_snippet(&insertion_ranges, snippet, cx)
8897                .unwrap();
8898
8899            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
8900                let range_markers = ('<', '>');
8901                let (expected_text, mut selection_ranges_lookup) =
8902                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
8903                let selection_ranges = selection_ranges_lookup
8904                    .remove(&range_markers.into())
8905                    .unwrap();
8906                assert_eq!(editor.text(cx), expected_text);
8907                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
8908            }
8909            assert(
8910                editor,
8911                cx,
8912                indoc! {"
8913                    a.f(<one>, two, <three>) b
8914                    a.f(<one>, two, <three>) b
8915                    a.f(<one>, two, <three>) b"},
8916            );
8917
8918            // Can't move earlier than the first tab stop
8919            assert!(!editor.move_to_prev_snippet_tabstop(cx));
8920            assert(
8921                editor,
8922                cx,
8923                indoc! {"
8924                    a.f(<one>, two, <three>) b
8925                    a.f(<one>, two, <three>) b
8926                    a.f(<one>, two, <three>) b"},
8927            );
8928
8929            assert!(editor.move_to_next_snippet_tabstop(cx));
8930            assert(
8931                editor,
8932                cx,
8933                indoc! {"
8934                    a.f(one, <two>, three) b
8935                    a.f(one, <two>, three) b
8936                    a.f(one, <two>, three) b"},
8937            );
8938
8939            editor.move_to_prev_snippet_tabstop(cx);
8940            assert(
8941                editor,
8942                cx,
8943                indoc! {"
8944                    a.f(<one>, two, <three>) b
8945                    a.f(<one>, two, <three>) b
8946                    a.f(<one>, two, <three>) b"},
8947            );
8948
8949            assert!(editor.move_to_next_snippet_tabstop(cx));
8950            assert(
8951                editor,
8952                cx,
8953                indoc! {"
8954                    a.f(one, <two>, three) b
8955                    a.f(one, <two>, three) b
8956                    a.f(one, <two>, three) b"},
8957            );
8958            assert!(editor.move_to_next_snippet_tabstop(cx));
8959            assert(
8960                editor,
8961                cx,
8962                indoc! {"
8963                    a.f(one, two, three)<> b
8964                    a.f(one, two, three)<> b
8965                    a.f(one, two, three)<> b"},
8966            );
8967
8968            // As soon as the last tab stop is reached, snippet state is gone
8969            editor.move_to_prev_snippet_tabstop(cx);
8970            assert(
8971                editor,
8972                cx,
8973                indoc! {"
8974                    a.f(one, two, three)<> b
8975                    a.f(one, two, three)<> b
8976                    a.f(one, two, three)<> b"},
8977            );
8978        });
8979    }
8980
8981    #[gpui::test]
8982    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
8983        cx.foreground().forbid_parking();
8984        cx.update(|cx| cx.set_global(Settings::test(cx)));
8985
8986        let mut language = Language::new(
8987            LanguageConfig {
8988                name: "Rust".into(),
8989                path_suffixes: vec!["rs".to_string()],
8990                ..Default::default()
8991            },
8992            Some(tree_sitter_rust::language()),
8993        );
8994        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
8995            capabilities: lsp::ServerCapabilities {
8996                document_formatting_provider: Some(lsp::OneOf::Left(true)),
8997                ..Default::default()
8998            },
8999            ..Default::default()
9000        });
9001
9002        let fs = FakeFs::new(cx.background().clone());
9003        fs.insert_file("/file.rs", Default::default()).await;
9004
9005        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
9006        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
9007        let buffer = project
9008            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
9009            .await
9010            .unwrap();
9011
9012        cx.foreground().start_waiting();
9013        let fake_server = fake_servers.next().await.unwrap();
9014
9015        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9016        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
9017        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
9018        assert!(cx.read(|cx| editor.is_dirty(cx)));
9019
9020        let save = cx.update(|cx| editor.save(project.clone(), cx));
9021        fake_server
9022            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
9023                assert_eq!(
9024                    params.text_document.uri,
9025                    lsp::Url::from_file_path("/file.rs").unwrap()
9026                );
9027                assert_eq!(params.options.tab_size, 4);
9028                Ok(Some(vec![lsp::TextEdit::new(
9029                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
9030                    ", ".to_string(),
9031                )]))
9032            })
9033            .next()
9034            .await;
9035        cx.foreground().start_waiting();
9036        save.await.unwrap();
9037        assert_eq!(
9038            editor.read_with(cx, |editor, cx| editor.text(cx)),
9039            "one, two\nthree\n"
9040        );
9041        assert!(!cx.read(|cx| editor.is_dirty(cx)));
9042
9043        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
9044        assert!(cx.read(|cx| editor.is_dirty(cx)));
9045
9046        // Ensure we can still save even if formatting hangs.
9047        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
9048            assert_eq!(
9049                params.text_document.uri,
9050                lsp::Url::from_file_path("/file.rs").unwrap()
9051            );
9052            futures::future::pending::<()>().await;
9053            unreachable!()
9054        });
9055        let save = cx.update(|cx| editor.save(project.clone(), cx));
9056        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
9057        cx.foreground().start_waiting();
9058        save.await.unwrap();
9059        assert_eq!(
9060            editor.read_with(cx, |editor, cx| editor.text(cx)),
9061            "one\ntwo\nthree\n"
9062        );
9063        assert!(!cx.read(|cx| editor.is_dirty(cx)));
9064
9065        // Set rust language override and assert overriden tabsize is sent to language server
9066        cx.update(|cx| {
9067            cx.update_global::<Settings, _, _>(|settings, _| {
9068                settings.language_overrides.insert(
9069                    "Rust".into(),
9070                    LanguageOverride {
9071                        tab_size: Some(8),
9072                        ..Default::default()
9073                    },
9074                );
9075            })
9076        });
9077
9078        let save = cx.update(|cx| editor.save(project.clone(), cx));
9079        fake_server
9080            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
9081                assert_eq!(
9082                    params.text_document.uri,
9083                    lsp::Url::from_file_path("/file.rs").unwrap()
9084                );
9085                assert_eq!(params.options.tab_size, 8);
9086                Ok(Some(vec![]))
9087            })
9088            .next()
9089            .await;
9090        cx.foreground().start_waiting();
9091        save.await.unwrap();
9092    }
9093
9094    #[gpui::test]
9095    async fn test_completion(cx: &mut gpui::TestAppContext) {
9096        cx.update(|cx| cx.set_global(Settings::test(cx)));
9097
9098        let mut language = Language::new(
9099            LanguageConfig {
9100                name: "Rust".into(),
9101                path_suffixes: vec!["rs".to_string()],
9102                ..Default::default()
9103            },
9104            Some(tree_sitter_rust::language()),
9105        );
9106        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
9107            capabilities: lsp::ServerCapabilities {
9108                completion_provider: Some(lsp::CompletionOptions {
9109                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
9110                    ..Default::default()
9111                }),
9112                ..Default::default()
9113            },
9114            ..Default::default()
9115        });
9116
9117        let text = "
9118            one
9119            two
9120            three
9121        "
9122        .unindent();
9123
9124        let fs = FakeFs::new(cx.background().clone());
9125        fs.insert_file("/file.rs", text).await;
9126
9127        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
9128        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
9129        let buffer = project
9130            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
9131            .await
9132            .unwrap();
9133        let mut fake_server = fake_servers.next().await.unwrap();
9134
9135        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9136        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
9137
9138        editor.update(cx, |editor, cx| {
9139            editor.project = Some(project);
9140            editor.change_selections(None, cx, |s| {
9141                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
9142            });
9143            editor.handle_input(&Input(".".to_string()), cx);
9144        });
9145
9146        handle_completion_request(
9147            &mut fake_server,
9148            "/file.rs",
9149            Point::new(0, 4),
9150            vec![
9151                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
9152                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
9153            ],
9154        )
9155        .await;
9156        editor
9157            .condition(&cx, |editor, _| editor.context_menu_visible())
9158            .await;
9159
9160        let apply_additional_edits = editor.update(cx, |editor, cx| {
9161            editor.move_down(&MoveDown, cx);
9162            let apply_additional_edits = editor
9163                .confirm_completion(&ConfirmCompletion::default(), cx)
9164                .unwrap();
9165            assert_eq!(
9166                editor.text(cx),
9167                "
9168                    one.second_completion
9169                    two
9170                    three
9171                "
9172                .unindent()
9173            );
9174            apply_additional_edits
9175        });
9176
9177        handle_resolve_completion_request(
9178            &mut fake_server,
9179            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
9180        )
9181        .await;
9182        apply_additional_edits.await.unwrap();
9183        assert_eq!(
9184            editor.read_with(cx, |editor, cx| editor.text(cx)),
9185            "
9186                one.second_completion
9187                two
9188                three
9189                additional edit
9190            "
9191            .unindent()
9192        );
9193
9194        editor.update(cx, |editor, cx| {
9195            editor.change_selections(None, cx, |s| {
9196                s.select_ranges([
9197                    Point::new(1, 3)..Point::new(1, 3),
9198                    Point::new(2, 5)..Point::new(2, 5),
9199                ])
9200            });
9201
9202            editor.handle_input(&Input(" ".to_string()), cx);
9203            assert!(editor.context_menu.is_none());
9204            editor.handle_input(&Input("s".to_string()), cx);
9205            assert!(editor.context_menu.is_none());
9206        });
9207
9208        handle_completion_request(
9209            &mut fake_server,
9210            "/file.rs",
9211            Point::new(2, 7),
9212            vec![
9213                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
9214                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
9215                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
9216            ],
9217        )
9218        .await;
9219        editor
9220            .condition(&cx, |editor, _| editor.context_menu_visible())
9221            .await;
9222
9223        editor.update(cx, |editor, cx| {
9224            editor.handle_input(&Input("i".to_string()), cx);
9225        });
9226
9227        handle_completion_request(
9228            &mut fake_server,
9229            "/file.rs",
9230            Point::new(2, 8),
9231            vec![
9232                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
9233                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
9234                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
9235            ],
9236        )
9237        .await;
9238        editor
9239            .condition(&cx, |editor, _| editor.context_menu_visible())
9240            .await;
9241
9242        let apply_additional_edits = editor.update(cx, |editor, cx| {
9243            let apply_additional_edits = editor
9244                .confirm_completion(&ConfirmCompletion::default(), cx)
9245                .unwrap();
9246            assert_eq!(
9247                editor.text(cx),
9248                "
9249                    one.second_completion
9250                    two sixth_completion
9251                    three sixth_completion
9252                    additional edit
9253                "
9254                .unindent()
9255            );
9256            apply_additional_edits
9257        });
9258        handle_resolve_completion_request(&mut fake_server, None).await;
9259        apply_additional_edits.await.unwrap();
9260
9261        async fn handle_completion_request(
9262            fake: &mut FakeLanguageServer,
9263            path: &'static str,
9264            position: Point,
9265            completions: Vec<(Range<Point>, &'static str)>,
9266        ) {
9267            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
9268                let completions = completions.clone();
9269                async move {
9270                    assert_eq!(
9271                        params.text_document_position.text_document.uri,
9272                        lsp::Url::from_file_path(path).unwrap()
9273                    );
9274                    assert_eq!(
9275                        params.text_document_position.position,
9276                        lsp::Position::new(position.row, position.column)
9277                    );
9278                    Ok(Some(lsp::CompletionResponse::Array(
9279                        completions
9280                            .iter()
9281                            .map(|(range, new_text)| lsp::CompletionItem {
9282                                label: new_text.to_string(),
9283                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
9284                                    range: lsp::Range::new(
9285                                        lsp::Position::new(range.start.row, range.start.column),
9286                                        lsp::Position::new(range.start.row, range.start.column),
9287                                    ),
9288                                    new_text: new_text.to_string(),
9289                                })),
9290                                ..Default::default()
9291                            })
9292                            .collect(),
9293                    )))
9294                }
9295            })
9296            .next()
9297            .await;
9298        }
9299
9300        async fn handle_resolve_completion_request(
9301            fake: &mut FakeLanguageServer,
9302            edit: Option<(Range<Point>, &'static str)>,
9303        ) {
9304            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
9305                let edit = edit.clone();
9306                async move {
9307                    Ok(lsp::CompletionItem {
9308                        additional_text_edits: edit.map(|(range, new_text)| {
9309                            vec![lsp::TextEdit::new(
9310                                lsp::Range::new(
9311                                    lsp::Position::new(range.start.row, range.start.column),
9312                                    lsp::Position::new(range.end.row, range.end.column),
9313                                ),
9314                                new_text.to_string(),
9315                            )]
9316                        }),
9317                        ..Default::default()
9318                    })
9319                }
9320            })
9321            .next()
9322            .await;
9323        }
9324    }
9325
9326    #[gpui::test]
9327    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
9328        cx.update(|cx| cx.set_global(Settings::test(cx)));
9329        let language = Arc::new(Language::new(
9330            LanguageConfig {
9331                line_comment: Some("// ".to_string()),
9332                ..Default::default()
9333            },
9334            Some(tree_sitter_rust::language()),
9335        ));
9336
9337        let text = "
9338            fn a() {
9339                //b();
9340                // c();
9341                //  d();
9342            }
9343        "
9344        .unindent();
9345
9346        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
9347        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9348        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
9349
9350        view.update(cx, |editor, cx| {
9351            // If multiple selections intersect a line, the line is only
9352            // toggled once.
9353            editor.change_selections(None, cx, |s| {
9354                s.select_display_ranges([
9355                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
9356                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
9357                ])
9358            });
9359            editor.toggle_comments(&ToggleComments, cx);
9360            assert_eq!(
9361                editor.text(cx),
9362                "
9363                    fn a() {
9364                        b();
9365                        c();
9366                         d();
9367                    }
9368                "
9369                .unindent()
9370            );
9371
9372            // The comment prefix is inserted at the same column for every line
9373            // in a selection.
9374            editor.change_selections(None, cx, |s| {
9375                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
9376            });
9377            editor.toggle_comments(&ToggleComments, cx);
9378            assert_eq!(
9379                editor.text(cx),
9380                "
9381                    fn a() {
9382                        // b();
9383                        // c();
9384                        //  d();
9385                    }
9386                "
9387                .unindent()
9388            );
9389
9390            // If a selection ends at the beginning of a line, that line is not toggled.
9391            editor.change_selections(None, cx, |s| {
9392                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
9393            });
9394            editor.toggle_comments(&ToggleComments, cx);
9395            assert_eq!(
9396                editor.text(cx),
9397                "
9398                        fn a() {
9399                            // b();
9400                            c();
9401                            //  d();
9402                        }
9403                    "
9404                .unindent()
9405            );
9406        });
9407    }
9408
9409    #[gpui::test]
9410    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
9411        cx.set_global(Settings::test(cx));
9412        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9413        let multibuffer = cx.add_model(|cx| {
9414            let mut multibuffer = MultiBuffer::new(0);
9415            multibuffer.push_excerpts(
9416                buffer.clone(),
9417                [
9418                    Point::new(0, 0)..Point::new(0, 4),
9419                    Point::new(1, 0)..Point::new(1, 4),
9420                ],
9421                cx,
9422            );
9423            multibuffer
9424        });
9425
9426        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
9427
9428        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9429        view.update(cx, |view, cx| {
9430            assert_eq!(view.text(cx), "aaaa\nbbbb");
9431            view.change_selections(None, cx, |s| {
9432                s.select_ranges([
9433                    Point::new(0, 0)..Point::new(0, 0),
9434                    Point::new(1, 0)..Point::new(1, 0),
9435                ])
9436            });
9437
9438            view.handle_input(&Input("X".to_string()), cx);
9439            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
9440            assert_eq!(
9441                view.selections.ranges(cx),
9442                [
9443                    Point::new(0, 1)..Point::new(0, 1),
9444                    Point::new(1, 1)..Point::new(1, 1),
9445                ]
9446            )
9447        });
9448    }
9449
9450    #[gpui::test]
9451    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
9452        cx.set_global(Settings::test(cx));
9453        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
9454                [aaaa
9455                (bbbb]
9456                cccc)"});
9457        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
9458        let multibuffer = cx.add_model(|cx| {
9459            let mut multibuffer = MultiBuffer::new(0);
9460            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
9461            multibuffer
9462        });
9463
9464        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9465        view.update(cx, |view, cx| {
9466            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
9467                aaaa
9468                b|bbb
9469                b|bb|b
9470                cccc"});
9471            assert_eq!(view.text(cx), expected_text);
9472            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
9473
9474            view.handle_input(&Input("X".to_string()), cx);
9475
9476            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
9477                aaaa
9478                bX|bbXb
9479                bX|bbX|b
9480                cccc"});
9481            assert_eq!(view.text(cx), expected_text);
9482            assert_eq!(view.selections.ranges(cx), expected_selections);
9483
9484            view.newline(&Newline, cx);
9485            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
9486                aaaa
9487                bX
9488                |bbX
9489                b
9490                bX
9491                |bbX
9492                |b
9493                cccc"});
9494            assert_eq!(view.text(cx), expected_text);
9495            assert_eq!(view.selections.ranges(cx), expected_selections);
9496        });
9497    }
9498
9499    #[gpui::test]
9500    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
9501        cx.set_global(Settings::test(cx));
9502        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9503        let mut excerpt1_id = None;
9504        let multibuffer = cx.add_model(|cx| {
9505            let mut multibuffer = MultiBuffer::new(0);
9506            excerpt1_id = multibuffer
9507                .push_excerpts(
9508                    buffer.clone(),
9509                    [
9510                        Point::new(0, 0)..Point::new(1, 4),
9511                        Point::new(1, 0)..Point::new(2, 4),
9512                    ],
9513                    cx,
9514                )
9515                .into_iter()
9516                .next();
9517            multibuffer
9518        });
9519        assert_eq!(
9520            multibuffer.read(cx).read(cx).text(),
9521            "aaaa\nbbbb\nbbbb\ncccc"
9522        );
9523        let (_, editor) = cx.add_window(Default::default(), |cx| {
9524            let mut editor = build_editor(multibuffer.clone(), cx);
9525            let snapshot = editor.snapshot(cx);
9526            editor.change_selections(None, cx, |s| {
9527                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
9528            });
9529            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
9530            assert_eq!(
9531                editor.selections.ranges(cx),
9532                [
9533                    Point::new(1, 3)..Point::new(1, 3),
9534                    Point::new(2, 1)..Point::new(2, 1),
9535                ]
9536            );
9537            editor
9538        });
9539
9540        // Refreshing selections is a no-op when excerpts haven't changed.
9541        editor.update(cx, |editor, cx| {
9542            editor.change_selections(None, cx, |s| {
9543                s.refresh();
9544            });
9545            assert_eq!(
9546                editor.selections.ranges(cx),
9547                [
9548                    Point::new(1, 3)..Point::new(1, 3),
9549                    Point::new(2, 1)..Point::new(2, 1),
9550                ]
9551            );
9552        });
9553
9554        multibuffer.update(cx, |multibuffer, cx| {
9555            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9556        });
9557        editor.update(cx, |editor, cx| {
9558            // Removing an excerpt causes the first selection to become degenerate.
9559            assert_eq!(
9560                editor.selections.ranges(cx),
9561                [
9562                    Point::new(0, 0)..Point::new(0, 0),
9563                    Point::new(0, 1)..Point::new(0, 1)
9564                ]
9565            );
9566
9567            // Refreshing selections will relocate the first selection to the original buffer
9568            // location.
9569            editor.change_selections(None, cx, |s| {
9570                s.refresh();
9571            });
9572            assert_eq!(
9573                editor.selections.ranges(cx),
9574                [
9575                    Point::new(0, 1)..Point::new(0, 1),
9576                    Point::new(0, 3)..Point::new(0, 3)
9577                ]
9578            );
9579            assert!(editor.selections.pending_anchor().is_some());
9580        });
9581    }
9582
9583    #[gpui::test]
9584    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
9585        cx.set_global(Settings::test(cx));
9586        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9587        let mut excerpt1_id = None;
9588        let multibuffer = cx.add_model(|cx| {
9589            let mut multibuffer = MultiBuffer::new(0);
9590            excerpt1_id = multibuffer
9591                .push_excerpts(
9592                    buffer.clone(),
9593                    [
9594                        Point::new(0, 0)..Point::new(1, 4),
9595                        Point::new(1, 0)..Point::new(2, 4),
9596                    ],
9597                    cx,
9598                )
9599                .into_iter()
9600                .next();
9601            multibuffer
9602        });
9603        assert_eq!(
9604            multibuffer.read(cx).read(cx).text(),
9605            "aaaa\nbbbb\nbbbb\ncccc"
9606        );
9607        let (_, editor) = cx.add_window(Default::default(), |cx| {
9608            let mut editor = build_editor(multibuffer.clone(), cx);
9609            let snapshot = editor.snapshot(cx);
9610            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
9611            assert_eq!(
9612                editor.selections.ranges(cx),
9613                [Point::new(1, 3)..Point::new(1, 3)]
9614            );
9615            editor
9616        });
9617
9618        multibuffer.update(cx, |multibuffer, cx| {
9619            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9620        });
9621        editor.update(cx, |editor, cx| {
9622            assert_eq!(
9623                editor.selections.ranges(cx),
9624                [Point::new(0, 0)..Point::new(0, 0)]
9625            );
9626
9627            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
9628            editor.change_selections(None, cx, |s| {
9629                s.refresh();
9630            });
9631            assert_eq!(
9632                editor.selections.ranges(cx),
9633                [Point::new(0, 3)..Point::new(0, 3)]
9634            );
9635            assert!(editor.selections.pending_anchor().is_some());
9636        });
9637    }
9638
9639    #[gpui::test]
9640    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
9641        cx.update(|cx| cx.set_global(Settings::test(cx)));
9642        let language = Arc::new(Language::new(
9643            LanguageConfig {
9644                brackets: vec![
9645                    BracketPair {
9646                        start: "{".to_string(),
9647                        end: "}".to_string(),
9648                        close: true,
9649                        newline: true,
9650                    },
9651                    BracketPair {
9652                        start: "/* ".to_string(),
9653                        end: " */".to_string(),
9654                        close: true,
9655                        newline: true,
9656                    },
9657                ],
9658                ..Default::default()
9659            },
9660            Some(tree_sitter_rust::language()),
9661        ));
9662
9663        let text = concat!(
9664            "{   }\n",     // Suppress rustfmt
9665            "  x\n",       //
9666            "  /*   */\n", //
9667            "x\n",         //
9668            "{{} }\n",     //
9669        );
9670
9671        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
9672        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9673        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
9674        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
9675            .await;
9676
9677        view.update(cx, |view, cx| {
9678            view.change_selections(None, cx, |s| {
9679                s.select_display_ranges([
9680                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
9681                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
9682                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
9683                ])
9684            });
9685            view.newline(&Newline, cx);
9686
9687            assert_eq!(
9688                view.buffer().read(cx).read(cx).text(),
9689                concat!(
9690                    "{ \n",    // Suppress rustfmt
9691                    "\n",      //
9692                    "}\n",     //
9693                    "  x\n",   //
9694                    "  /* \n", //
9695                    "  \n",    //
9696                    "  */\n",  //
9697                    "x\n",     //
9698                    "{{} \n",  //
9699                    "}\n",     //
9700                )
9701            );
9702        });
9703    }
9704
9705    #[gpui::test]
9706    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
9707        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9708
9709        cx.set_global(Settings::test(cx));
9710        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9711
9712        editor.update(cx, |editor, cx| {
9713            struct Type1;
9714            struct Type2;
9715
9716            let buffer = buffer.read(cx).snapshot(cx);
9717
9718            let anchor_range = |range: Range<Point>| {
9719                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
9720            };
9721
9722            editor.highlight_background::<Type1>(
9723                vec![
9724                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
9725                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
9726                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
9727                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
9728                ],
9729                |_| Color::red(),
9730                cx,
9731            );
9732            editor.highlight_background::<Type2>(
9733                vec![
9734                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
9735                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
9736                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
9737                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
9738                ],
9739                |_| Color::green(),
9740                cx,
9741            );
9742
9743            let snapshot = editor.snapshot(cx);
9744            let mut highlighted_ranges = editor.background_highlights_in_range(
9745                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
9746                &snapshot,
9747                cx.global::<Settings>().theme.as_ref(),
9748            );
9749            // Enforce a consistent ordering based on color without relying on the ordering of the
9750            // highlight's `TypeId` which is non-deterministic.
9751            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
9752            assert_eq!(
9753                highlighted_ranges,
9754                &[
9755                    (
9756                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
9757                        Color::green(),
9758                    ),
9759                    (
9760                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
9761                        Color::green(),
9762                    ),
9763                    (
9764                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
9765                        Color::red(),
9766                    ),
9767                    (
9768                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9769                        Color::red(),
9770                    ),
9771                ]
9772            );
9773            assert_eq!(
9774                editor.background_highlights_in_range(
9775                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
9776                    &snapshot,
9777                    cx.global::<Settings>().theme.as_ref(),
9778                ),
9779                &[(
9780                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9781                    Color::red(),
9782                )]
9783            );
9784        });
9785    }
9786
9787    #[gpui::test]
9788    fn test_following(cx: &mut gpui::MutableAppContext) {
9789        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9790
9791        cx.set_global(Settings::test(cx));
9792
9793        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9794        let (_, follower) = cx.add_window(
9795            WindowOptions {
9796                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
9797                ..Default::default()
9798            },
9799            |cx| build_editor(buffer.clone(), cx),
9800        );
9801
9802        let pending_update = Rc::new(RefCell::new(None));
9803        follower.update(cx, {
9804            let update = pending_update.clone();
9805            |_, cx| {
9806                cx.subscribe(&leader, move |_, leader, event, cx| {
9807                    leader
9808                        .read(cx)
9809                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
9810                })
9811                .detach();
9812            }
9813        });
9814
9815        // Update the selections only
9816        leader.update(cx, |leader, cx| {
9817            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
9818        });
9819        follower.update(cx, |follower, cx| {
9820            follower
9821                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9822                .unwrap();
9823        });
9824        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
9825
9826        // Update the scroll position only
9827        leader.update(cx, |leader, cx| {
9828            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9829        });
9830        follower.update(cx, |follower, cx| {
9831            follower
9832                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9833                .unwrap();
9834        });
9835        assert_eq!(
9836            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
9837            vec2f(1.5, 3.5)
9838        );
9839
9840        // Update the selections and scroll position
9841        leader.update(cx, |leader, cx| {
9842            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
9843            leader.request_autoscroll(Autoscroll::Newest, cx);
9844            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9845        });
9846        follower.update(cx, |follower, cx| {
9847            let initial_scroll_position = follower.scroll_position(cx);
9848            follower
9849                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9850                .unwrap();
9851            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
9852            assert!(follower.autoscroll_request.is_some());
9853        });
9854        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
9855
9856        // Creating a pending selection that precedes another selection
9857        leader.update(cx, |leader, cx| {
9858            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
9859            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
9860        });
9861        follower.update(cx, |follower, cx| {
9862            follower
9863                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9864                .unwrap();
9865        });
9866        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
9867
9868        // Extend the pending selection so that it surrounds another selection
9869        leader.update(cx, |leader, cx| {
9870            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
9871        });
9872        follower.update(cx, |follower, cx| {
9873            follower
9874                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9875                .unwrap();
9876        });
9877        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
9878    }
9879
9880    #[test]
9881    fn test_combine_syntax_and_fuzzy_match_highlights() {
9882        let string = "abcdefghijklmnop";
9883        let syntax_ranges = [
9884            (
9885                0..3,
9886                HighlightStyle {
9887                    color: Some(Color::red()),
9888                    ..Default::default()
9889                },
9890            ),
9891            (
9892                4..8,
9893                HighlightStyle {
9894                    color: Some(Color::green()),
9895                    ..Default::default()
9896                },
9897            ),
9898        ];
9899        let match_indices = [4, 6, 7, 8];
9900        assert_eq!(
9901            combine_syntax_and_fuzzy_match_highlights(
9902                &string,
9903                Default::default(),
9904                syntax_ranges.into_iter(),
9905                &match_indices,
9906            ),
9907            &[
9908                (
9909                    0..3,
9910                    HighlightStyle {
9911                        color: Some(Color::red()),
9912                        ..Default::default()
9913                    },
9914                ),
9915                (
9916                    4..5,
9917                    HighlightStyle {
9918                        color: Some(Color::green()),
9919                        weight: Some(fonts::Weight::BOLD),
9920                        ..Default::default()
9921                    },
9922                ),
9923                (
9924                    5..6,
9925                    HighlightStyle {
9926                        color: Some(Color::green()),
9927                        ..Default::default()
9928                    },
9929                ),
9930                (
9931                    6..8,
9932                    HighlightStyle {
9933                        color: Some(Color::green()),
9934                        weight: Some(fonts::Weight::BOLD),
9935                        ..Default::default()
9936                    },
9937                ),
9938                (
9939                    8..9,
9940                    HighlightStyle {
9941                        weight: Some(fonts::Weight::BOLD),
9942                        ..Default::default()
9943                    },
9944                ),
9945            ]
9946        );
9947    }
9948
9949    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
9950        let point = DisplayPoint::new(row as u32, column as u32);
9951        point..point
9952    }
9953
9954    fn assert_selection_ranges(
9955        marked_text: &str,
9956        selection_marker_pairs: Vec<(char, char)>,
9957        view: &mut Editor,
9958        cx: &mut ViewContext<Editor>,
9959    ) {
9960        let snapshot = view.snapshot(cx).display_snapshot;
9961        let mut marker_chars = Vec::new();
9962        for (start, end) in selection_marker_pairs.iter() {
9963            marker_chars.push(*start);
9964            marker_chars.push(*end);
9965        }
9966        let (_, markers) = marked_text_by(marked_text, marker_chars);
9967        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
9968            .iter()
9969            .map(|(start, end)| {
9970                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
9971                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
9972                start..end
9973            })
9974            .collect();
9975        assert_eq!(
9976            view.selections.display_ranges(cx),
9977            &asserted_ranges[..],
9978            "Assert selections are {}",
9979            marked_text
9980        );
9981    }
9982}
9983
9984trait RangeExt<T> {
9985    fn sorted(&self) -> Range<T>;
9986    fn to_inclusive(&self) -> RangeInclusive<T>;
9987}
9988
9989impl<T: Ord + Clone> RangeExt<T> for Range<T> {
9990    fn sorted(&self) -> Self {
9991        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
9992    }
9993
9994    fn to_inclusive(&self) -> RangeInclusive<T> {
9995        self.start.clone()..=self.end.clone()
9996    }
9997}