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