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 hover = HoverPopover {
2443            // TODO: beginning of symbol based on range
2444            point: action.0,
2445            text: "Test hover information".to_string(),
2446            runs: Vec::new(),
2447        };
2448
2449        let id = post_inc(&mut self.next_completion_id);
2450        let task = cx.spawn_weak(|this, mut cx| {
2451            async move {
2452                if let Some(this) = this.upgrade(&cx) {
2453                    this.update(&mut cx, |this, cx| {
2454                        if !matches!(
2455                            this.context_menu.as_ref(),
2456                            None | Some(ContextMenu::Hover(_))
2457                        ) {
2458                            return;
2459                        }
2460
2461                        if this.focused {
2462                            this.show_context_menu(ContextMenu::Hover(hover), cx);
2463                        }
2464
2465                        cx.notify();
2466                    });
2467                }
2468                Ok::<_, anyhow::Error>(())
2469            }
2470            .log_err()
2471        });
2472        self.completion_tasks.push((id, task));
2473    }
2474
2475    async fn open_project_transaction(
2476        this: ViewHandle<Editor>,
2477        workspace: ViewHandle<Workspace>,
2478        transaction: ProjectTransaction,
2479        title: String,
2480        mut cx: AsyncAppContext,
2481    ) -> Result<()> {
2482        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
2483
2484        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2485        entries.sort_unstable_by_key(|(buffer, _)| {
2486            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2487        });
2488
2489        // If the project transaction's edits are all contained within this editor, then
2490        // avoid opening a new editor to display them.
2491
2492        if let Some((buffer, transaction)) = entries.first() {
2493            if entries.len() == 1 {
2494                let excerpt = this.read_with(&cx, |editor, cx| {
2495                    editor
2496                        .buffer()
2497                        .read(cx)
2498                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2499                });
2500                if let Some((excerpted_buffer, excerpt_range)) = excerpt {
2501                    if excerpted_buffer == *buffer {
2502                        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
2503                        let excerpt_range = excerpt_range.to_offset(&snapshot);
2504                        if snapshot
2505                            .edited_ranges_for_transaction(transaction)
2506                            .all(|range| {
2507                                excerpt_range.start <= range.start && excerpt_range.end >= range.end
2508                            })
2509                        {
2510                            return Ok(());
2511                        }
2512                    }
2513                }
2514            }
2515        } else {
2516            return Ok(());
2517        }
2518
2519        let mut ranges_to_highlight = Vec::new();
2520        let excerpt_buffer = cx.add_model(|cx| {
2521            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2522            for (buffer, transaction) in &entries {
2523                let snapshot = buffer.read(cx).snapshot();
2524                ranges_to_highlight.extend(
2525                    multibuffer.push_excerpts_with_context_lines(
2526                        buffer.clone(),
2527                        snapshot
2528                            .edited_ranges_for_transaction::<usize>(transaction)
2529                            .collect(),
2530                        1,
2531                        cx,
2532                    ),
2533                );
2534            }
2535            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
2536            multibuffer
2537        });
2538
2539        workspace.update(&mut cx, |workspace, cx| {
2540            let project = workspace.project().clone();
2541            let editor =
2542                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2543            workspace.add_item(Box::new(editor.clone()), cx);
2544            editor.update(cx, |editor, cx| {
2545                editor.highlight_background::<Self>(
2546                    ranges_to_highlight,
2547                    |theme| theme.editor.highlighted_line_background,
2548                    cx,
2549                );
2550            });
2551        });
2552
2553        Ok(())
2554    }
2555
2556    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2557        let project = self.project.as_ref()?;
2558        let buffer = self.buffer.read(cx);
2559        let newest_selection = self.selections.newest_anchor().clone();
2560        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2561        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2562        if start_buffer != end_buffer {
2563            return None;
2564        }
2565
2566        let actions = project.update(cx, |project, cx| {
2567            project.code_actions(&start_buffer, start..end, cx)
2568        });
2569        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
2570            let actions = actions.await;
2571            if let Some(this) = this.upgrade(&cx) {
2572                this.update(&mut cx, |this, cx| {
2573                    this.available_code_actions = actions.log_err().and_then(|actions| {
2574                        if actions.is_empty() {
2575                            None
2576                        } else {
2577                            Some((start_buffer, actions.into()))
2578                        }
2579                    });
2580                    cx.notify();
2581                })
2582            }
2583        }));
2584        None
2585    }
2586
2587    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2588        if self.pending_rename.is_some() {
2589            return None;
2590        }
2591
2592        let project = self.project.as_ref()?;
2593        let buffer = self.buffer.read(cx);
2594        let newest_selection = self.selections.newest_anchor().clone();
2595        let cursor_position = newest_selection.head();
2596        let (cursor_buffer, cursor_buffer_position) =
2597            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2598        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2599        if cursor_buffer != tail_buffer {
2600            return None;
2601        }
2602
2603        let highlights = project.update(cx, |project, cx| {
2604            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2605        });
2606
2607        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
2608            let highlights = highlights.log_err().await;
2609            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
2610                this.update(&mut cx, |this, cx| {
2611                    if this.pending_rename.is_some() {
2612                        return;
2613                    }
2614
2615                    let buffer_id = cursor_position.buffer_id;
2616                    let buffer = this.buffer.read(cx);
2617                    if !buffer
2618                        .text_anchor_for_position(cursor_position, cx)
2619                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2620                    {
2621                        return;
2622                    }
2623
2624                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2625                    let mut write_ranges = Vec::new();
2626                    let mut read_ranges = Vec::new();
2627                    for highlight in highlights {
2628                        for (excerpt_id, excerpt_range) in
2629                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2630                        {
2631                            let start = highlight
2632                                .range
2633                                .start
2634                                .max(&excerpt_range.start, cursor_buffer_snapshot);
2635                            let end = highlight
2636                                .range
2637                                .end
2638                                .min(&excerpt_range.end, cursor_buffer_snapshot);
2639                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2640                                continue;
2641                            }
2642
2643                            let range = Anchor {
2644                                buffer_id,
2645                                excerpt_id: excerpt_id.clone(),
2646                                text_anchor: start,
2647                            }..Anchor {
2648                                buffer_id,
2649                                excerpt_id,
2650                                text_anchor: end,
2651                            };
2652                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2653                                write_ranges.push(range);
2654                            } else {
2655                                read_ranges.push(range);
2656                            }
2657                        }
2658                    }
2659
2660                    this.highlight_background::<DocumentHighlightRead>(
2661                        read_ranges,
2662                        |theme| theme.editor.document_highlight_read_background,
2663                        cx,
2664                    );
2665                    this.highlight_background::<DocumentHighlightWrite>(
2666                        write_ranges,
2667                        |theme| theme.editor.document_highlight_write_background,
2668                        cx,
2669                    );
2670                    cx.notify();
2671                });
2672            }
2673        }));
2674        None
2675    }
2676
2677    pub fn render_code_actions_indicator(
2678        &self,
2679        style: &EditorStyle,
2680        cx: &mut RenderContext<Self>,
2681    ) -> Option<ElementBox> {
2682        if self.available_code_actions.is_some() {
2683            enum Tag {}
2684            Some(
2685                MouseEventHandler::new::<Tag, _, _>(0, cx, |_, _| {
2686                    Svg::new("icons/zap.svg")
2687                        .with_color(style.code_actions_indicator)
2688                        .boxed()
2689                })
2690                .with_cursor_style(CursorStyle::PointingHand)
2691                .with_padding(Padding::uniform(3.))
2692                .on_mouse_down(|_, cx| {
2693                    cx.dispatch_action(ToggleCodeActions {
2694                        deployed_from_indicator: true,
2695                    });
2696                })
2697                .boxed(),
2698            )
2699        } else {
2700            None
2701        }
2702    }
2703
2704    pub fn context_menu_visible(&self) -> bool {
2705        self.context_menu
2706            .as_ref()
2707            .map_or(false, |menu| menu.visible())
2708    }
2709
2710    pub fn render_context_menu(
2711        &self,
2712        cursor_position: DisplayPoint,
2713        style: EditorStyle,
2714        cx: &mut RenderContext<Editor>,
2715    ) -> Option<(DisplayPoint, ElementBox)> {
2716        self.context_menu
2717            .as_ref()
2718            .map(|menu| menu.render(cursor_position, style))
2719    }
2720
2721    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
2722        if !matches!(menu, ContextMenu::Completions(_)) {
2723            self.completion_tasks.clear();
2724        }
2725        self.context_menu = Some(menu);
2726        cx.notify();
2727    }
2728
2729    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
2730        cx.notify();
2731        self.completion_tasks.clear();
2732        self.context_menu.take()
2733    }
2734
2735    pub fn insert_snippet(
2736        &mut self,
2737        insertion_ranges: &[Range<usize>],
2738        snippet: Snippet,
2739        cx: &mut ViewContext<Self>,
2740    ) -> Result<()> {
2741        let tabstops = self.buffer.update(cx, |buffer, cx| {
2742            let snippet_text: Arc<str> = snippet.text.clone().into();
2743            buffer.edit_with_autoindent(
2744                insertion_ranges
2745                    .iter()
2746                    .cloned()
2747                    .map(|range| (range, snippet_text.clone())),
2748                cx,
2749            );
2750
2751            let snapshot = &*buffer.read(cx);
2752            let snippet = &snippet;
2753            snippet
2754                .tabstops
2755                .iter()
2756                .map(|tabstop| {
2757                    let mut tabstop_ranges = tabstop
2758                        .iter()
2759                        .flat_map(|tabstop_range| {
2760                            let mut delta = 0 as isize;
2761                            insertion_ranges.iter().map(move |insertion_range| {
2762                                let insertion_start = insertion_range.start as isize + delta;
2763                                delta +=
2764                                    snippet.text.len() as isize - insertion_range.len() as isize;
2765
2766                                let start = snapshot.anchor_before(
2767                                    (insertion_start + tabstop_range.start) as usize,
2768                                );
2769                                let end = snapshot
2770                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
2771                                start..end
2772                            })
2773                        })
2774                        .collect::<Vec<_>>();
2775                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
2776                    tabstop_ranges
2777                })
2778                .collect::<Vec<_>>()
2779        });
2780
2781        if let Some(tabstop) = tabstops.first() {
2782            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2783                s.select_ranges(tabstop.iter().cloned());
2784            });
2785            self.snippet_stack.push(SnippetState {
2786                active_index: 0,
2787                ranges: tabstops,
2788            });
2789        }
2790
2791        Ok(())
2792    }
2793
2794    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2795        self.move_to_snippet_tabstop(Bias::Right, cx)
2796    }
2797
2798    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2799        self.move_to_snippet_tabstop(Bias::Left, cx)
2800    }
2801
2802    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
2803        if let Some(mut snippet) = self.snippet_stack.pop() {
2804            match bias {
2805                Bias::Left => {
2806                    if snippet.active_index > 0 {
2807                        snippet.active_index -= 1;
2808                    } else {
2809                        self.snippet_stack.push(snippet);
2810                        return false;
2811                    }
2812                }
2813                Bias::Right => {
2814                    if snippet.active_index + 1 < snippet.ranges.len() {
2815                        snippet.active_index += 1;
2816                    } else {
2817                        self.snippet_stack.push(snippet);
2818                        return false;
2819                    }
2820                }
2821            }
2822            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
2823                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2824                    s.select_anchor_ranges(current_ranges.into_iter().cloned())
2825                });
2826                // If snippet state is not at the last tabstop, push it back on the stack
2827                if snippet.active_index + 1 < snippet.ranges.len() {
2828                    self.snippet_stack.push(snippet);
2829                }
2830                return true;
2831            }
2832        }
2833
2834        false
2835    }
2836
2837    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
2838        self.transact(cx, |this, cx| {
2839            this.select_all(&SelectAll, cx);
2840            this.insert("", cx);
2841        });
2842    }
2843
2844    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
2845        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2846        let mut selections = self.selections.all::<Point>(cx);
2847        if !self.selections.line_mode {
2848            for selection in &mut selections {
2849                if selection.is_empty() {
2850                    let old_head = selection.head();
2851                    let mut new_head =
2852                        movement::left(&display_map, old_head.to_display_point(&display_map))
2853                            .to_point(&display_map);
2854                    if let Some((buffer, line_buffer_range)) = display_map
2855                        .buffer_snapshot
2856                        .buffer_line_for_row(old_head.row)
2857                    {
2858                        let indent_column =
2859                            buffer.indent_column_for_line(line_buffer_range.start.row);
2860                        let language_name = buffer.language().map(|language| language.name());
2861                        let indent = cx.global::<Settings>().tab_size(language_name.as_deref());
2862                        if old_head.column <= indent_column && old_head.column > 0 {
2863                            new_head = cmp::min(
2864                                new_head,
2865                                Point::new(old_head.row, ((old_head.column - 1) / indent) * indent),
2866                            );
2867                        }
2868                    }
2869
2870                    selection.set_head(new_head, SelectionGoal::None);
2871                }
2872            }
2873        }
2874
2875        self.transact(cx, |this, cx| {
2876            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
2877            this.insert("", cx);
2878        });
2879    }
2880
2881    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
2882        self.transact(cx, |this, cx| {
2883            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
2884                let line_mode = s.line_mode;
2885                s.move_with(|map, selection| {
2886                    if selection.is_empty() && !line_mode {
2887                        let cursor = movement::right(map, selection.head());
2888                        selection.set_head(cursor, SelectionGoal::None);
2889                    }
2890                })
2891            });
2892            this.insert(&"", cx);
2893        });
2894    }
2895
2896    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
2897        if self.move_to_prev_snippet_tabstop(cx) {
2898            return;
2899        }
2900
2901        self.outdent(&Outdent, cx);
2902    }
2903
2904    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
2905        if self.move_to_next_snippet_tabstop(cx) {
2906            return;
2907        }
2908
2909        let mut selections = self.selections.all_adjusted(cx);
2910        if selections.iter().all(|s| s.is_empty()) {
2911            self.transact(cx, |this, cx| {
2912                this.buffer.update(cx, |buffer, cx| {
2913                    for selection in &mut selections {
2914                        let language_name =
2915                            buffer.language_at(selection.start, cx).map(|l| l.name());
2916                        let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
2917                        let char_column = buffer
2918                            .read(cx)
2919                            .text_for_range(Point::new(selection.start.row, 0)..selection.start)
2920                            .flat_map(str::chars)
2921                            .count();
2922                        let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
2923                        buffer.edit(
2924                            [(
2925                                selection.start..selection.start,
2926                                " ".repeat(chars_to_next_tab_stop as usize),
2927                            )],
2928                            cx,
2929                        );
2930                        selection.start.column += chars_to_next_tab_stop;
2931                        selection.end = selection.start;
2932                    }
2933                });
2934                this.change_selections(Some(Autoscroll::Fit), cx, |s| {
2935                    s.select(selections);
2936                });
2937            });
2938        } else {
2939            self.indent(&Indent, cx);
2940        }
2941    }
2942
2943    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
2944        let mut selections = self.selections.all::<Point>(cx);
2945        self.transact(cx, |this, cx| {
2946            let mut last_indent = None;
2947            this.buffer.update(cx, |buffer, cx| {
2948                let snapshot = buffer.snapshot(cx);
2949                for selection in &mut selections {
2950                    let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
2951                    let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
2952                    let mut start_row = selection.start.row;
2953                    let mut end_row = selection.end.row + 1;
2954
2955                    // If a selection ends at the beginning of a line, don't indent
2956                    // that last line.
2957                    if selection.end.column == 0 {
2958                        end_row -= 1;
2959                    }
2960
2961                    // Avoid re-indenting a row that has already been indented by a
2962                    // previous selection, but still update this selection's column
2963                    // to reflect that indentation.
2964                    if let Some((last_indent_row, last_indent_len)) = last_indent {
2965                        if last_indent_row == selection.start.row {
2966                            selection.start.column += last_indent_len;
2967                            start_row += 1;
2968                        }
2969                        if last_indent_row == selection.end.row {
2970                            selection.end.column += last_indent_len;
2971                        }
2972                    }
2973
2974                    for row in start_row..end_row {
2975                        let indent_column = snapshot.indent_column_for_line(row);
2976                        let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
2977                        let row_start = Point::new(row, 0);
2978                        buffer.edit(
2979                            [(
2980                                row_start..row_start,
2981                                " ".repeat(columns_to_next_tab_stop as usize),
2982                            )],
2983                            cx,
2984                        );
2985
2986                        // Update this selection's endpoints to reflect the indentation.
2987                        if row == selection.start.row {
2988                            selection.start.column += columns_to_next_tab_stop as u32;
2989                        }
2990                        if row == selection.end.row {
2991                            selection.end.column += columns_to_next_tab_stop as u32;
2992                        }
2993
2994                        last_indent = Some((row, columns_to_next_tab_stop as u32));
2995                    }
2996                }
2997            });
2998
2999            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3000                s.select(selections);
3001            });
3002        });
3003    }
3004
3005    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3006        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3007        let selections = self.selections.all::<Point>(cx);
3008        let mut deletion_ranges = Vec::new();
3009        let mut last_outdent = None;
3010        {
3011            let buffer = self.buffer.read(cx);
3012            let snapshot = buffer.snapshot(cx);
3013            for selection in &selections {
3014                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3015                let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
3016                let mut rows = selection.spanned_rows(false, &display_map);
3017
3018                // Avoid re-outdenting a row that has already been outdented by a
3019                // previous selection.
3020                if let Some(last_row) = last_outdent {
3021                    if last_row == rows.start {
3022                        rows.start += 1;
3023                    }
3024                }
3025
3026                for row in rows {
3027                    let column = snapshot.indent_column_for_line(row);
3028                    if column > 0 {
3029                        let mut deletion_len = column % tab_size;
3030                        if deletion_len == 0 {
3031                            deletion_len = tab_size;
3032                        }
3033                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3034                        last_outdent = Some(row);
3035                    }
3036                }
3037            }
3038        }
3039
3040        self.transact(cx, |this, cx| {
3041            this.buffer.update(cx, |buffer, cx| {
3042                let empty_str: Arc<str> = "".into();
3043                buffer.edit(
3044                    deletion_ranges
3045                        .into_iter()
3046                        .map(|range| (range, empty_str.clone())),
3047                    cx,
3048                );
3049            });
3050            let selections = this.selections.all::<usize>(cx);
3051            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3052        });
3053    }
3054
3055    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3056        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3057        let selections = self.selections.all::<Point>(cx);
3058
3059        let mut new_cursors = Vec::new();
3060        let mut edit_ranges = Vec::new();
3061        let mut selections = selections.iter().peekable();
3062        while let Some(selection) = selections.next() {
3063            let mut rows = selection.spanned_rows(false, &display_map);
3064            let goal_display_column = selection.head().to_display_point(&display_map).column();
3065
3066            // Accumulate contiguous regions of rows that we want to delete.
3067            while let Some(next_selection) = selections.peek() {
3068                let next_rows = next_selection.spanned_rows(false, &display_map);
3069                if next_rows.start <= rows.end {
3070                    rows.end = next_rows.end;
3071                    selections.next().unwrap();
3072                } else {
3073                    break;
3074                }
3075            }
3076
3077            let buffer = &display_map.buffer_snapshot;
3078            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
3079            let edit_end;
3080            let cursor_buffer_row;
3081            if buffer.max_point().row >= rows.end {
3082                // If there's a line after the range, delete the \n from the end of the row range
3083                // and position the cursor on the next line.
3084                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
3085                cursor_buffer_row = rows.end;
3086            } else {
3087                // If there isn't a line after the range, delete the \n from the line before the
3088                // start of the row range and position the cursor there.
3089                edit_start = edit_start.saturating_sub(1);
3090                edit_end = buffer.len();
3091                cursor_buffer_row = rows.start.saturating_sub(1);
3092            }
3093
3094            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3095            *cursor.column_mut() =
3096                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3097
3098            new_cursors.push((
3099                selection.id,
3100                buffer.anchor_after(cursor.to_point(&display_map)),
3101            ));
3102            edit_ranges.push(edit_start..edit_end);
3103        }
3104
3105        self.transact(cx, |this, cx| {
3106            let buffer = this.buffer.update(cx, |buffer, cx| {
3107                let empty_str: Arc<str> = "".into();
3108                buffer.edit(
3109                    edit_ranges
3110                        .into_iter()
3111                        .map(|range| (range, empty_str.clone())),
3112                    cx,
3113                );
3114                buffer.snapshot(cx)
3115            });
3116            let new_selections = new_cursors
3117                .into_iter()
3118                .map(|(id, cursor)| {
3119                    let cursor = cursor.to_point(&buffer);
3120                    Selection {
3121                        id,
3122                        start: cursor,
3123                        end: cursor,
3124                        reversed: false,
3125                        goal: SelectionGoal::None,
3126                    }
3127                })
3128                .collect();
3129
3130            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3131                s.select(new_selections);
3132            });
3133        });
3134    }
3135
3136    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3137        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3138        let buffer = &display_map.buffer_snapshot;
3139        let selections = self.selections.all::<Point>(cx);
3140
3141        let mut edits = Vec::new();
3142        let mut selections_iter = selections.iter().peekable();
3143        while let Some(selection) = selections_iter.next() {
3144            // Avoid duplicating the same lines twice.
3145            let mut rows = selection.spanned_rows(false, &display_map);
3146
3147            while let Some(next_selection) = selections_iter.peek() {
3148                let next_rows = next_selection.spanned_rows(false, &display_map);
3149                if next_rows.start <= rows.end - 1 {
3150                    rows.end = next_rows.end;
3151                    selections_iter.next().unwrap();
3152                } else {
3153                    break;
3154                }
3155            }
3156
3157            // Copy the text from the selected row region and splice it at the start of the region.
3158            let start = Point::new(rows.start, 0);
3159            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3160            let text = buffer
3161                .text_for_range(start..end)
3162                .chain(Some("\n"))
3163                .collect::<String>();
3164            edits.push((start..start, text));
3165        }
3166
3167        self.transact(cx, |this, cx| {
3168            this.buffer.update(cx, |buffer, cx| {
3169                buffer.edit(edits, cx);
3170            });
3171
3172            this.request_autoscroll(Autoscroll::Fit, cx);
3173        });
3174    }
3175
3176    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3177        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3178        let buffer = self.buffer.read(cx).snapshot(cx);
3179
3180        let mut edits = Vec::new();
3181        let mut unfold_ranges = Vec::new();
3182        let mut refold_ranges = Vec::new();
3183
3184        let selections = self.selections.all::<Point>(cx);
3185        let mut selections = selections.iter().peekable();
3186        let mut contiguous_row_selections = Vec::new();
3187        let mut new_selections = Vec::new();
3188
3189        while let Some(selection) = selections.next() {
3190            // Find all the selections that span a contiguous row range
3191            contiguous_row_selections.push(selection.clone());
3192            let start_row = selection.start.row;
3193            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3194                display_map.next_line_boundary(selection.end).0.row + 1
3195            } else {
3196                selection.end.row
3197            };
3198
3199            while let Some(next_selection) = selections.peek() {
3200                if next_selection.start.row <= end_row {
3201                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3202                        display_map.next_line_boundary(next_selection.end).0.row + 1
3203                    } else {
3204                        next_selection.end.row
3205                    };
3206                    contiguous_row_selections.push(selections.next().unwrap().clone());
3207                } else {
3208                    break;
3209                }
3210            }
3211
3212            // Move the text spanned by the row range to be before the line preceding the row range
3213            if start_row > 0 {
3214                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3215                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3216                let insertion_point = display_map
3217                    .prev_line_boundary(Point::new(start_row - 1, 0))
3218                    .0;
3219
3220                // Don't move lines across excerpts
3221                if buffer
3222                    .excerpt_boundaries_in_range((
3223                        Bound::Excluded(insertion_point),
3224                        Bound::Included(range_to_move.end),
3225                    ))
3226                    .next()
3227                    .is_none()
3228                {
3229                    let text = buffer
3230                        .text_for_range(range_to_move.clone())
3231                        .flat_map(|s| s.chars())
3232                        .skip(1)
3233                        .chain(['\n'])
3234                        .collect::<String>();
3235
3236                    edits.push((
3237                        buffer.anchor_after(range_to_move.start)
3238                            ..buffer.anchor_before(range_to_move.end),
3239                        String::new(),
3240                    ));
3241                    let insertion_anchor = buffer.anchor_after(insertion_point);
3242                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3243
3244                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3245
3246                    // Move selections up
3247                    new_selections.extend(contiguous_row_selections.drain(..).map(
3248                        |mut selection| {
3249                            selection.start.row -= row_delta;
3250                            selection.end.row -= row_delta;
3251                            selection
3252                        },
3253                    ));
3254
3255                    // Move folds up
3256                    unfold_ranges.push(range_to_move.clone());
3257                    for fold in display_map.folds_in_range(
3258                        buffer.anchor_before(range_to_move.start)
3259                            ..buffer.anchor_after(range_to_move.end),
3260                    ) {
3261                        let mut start = fold.start.to_point(&buffer);
3262                        let mut end = fold.end.to_point(&buffer);
3263                        start.row -= row_delta;
3264                        end.row -= row_delta;
3265                        refold_ranges.push(start..end);
3266                    }
3267                }
3268            }
3269
3270            // If we didn't move line(s), preserve the existing selections
3271            new_selections.extend(contiguous_row_selections.drain(..));
3272        }
3273
3274        self.transact(cx, |this, cx| {
3275            this.unfold_ranges(unfold_ranges, true, cx);
3276            this.buffer.update(cx, |buffer, cx| {
3277                for (range, text) in edits {
3278                    buffer.edit([(range, text)], cx);
3279                }
3280            });
3281            this.fold_ranges(refold_ranges, cx);
3282            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3283                s.select(new_selections);
3284            })
3285        });
3286    }
3287
3288    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3289        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3290        let buffer = self.buffer.read(cx).snapshot(cx);
3291
3292        let mut edits = Vec::new();
3293        let mut unfold_ranges = Vec::new();
3294        let mut refold_ranges = Vec::new();
3295
3296        let selections = self.selections.all::<Point>(cx);
3297        let mut selections = selections.iter().peekable();
3298        let mut contiguous_row_selections = Vec::new();
3299        let mut new_selections = Vec::new();
3300
3301        while let Some(selection) = selections.next() {
3302            // Find all the selections that span a contiguous row range
3303            contiguous_row_selections.push(selection.clone());
3304            let start_row = selection.start.row;
3305            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3306                display_map.next_line_boundary(selection.end).0.row + 1
3307            } else {
3308                selection.end.row
3309            };
3310
3311            while let Some(next_selection) = selections.peek() {
3312                if next_selection.start.row <= end_row {
3313                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3314                        display_map.next_line_boundary(next_selection.end).0.row + 1
3315                    } else {
3316                        next_selection.end.row
3317                    };
3318                    contiguous_row_selections.push(selections.next().unwrap().clone());
3319                } else {
3320                    break;
3321                }
3322            }
3323
3324            // Move the text spanned by the row range to be after the last line of the row range
3325            if end_row <= buffer.max_point().row {
3326                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3327                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3328
3329                // Don't move lines across excerpt boundaries
3330                if buffer
3331                    .excerpt_boundaries_in_range((
3332                        Bound::Excluded(range_to_move.start),
3333                        Bound::Included(insertion_point),
3334                    ))
3335                    .next()
3336                    .is_none()
3337                {
3338                    let mut text = String::from("\n");
3339                    text.extend(buffer.text_for_range(range_to_move.clone()));
3340                    text.pop(); // Drop trailing newline
3341                    edits.push((
3342                        buffer.anchor_after(range_to_move.start)
3343                            ..buffer.anchor_before(range_to_move.end),
3344                        String::new(),
3345                    ));
3346                    let insertion_anchor = buffer.anchor_after(insertion_point);
3347                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3348
3349                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3350
3351                    // Move selections down
3352                    new_selections.extend(contiguous_row_selections.drain(..).map(
3353                        |mut selection| {
3354                            selection.start.row += row_delta;
3355                            selection.end.row += row_delta;
3356                            selection
3357                        },
3358                    ));
3359
3360                    // Move folds down
3361                    unfold_ranges.push(range_to_move.clone());
3362                    for fold in display_map.folds_in_range(
3363                        buffer.anchor_before(range_to_move.start)
3364                            ..buffer.anchor_after(range_to_move.end),
3365                    ) {
3366                        let mut start = fold.start.to_point(&buffer);
3367                        let mut end = fold.end.to_point(&buffer);
3368                        start.row += row_delta;
3369                        end.row += row_delta;
3370                        refold_ranges.push(start..end);
3371                    }
3372                }
3373            }
3374
3375            // If we didn't move line(s), preserve the existing selections
3376            new_selections.extend(contiguous_row_selections.drain(..));
3377        }
3378
3379        self.transact(cx, |this, cx| {
3380            this.unfold_ranges(unfold_ranges, true, cx);
3381            this.buffer.update(cx, |buffer, cx| {
3382                for (range, text) in edits {
3383                    buffer.edit([(range, text)], cx);
3384                }
3385            });
3386            this.fold_ranges(refold_ranges, cx);
3387            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
3388        });
3389    }
3390
3391    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3392        self.transact(cx, |this, cx| {
3393            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3394                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3395                let line_mode = s.line_mode;
3396                s.move_with(|display_map, selection| {
3397                    if !selection.is_empty() || line_mode {
3398                        return;
3399                    }
3400
3401                    let mut head = selection.head();
3402                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3403                    if head.column() == display_map.line_len(head.row()) {
3404                        transpose_offset = display_map
3405                            .buffer_snapshot
3406                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3407                    }
3408
3409                    if transpose_offset == 0 {
3410                        return;
3411                    }
3412
3413                    *head.column_mut() += 1;
3414                    head = display_map.clip_point(head, Bias::Right);
3415                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3416
3417                    let transpose_start = display_map
3418                        .buffer_snapshot
3419                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3420                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3421                        let transpose_end = display_map
3422                            .buffer_snapshot
3423                            .clip_offset(transpose_offset + 1, Bias::Right);
3424                        if let Some(ch) =
3425                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3426                        {
3427                            edits.push((transpose_start..transpose_offset, String::new()));
3428                            edits.push((transpose_end..transpose_end, ch.to_string()));
3429                        }
3430                    }
3431                });
3432                edits
3433            });
3434            this.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
3435            let selections = this.selections.all::<usize>(cx);
3436            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3437                s.select(selections);
3438            });
3439        });
3440    }
3441
3442    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3443        let mut text = String::new();
3444        let buffer = self.buffer.read(cx).snapshot(cx);
3445        let mut selections = self.selections.all::<Point>(cx);
3446        let mut clipboard_selections = Vec::with_capacity(selections.len());
3447        {
3448            let max_point = buffer.max_point();
3449            for selection in &mut selections {
3450                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3451                if is_entire_line {
3452                    selection.start = Point::new(selection.start.row, 0);
3453                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3454                    selection.goal = SelectionGoal::None;
3455                }
3456                let mut len = 0;
3457                for chunk in buffer.text_for_range(selection.start..selection.end) {
3458                    text.push_str(chunk);
3459                    len += chunk.len();
3460                }
3461                clipboard_selections.push(ClipboardSelection {
3462                    len,
3463                    is_entire_line,
3464                });
3465            }
3466        }
3467
3468        self.transact(cx, |this, cx| {
3469            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3470                s.select(selections);
3471            });
3472            this.insert("", cx);
3473            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3474        });
3475    }
3476
3477    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3478        let selections = self.selections.all::<Point>(cx);
3479        let buffer = self.buffer.read(cx).read(cx);
3480        let mut text = String::new();
3481
3482        let mut clipboard_selections = Vec::with_capacity(selections.len());
3483        {
3484            let max_point = buffer.max_point();
3485            for selection in selections.iter() {
3486                let mut start = selection.start;
3487                let mut end = selection.end;
3488                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3489                if is_entire_line {
3490                    start = Point::new(start.row, 0);
3491                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3492                }
3493                let mut len = 0;
3494                for chunk in buffer.text_for_range(start..end) {
3495                    text.push_str(chunk);
3496                    len += chunk.len();
3497                }
3498                clipboard_selections.push(ClipboardSelection {
3499                    len,
3500                    is_entire_line,
3501                });
3502            }
3503        }
3504
3505        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3506    }
3507
3508    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3509        self.transact(cx, |this, cx| {
3510            if let Some(item) = cx.as_mut().read_from_clipboard() {
3511                let mut clipboard_text = Cow::Borrowed(item.text());
3512                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3513                    let old_selections = this.selections.all::<usize>(cx);
3514                    let all_selections_were_entire_line =
3515                        clipboard_selections.iter().all(|s| s.is_entire_line);
3516                    if clipboard_selections.len() != old_selections.len() {
3517                        let mut newline_separated_text = String::new();
3518                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3519                        let mut ix = 0;
3520                        while let Some(clipboard_selection) = clipboard_selections.next() {
3521                            newline_separated_text
3522                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3523                            ix += clipboard_selection.len;
3524                            if clipboard_selections.peek().is_some() {
3525                                newline_separated_text.push('\n');
3526                            }
3527                        }
3528                        clipboard_text = Cow::Owned(newline_separated_text);
3529                    }
3530
3531                    this.buffer.update(cx, |buffer, cx| {
3532                        let snapshot = buffer.read(cx);
3533                        let mut start_offset = 0;
3534                        let mut edits = Vec::new();
3535                        let line_mode = this.selections.line_mode;
3536                        for (ix, selection) in old_selections.iter().enumerate() {
3537                            let to_insert;
3538                            let entire_line;
3539                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3540                                let end_offset = start_offset + clipboard_selection.len;
3541                                to_insert = &clipboard_text[start_offset..end_offset];
3542                                entire_line = clipboard_selection.is_entire_line;
3543                                start_offset = end_offset;
3544                            } else {
3545                                to_insert = clipboard_text.as_str();
3546                                entire_line = all_selections_were_entire_line;
3547                            }
3548
3549                            // If the corresponding selection was empty when this slice of the
3550                            // clipboard text was written, then the entire line containing the
3551                            // selection was copied. If this selection is also currently empty,
3552                            // then paste the line before the current line of the buffer.
3553                            let range = if selection.is_empty() && !line_mode && entire_line {
3554                                let column = selection.start.to_point(&snapshot).column as usize;
3555                                let line_start = selection.start - column;
3556                                line_start..line_start
3557                            } else {
3558                                selection.range()
3559                            };
3560
3561                            edits.push((range, to_insert));
3562                        }
3563                        drop(snapshot);
3564                        buffer.edit_with_autoindent(edits, cx);
3565                    });
3566
3567                    let selections = this.selections.all::<usize>(cx);
3568                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3569                } else {
3570                    this.insert(&clipboard_text, cx);
3571                }
3572            }
3573        });
3574    }
3575
3576    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3577        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3578            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3579                self.change_selections(None, cx, |s| {
3580                    s.select_anchors(selections.to_vec());
3581                });
3582            }
3583            self.request_autoscroll(Autoscroll::Fit, cx);
3584            cx.emit(Event::Edited);
3585        }
3586    }
3587
3588    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3589        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3590            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3591            {
3592                self.change_selections(None, cx, |s| {
3593                    s.select_anchors(selections.to_vec());
3594                });
3595            }
3596            self.request_autoscroll(Autoscroll::Fit, cx);
3597            cx.emit(Event::Edited);
3598        }
3599    }
3600
3601    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3602        self.buffer
3603            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3604    }
3605
3606    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3607        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3608            let line_mode = s.line_mode;
3609            s.move_with(|map, selection| {
3610                let cursor = if selection.is_empty() && !line_mode {
3611                    movement::left(map, selection.start)
3612                } else {
3613                    selection.start
3614                };
3615                selection.collapse_to(cursor, SelectionGoal::None);
3616            });
3617        })
3618    }
3619
3620    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3621        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3622            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3623        })
3624    }
3625
3626    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3627        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3628            let line_mode = s.line_mode;
3629            s.move_with(|map, selection| {
3630                let cursor = if selection.is_empty() && !line_mode {
3631                    movement::right(map, selection.end)
3632                } else {
3633                    selection.end
3634                };
3635                selection.collapse_to(cursor, SelectionGoal::None)
3636            });
3637        })
3638    }
3639
3640    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3641        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3642            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3643        })
3644    }
3645
3646    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3647        if self.take_rename(true, cx).is_some() {
3648            return;
3649        }
3650
3651        if let Some(context_menu) = self.context_menu.as_mut() {
3652            if context_menu.select_prev(cx) {
3653                return;
3654            }
3655        }
3656
3657        if matches!(self.mode, EditorMode::SingleLine) {
3658            cx.propagate_action();
3659            return;
3660        }
3661
3662        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3663            let line_mode = s.line_mode;
3664            s.move_with(|map, selection| {
3665                if !selection.is_empty() && !line_mode {
3666                    selection.goal = SelectionGoal::None;
3667                }
3668                let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false);
3669                selection.collapse_to(cursor, goal);
3670            });
3671        })
3672    }
3673
3674    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3675        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3676            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3677        })
3678    }
3679
3680    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3681        self.take_rename(true, cx);
3682
3683        if let Some(context_menu) = self.context_menu.as_mut() {
3684            if context_menu.select_next(cx) {
3685                return;
3686            }
3687        }
3688
3689        if matches!(self.mode, EditorMode::SingleLine) {
3690            cx.propagate_action();
3691            return;
3692        }
3693
3694        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3695            let line_mode = s.line_mode;
3696            s.move_with(|map, selection| {
3697                if !selection.is_empty() && !line_mode {
3698                    selection.goal = SelectionGoal::None;
3699                }
3700                let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false);
3701                selection.collapse_to(cursor, goal);
3702            });
3703        });
3704    }
3705
3706    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3707        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3708            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3709        });
3710    }
3711
3712    pub fn move_to_previous_word_start(
3713        &mut self,
3714        _: &MoveToPreviousWordStart,
3715        cx: &mut ViewContext<Self>,
3716    ) {
3717        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3718            s.move_cursors_with(|map, head, _| {
3719                (
3720                    movement::previous_word_start(map, head),
3721                    SelectionGoal::None,
3722                )
3723            });
3724        })
3725    }
3726
3727    pub fn move_to_previous_subword_start(
3728        &mut self,
3729        _: &MoveToPreviousSubwordStart,
3730        cx: &mut ViewContext<Self>,
3731    ) {
3732        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3733            s.move_cursors_with(|map, head, _| {
3734                (
3735                    movement::previous_subword_start(map, head),
3736                    SelectionGoal::None,
3737                )
3738            });
3739        })
3740    }
3741
3742    pub fn select_to_previous_word_start(
3743        &mut self,
3744        _: &SelectToPreviousWordStart,
3745        cx: &mut ViewContext<Self>,
3746    ) {
3747        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3748            s.move_heads_with(|map, head, _| {
3749                (
3750                    movement::previous_word_start(map, head),
3751                    SelectionGoal::None,
3752                )
3753            });
3754        })
3755    }
3756
3757    pub fn select_to_previous_subword_start(
3758        &mut self,
3759        _: &SelectToPreviousSubwordStart,
3760        cx: &mut ViewContext<Self>,
3761    ) {
3762        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3763            s.move_heads_with(|map, head, _| {
3764                (
3765                    movement::previous_subword_start(map, head),
3766                    SelectionGoal::None,
3767                )
3768            });
3769        })
3770    }
3771
3772    pub fn delete_to_previous_word_start(
3773        &mut self,
3774        _: &DeleteToPreviousWordStart,
3775        cx: &mut ViewContext<Self>,
3776    ) {
3777        self.transact(cx, |this, cx| {
3778            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3779                let line_mode = s.line_mode;
3780                s.move_with(|map, selection| {
3781                    if selection.is_empty() && !line_mode {
3782                        let cursor = movement::previous_word_start(map, selection.head());
3783                        selection.set_head(cursor, SelectionGoal::None);
3784                    }
3785                });
3786            });
3787            this.insert("", cx);
3788        });
3789    }
3790
3791    pub fn delete_to_previous_subword_start(
3792        &mut self,
3793        _: &DeleteToPreviousSubwordStart,
3794        cx: &mut ViewContext<Self>,
3795    ) {
3796        self.transact(cx, |this, cx| {
3797            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3798                let line_mode = s.line_mode;
3799                s.move_with(|map, selection| {
3800                    if selection.is_empty() && !line_mode {
3801                        let cursor = movement::previous_subword_start(map, selection.head());
3802                        selection.set_head(cursor, SelectionGoal::None);
3803                    }
3804                });
3805            });
3806            this.insert("", cx);
3807        });
3808    }
3809
3810    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3811        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3812            s.move_cursors_with(|map, head, _| {
3813                (movement::next_word_end(map, head), SelectionGoal::None)
3814            });
3815        })
3816    }
3817
3818    pub fn move_to_next_subword_end(
3819        &mut self,
3820        _: &MoveToNextSubwordEnd,
3821        cx: &mut ViewContext<Self>,
3822    ) {
3823        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3824            s.move_cursors_with(|map, head, _| {
3825                (movement::next_subword_end(map, head), SelectionGoal::None)
3826            });
3827        })
3828    }
3829
3830    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
3831        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3832            s.move_heads_with(|map, head, _| {
3833                (movement::next_word_end(map, head), SelectionGoal::None)
3834            });
3835        })
3836    }
3837
3838    pub fn select_to_next_subword_end(
3839        &mut self,
3840        _: &SelectToNextSubwordEnd,
3841        cx: &mut ViewContext<Self>,
3842    ) {
3843        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3844            s.move_heads_with(|map, head, _| {
3845                (movement::next_subword_end(map, head), SelectionGoal::None)
3846            });
3847        })
3848    }
3849
3850    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
3851        self.transact(cx, |this, cx| {
3852            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3853                let line_mode = s.line_mode;
3854                s.move_with(|map, selection| {
3855                    if selection.is_empty() && !line_mode {
3856                        let cursor = movement::next_word_end(map, selection.head());
3857                        selection.set_head(cursor, SelectionGoal::None);
3858                    }
3859                });
3860            });
3861            this.insert("", cx);
3862        });
3863    }
3864
3865    pub fn delete_to_next_subword_end(
3866        &mut self,
3867        _: &DeleteToNextSubwordEnd,
3868        cx: &mut ViewContext<Self>,
3869    ) {
3870        self.transact(cx, |this, cx| {
3871            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3872                s.move_with(|map, selection| {
3873                    if selection.is_empty() {
3874                        let cursor = movement::next_subword_end(map, selection.head());
3875                        selection.set_head(cursor, SelectionGoal::None);
3876                    }
3877                });
3878            });
3879            this.insert("", cx);
3880        });
3881    }
3882
3883    pub fn move_to_beginning_of_line(
3884        &mut self,
3885        _: &MoveToBeginningOfLine,
3886        cx: &mut ViewContext<Self>,
3887    ) {
3888        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3889            s.move_cursors_with(|map, head, _| {
3890                (
3891                    movement::line_beginning(map, head, true),
3892                    SelectionGoal::None,
3893                )
3894            });
3895        })
3896    }
3897
3898    pub fn select_to_beginning_of_line(
3899        &mut self,
3900        action: &SelectToBeginningOfLine,
3901        cx: &mut ViewContext<Self>,
3902    ) {
3903        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3904            s.move_heads_with(|map, head, _| {
3905                (
3906                    movement::line_beginning(map, head, action.stop_at_soft_wraps),
3907                    SelectionGoal::None,
3908                )
3909            });
3910        });
3911    }
3912
3913    pub fn delete_to_beginning_of_line(
3914        &mut self,
3915        _: &DeleteToBeginningOfLine,
3916        cx: &mut ViewContext<Self>,
3917    ) {
3918        self.transact(cx, |this, cx| {
3919            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3920                s.move_with(|_, selection| {
3921                    selection.reversed = true;
3922                });
3923            });
3924
3925            this.select_to_beginning_of_line(
3926                &SelectToBeginningOfLine {
3927                    stop_at_soft_wraps: false,
3928                },
3929                cx,
3930            );
3931            this.backspace(&Backspace, cx);
3932        });
3933    }
3934
3935    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
3936        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3937            s.move_cursors_with(|map, head, _| {
3938                (movement::line_end(map, head, true), SelectionGoal::None)
3939            });
3940        })
3941    }
3942
3943    pub fn select_to_end_of_line(
3944        &mut self,
3945        action: &SelectToEndOfLine,
3946        cx: &mut ViewContext<Self>,
3947    ) {
3948        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3949            s.move_heads_with(|map, head, _| {
3950                (
3951                    movement::line_end(map, head, action.stop_at_soft_wraps),
3952                    SelectionGoal::None,
3953                )
3954            });
3955        })
3956    }
3957
3958    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
3959        self.transact(cx, |this, cx| {
3960            this.select_to_end_of_line(
3961                &SelectToEndOfLine {
3962                    stop_at_soft_wraps: false,
3963                },
3964                cx,
3965            );
3966            this.delete(&Delete, cx);
3967        });
3968    }
3969
3970    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
3971        self.transact(cx, |this, cx| {
3972            this.select_to_end_of_line(
3973                &SelectToEndOfLine {
3974                    stop_at_soft_wraps: false,
3975                },
3976                cx,
3977            );
3978            this.cut(&Cut, cx);
3979        });
3980    }
3981
3982    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
3983        if matches!(self.mode, EditorMode::SingleLine) {
3984            cx.propagate_action();
3985            return;
3986        }
3987
3988        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3989            s.select_ranges(vec![0..0]);
3990        });
3991    }
3992
3993    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
3994        let mut selection = self.selections.last::<Point>(cx);
3995        selection.set_head(Point::zero(), SelectionGoal::None);
3996
3997        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3998            s.select(vec![selection]);
3999        });
4000    }
4001
4002    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4003        if matches!(self.mode, EditorMode::SingleLine) {
4004            cx.propagate_action();
4005            return;
4006        }
4007
4008        let cursor = self.buffer.read(cx).read(cx).len();
4009        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4010            s.select_ranges(vec![cursor..cursor])
4011        });
4012    }
4013
4014    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4015        self.nav_history = nav_history;
4016    }
4017
4018    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4019        self.nav_history.as_ref()
4020    }
4021
4022    fn push_to_nav_history(
4023        &self,
4024        position: Anchor,
4025        new_position: Option<Point>,
4026        cx: &mut ViewContext<Self>,
4027    ) {
4028        if let Some(nav_history) = &self.nav_history {
4029            let buffer = self.buffer.read(cx).read(cx);
4030            let point = position.to_point(&buffer);
4031            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
4032            drop(buffer);
4033
4034            if let Some(new_position) = new_position {
4035                let row_delta = (new_position.row as i64 - point.row as i64).abs();
4036                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4037                    return;
4038                }
4039            }
4040
4041            nav_history.push(Some(NavigationData {
4042                cursor_anchor: position,
4043                cursor_position: point,
4044                scroll_position: self.scroll_position,
4045                scroll_top_anchor: self.scroll_top_anchor.clone(),
4046                scroll_top_row,
4047            }));
4048        }
4049    }
4050
4051    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4052        let buffer = self.buffer.read(cx).snapshot(cx);
4053        let mut selection = self.selections.first::<usize>(cx);
4054        selection.set_head(buffer.len(), SelectionGoal::None);
4055        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4056            s.select(vec![selection]);
4057        });
4058    }
4059
4060    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4061        let end = self.buffer.read(cx).read(cx).len();
4062        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4063            s.select_ranges(vec![0..end]);
4064        });
4065    }
4066
4067    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4068        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4069        let mut selections = self.selections.all::<Point>(cx);
4070        let max_point = display_map.buffer_snapshot.max_point();
4071        for selection in &mut selections {
4072            let rows = selection.spanned_rows(true, &display_map);
4073            selection.start = Point::new(rows.start, 0);
4074            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4075            selection.reversed = false;
4076        }
4077        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4078            s.select(selections);
4079        });
4080    }
4081
4082    pub fn split_selection_into_lines(
4083        &mut self,
4084        _: &SplitSelectionIntoLines,
4085        cx: &mut ViewContext<Self>,
4086    ) {
4087        let mut to_unfold = Vec::new();
4088        let mut new_selection_ranges = Vec::new();
4089        {
4090            let selections = self.selections.all::<Point>(cx);
4091            let buffer = self.buffer.read(cx).read(cx);
4092            for selection in selections {
4093                for row in selection.start.row..selection.end.row {
4094                    let cursor = Point::new(row, buffer.line_len(row));
4095                    new_selection_ranges.push(cursor..cursor);
4096                }
4097                new_selection_ranges.push(selection.end..selection.end);
4098                to_unfold.push(selection.start..selection.end);
4099            }
4100        }
4101        self.unfold_ranges(to_unfold, true, cx);
4102        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4103            s.select_ranges(new_selection_ranges);
4104        });
4105    }
4106
4107    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4108        self.add_selection(true, cx);
4109    }
4110
4111    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4112        self.add_selection(false, cx);
4113    }
4114
4115    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4116        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4117        let mut selections = self.selections.all::<Point>(cx);
4118        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4119            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4120            let range = oldest_selection.display_range(&display_map).sorted();
4121            let columns = cmp::min(range.start.column(), range.end.column())
4122                ..cmp::max(range.start.column(), range.end.column());
4123
4124            selections.clear();
4125            let mut stack = Vec::new();
4126            for row in range.start.row()..=range.end.row() {
4127                if let Some(selection) = self.selections.build_columnar_selection(
4128                    &display_map,
4129                    row,
4130                    &columns,
4131                    oldest_selection.reversed,
4132                ) {
4133                    stack.push(selection.id);
4134                    selections.push(selection);
4135                }
4136            }
4137
4138            if above {
4139                stack.reverse();
4140            }
4141
4142            AddSelectionsState { above, stack }
4143        });
4144
4145        let last_added_selection = *state.stack.last().unwrap();
4146        let mut new_selections = Vec::new();
4147        if above == state.above {
4148            let end_row = if above {
4149                0
4150            } else {
4151                display_map.max_point().row()
4152            };
4153
4154            'outer: for selection in selections {
4155                if selection.id == last_added_selection {
4156                    let range = selection.display_range(&display_map).sorted();
4157                    debug_assert_eq!(range.start.row(), range.end.row());
4158                    let mut row = range.start.row();
4159                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4160                    {
4161                        start..end
4162                    } else {
4163                        cmp::min(range.start.column(), range.end.column())
4164                            ..cmp::max(range.start.column(), range.end.column())
4165                    };
4166
4167                    while row != end_row {
4168                        if above {
4169                            row -= 1;
4170                        } else {
4171                            row += 1;
4172                        }
4173
4174                        if let Some(new_selection) = self.selections.build_columnar_selection(
4175                            &display_map,
4176                            row,
4177                            &columns,
4178                            selection.reversed,
4179                        ) {
4180                            state.stack.push(new_selection.id);
4181                            if above {
4182                                new_selections.push(new_selection);
4183                                new_selections.push(selection);
4184                            } else {
4185                                new_selections.push(selection);
4186                                new_selections.push(new_selection);
4187                            }
4188
4189                            continue 'outer;
4190                        }
4191                    }
4192                }
4193
4194                new_selections.push(selection);
4195            }
4196        } else {
4197            new_selections = selections;
4198            new_selections.retain(|s| s.id != last_added_selection);
4199            state.stack.pop();
4200        }
4201
4202        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4203            s.select(new_selections);
4204        });
4205        if state.stack.len() > 1 {
4206            self.add_selections_state = Some(state);
4207        }
4208    }
4209
4210    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4211        self.push_to_selection_history();
4212        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4213        let buffer = &display_map.buffer_snapshot;
4214        let mut selections = self.selections.all::<usize>(cx);
4215        if let Some(mut select_next_state) = self.select_next_state.take() {
4216            let query = &select_next_state.query;
4217            if !select_next_state.done {
4218                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4219                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4220                let mut next_selected_range = None;
4221
4222                let bytes_after_last_selection =
4223                    buffer.bytes_in_range(last_selection.end..buffer.len());
4224                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4225                let query_matches = query
4226                    .stream_find_iter(bytes_after_last_selection)
4227                    .map(|result| (last_selection.end, result))
4228                    .chain(
4229                        query
4230                            .stream_find_iter(bytes_before_first_selection)
4231                            .map(|result| (0, result)),
4232                    );
4233                for (start_offset, query_match) in query_matches {
4234                    let query_match = query_match.unwrap(); // can only fail due to I/O
4235                    let offset_range =
4236                        start_offset + query_match.start()..start_offset + query_match.end();
4237                    let display_range = offset_range.start.to_display_point(&display_map)
4238                        ..offset_range.end.to_display_point(&display_map);
4239
4240                    if !select_next_state.wordwise
4241                        || (!movement::is_inside_word(&display_map, display_range.start)
4242                            && !movement::is_inside_word(&display_map, display_range.end))
4243                    {
4244                        next_selected_range = Some(offset_range);
4245                        break;
4246                    }
4247                }
4248
4249                if let Some(next_selected_range) = next_selected_range {
4250                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4251                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4252                        if action.replace_newest {
4253                            s.delete(s.newest_anchor().id);
4254                        }
4255                        s.insert_range(next_selected_range);
4256                    });
4257                } else {
4258                    select_next_state.done = true;
4259                }
4260            }
4261
4262            self.select_next_state = Some(select_next_state);
4263        } else if selections.len() == 1 {
4264            let selection = selections.last_mut().unwrap();
4265            if selection.start == selection.end {
4266                let word_range = movement::surrounding_word(
4267                    &display_map,
4268                    selection.start.to_display_point(&display_map),
4269                );
4270                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4271                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4272                selection.goal = SelectionGoal::None;
4273                selection.reversed = false;
4274
4275                let query = buffer
4276                    .text_for_range(selection.start..selection.end)
4277                    .collect::<String>();
4278                let select_state = SelectNextState {
4279                    query: AhoCorasick::new_auto_configured(&[query]),
4280                    wordwise: true,
4281                    done: false,
4282                };
4283                self.unfold_ranges([selection.start..selection.end], false, cx);
4284                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4285                    s.select(selections);
4286                });
4287                self.select_next_state = Some(select_state);
4288            } else {
4289                let query = buffer
4290                    .text_for_range(selection.start..selection.end)
4291                    .collect::<String>();
4292                self.select_next_state = Some(SelectNextState {
4293                    query: AhoCorasick::new_auto_configured(&[query]),
4294                    wordwise: false,
4295                    done: false,
4296                });
4297                self.select_next(action, cx);
4298            }
4299        }
4300    }
4301
4302    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4303        self.transact(cx, |this, cx| {
4304            let mut selections = this.selections.all::<Point>(cx);
4305            let mut all_selection_lines_are_comments = true;
4306            let mut edit_ranges = Vec::new();
4307            let mut last_toggled_row = None;
4308            this.buffer.update(cx, |buffer, cx| {
4309                // TODO: Handle selections that cross excerpts
4310                for selection in &mut selections {
4311                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
4312                    // as that portion won't be used for detecting if a line is a comment.
4313                    let full_comment_prefix: Arc<str> = if let Some(prefix) = buffer
4314                        .language_at(selection.start, cx)
4315                        .and_then(|l| l.line_comment_prefix())
4316                    {
4317                        prefix.into()
4318                    } else {
4319                        return;
4320                    };
4321                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4322                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4323                    edit_ranges.clear();
4324                    let snapshot = buffer.snapshot(cx);
4325
4326                    let end_row =
4327                        if selection.end.row > selection.start.row && selection.end.column == 0 {
4328                            selection.end.row
4329                        } else {
4330                            selection.end.row + 1
4331                        };
4332
4333                    for row in selection.start.row..end_row {
4334                        // If multiple selections contain a given row, avoid processing that
4335                        // row more than once.
4336                        if last_toggled_row == Some(row) {
4337                            continue;
4338                        } else {
4339                            last_toggled_row = Some(row);
4340                        }
4341
4342                        if snapshot.is_line_blank(row) {
4343                            continue;
4344                        }
4345
4346                        let start = Point::new(row, snapshot.indent_column_for_line(row));
4347                        let mut line_bytes = snapshot
4348                            .bytes_in_range(start..snapshot.max_point())
4349                            .flatten()
4350                            .copied();
4351
4352                        // If this line currently begins with the line comment prefix, then record
4353                        // the range containing the prefix.
4354                        if all_selection_lines_are_comments
4355                            && line_bytes
4356                                .by_ref()
4357                                .take(comment_prefix.len())
4358                                .eq(comment_prefix.bytes())
4359                        {
4360                            // Include any whitespace that matches the comment prefix.
4361                            let matching_whitespace_len = line_bytes
4362                                .zip(comment_prefix_whitespace.bytes())
4363                                .take_while(|(a, b)| a == b)
4364                                .count()
4365                                as u32;
4366                            let end = Point::new(
4367                                row,
4368                                start.column
4369                                    + comment_prefix.len() as u32
4370                                    + matching_whitespace_len,
4371                            );
4372                            edit_ranges.push(start..end);
4373                        }
4374                        // If this line does not begin with the line comment prefix, then record
4375                        // the position where the prefix should be inserted.
4376                        else {
4377                            all_selection_lines_are_comments = false;
4378                            edit_ranges.push(start..start);
4379                        }
4380                    }
4381
4382                    if !edit_ranges.is_empty() {
4383                        if all_selection_lines_are_comments {
4384                            let empty_str: Arc<str> = "".into();
4385                            buffer.edit(
4386                                edit_ranges
4387                                    .iter()
4388                                    .cloned()
4389                                    .map(|range| (range, empty_str.clone())),
4390                                cx,
4391                            );
4392                        } else {
4393                            let min_column =
4394                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
4395                            let edits = edit_ranges.iter().map(|range| {
4396                                let position = Point::new(range.start.row, min_column);
4397                                (position..position, full_comment_prefix.clone())
4398                            });
4399                            buffer.edit(edits, cx);
4400                        }
4401                    }
4402                }
4403            });
4404
4405            let selections = this.selections.all::<usize>(cx);
4406            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
4407        });
4408    }
4409
4410    pub fn select_larger_syntax_node(
4411        &mut self,
4412        _: &SelectLargerSyntaxNode,
4413        cx: &mut ViewContext<Self>,
4414    ) {
4415        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4416        let buffer = self.buffer.read(cx).snapshot(cx);
4417        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4418
4419        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4420        let mut selected_larger_node = false;
4421        let new_selections = old_selections
4422            .iter()
4423            .map(|selection| {
4424                let old_range = selection.start..selection.end;
4425                let mut new_range = old_range.clone();
4426                while let Some(containing_range) =
4427                    buffer.range_for_syntax_ancestor(new_range.clone())
4428                {
4429                    new_range = containing_range;
4430                    if !display_map.intersects_fold(new_range.start)
4431                        && !display_map.intersects_fold(new_range.end)
4432                    {
4433                        break;
4434                    }
4435                }
4436
4437                selected_larger_node |= new_range != old_range;
4438                Selection {
4439                    id: selection.id,
4440                    start: new_range.start,
4441                    end: new_range.end,
4442                    goal: SelectionGoal::None,
4443                    reversed: selection.reversed,
4444                }
4445            })
4446            .collect::<Vec<_>>();
4447
4448        if selected_larger_node {
4449            stack.push(old_selections);
4450            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4451                s.select(new_selections);
4452            });
4453        }
4454        self.select_larger_syntax_node_stack = stack;
4455    }
4456
4457    pub fn select_smaller_syntax_node(
4458        &mut self,
4459        _: &SelectSmallerSyntaxNode,
4460        cx: &mut ViewContext<Self>,
4461    ) {
4462        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4463        if let Some(selections) = stack.pop() {
4464            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4465                s.select(selections.to_vec());
4466            });
4467        }
4468        self.select_larger_syntax_node_stack = stack;
4469    }
4470
4471    pub fn move_to_enclosing_bracket(
4472        &mut self,
4473        _: &MoveToEnclosingBracket,
4474        cx: &mut ViewContext<Self>,
4475    ) {
4476        let buffer = self.buffer.read(cx).snapshot(cx);
4477        let mut selections = self.selections.all::<usize>(cx);
4478        for selection in &mut selections {
4479            if let Some((open_range, close_range)) =
4480                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4481            {
4482                let close_range = close_range.to_inclusive();
4483                let destination = if close_range.contains(&selection.start)
4484                    && close_range.contains(&selection.end)
4485                {
4486                    open_range.end
4487                } else {
4488                    *close_range.start()
4489                };
4490                selection.start = destination;
4491                selection.end = destination;
4492            }
4493        }
4494
4495        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4496            s.select(selections);
4497        });
4498    }
4499
4500    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4501        self.end_selection(cx);
4502        self.selection_history.mode = SelectionHistoryMode::Undoing;
4503        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4504            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4505            self.select_next_state = entry.select_next_state;
4506            self.add_selections_state = entry.add_selections_state;
4507            self.request_autoscroll(Autoscroll::Newest, cx);
4508        }
4509        self.selection_history.mode = SelectionHistoryMode::Normal;
4510    }
4511
4512    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4513        self.end_selection(cx);
4514        self.selection_history.mode = SelectionHistoryMode::Redoing;
4515        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4516            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4517            self.select_next_state = entry.select_next_state;
4518            self.add_selections_state = entry.add_selections_state;
4519            self.request_autoscroll(Autoscroll::Newest, cx);
4520        }
4521        self.selection_history.mode = SelectionHistoryMode::Normal;
4522    }
4523
4524    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
4525        self.go_to_diagnostic(Direction::Next, cx)
4526    }
4527
4528    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4529        self.go_to_diagnostic(Direction::Prev, cx)
4530    }
4531
4532    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4533        let buffer = self.buffer.read(cx).snapshot(cx);
4534        let selection = self.selections.newest::<usize>(cx);
4535        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4536            active_diagnostics
4537                .primary_range
4538                .to_offset(&buffer)
4539                .to_inclusive()
4540        });
4541        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4542            if active_primary_range.contains(&selection.head()) {
4543                *active_primary_range.end()
4544            } else {
4545                selection.head()
4546            }
4547        } else {
4548            selection.head()
4549        };
4550
4551        loop {
4552            let mut diagnostics = if direction == Direction::Prev {
4553                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4554            } else {
4555                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4556            };
4557            let group = diagnostics.find_map(|entry| {
4558                if entry.diagnostic.is_primary
4559                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4560                    && !entry.range.is_empty()
4561                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4562                {
4563                    Some((entry.range, entry.diagnostic.group_id))
4564                } else {
4565                    None
4566                }
4567            });
4568
4569            if let Some((primary_range, group_id)) = group {
4570                self.activate_diagnostics(group_id, cx);
4571                self.change_selections(Some(Autoscroll::Center), cx, |s| {
4572                    s.select(vec![Selection {
4573                        id: selection.id,
4574                        start: primary_range.start,
4575                        end: primary_range.start,
4576                        reversed: false,
4577                        goal: SelectionGoal::None,
4578                    }]);
4579                });
4580                break;
4581            } else {
4582                // Cycle around to the start of the buffer, potentially moving back to the start of
4583                // the currently active diagnostic.
4584                active_primary_range.take();
4585                if direction == Direction::Prev {
4586                    if search_start == buffer.len() {
4587                        break;
4588                    } else {
4589                        search_start = buffer.len();
4590                    }
4591                } else {
4592                    if search_start == 0 {
4593                        break;
4594                    } else {
4595                        search_start = 0;
4596                    }
4597                }
4598            }
4599        }
4600    }
4601
4602    pub fn go_to_definition(
4603        workspace: &mut Workspace,
4604        _: &GoToDefinition,
4605        cx: &mut ViewContext<Workspace>,
4606    ) {
4607        let active_item = workspace.active_item(cx);
4608        let editor_handle = if let Some(editor) = active_item
4609            .as_ref()
4610            .and_then(|item| item.act_as::<Self>(cx))
4611        {
4612            editor
4613        } else {
4614            return;
4615        };
4616
4617        let editor = editor_handle.read(cx);
4618        let buffer = editor.buffer.read(cx);
4619        let head = editor.selections.newest::<usize>(cx).head();
4620        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
4621            text_anchor
4622        } else {
4623            return;
4624        };
4625
4626        let project = workspace.project().clone();
4627        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
4628        cx.spawn(|workspace, mut cx| async move {
4629            let definitions = definitions.await?;
4630            workspace.update(&mut cx, |workspace, cx| {
4631                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
4632                for definition in definitions {
4633                    let range = definition.range.to_offset(definition.buffer.read(cx));
4634
4635                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
4636                    target_editor_handle.update(cx, |target_editor, cx| {
4637                        // When selecting a definition in a different buffer, disable the nav history
4638                        // to avoid creating a history entry at the previous cursor location.
4639                        if editor_handle != target_editor_handle {
4640                            nav_history.borrow_mut().disable();
4641                        }
4642                        target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
4643                            s.select_ranges([range]);
4644                        });
4645
4646                        nav_history.borrow_mut().enable();
4647                    });
4648                }
4649            });
4650
4651            Ok::<(), anyhow::Error>(())
4652        })
4653        .detach_and_log_err(cx);
4654    }
4655
4656    pub fn find_all_references(
4657        workspace: &mut Workspace,
4658        _: &FindAllReferences,
4659        cx: &mut ViewContext<Workspace>,
4660    ) -> Option<Task<Result<()>>> {
4661        let active_item = workspace.active_item(cx)?;
4662        let editor_handle = active_item.act_as::<Self>(cx)?;
4663
4664        let editor = editor_handle.read(cx);
4665        let buffer = editor.buffer.read(cx);
4666        let head = editor.selections.newest::<usize>(cx).head();
4667        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
4668        let replica_id = editor.replica_id(cx);
4669
4670        let project = workspace.project().clone();
4671        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
4672        Some(cx.spawn(|workspace, mut cx| async move {
4673            let mut locations = references.await?;
4674            if locations.is_empty() {
4675                return Ok(());
4676            }
4677
4678            locations.sort_by_key(|location| location.buffer.id());
4679            let mut locations = locations.into_iter().peekable();
4680            let mut ranges_to_highlight = Vec::new();
4681
4682            let excerpt_buffer = cx.add_model(|cx| {
4683                let mut symbol_name = None;
4684                let mut multibuffer = MultiBuffer::new(replica_id);
4685                while let Some(location) = locations.next() {
4686                    let buffer = location.buffer.read(cx);
4687                    let mut ranges_for_buffer = Vec::new();
4688                    let range = location.range.to_offset(buffer);
4689                    ranges_for_buffer.push(range.clone());
4690                    if symbol_name.is_none() {
4691                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
4692                    }
4693
4694                    while let Some(next_location) = locations.peek() {
4695                        if next_location.buffer == location.buffer {
4696                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
4697                            locations.next();
4698                        } else {
4699                            break;
4700                        }
4701                    }
4702
4703                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
4704                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
4705                        location.buffer.clone(),
4706                        ranges_for_buffer,
4707                        1,
4708                        cx,
4709                    ));
4710                }
4711                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
4712            });
4713
4714            workspace.update(&mut cx, |workspace, cx| {
4715                let editor =
4716                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
4717                editor.update(cx, |editor, cx| {
4718                    editor.highlight_background::<Self>(
4719                        ranges_to_highlight,
4720                        |theme| theme.editor.highlighted_line_background,
4721                        cx,
4722                    );
4723                });
4724                workspace.add_item(Box::new(editor), cx);
4725            });
4726
4727            Ok(())
4728        }))
4729    }
4730
4731    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
4732        use language::ToOffset as _;
4733
4734        let project = self.project.clone()?;
4735        let selection = self.selections.newest_anchor().clone();
4736        let (cursor_buffer, cursor_buffer_position) = self
4737            .buffer
4738            .read(cx)
4739            .text_anchor_for_position(selection.head(), cx)?;
4740        let (tail_buffer, _) = self
4741            .buffer
4742            .read(cx)
4743            .text_anchor_for_position(selection.tail(), cx)?;
4744        if tail_buffer != cursor_buffer {
4745            return None;
4746        }
4747
4748        let snapshot = cursor_buffer.read(cx).snapshot();
4749        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
4750        let prepare_rename = project.update(cx, |project, cx| {
4751            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
4752        });
4753
4754        Some(cx.spawn(|this, mut cx| async move {
4755            let rename_range = if let Some(range) = prepare_rename.await? {
4756                Some(range)
4757            } else {
4758                this.read_with(&cx, |this, cx| {
4759                    let buffer = this.buffer.read(cx).snapshot(cx);
4760                    let mut buffer_highlights = this
4761                        .document_highlights_for_position(selection.head(), &buffer)
4762                        .filter(|highlight| {
4763                            highlight.start.excerpt_id() == selection.head().excerpt_id()
4764                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
4765                        });
4766                    buffer_highlights
4767                        .next()
4768                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
4769                })
4770            };
4771            if let Some(rename_range) = rename_range {
4772                let rename_buffer_range = rename_range.to_offset(&snapshot);
4773                let cursor_offset_in_rename_range =
4774                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
4775
4776                this.update(&mut cx, |this, cx| {
4777                    this.take_rename(false, cx);
4778                    let style = this.style(cx);
4779                    let buffer = this.buffer.read(cx).read(cx);
4780                    let cursor_offset = selection.head().to_offset(&buffer);
4781                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
4782                    let rename_end = rename_start + rename_buffer_range.len();
4783                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
4784                    let mut old_highlight_id = None;
4785                    let old_name: Arc<str> = buffer
4786                        .chunks(rename_start..rename_end, true)
4787                        .map(|chunk| {
4788                            if old_highlight_id.is_none() {
4789                                old_highlight_id = chunk.syntax_highlight_id;
4790                            }
4791                            chunk.text
4792                        })
4793                        .collect::<String>()
4794                        .into();
4795
4796                    drop(buffer);
4797
4798                    // Position the selection in the rename editor so that it matches the current selection.
4799                    this.show_local_selections = false;
4800                    let rename_editor = cx.add_view(|cx| {
4801                        println!("Rename editor created.");
4802                        let mut editor = Editor::single_line(None, cx);
4803                        if let Some(old_highlight_id) = old_highlight_id {
4804                            editor.override_text_style =
4805                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
4806                        }
4807                        editor
4808                            .buffer
4809                            .update(cx, |buffer, cx| buffer.edit([(0..0, old_name.clone())], cx));
4810                        editor.select_all(&SelectAll, cx);
4811                        editor
4812                    });
4813
4814                    let ranges = this
4815                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
4816                        .into_iter()
4817                        .flat_map(|(_, ranges)| ranges)
4818                        .chain(
4819                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
4820                                .into_iter()
4821                                .flat_map(|(_, ranges)| ranges),
4822                        )
4823                        .collect();
4824
4825                    this.highlight_text::<Rename>(
4826                        ranges,
4827                        HighlightStyle {
4828                            fade_out: Some(style.rename_fade),
4829                            ..Default::default()
4830                        },
4831                        cx,
4832                    );
4833                    cx.focus(&rename_editor);
4834                    let block_id = this.insert_blocks(
4835                        [BlockProperties {
4836                            position: range.start.clone(),
4837                            height: 1,
4838                            render: Arc::new({
4839                                let editor = rename_editor.clone();
4840                                move |cx: &mut BlockContext| {
4841                                    ChildView::new(editor.clone())
4842                                        .contained()
4843                                        .with_padding_left(cx.anchor_x)
4844                                        .boxed()
4845                                }
4846                            }),
4847                            disposition: BlockDisposition::Below,
4848                        }],
4849                        cx,
4850                    )[0];
4851                    this.pending_rename = Some(RenameState {
4852                        range,
4853                        old_name,
4854                        editor: rename_editor,
4855                        block_id,
4856                    });
4857                });
4858            }
4859
4860            Ok(())
4861        }))
4862    }
4863
4864    pub fn confirm_rename(
4865        workspace: &mut Workspace,
4866        _: &ConfirmRename,
4867        cx: &mut ViewContext<Workspace>,
4868    ) -> Option<Task<Result<()>>> {
4869        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
4870
4871        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
4872            let rename = editor.take_rename(false, cx)?;
4873            let buffer = editor.buffer.read(cx);
4874            let (start_buffer, start) =
4875                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
4876            let (end_buffer, end) =
4877                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
4878            if start_buffer == end_buffer {
4879                let new_name = rename.editor.read(cx).text(cx);
4880                Some((start_buffer, start..end, rename.old_name, new_name))
4881            } else {
4882                None
4883            }
4884        })?;
4885
4886        let rename = workspace.project().clone().update(cx, |project, cx| {
4887            project.perform_rename(
4888                buffer.clone(),
4889                range.start.clone(),
4890                new_name.clone(),
4891                true,
4892                cx,
4893            )
4894        });
4895
4896        Some(cx.spawn(|workspace, mut cx| async move {
4897            let project_transaction = rename.await?;
4898            Self::open_project_transaction(
4899                editor.clone(),
4900                workspace,
4901                project_transaction,
4902                format!("Rename: {}{}", old_name, new_name),
4903                cx.clone(),
4904            )
4905            .await?;
4906
4907            editor.update(&mut cx, |editor, cx| {
4908                editor.refresh_document_highlights(cx);
4909            });
4910            Ok(())
4911        }))
4912    }
4913
4914    fn take_rename(
4915        &mut self,
4916        moving_cursor: bool,
4917        cx: &mut ViewContext<Self>,
4918    ) -> Option<RenameState> {
4919        let rename = self.pending_rename.take()?;
4920        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
4921        self.clear_text_highlights::<Rename>(cx);
4922        self.show_local_selections = true;
4923
4924        if moving_cursor {
4925            let rename_editor = rename.editor.read(cx);
4926            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
4927
4928            // Update the selection to match the position of the selection inside
4929            // the rename editor.
4930            let snapshot = self.buffer.read(cx).read(cx);
4931            let rename_range = rename.range.to_offset(&snapshot);
4932            let cursor_in_editor = snapshot
4933                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
4934                .min(rename_range.end);
4935            drop(snapshot);
4936
4937            self.change_selections(None, cx, |s| {
4938                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
4939            });
4940        }
4941
4942        Some(rename)
4943    }
4944
4945    #[cfg(any(test, feature = "test-support"))]
4946    pub fn pending_rename(&self) -> Option<&RenameState> {
4947        self.pending_rename.as_ref()
4948    }
4949
4950    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
4951        if let Some(project) = self.project.clone() {
4952            self.buffer.update(cx, |multi_buffer, cx| {
4953                project.update(cx, |project, cx| {
4954                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
4955                });
4956            })
4957        }
4958    }
4959
4960    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
4961        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
4962            let buffer = self.buffer.read(cx).snapshot(cx);
4963            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
4964            let is_valid = buffer
4965                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
4966                .any(|entry| {
4967                    entry.diagnostic.is_primary
4968                        && !entry.range.is_empty()
4969                        && entry.range.start == primary_range_start
4970                        && entry.diagnostic.message == active_diagnostics.primary_message
4971                });
4972
4973            if is_valid != active_diagnostics.is_valid {
4974                active_diagnostics.is_valid = is_valid;
4975                let mut new_styles = HashMap::default();
4976                for (block_id, diagnostic) in &active_diagnostics.blocks {
4977                    new_styles.insert(
4978                        *block_id,
4979                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
4980                    );
4981                }
4982                self.display_map
4983                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
4984            }
4985        }
4986    }
4987
4988    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
4989        self.dismiss_diagnostics(cx);
4990        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
4991            let buffer = self.buffer.read(cx).snapshot(cx);
4992
4993            let mut primary_range = None;
4994            let mut primary_message = None;
4995            let mut group_end = Point::zero();
4996            let diagnostic_group = buffer
4997                .diagnostic_group::<Point>(group_id)
4998                .map(|entry| {
4999                    if entry.range.end > group_end {
5000                        group_end = entry.range.end;
5001                    }
5002                    if entry.diagnostic.is_primary {
5003                        primary_range = Some(entry.range.clone());
5004                        primary_message = Some(entry.diagnostic.message.clone());
5005                    }
5006                    entry
5007                })
5008                .collect::<Vec<_>>();
5009            let primary_range = primary_range.unwrap();
5010            let primary_message = primary_message.unwrap();
5011            let primary_range =
5012                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5013
5014            let blocks = display_map
5015                .insert_blocks(
5016                    diagnostic_group.iter().map(|entry| {
5017                        let diagnostic = entry.diagnostic.clone();
5018                        let message_height = diagnostic.message.lines().count() as u8;
5019                        BlockProperties {
5020                            position: buffer.anchor_after(entry.range.start),
5021                            height: message_height,
5022                            render: diagnostic_block_renderer(diagnostic, true),
5023                            disposition: BlockDisposition::Below,
5024                        }
5025                    }),
5026                    cx,
5027                )
5028                .into_iter()
5029                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5030                .collect();
5031
5032            Some(ActiveDiagnosticGroup {
5033                primary_range,
5034                primary_message,
5035                blocks,
5036                is_valid: true,
5037            })
5038        });
5039    }
5040
5041    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5042        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5043            self.display_map.update(cx, |display_map, cx| {
5044                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5045            });
5046            cx.notify();
5047        }
5048    }
5049
5050    pub fn set_selections_from_remote(
5051        &mut self,
5052        selections: Vec<Selection<Anchor>>,
5053        cx: &mut ViewContext<Self>,
5054    ) {
5055        let old_cursor_position = self.selections.newest_anchor().head();
5056        self.selections.change_with(cx, |s| {
5057            s.select_anchors(selections);
5058        });
5059        self.selections_did_change(false, &old_cursor_position, cx);
5060    }
5061
5062    fn push_to_selection_history(&mut self) {
5063        self.selection_history.push(SelectionHistoryEntry {
5064            selections: self.selections.disjoint_anchors().clone(),
5065            select_next_state: self.select_next_state.clone(),
5066            add_selections_state: self.add_selections_state.clone(),
5067        });
5068    }
5069
5070    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5071        self.autoscroll_request = Some((autoscroll, true));
5072        cx.notify();
5073    }
5074
5075    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5076        self.autoscroll_request = Some((autoscroll, false));
5077        cx.notify();
5078    }
5079
5080    pub fn transact(
5081        &mut self,
5082        cx: &mut ViewContext<Self>,
5083        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5084    ) {
5085        self.start_transaction_at(Instant::now(), cx);
5086        update(self, cx);
5087        self.end_transaction_at(Instant::now(), cx);
5088    }
5089
5090    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5091        self.end_selection(cx);
5092        if let Some(tx_id) = self
5093            .buffer
5094            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5095        {
5096            self.selection_history
5097                .insert_transaction(tx_id, self.selections.disjoint_anchors().clone());
5098        }
5099    }
5100
5101    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5102        if let Some(tx_id) = self
5103            .buffer
5104            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5105        {
5106            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5107                *end_selections = Some(self.selections.disjoint_anchors().clone());
5108            } else {
5109                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5110            }
5111
5112            cx.emit(Event::Edited);
5113        }
5114    }
5115
5116    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
5117        log::info!("Editor::page_up");
5118    }
5119
5120    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
5121        log::info!("Editor::page_down");
5122    }
5123
5124    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5125        let mut fold_ranges = Vec::new();
5126
5127        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5128        let selections = self.selections.all::<Point>(cx);
5129        for selection in selections {
5130            let range = selection.display_range(&display_map).sorted();
5131            let buffer_start_row = range.start.to_point(&display_map).row;
5132
5133            for row in (0..=range.end.row()).rev() {
5134                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5135                    let fold_range = self.foldable_range_for_line(&display_map, row);
5136                    if fold_range.end.row >= buffer_start_row {
5137                        fold_ranges.push(fold_range);
5138                        if row <= range.start.row() {
5139                            break;
5140                        }
5141                    }
5142                }
5143            }
5144        }
5145
5146        self.fold_ranges(fold_ranges, cx);
5147    }
5148
5149    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5150        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5151        let buffer = &display_map.buffer_snapshot;
5152        let selections = self.selections.all::<Point>(cx);
5153        let ranges = selections
5154            .iter()
5155            .map(|s| {
5156                let range = s.display_range(&display_map).sorted();
5157                let mut start = range.start.to_point(&display_map);
5158                let mut end = range.end.to_point(&display_map);
5159                start.column = 0;
5160                end.column = buffer.line_len(end.row);
5161                start..end
5162            })
5163            .collect::<Vec<_>>();
5164        self.unfold_ranges(ranges, true, cx);
5165    }
5166
5167    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5168        let max_point = display_map.max_point();
5169        if display_row >= max_point.row() {
5170            false
5171        } else {
5172            let (start_indent, is_blank) = display_map.line_indent(display_row);
5173            if is_blank {
5174                false
5175            } else {
5176                for display_row in display_row + 1..=max_point.row() {
5177                    let (indent, is_blank) = display_map.line_indent(display_row);
5178                    if !is_blank {
5179                        return indent > start_indent;
5180                    }
5181                }
5182                false
5183            }
5184        }
5185    }
5186
5187    fn foldable_range_for_line(
5188        &self,
5189        display_map: &DisplaySnapshot,
5190        start_row: u32,
5191    ) -> Range<Point> {
5192        let max_point = display_map.max_point();
5193
5194        let (start_indent, _) = display_map.line_indent(start_row);
5195        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5196        let mut end = None;
5197        for row in start_row + 1..=max_point.row() {
5198            let (indent, is_blank) = display_map.line_indent(row);
5199            if !is_blank && indent <= start_indent {
5200                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5201                break;
5202            }
5203        }
5204
5205        let end = end.unwrap_or(max_point);
5206        return start.to_point(display_map)..end.to_point(display_map);
5207    }
5208
5209    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5210        let selections = self.selections.all::<Point>(cx);
5211        let ranges = selections.into_iter().map(|s| s.start..s.end);
5212        self.fold_ranges(ranges, cx);
5213    }
5214
5215    pub fn fold_ranges<T: ToOffset>(
5216        &mut self,
5217        ranges: impl IntoIterator<Item = Range<T>>,
5218        cx: &mut ViewContext<Self>,
5219    ) {
5220        let mut ranges = ranges.into_iter().peekable();
5221        if ranges.peek().is_some() {
5222            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5223            self.request_autoscroll(Autoscroll::Fit, cx);
5224            cx.notify();
5225        }
5226    }
5227
5228    pub fn unfold_ranges<T: ToOffset>(
5229        &mut self,
5230        ranges: impl IntoIterator<Item = Range<T>>,
5231        inclusive: bool,
5232        cx: &mut ViewContext<Self>,
5233    ) {
5234        let mut ranges = ranges.into_iter().peekable();
5235        if ranges.peek().is_some() {
5236            self.display_map
5237                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5238            self.request_autoscroll(Autoscroll::Fit, cx);
5239            cx.notify();
5240        }
5241    }
5242
5243    pub fn insert_blocks(
5244        &mut self,
5245        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5246        cx: &mut ViewContext<Self>,
5247    ) -> Vec<BlockId> {
5248        let blocks = self
5249            .display_map
5250            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5251        self.request_autoscroll(Autoscroll::Fit, cx);
5252        blocks
5253    }
5254
5255    pub fn replace_blocks(
5256        &mut self,
5257        blocks: HashMap<BlockId, RenderBlock>,
5258        cx: &mut ViewContext<Self>,
5259    ) {
5260        self.display_map
5261            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5262        self.request_autoscroll(Autoscroll::Fit, cx);
5263    }
5264
5265    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5266        self.display_map.update(cx, |display_map, cx| {
5267            display_map.remove_blocks(block_ids, cx)
5268        });
5269    }
5270
5271    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5272        self.display_map
5273            .update(cx, |map, cx| map.snapshot(cx))
5274            .longest_row()
5275    }
5276
5277    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5278        self.display_map
5279            .update(cx, |map, cx| map.snapshot(cx))
5280            .max_point()
5281    }
5282
5283    pub fn text(&self, cx: &AppContext) -> String {
5284        self.buffer.read(cx).read(cx).text()
5285    }
5286
5287    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5288        self.transact(cx, |this, cx| {
5289            this.buffer
5290                .read(cx)
5291                .as_singleton()
5292                .expect("you can only call set_text on editors for singleton buffers")
5293                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5294        });
5295    }
5296
5297    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5298        self.display_map
5299            .update(cx, |map, cx| map.snapshot(cx))
5300            .text()
5301    }
5302
5303    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5304        let language_name = self
5305            .buffer
5306            .read(cx)
5307            .as_singleton()
5308            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5309            .map(|l| l.name());
5310
5311        let settings = cx.global::<Settings>();
5312        let mode = self
5313            .soft_wrap_mode_override
5314            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5315        match mode {
5316            settings::SoftWrap::None => SoftWrap::None,
5317            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5318            settings::SoftWrap::PreferredLineLength => {
5319                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5320            }
5321        }
5322    }
5323
5324    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5325        self.soft_wrap_mode_override = Some(mode);
5326        cx.notify();
5327    }
5328
5329    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5330        self.display_map
5331            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5332    }
5333
5334    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5335        self.highlighted_rows = rows;
5336    }
5337
5338    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5339        self.highlighted_rows.clone()
5340    }
5341
5342    pub fn highlight_background<T: 'static>(
5343        &mut self,
5344        ranges: Vec<Range<Anchor>>,
5345        color_fetcher: fn(&Theme) -> Color,
5346        cx: &mut ViewContext<Self>,
5347    ) {
5348        self.background_highlights
5349            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5350        cx.notify();
5351    }
5352
5353    pub fn clear_background_highlights<T: 'static>(
5354        &mut self,
5355        cx: &mut ViewContext<Self>,
5356    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5357        cx.notify();
5358        self.background_highlights.remove(&TypeId::of::<T>())
5359    }
5360
5361    #[cfg(feature = "test-support")]
5362    pub fn all_background_highlights(
5363        &mut self,
5364        cx: &mut ViewContext<Self>,
5365    ) -> Vec<(Range<DisplayPoint>, Color)> {
5366        let snapshot = self.snapshot(cx);
5367        let buffer = &snapshot.buffer_snapshot;
5368        let start = buffer.anchor_before(0);
5369        let end = buffer.anchor_after(buffer.len());
5370        let theme = cx.global::<Settings>().theme.as_ref();
5371        self.background_highlights_in_range(start..end, &snapshot, theme)
5372    }
5373
5374    fn document_highlights_for_position<'a>(
5375        &'a self,
5376        position: Anchor,
5377        buffer: &'a MultiBufferSnapshot,
5378    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5379        let read_highlights = self
5380            .background_highlights
5381            .get(&TypeId::of::<DocumentHighlightRead>())
5382            .map(|h| &h.1);
5383        let write_highlights = self
5384            .background_highlights
5385            .get(&TypeId::of::<DocumentHighlightRead>())
5386            .map(|h| &h.1);
5387        let left_position = position.bias_left(buffer);
5388        let right_position = position.bias_right(buffer);
5389        read_highlights
5390            .into_iter()
5391            .chain(write_highlights)
5392            .flat_map(move |ranges| {
5393                let start_ix = match ranges.binary_search_by(|probe| {
5394                    let cmp = probe.end.cmp(&left_position, &buffer);
5395                    if cmp.is_ge() {
5396                        Ordering::Greater
5397                    } else {
5398                        Ordering::Less
5399                    }
5400                }) {
5401                    Ok(i) | Err(i) => i,
5402                };
5403
5404                let right_position = right_position.clone();
5405                ranges[start_ix..]
5406                    .iter()
5407                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
5408            })
5409    }
5410
5411    pub fn background_highlights_in_range(
5412        &self,
5413        search_range: Range<Anchor>,
5414        display_snapshot: &DisplaySnapshot,
5415        theme: &Theme,
5416    ) -> Vec<(Range<DisplayPoint>, Color)> {
5417        let mut results = Vec::new();
5418        let buffer = &display_snapshot.buffer_snapshot;
5419        for (color_fetcher, ranges) in self.background_highlights.values() {
5420            let color = color_fetcher(theme);
5421            let start_ix = match ranges.binary_search_by(|probe| {
5422                let cmp = probe.end.cmp(&search_range.start, &buffer);
5423                if cmp.is_gt() {
5424                    Ordering::Greater
5425                } else {
5426                    Ordering::Less
5427                }
5428            }) {
5429                Ok(i) | Err(i) => i,
5430            };
5431            for range in &ranges[start_ix..] {
5432                if range.start.cmp(&search_range.end, &buffer).is_ge() {
5433                    break;
5434                }
5435                let start = range
5436                    .start
5437                    .to_point(buffer)
5438                    .to_display_point(display_snapshot);
5439                let end = range
5440                    .end
5441                    .to_point(buffer)
5442                    .to_display_point(display_snapshot);
5443                results.push((start..end, color))
5444            }
5445        }
5446        results
5447    }
5448
5449    pub fn highlight_text<T: 'static>(
5450        &mut self,
5451        ranges: Vec<Range<Anchor>>,
5452        style: HighlightStyle,
5453        cx: &mut ViewContext<Self>,
5454    ) {
5455        self.display_map.update(cx, |map, _| {
5456            map.highlight_text(TypeId::of::<T>(), ranges, style)
5457        });
5458        cx.notify();
5459    }
5460
5461    pub fn clear_text_highlights<T: 'static>(
5462        &mut self,
5463        cx: &mut ViewContext<Self>,
5464    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5465        cx.notify();
5466        self.display_map
5467            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
5468    }
5469
5470    fn next_blink_epoch(&mut self) -> usize {
5471        self.blink_epoch += 1;
5472        self.blink_epoch
5473    }
5474
5475    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5476        if !self.focused {
5477            return;
5478        }
5479
5480        self.show_local_cursors = true;
5481        cx.notify();
5482
5483        let epoch = self.next_blink_epoch();
5484        cx.spawn(|this, mut cx| {
5485            let this = this.downgrade();
5486            async move {
5487                Timer::after(CURSOR_BLINK_INTERVAL).await;
5488                if let Some(this) = this.upgrade(&cx) {
5489                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5490                }
5491            }
5492        })
5493        .detach();
5494    }
5495
5496    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5497        if epoch == self.blink_epoch {
5498            self.blinking_paused = false;
5499            self.blink_cursors(epoch, cx);
5500        }
5501    }
5502
5503    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5504        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5505            self.show_local_cursors = !self.show_local_cursors;
5506            cx.notify();
5507
5508            let epoch = self.next_blink_epoch();
5509            cx.spawn(|this, mut cx| {
5510                let this = this.downgrade();
5511                async move {
5512                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5513                    if let Some(this) = this.upgrade(&cx) {
5514                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5515                    }
5516                }
5517            })
5518            .detach();
5519        }
5520    }
5521
5522    pub fn show_local_cursors(&self) -> bool {
5523        self.show_local_cursors && self.focused
5524    }
5525
5526    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5527        cx.notify();
5528    }
5529
5530    fn on_buffer_event(
5531        &mut self,
5532        _: ModelHandle<MultiBuffer>,
5533        event: &language::Event,
5534        cx: &mut ViewContext<Self>,
5535    ) {
5536        match event {
5537            language::Event::Edited => {
5538                self.refresh_active_diagnostics(cx);
5539                self.refresh_code_actions(cx);
5540                cx.emit(Event::BufferEdited);
5541            }
5542            language::Event::Reparsed => cx.emit(Event::Reparsed),
5543            language::Event::Dirtied => cx.emit(Event::Dirtied),
5544            language::Event::Saved => cx.emit(Event::Saved),
5545            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5546            language::Event::Reloaded => cx.emit(Event::TitleChanged),
5547            language::Event::Closed => cx.emit(Event::Closed),
5548            language::Event::DiagnosticsUpdated => {
5549                self.refresh_active_diagnostics(cx);
5550            }
5551            _ => {}
5552        }
5553    }
5554
5555    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5556        cx.notify();
5557    }
5558
5559    pub fn set_searchable(&mut self, searchable: bool) {
5560        self.searchable = searchable;
5561    }
5562
5563    pub fn searchable(&self) -> bool {
5564        self.searchable
5565    }
5566
5567    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
5568        let active_item = workspace.active_item(cx);
5569        let editor_handle = if let Some(editor) = active_item
5570            .as_ref()
5571            .and_then(|item| item.act_as::<Self>(cx))
5572        {
5573            editor
5574        } else {
5575            cx.propagate_action();
5576            return;
5577        };
5578
5579        let editor = editor_handle.read(cx);
5580        let buffer = editor.buffer.read(cx);
5581        if buffer.is_singleton() {
5582            cx.propagate_action();
5583            return;
5584        }
5585
5586        let mut new_selections_by_buffer = HashMap::default();
5587        for selection in editor.selections.all::<usize>(cx) {
5588            for (buffer, mut range) in
5589                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
5590            {
5591                if selection.reversed {
5592                    mem::swap(&mut range.start, &mut range.end);
5593                }
5594                new_selections_by_buffer
5595                    .entry(buffer)
5596                    .or_insert(Vec::new())
5597                    .push(range)
5598            }
5599        }
5600
5601        editor_handle.update(cx, |editor, cx| {
5602            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
5603        });
5604        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
5605        nav_history.borrow_mut().disable();
5606
5607        // We defer the pane interaction because we ourselves are a workspace item
5608        // and activating a new item causes the pane to call a method on us reentrantly,
5609        // which panics if we're on the stack.
5610        cx.defer(move |workspace, cx| {
5611            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
5612                let editor = workspace.open_project_item::<Self>(buffer, cx);
5613                editor.update(cx, |editor, cx| {
5614                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
5615                        s.select_ranges(ranges);
5616                    });
5617                });
5618            }
5619
5620            nav_history.borrow_mut().enable();
5621        });
5622    }
5623}
5624
5625impl EditorSnapshot {
5626    pub fn is_focused(&self) -> bool {
5627        self.is_focused
5628    }
5629
5630    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
5631        self.placeholder_text.as_ref()
5632    }
5633
5634    pub fn scroll_position(&self) -> Vector2F {
5635        compute_scroll_position(
5636            &self.display_snapshot,
5637            self.scroll_position,
5638            &self.scroll_top_anchor,
5639        )
5640    }
5641}
5642
5643impl Deref for EditorSnapshot {
5644    type Target = DisplaySnapshot;
5645
5646    fn deref(&self) -> &Self::Target {
5647        &self.display_snapshot
5648    }
5649}
5650
5651fn compute_scroll_position(
5652    snapshot: &DisplaySnapshot,
5653    mut scroll_position: Vector2F,
5654    scroll_top_anchor: &Anchor,
5655) -> Vector2F {
5656    if *scroll_top_anchor != Anchor::min() {
5657        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
5658        scroll_position.set_y(scroll_top + scroll_position.y());
5659    } else {
5660        scroll_position.set_y(0.);
5661    }
5662    scroll_position
5663}
5664
5665#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5666pub enum Event {
5667    Activate,
5668    BufferEdited,
5669    Edited,
5670    Reparsed,
5671    Blurred,
5672    Dirtied,
5673    Saved,
5674    TitleChanged,
5675    SelectionsChanged { local: bool },
5676    ScrollPositionChanged { local: bool },
5677    Closed,
5678}
5679
5680pub struct EditorFocused(pub ViewHandle<Editor>);
5681pub struct EditorBlurred(pub ViewHandle<Editor>);
5682pub struct EditorReleased(pub WeakViewHandle<Editor>);
5683
5684impl Entity for Editor {
5685    type Event = Event;
5686
5687    fn release(&mut self, cx: &mut MutableAppContext) {
5688        cx.emit_global(EditorReleased(self.handle.clone()));
5689    }
5690}
5691
5692impl View for Editor {
5693    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
5694        let style = self.style(cx);
5695        self.display_map.update(cx, |map, cx| {
5696            map.set_font(style.text.font_id, style.text.font_size, cx)
5697        });
5698        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
5699    }
5700
5701    fn ui_name() -> &'static str {
5702        "Editor"
5703    }
5704
5705    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
5706        let focused_event = EditorFocused(cx.handle());
5707        cx.emit_global(focused_event);
5708        if let Some(rename) = self.pending_rename.as_ref() {
5709            cx.focus(&rename.editor);
5710        } else {
5711            self.focused = true;
5712            self.blink_cursors(self.blink_epoch, cx);
5713            self.buffer.update(cx, |buffer, cx| {
5714                buffer.finalize_last_transaction(cx);
5715                if self.leader_replica_id.is_none() {
5716                    buffer.set_active_selections(
5717                        &self.selections.disjoint_anchors(),
5718                        self.selections.line_mode,
5719                        cx,
5720                    );
5721                }
5722            });
5723        }
5724    }
5725
5726    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
5727        let blurred_event = EditorBlurred(cx.handle());
5728        cx.emit_global(blurred_event);
5729        self.focused = false;
5730        self.buffer
5731            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
5732        self.hide_context_menu(cx);
5733        cx.emit(Event::Blurred);
5734        cx.notify();
5735    }
5736
5737    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
5738        let mut context = Self::default_keymap_context();
5739        let mode = match self.mode {
5740            EditorMode::SingleLine => "single_line",
5741            EditorMode::AutoHeight { .. } => "auto_height",
5742            EditorMode::Full => "full",
5743        };
5744        context.map.insert("mode".into(), mode.into());
5745        if self.pending_rename.is_some() {
5746            context.set.insert("renaming".into());
5747        }
5748        match self.context_menu.as_ref() {
5749            Some(ContextMenu::Completions(_)) => {
5750                context.set.insert("showing_completions".into());
5751            }
5752            Some(ContextMenu::CodeActions(_)) => {
5753                context.set.insert("showing_code_actions".into());
5754            }
5755            Some(ContextMenu::Hover(_)) => {
5756                context.set.insert("showing_hover".into());
5757            }
5758            None => {}
5759        }
5760
5761        for layer in self.keymap_context_layers.values() {
5762            context.extend(layer);
5763        }
5764
5765        context
5766    }
5767}
5768
5769fn build_style(
5770    settings: &Settings,
5771    get_field_editor_theme: Option<GetFieldEditorTheme>,
5772    override_text_style: Option<&OverrideTextStyle>,
5773    cx: &AppContext,
5774) -> EditorStyle {
5775    let font_cache = cx.font_cache();
5776
5777    let mut theme = settings.theme.editor.clone();
5778    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
5779        let field_editor_theme = get_field_editor_theme(&settings.theme);
5780        theme.text_color = field_editor_theme.text.color;
5781        theme.selection = field_editor_theme.selection;
5782        theme.background = field_editor_theme
5783            .container
5784            .background_color
5785            .unwrap_or_default();
5786        EditorStyle {
5787            text: field_editor_theme.text,
5788            placeholder_text: field_editor_theme.placeholder_text,
5789            theme,
5790        }
5791    } else {
5792        let font_family_id = settings.buffer_font_family;
5793        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
5794        let font_properties = Default::default();
5795        let font_id = font_cache
5796            .select_font(font_family_id, &font_properties)
5797            .unwrap();
5798        let font_size = settings.buffer_font_size;
5799        EditorStyle {
5800            text: TextStyle {
5801                color: settings.theme.editor.text_color,
5802                font_family_name,
5803                font_family_id,
5804                font_id,
5805                font_size,
5806                font_properties,
5807                underline: Default::default(),
5808            },
5809            placeholder_text: None,
5810            theme,
5811        }
5812    };
5813
5814    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
5815        if let Some(highlighted) = style
5816            .text
5817            .clone()
5818            .highlight(highlight_style, font_cache)
5819            .log_err()
5820        {
5821            style.text = highlighted;
5822        }
5823    }
5824
5825    style
5826}
5827
5828trait SelectionExt {
5829    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
5830    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
5831    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
5832    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
5833        -> Range<u32>;
5834}
5835
5836impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
5837    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
5838        let start = self.start.to_point(buffer);
5839        let end = self.end.to_point(buffer);
5840        if self.reversed {
5841            end..start
5842        } else {
5843            start..end
5844        }
5845    }
5846
5847    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
5848        let start = self.start.to_offset(buffer);
5849        let end = self.end.to_offset(buffer);
5850        if self.reversed {
5851            end..start
5852        } else {
5853            start..end
5854        }
5855    }
5856
5857    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
5858        let start = self
5859            .start
5860            .to_point(&map.buffer_snapshot)
5861            .to_display_point(map);
5862        let end = self
5863            .end
5864            .to_point(&map.buffer_snapshot)
5865            .to_display_point(map);
5866        if self.reversed {
5867            end..start
5868        } else {
5869            start..end
5870        }
5871    }
5872
5873    fn spanned_rows(
5874        &self,
5875        include_end_if_at_line_start: bool,
5876        map: &DisplaySnapshot,
5877    ) -> Range<u32> {
5878        let start = self.start.to_point(&map.buffer_snapshot);
5879        let mut end = self.end.to_point(&map.buffer_snapshot);
5880        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
5881            end.row -= 1;
5882        }
5883
5884        let buffer_start = map.prev_line_boundary(start).0;
5885        let buffer_end = map.next_line_boundary(end).0;
5886        buffer_start.row..buffer_end.row + 1
5887    }
5888}
5889
5890impl<T: InvalidationRegion> InvalidationStack<T> {
5891    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
5892    where
5893        S: Clone + ToOffset,
5894    {
5895        while let Some(region) = self.last() {
5896            let all_selections_inside_invalidation_ranges =
5897                if selections.len() == region.ranges().len() {
5898                    selections
5899                        .iter()
5900                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
5901                        .all(|(selection, invalidation_range)| {
5902                            let head = selection.head().to_offset(&buffer);
5903                            invalidation_range.start <= head && invalidation_range.end >= head
5904                        })
5905                } else {
5906                    false
5907                };
5908
5909            if all_selections_inside_invalidation_ranges {
5910                break;
5911            } else {
5912                self.pop();
5913            }
5914        }
5915    }
5916}
5917
5918impl<T> Default for InvalidationStack<T> {
5919    fn default() -> Self {
5920        Self(Default::default())
5921    }
5922}
5923
5924impl<T> Deref for InvalidationStack<T> {
5925    type Target = Vec<T>;
5926
5927    fn deref(&self) -> &Self::Target {
5928        &self.0
5929    }
5930}
5931
5932impl<T> DerefMut for InvalidationStack<T> {
5933    fn deref_mut(&mut self) -> &mut Self::Target {
5934        &mut self.0
5935    }
5936}
5937
5938impl InvalidationRegion for BracketPairState {
5939    fn ranges(&self) -> &[Range<Anchor>] {
5940        &self.ranges
5941    }
5942}
5943
5944impl InvalidationRegion for SnippetState {
5945    fn ranges(&self) -> &[Range<Anchor>] {
5946        &self.ranges[self.active_index]
5947    }
5948}
5949
5950impl Deref for EditorStyle {
5951    type Target = theme::Editor;
5952
5953    fn deref(&self) -> &Self::Target {
5954        &self.theme
5955    }
5956}
5957
5958pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
5959    let mut highlighted_lines = Vec::new();
5960    for line in diagnostic.message.lines() {
5961        highlighted_lines.push(highlight_diagnostic_message(line));
5962    }
5963
5964    Arc::new(move |cx: &mut BlockContext| {
5965        let settings = cx.global::<Settings>();
5966        let theme = &settings.theme.editor;
5967        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
5968        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
5969        Flex::column()
5970            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
5971                Label::new(
5972                    line.clone(),
5973                    style.message.clone().with_font_size(font_size),
5974                )
5975                .with_highlights(highlights.clone())
5976                .contained()
5977                .with_margin_left(cx.anchor_x)
5978                .boxed()
5979            }))
5980            .aligned()
5981            .left()
5982            .boxed()
5983    })
5984}
5985
5986pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
5987    let mut message_without_backticks = String::new();
5988    let mut prev_offset = 0;
5989    let mut inside_block = false;
5990    let mut highlights = Vec::new();
5991    for (match_ix, (offset, _)) in message
5992        .match_indices('`')
5993        .chain([(message.len(), "")])
5994        .enumerate()
5995    {
5996        message_without_backticks.push_str(&message[prev_offset..offset]);
5997        if inside_block {
5998            highlights.extend(prev_offset - match_ix..offset - match_ix);
5999        }
6000
6001        inside_block = !inside_block;
6002        prev_offset = offset + 1;
6003    }
6004
6005    (message_without_backticks, highlights)
6006}
6007
6008pub fn diagnostic_style(
6009    severity: DiagnosticSeverity,
6010    valid: bool,
6011    theme: &theme::Editor,
6012) -> DiagnosticStyle {
6013    match (severity, valid) {
6014        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6015        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6016        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6017        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6018        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6019        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6020        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6021        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6022        _ => theme.invalid_hint_diagnostic.clone(),
6023    }
6024}
6025
6026pub fn combine_syntax_and_fuzzy_match_highlights(
6027    text: &str,
6028    default_style: HighlightStyle,
6029    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6030    match_indices: &[usize],
6031) -> Vec<(Range<usize>, HighlightStyle)> {
6032    let mut result = Vec::new();
6033    let mut match_indices = match_indices.iter().copied().peekable();
6034
6035    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6036    {
6037        syntax_highlight.weight = None;
6038
6039        // Add highlights for any fuzzy match characters before the next
6040        // syntax highlight range.
6041        while let Some(&match_index) = match_indices.peek() {
6042            if match_index >= range.start {
6043                break;
6044            }
6045            match_indices.next();
6046            let end_index = char_ix_after(match_index, text);
6047            let mut match_style = default_style;
6048            match_style.weight = Some(fonts::Weight::BOLD);
6049            result.push((match_index..end_index, match_style));
6050        }
6051
6052        if range.start == usize::MAX {
6053            break;
6054        }
6055
6056        // Add highlights for any fuzzy match characters within the
6057        // syntax highlight range.
6058        let mut offset = range.start;
6059        while let Some(&match_index) = match_indices.peek() {
6060            if match_index >= range.end {
6061                break;
6062            }
6063
6064            match_indices.next();
6065            if match_index > offset {
6066                result.push((offset..match_index, syntax_highlight));
6067            }
6068
6069            let mut end_index = char_ix_after(match_index, text);
6070            while let Some(&next_match_index) = match_indices.peek() {
6071                if next_match_index == end_index && next_match_index < range.end {
6072                    end_index = char_ix_after(next_match_index, text);
6073                    match_indices.next();
6074                } else {
6075                    break;
6076                }
6077            }
6078
6079            let mut match_style = syntax_highlight;
6080            match_style.weight = Some(fonts::Weight::BOLD);
6081            result.push((match_index..end_index, match_style));
6082            offset = end_index;
6083        }
6084
6085        if offset < range.end {
6086            result.push((offset..range.end, syntax_highlight));
6087        }
6088    }
6089
6090    fn char_ix_after(ix: usize, text: &str) -> usize {
6091        ix + text[ix..].chars().next().unwrap().len_utf8()
6092    }
6093
6094    result
6095}
6096
6097pub fn styled_runs_for_code_label<'a>(
6098    label: &'a CodeLabel,
6099    syntax_theme: &'a theme::SyntaxTheme,
6100) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6101    let fade_out = HighlightStyle {
6102        fade_out: Some(0.35),
6103        ..Default::default()
6104    };
6105
6106    let mut prev_end = label.filter_range.end;
6107    label
6108        .runs
6109        .iter()
6110        .enumerate()
6111        .flat_map(move |(ix, (range, highlight_id))| {
6112            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6113                style
6114            } else {
6115                return Default::default();
6116            };
6117            let mut muted_style = style.clone();
6118            muted_style.highlight(fade_out);
6119
6120            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6121            if range.start >= label.filter_range.end {
6122                if range.start > prev_end {
6123                    runs.push((prev_end..range.start, fade_out));
6124                }
6125                runs.push((range.clone(), muted_style));
6126            } else if range.end <= label.filter_range.end {
6127                runs.push((range.clone(), style));
6128            } else {
6129                runs.push((range.start..label.filter_range.end, style));
6130                runs.push((label.filter_range.end..range.end, muted_style));
6131            }
6132            prev_end = cmp::max(prev_end, range.end);
6133
6134            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6135                runs.push((prev_end..label.text.len(), fade_out));
6136            }
6137
6138            runs
6139        })
6140}
6141
6142#[cfg(test)]
6143mod tests {
6144    use crate::test::{
6145        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
6146    };
6147
6148    use super::*;
6149    use gpui::{
6150        geometry::rect::RectF,
6151        platform::{WindowBounds, WindowOptions},
6152    };
6153    use indoc::indoc;
6154    use language::{FakeLspAdapter, LanguageConfig};
6155    use lsp::FakeLanguageServer;
6156    use project::FakeFs;
6157    use settings::LanguageOverride;
6158    use smol::stream::StreamExt;
6159    use std::{cell::RefCell, rc::Rc, time::Instant};
6160    use text::Point;
6161    use unindent::Unindent;
6162    use util::{
6163        assert_set_eq,
6164        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
6165    };
6166    use workspace::{FollowableItem, ItemHandle};
6167
6168    #[gpui::test]
6169    fn test_edit_events(cx: &mut MutableAppContext) {
6170        cx.set_global(Settings::test(cx));
6171        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6172
6173        let events = Rc::new(RefCell::new(Vec::new()));
6174        let (_, editor1) = cx.add_window(Default::default(), {
6175            let events = events.clone();
6176            |cx| {
6177                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6178                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6179                        events.borrow_mut().push(("editor1", *event));
6180                    }
6181                })
6182                .detach();
6183                Editor::for_buffer(buffer.clone(), None, cx)
6184            }
6185        });
6186        let (_, editor2) = cx.add_window(Default::default(), {
6187            let events = events.clone();
6188            |cx| {
6189                cx.subscribe(&cx.handle(), move |_, _, event, _| {
6190                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
6191                        events.borrow_mut().push(("editor2", *event));
6192                    }
6193                })
6194                .detach();
6195                Editor::for_buffer(buffer.clone(), None, cx)
6196            }
6197        });
6198        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6199
6200        // Mutating editor 1 will emit an `Edited` event only for that editor.
6201        editor1.update(cx, |editor, cx| editor.insert("X", cx));
6202        assert_eq!(
6203            mem::take(&mut *events.borrow_mut()),
6204            [
6205                ("editor1", Event::Edited),
6206                ("editor1", Event::BufferEdited),
6207                ("editor2", Event::BufferEdited),
6208                ("editor1", Event::Dirtied),
6209                ("editor2", Event::Dirtied)
6210            ]
6211        );
6212
6213        // Mutating editor 2 will emit an `Edited` event only for that editor.
6214        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
6215        assert_eq!(
6216            mem::take(&mut *events.borrow_mut()),
6217            [
6218                ("editor2", Event::Edited),
6219                ("editor1", Event::BufferEdited),
6220                ("editor2", Event::BufferEdited),
6221            ]
6222        );
6223
6224        // Undoing on editor 1 will emit an `Edited` event only for that editor.
6225        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
6226        assert_eq!(
6227            mem::take(&mut *events.borrow_mut()),
6228            [
6229                ("editor1", Event::Edited),
6230                ("editor1", Event::BufferEdited),
6231                ("editor2", Event::BufferEdited),
6232            ]
6233        );
6234
6235        // Redoing on editor 1 will emit an `Edited` event only for that editor.
6236        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
6237        assert_eq!(
6238            mem::take(&mut *events.borrow_mut()),
6239            [
6240                ("editor1", Event::Edited),
6241                ("editor1", Event::BufferEdited),
6242                ("editor2", Event::BufferEdited),
6243            ]
6244        );
6245
6246        // Undoing on editor 2 will emit an `Edited` event only for that editor.
6247        editor2.update(cx, |editor, cx| editor.undo(&Undo, 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        // Redoing on editor 2 will emit an `Edited` event only for that editor.
6258        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
6259        assert_eq!(
6260            mem::take(&mut *events.borrow_mut()),
6261            [
6262                ("editor2", Event::Edited),
6263                ("editor1", Event::BufferEdited),
6264                ("editor2", Event::BufferEdited),
6265            ]
6266        );
6267
6268        // No event is emitted when the mutation is a no-op.
6269        editor2.update(cx, |editor, cx| {
6270            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
6271
6272            editor.backspace(&Backspace, cx);
6273        });
6274        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
6275    }
6276
6277    #[gpui::test]
6278    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
6279        cx.set_global(Settings::test(cx));
6280        let mut now = Instant::now();
6281        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
6282        let group_interval = buffer.read(cx).transaction_group_interval();
6283        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
6284        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6285
6286        editor.update(cx, |editor, cx| {
6287            editor.start_transaction_at(now, cx);
6288            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
6289
6290            editor.insert("cd", cx);
6291            editor.end_transaction_at(now, cx);
6292            assert_eq!(editor.text(cx), "12cd56");
6293            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
6294
6295            editor.start_transaction_at(now, cx);
6296            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
6297            editor.insert("e", cx);
6298            editor.end_transaction_at(now, cx);
6299            assert_eq!(editor.text(cx), "12cde6");
6300            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
6301
6302            now += group_interval + Duration::from_millis(1);
6303            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
6304
6305            // Simulate an edit in another editor
6306            buffer.update(cx, |buffer, cx| {
6307                buffer.start_transaction_at(now, cx);
6308                buffer.edit([(0..1, "a")], cx);
6309                buffer.edit([(1..1, "b")], cx);
6310                buffer.end_transaction_at(now, cx);
6311            });
6312
6313            assert_eq!(editor.text(cx), "ab2cde6");
6314            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
6315
6316            // Last transaction happened past the group interval in a different editor.
6317            // Undo it individually and don't restore selections.
6318            editor.undo(&Undo, cx);
6319            assert_eq!(editor.text(cx), "12cde6");
6320            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
6321
6322            // First two transactions happened within the group interval in this editor.
6323            // Undo them together and restore selections.
6324            editor.undo(&Undo, cx);
6325            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
6326            assert_eq!(editor.text(cx), "123456");
6327            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
6328
6329            // Redo the first two transactions together.
6330            editor.redo(&Redo, cx);
6331            assert_eq!(editor.text(cx), "12cde6");
6332            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
6333
6334            // Redo the last transaction on its own.
6335            editor.redo(&Redo, cx);
6336            assert_eq!(editor.text(cx), "ab2cde6");
6337            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
6338
6339            // Test empty transactions.
6340            editor.start_transaction_at(now, cx);
6341            editor.end_transaction_at(now, cx);
6342            editor.undo(&Undo, cx);
6343            assert_eq!(editor.text(cx), "12cde6");
6344        });
6345    }
6346
6347    #[gpui::test]
6348    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
6349        cx.set_global(Settings::test(cx));
6350
6351        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
6352        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6353        editor.update(cx, |view, cx| {
6354            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6355        });
6356        assert_eq!(
6357            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6358            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6359        );
6360
6361        editor.update(cx, |view, cx| {
6362            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6363        });
6364
6365        assert_eq!(
6366            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6367            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6368        );
6369
6370        editor.update(cx, |view, cx| {
6371            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6372        });
6373
6374        assert_eq!(
6375            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6376            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6377        );
6378
6379        editor.update(cx, |view, cx| {
6380            view.end_selection(cx);
6381            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6382        });
6383
6384        assert_eq!(
6385            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6386            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
6387        );
6388
6389        editor.update(cx, |view, cx| {
6390            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
6391            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
6392        });
6393
6394        assert_eq!(
6395            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6396            [
6397                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
6398                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
6399            ]
6400        );
6401
6402        editor.update(cx, |view, cx| {
6403            view.end_selection(cx);
6404        });
6405
6406        assert_eq!(
6407            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
6408            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
6409        );
6410    }
6411
6412    #[gpui::test]
6413    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
6414        cx.set_global(Settings::test(cx));
6415        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6416        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6417
6418        view.update(cx, |view, cx| {
6419            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
6420            assert_eq!(
6421                view.selections.display_ranges(cx),
6422                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
6423            );
6424        });
6425
6426        view.update(cx, |view, cx| {
6427            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
6428            assert_eq!(
6429                view.selections.display_ranges(cx),
6430                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6431            );
6432        });
6433
6434        view.update(cx, |view, cx| {
6435            view.cancel(&Cancel, cx);
6436            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6437            assert_eq!(
6438                view.selections.display_ranges(cx),
6439                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
6440            );
6441        });
6442    }
6443
6444    #[gpui::test]
6445    fn test_clone_with_selections(cx: &mut gpui::MutableAppContext) {
6446        let (text, selection_ranges) = marked_text_ranges(indoc! {"
6447            The qu[ick brown
6448            fox jum]ps over
6449            the lazy dog
6450        "});
6451        cx.set_global(Settings::test(cx));
6452        let buffer = MultiBuffer::build_simple(&text, cx);
6453
6454        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6455
6456        let cloned_editor = view.update(cx, |view, cx| {
6457            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
6458            view.clone(cx)
6459        });
6460
6461        assert_set_eq!(cloned_editor.selections.ranges(cx), selection_ranges);
6462    }
6463
6464    #[gpui::test]
6465    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
6466        cx.set_global(Settings::test(cx));
6467        use workspace::Item;
6468        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
6469        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
6470
6471        cx.add_window(Default::default(), |cx| {
6472            let mut editor = build_editor(buffer.clone(), cx);
6473            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
6474
6475            // Move the cursor a small distance.
6476            // Nothing is added to the navigation history.
6477            editor.change_selections(None, cx, |s| {
6478                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
6479            });
6480            editor.change_selections(None, cx, |s| {
6481                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
6482            });
6483            assert!(nav_history.borrow_mut().pop_backward().is_none());
6484
6485            // Move the cursor a large distance.
6486            // The history can jump back to the previous position.
6487            editor.change_selections(None, cx, |s| {
6488                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
6489            });
6490            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6491            editor.navigate(nav_entry.data.unwrap(), cx);
6492            assert_eq!(nav_entry.item.id(), cx.view_id());
6493            assert_eq!(
6494                editor.selections.display_ranges(cx),
6495                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
6496            );
6497            assert!(nav_history.borrow_mut().pop_backward().is_none());
6498
6499            // Move the cursor a small distance via the mouse.
6500            // Nothing is added to the navigation history.
6501            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
6502            editor.end_selection(cx);
6503            assert_eq!(
6504                editor.selections.display_ranges(cx),
6505                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6506            );
6507            assert!(nav_history.borrow_mut().pop_backward().is_none());
6508
6509            // Move the cursor a large distance via the mouse.
6510            // The history can jump back to the previous position.
6511            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
6512            editor.end_selection(cx);
6513            assert_eq!(
6514                editor.selections.display_ranges(cx),
6515                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
6516            );
6517            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6518            editor.navigate(nav_entry.data.unwrap(), cx);
6519            assert_eq!(nav_entry.item.id(), cx.view_id());
6520            assert_eq!(
6521                editor.selections.display_ranges(cx),
6522                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
6523            );
6524            assert!(nav_history.borrow_mut().pop_backward().is_none());
6525
6526            // Set scroll position to check later
6527            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
6528            let original_scroll_position = editor.scroll_position;
6529            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
6530
6531            // Jump to the end of the document and adjust scroll
6532            editor.move_to_end(&MoveToEnd, cx);
6533            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
6534            assert_ne!(editor.scroll_position, original_scroll_position);
6535            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
6536
6537            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
6538            editor.navigate(nav_entry.data.unwrap(), cx);
6539            assert_eq!(editor.scroll_position, original_scroll_position);
6540            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
6541
6542            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
6543            let mut invalid_anchor = editor.scroll_top_anchor.clone();
6544            invalid_anchor.text_anchor.buffer_id = Some(999);
6545            let invalid_point = Point::new(9999, 0);
6546            editor.navigate(
6547                Box::new(NavigationData {
6548                    cursor_anchor: invalid_anchor.clone(),
6549                    cursor_position: invalid_point,
6550                    scroll_top_anchor: invalid_anchor.clone(),
6551                    scroll_top_row: invalid_point.row,
6552                    scroll_position: Default::default(),
6553                }),
6554                cx,
6555            );
6556            assert_eq!(
6557                editor.selections.display_ranges(cx),
6558                &[editor.max_point(cx)..editor.max_point(cx)]
6559            );
6560            assert_eq!(
6561                editor.scroll_position(cx),
6562                vec2f(0., editor.max_point(cx).row() as f32)
6563            );
6564
6565            editor
6566        });
6567    }
6568
6569    #[gpui::test]
6570    fn test_cancel(cx: &mut gpui::MutableAppContext) {
6571        cx.set_global(Settings::test(cx));
6572        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
6573        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6574
6575        view.update(cx, |view, cx| {
6576            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
6577            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
6578            view.end_selection(cx);
6579
6580            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
6581            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
6582            view.end_selection(cx);
6583            assert_eq!(
6584                view.selections.display_ranges(cx),
6585                [
6586                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
6587                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
6588                ]
6589            );
6590        });
6591
6592        view.update(cx, |view, cx| {
6593            view.cancel(&Cancel, cx);
6594            assert_eq!(
6595                view.selections.display_ranges(cx),
6596                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
6597            );
6598        });
6599
6600        view.update(cx, |view, cx| {
6601            view.cancel(&Cancel, cx);
6602            assert_eq!(
6603                view.selections.display_ranges(cx),
6604                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
6605            );
6606        });
6607    }
6608
6609    #[gpui::test]
6610    fn test_fold(cx: &mut gpui::MutableAppContext) {
6611        cx.set_global(Settings::test(cx));
6612        let buffer = MultiBuffer::build_simple(
6613            &"
6614                impl Foo {
6615                    // Hello!
6616
6617                    fn a() {
6618                        1
6619                    }
6620
6621                    fn b() {
6622                        2
6623                    }
6624
6625                    fn c() {
6626                        3
6627                    }
6628                }
6629            "
6630            .unindent(),
6631            cx,
6632        );
6633        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6634
6635        view.update(cx, |view, cx| {
6636            view.change_selections(None, cx, |s| {
6637                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
6638            });
6639            view.fold(&Fold, cx);
6640            assert_eq!(
6641                view.display_text(cx),
6642                "
6643                    impl Foo {
6644                        // Hello!
6645
6646                        fn a() {
6647                            1
6648                        }
6649
6650                        fn b() {…
6651                        }
6652
6653                        fn c() {…
6654                        }
6655                    }
6656                "
6657                .unindent(),
6658            );
6659
6660            view.fold(&Fold, cx);
6661            assert_eq!(
6662                view.display_text(cx),
6663                "
6664                    impl Foo {…
6665                    }
6666                "
6667                .unindent(),
6668            );
6669
6670            view.unfold_lines(&UnfoldLines, cx);
6671            assert_eq!(
6672                view.display_text(cx),
6673                "
6674                    impl Foo {
6675                        // Hello!
6676
6677                        fn a() {
6678                            1
6679                        }
6680
6681                        fn b() {…
6682                        }
6683
6684                        fn c() {…
6685                        }
6686                    }
6687                "
6688                .unindent(),
6689            );
6690
6691            view.unfold_lines(&UnfoldLines, cx);
6692            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
6693        });
6694    }
6695
6696    #[gpui::test]
6697    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
6698        cx.set_global(Settings::test(cx));
6699        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
6700        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6701
6702        buffer.update(cx, |buffer, cx| {
6703            buffer.edit(
6704                vec![
6705                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
6706                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
6707                ],
6708                cx,
6709            );
6710        });
6711
6712        view.update(cx, |view, cx| {
6713            assert_eq!(
6714                view.selections.display_ranges(cx),
6715                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6716            );
6717
6718            view.move_down(&MoveDown, cx);
6719            assert_eq!(
6720                view.selections.display_ranges(cx),
6721                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6722            );
6723
6724            view.move_right(&MoveRight, cx);
6725            assert_eq!(
6726                view.selections.display_ranges(cx),
6727                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
6728            );
6729
6730            view.move_left(&MoveLeft, cx);
6731            assert_eq!(
6732                view.selections.display_ranges(cx),
6733                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
6734            );
6735
6736            view.move_up(&MoveUp, cx);
6737            assert_eq!(
6738                view.selections.display_ranges(cx),
6739                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6740            );
6741
6742            view.move_to_end(&MoveToEnd, cx);
6743            assert_eq!(
6744                view.selections.display_ranges(cx),
6745                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
6746            );
6747
6748            view.move_to_beginning(&MoveToBeginning, cx);
6749            assert_eq!(
6750                view.selections.display_ranges(cx),
6751                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
6752            );
6753
6754            view.change_selections(None, cx, |s| {
6755                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
6756            });
6757            view.select_to_beginning(&SelectToBeginning, cx);
6758            assert_eq!(
6759                view.selections.display_ranges(cx),
6760                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
6761            );
6762
6763            view.select_to_end(&SelectToEnd, cx);
6764            assert_eq!(
6765                view.selections.display_ranges(cx),
6766                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
6767            );
6768        });
6769    }
6770
6771    #[gpui::test]
6772    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
6773        cx.set_global(Settings::test(cx));
6774        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
6775        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6776
6777        assert_eq!('ⓐ'.len_utf8(), 3);
6778        assert_eq!('α'.len_utf8(), 2);
6779
6780        view.update(cx, |view, cx| {
6781            view.fold_ranges(
6782                vec![
6783                    Point::new(0, 6)..Point::new(0, 12),
6784                    Point::new(1, 2)..Point::new(1, 4),
6785                    Point::new(2, 4)..Point::new(2, 8),
6786                ],
6787                cx,
6788            );
6789            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
6790
6791            view.move_right(&MoveRight, cx);
6792            assert_eq!(
6793                view.selections.display_ranges(cx),
6794                &[empty_range(0, "".len())]
6795            );
6796            view.move_right(&MoveRight, cx);
6797            assert_eq!(
6798                view.selections.display_ranges(cx),
6799                &[empty_range(0, "ⓐⓑ".len())]
6800            );
6801            view.move_right(&MoveRight, cx);
6802            assert_eq!(
6803                view.selections.display_ranges(cx),
6804                &[empty_range(0, "ⓐⓑ…".len())]
6805            );
6806
6807            view.move_down(&MoveDown, cx);
6808            assert_eq!(
6809                view.selections.display_ranges(cx),
6810                &[empty_range(1, "ab…".len())]
6811            );
6812            view.move_left(&MoveLeft, cx);
6813            assert_eq!(
6814                view.selections.display_ranges(cx),
6815                &[empty_range(1, "ab".len())]
6816            );
6817            view.move_left(&MoveLeft, cx);
6818            assert_eq!(
6819                view.selections.display_ranges(cx),
6820                &[empty_range(1, "a".len())]
6821            );
6822
6823            view.move_down(&MoveDown, cx);
6824            assert_eq!(
6825                view.selections.display_ranges(cx),
6826                &[empty_range(2, "α".len())]
6827            );
6828            view.move_right(&MoveRight, cx);
6829            assert_eq!(
6830                view.selections.display_ranges(cx),
6831                &[empty_range(2, "αβ".len())]
6832            );
6833            view.move_right(&MoveRight, cx);
6834            assert_eq!(
6835                view.selections.display_ranges(cx),
6836                &[empty_range(2, "αβ…".len())]
6837            );
6838            view.move_right(&MoveRight, cx);
6839            assert_eq!(
6840                view.selections.display_ranges(cx),
6841                &[empty_range(2, "αβ…ε".len())]
6842            );
6843
6844            view.move_up(&MoveUp, cx);
6845            assert_eq!(
6846                view.selections.display_ranges(cx),
6847                &[empty_range(1, "ab…e".len())]
6848            );
6849            view.move_up(&MoveUp, cx);
6850            assert_eq!(
6851                view.selections.display_ranges(cx),
6852                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
6853            );
6854            view.move_left(&MoveLeft, cx);
6855            assert_eq!(
6856                view.selections.display_ranges(cx),
6857                &[empty_range(0, "ⓐⓑ…".len())]
6858            );
6859            view.move_left(&MoveLeft, cx);
6860            assert_eq!(
6861                view.selections.display_ranges(cx),
6862                &[empty_range(0, "ⓐⓑ".len())]
6863            );
6864            view.move_left(&MoveLeft, cx);
6865            assert_eq!(
6866                view.selections.display_ranges(cx),
6867                &[empty_range(0, "".len())]
6868            );
6869        });
6870    }
6871
6872    #[gpui::test]
6873    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
6874        cx.set_global(Settings::test(cx));
6875        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
6876        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
6877        view.update(cx, |view, cx| {
6878            view.change_selections(None, cx, |s| {
6879                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
6880            });
6881            view.move_down(&MoveDown, cx);
6882            assert_eq!(
6883                view.selections.display_ranges(cx),
6884                &[empty_range(1, "abcd".len())]
6885            );
6886
6887            view.move_down(&MoveDown, cx);
6888            assert_eq!(
6889                view.selections.display_ranges(cx),
6890                &[empty_range(2, "αβγ".len())]
6891            );
6892
6893            view.move_down(&MoveDown, cx);
6894            assert_eq!(
6895                view.selections.display_ranges(cx),
6896                &[empty_range(3, "abcd".len())]
6897            );
6898
6899            view.move_down(&MoveDown, cx);
6900            assert_eq!(
6901                view.selections.display_ranges(cx),
6902                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
6903            );
6904
6905            view.move_up(&MoveUp, cx);
6906            assert_eq!(
6907                view.selections.display_ranges(cx),
6908                &[empty_range(3, "abcd".len())]
6909            );
6910
6911            view.move_up(&MoveUp, cx);
6912            assert_eq!(
6913                view.selections.display_ranges(cx),
6914                &[empty_range(2, "αβγ".len())]
6915            );
6916        });
6917    }
6918
6919    #[gpui::test]
6920    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
6921        cx.set_global(Settings::test(cx));
6922        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
6923        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
6924        view.update(cx, |view, cx| {
6925            view.change_selections(None, cx, |s| {
6926                s.select_display_ranges([
6927                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
6928                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
6929                ]);
6930            });
6931        });
6932
6933        view.update(cx, |view, cx| {
6934            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6935            assert_eq!(
6936                view.selections.display_ranges(cx),
6937                &[
6938                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6939                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
6940                ]
6941            );
6942        });
6943
6944        view.update(cx, |view, cx| {
6945            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6946            assert_eq!(
6947                view.selections.display_ranges(cx),
6948                &[
6949                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6950                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
6951                ]
6952            );
6953        });
6954
6955        view.update(cx, |view, cx| {
6956            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
6957            assert_eq!(
6958                view.selections.display_ranges(cx),
6959                &[
6960                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
6961                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
6962                ]
6963            );
6964        });
6965
6966        view.update(cx, |view, cx| {
6967            view.move_to_end_of_line(&MoveToEndOfLine, cx);
6968            assert_eq!(
6969                view.selections.display_ranges(cx),
6970                &[
6971                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6972                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
6973                ]
6974            );
6975        });
6976
6977        // Moving to the end of line again is a no-op.
6978        view.update(cx, |view, cx| {
6979            view.move_to_end_of_line(&MoveToEndOfLine, cx);
6980            assert_eq!(
6981                view.selections.display_ranges(cx),
6982                &[
6983                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
6984                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
6985                ]
6986            );
6987        });
6988
6989        view.update(cx, |view, cx| {
6990            view.move_left(&MoveLeft, cx);
6991            view.select_to_beginning_of_line(
6992                &SelectToBeginningOfLine {
6993                    stop_at_soft_wraps: true,
6994                },
6995                cx,
6996            );
6997            assert_eq!(
6998                view.selections.display_ranges(cx),
6999                &[
7000                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7001                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7002                ]
7003            );
7004        });
7005
7006        view.update(cx, |view, cx| {
7007            view.select_to_beginning_of_line(
7008                &SelectToBeginningOfLine {
7009                    stop_at_soft_wraps: true,
7010                },
7011                cx,
7012            );
7013            assert_eq!(
7014                view.selections.display_ranges(cx),
7015                &[
7016                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7017                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
7018                ]
7019            );
7020        });
7021
7022        view.update(cx, |view, cx| {
7023            view.select_to_beginning_of_line(
7024                &SelectToBeginningOfLine {
7025                    stop_at_soft_wraps: true,
7026                },
7027                cx,
7028            );
7029            assert_eq!(
7030                view.selections.display_ranges(cx),
7031                &[
7032                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
7033                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
7034                ]
7035            );
7036        });
7037
7038        view.update(cx, |view, cx| {
7039            view.select_to_end_of_line(
7040                &SelectToEndOfLine {
7041                    stop_at_soft_wraps: true,
7042                },
7043                cx,
7044            );
7045            assert_eq!(
7046                view.selections.display_ranges(cx),
7047                &[
7048                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
7049                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
7050                ]
7051            );
7052        });
7053
7054        view.update(cx, |view, cx| {
7055            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
7056            assert_eq!(view.display_text(cx), "ab\n  de");
7057            assert_eq!(
7058                view.selections.display_ranges(cx),
7059                &[
7060                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7061                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
7062                ]
7063            );
7064        });
7065
7066        view.update(cx, |view, cx| {
7067            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
7068            assert_eq!(view.display_text(cx), "\n");
7069            assert_eq!(
7070                view.selections.display_ranges(cx),
7071                &[
7072                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7073                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7074                ]
7075            );
7076        });
7077    }
7078
7079    #[gpui::test]
7080    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
7081        cx.set_global(Settings::test(cx));
7082        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
7083        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7084        view.update(cx, |view, cx| {
7085            view.change_selections(None, cx, |s| {
7086                s.select_display_ranges([
7087                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
7088                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
7089                ])
7090            });
7091
7092            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7093            assert_selection_ranges(
7094                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7095                vec![('<', '>'), ('[', ']')],
7096                view,
7097                cx,
7098            );
7099
7100            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7101            assert_selection_ranges(
7102                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
7103                vec![('<', '>'), ('[', ']')],
7104                view,
7105                cx,
7106            );
7107
7108            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7109            assert_selection_ranges(
7110                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
7111                vec![('<', '>'), ('[', ']')],
7112                view,
7113                cx,
7114            );
7115
7116            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7117            assert_selection_ranges(
7118                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
7119                vec![('<', '>'), ('[', ']')],
7120                view,
7121                cx,
7122            );
7123
7124            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7125            assert_selection_ranges(
7126                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
7127                vec![('<', '>'), ('[', ']')],
7128                view,
7129                cx,
7130            );
7131
7132            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7133            assert_selection_ranges(
7134                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
7135                vec![('<', '>'), ('[', ']')],
7136                view,
7137                cx,
7138            );
7139
7140            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7141            assert_selection_ranges(
7142                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
7143                vec![('<', '>'), ('[', ']')],
7144                view,
7145                cx,
7146            );
7147
7148            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7149            assert_selection_ranges(
7150                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
7151                vec![('<', '>'), ('[', ']')],
7152                view,
7153                cx,
7154            );
7155
7156            view.move_right(&MoveRight, cx);
7157            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7158            assert_selection_ranges(
7159                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7160                vec![('<', '>'), ('[', ']')],
7161                view,
7162                cx,
7163            );
7164
7165            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
7166            assert_selection_ranges(
7167                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
7168                vec![('<', '>'), ('[', ']')],
7169                view,
7170                cx,
7171            );
7172
7173            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
7174            assert_selection_ranges(
7175                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
7176                vec![('<', '>'), ('[', ']')],
7177                view,
7178                cx,
7179            );
7180        });
7181    }
7182
7183    #[gpui::test]
7184    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
7185        cx.set_global(Settings::test(cx));
7186        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
7187        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7188
7189        view.update(cx, |view, cx| {
7190            view.set_wrap_width(Some(140.), cx);
7191            assert_eq!(
7192                view.display_text(cx),
7193                "use one::{\n    two::three::\n    four::five\n};"
7194            );
7195
7196            view.change_selections(None, cx, |s| {
7197                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
7198            });
7199
7200            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7201            assert_eq!(
7202                view.selections.display_ranges(cx),
7203                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
7204            );
7205
7206            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7207            assert_eq!(
7208                view.selections.display_ranges(cx),
7209                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7210            );
7211
7212            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7213            assert_eq!(
7214                view.selections.display_ranges(cx),
7215                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7216            );
7217
7218            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
7219            assert_eq!(
7220                view.selections.display_ranges(cx),
7221                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
7222            );
7223
7224            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7225            assert_eq!(
7226                view.selections.display_ranges(cx),
7227                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
7228            );
7229
7230            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
7231            assert_eq!(
7232                view.selections.display_ranges(cx),
7233                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
7234            );
7235        });
7236    }
7237
7238    #[gpui::test]
7239    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
7240        cx.set_global(Settings::test(cx));
7241        let (text, ranges) = marked_text_ranges("one [two three] four");
7242        let buffer = MultiBuffer::build_simple(&text, cx);
7243
7244        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7245
7246        editor.update(cx, |editor, cx| {
7247            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
7248            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
7249            assert_eq!(editor.text(cx), " four");
7250        });
7251    }
7252
7253    #[gpui::test]
7254    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
7255        cx.set_global(Settings::test(cx));
7256        let buffer = MultiBuffer::build_simple("one two three four", cx);
7257        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7258
7259        view.update(cx, |view, cx| {
7260            view.change_selections(None, cx, |s| {
7261                s.select_display_ranges([
7262                    // an empty selection - the preceding word fragment is deleted
7263                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7264                    // characters selected - they are deleted
7265                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
7266                ])
7267            });
7268            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
7269        });
7270
7271        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
7272
7273        view.update(cx, |view, cx| {
7274            view.change_selections(None, cx, |s| {
7275                s.select_display_ranges([
7276                    // an empty selection - the following word fragment is deleted
7277                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
7278                    // characters selected - they are deleted
7279                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
7280                ])
7281            });
7282            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
7283        });
7284
7285        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
7286    }
7287
7288    #[gpui::test]
7289    fn test_newline(cx: &mut gpui::MutableAppContext) {
7290        cx.set_global(Settings::test(cx));
7291        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
7292        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
7293
7294        view.update(cx, |view, cx| {
7295            view.change_selections(None, cx, |s| {
7296                s.select_display_ranges([
7297                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7298                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7299                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
7300                ])
7301            });
7302
7303            view.newline(&Newline, cx);
7304            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
7305        });
7306    }
7307
7308    #[gpui::test]
7309    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
7310        cx.set_global(Settings::test(cx));
7311        let buffer = MultiBuffer::build_simple(
7312            "
7313                a
7314                b(
7315                    X
7316                )
7317                c(
7318                    X
7319                )
7320            "
7321            .unindent()
7322            .as_str(),
7323            cx,
7324        );
7325
7326        let (_, editor) = cx.add_window(Default::default(), |cx| {
7327            let mut editor = build_editor(buffer.clone(), cx);
7328            editor.change_selections(None, cx, |s| {
7329                s.select_ranges([
7330                    Point::new(2, 4)..Point::new(2, 5),
7331                    Point::new(5, 4)..Point::new(5, 5),
7332                ])
7333            });
7334            editor
7335        });
7336
7337        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7338        buffer.update(cx, |buffer, cx| {
7339            buffer.edit(
7340                [
7341                    (Point::new(1, 2)..Point::new(3, 0), ""),
7342                    (Point::new(4, 2)..Point::new(6, 0), ""),
7343                ],
7344                cx,
7345            );
7346            assert_eq!(
7347                buffer.read(cx).text(),
7348                "
7349                    a
7350                    b()
7351                    c()
7352                "
7353                .unindent()
7354            );
7355        });
7356
7357        editor.update(cx, |editor, cx| {
7358            assert_eq!(
7359                editor.selections.ranges(cx),
7360                &[
7361                    Point::new(1, 2)..Point::new(1, 2),
7362                    Point::new(2, 2)..Point::new(2, 2),
7363                ],
7364            );
7365
7366            editor.newline(&Newline, cx);
7367            assert_eq!(
7368                editor.text(cx),
7369                "
7370                    a
7371                    b(
7372                    )
7373                    c(
7374                    )
7375                "
7376                .unindent()
7377            );
7378
7379            // The selections are moved after the inserted newlines
7380            assert_eq!(
7381                editor.selections.ranges(cx),
7382                &[
7383                    Point::new(2, 0)..Point::new(2, 0),
7384                    Point::new(4, 0)..Point::new(4, 0),
7385                ],
7386            );
7387        });
7388    }
7389
7390    #[gpui::test]
7391    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
7392        cx.set_global(Settings::test(cx));
7393        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
7394        let (_, editor) = cx.add_window(Default::default(), |cx| {
7395            let mut editor = build_editor(buffer.clone(), cx);
7396            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
7397            editor
7398        });
7399
7400        // Edit the buffer directly, deleting ranges surrounding the editor's selections
7401        buffer.update(cx, |buffer, cx| {
7402            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
7403            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
7404        });
7405
7406        editor.update(cx, |editor, cx| {
7407            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
7408
7409            editor.insert("Z", cx);
7410            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
7411
7412            // The selections are moved after the inserted characters
7413            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
7414        });
7415    }
7416
7417    #[gpui::test]
7418    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
7419        let mut cx = EditorTestContext::new(cx).await;
7420
7421        cx.set_state(indoc! {"
7422              [one} [two}
7423            three
7424             four"});
7425        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7426        cx.assert_editor_state(indoc! {"
7427                [one} [two}
7428            three
7429             four"});
7430
7431        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7432        cx.assert_editor_state(indoc! {"
7433            [one} [two}
7434            three
7435             four"});
7436
7437        // select across line ending
7438        cx.set_state(indoc! {"
7439            one two
7440            t[hree
7441            } four"});
7442        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7443        cx.assert_editor_state(indoc! {"
7444            one two
7445                t[hree
7446            } four"});
7447
7448        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7449        cx.assert_editor_state(indoc! {"
7450            one two
7451            t[hree
7452            } four"});
7453
7454        // Ensure that indenting/outdenting works when the cursor is at column 0.
7455        cx.set_state(indoc! {"
7456            one two
7457            |three
7458                four"});
7459        cx.update_editor(|e, cx| e.tab(&Tab, cx));
7460        cx.assert_editor_state(indoc! {"
7461            one two
7462                |three
7463                four"});
7464
7465        cx.set_state(indoc! {"
7466            one two
7467            |    three
7468             four"});
7469        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
7470        cx.assert_editor_state(indoc! {"
7471            one two
7472            |three
7473             four"});
7474    }
7475
7476    #[gpui::test]
7477    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
7478        cx.set_global(
7479            Settings::test(cx)
7480                .with_overrides(
7481                    "TOML",
7482                    LanguageOverride {
7483                        tab_size: Some(2),
7484                        ..Default::default()
7485                    },
7486                )
7487                .with_overrides(
7488                    "Rust",
7489                    LanguageOverride {
7490                        tab_size: Some(4),
7491                        ..Default::default()
7492                    },
7493                ),
7494        );
7495        let toml_language = Arc::new(Language::new(
7496            LanguageConfig {
7497                name: "TOML".into(),
7498                ..Default::default()
7499            },
7500            None,
7501        ));
7502        let rust_language = Arc::new(Language::new(
7503            LanguageConfig {
7504                name: "Rust".into(),
7505                ..Default::default()
7506            },
7507            None,
7508        ));
7509
7510        let toml_buffer = cx
7511            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
7512        let rust_buffer = cx.add_model(|cx| {
7513            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
7514        });
7515        let multibuffer = cx.add_model(|cx| {
7516            let mut multibuffer = MultiBuffer::new(0);
7517            multibuffer.push_excerpts(
7518                toml_buffer.clone(),
7519                [Point::new(0, 0)..Point::new(2, 0)],
7520                cx,
7521            );
7522            multibuffer.push_excerpts(
7523                rust_buffer.clone(),
7524                [Point::new(0, 0)..Point::new(1, 0)],
7525                cx,
7526            );
7527            multibuffer
7528        });
7529
7530        cx.add_window(Default::default(), |cx| {
7531            let mut editor = build_editor(multibuffer, cx);
7532
7533            assert_eq!(
7534                editor.text(cx),
7535                indoc! {"
7536                    a = 1
7537                    b = 2
7538
7539                    const c: usize = 3;
7540                "}
7541            );
7542
7543            select_ranges(
7544                &mut editor,
7545                indoc! {"
7546                    [a] = 1
7547                    b = 2
7548
7549                    [const c:] usize = 3;
7550                "},
7551                cx,
7552            );
7553
7554            editor.tab(&Tab, cx);
7555            assert_text_with_selections(
7556                &mut editor,
7557                indoc! {"
7558                      [a] = 1
7559                    b = 2
7560
7561                        [const c:] usize = 3;
7562                "},
7563                cx,
7564            );
7565            editor.tab_prev(&TabPrev, cx);
7566            assert_text_with_selections(
7567                &mut editor,
7568                indoc! {"
7569                    [a] = 1
7570                    b = 2
7571
7572                    [const c:] usize = 3;
7573                "},
7574                cx,
7575            );
7576
7577            editor
7578        });
7579    }
7580
7581    #[gpui::test]
7582    async fn test_backspace(cx: &mut gpui::TestAppContext) {
7583        let mut cx = EditorTestContext::new(cx).await;
7584        // Basic backspace
7585        cx.set_state(indoc! {"
7586            on|e two three
7587            fou[r} five six
7588            seven {eight nine
7589            ]ten"});
7590        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7591        cx.assert_editor_state(indoc! {"
7592            o|e two three
7593            fou| five six
7594            seven |ten"});
7595
7596        // Test backspace inside and around indents
7597        cx.set_state(indoc! {"
7598            zero
7599                |one
7600                    |two
7601                | | |  three
7602            |  |  four"});
7603        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7604        cx.assert_editor_state(indoc! {"
7605            zero
7606            |one
7607                |two
7608            |  three|  four"});
7609
7610        // Test backspace with line_mode set to true
7611        cx.update_editor(|e, _| e.selections.line_mode = true);
7612        cx.set_state(indoc! {"
7613            The |quick |brown
7614            fox jumps over
7615            the lazy dog
7616            |The qu[ick b}rown"});
7617        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7618        cx.assert_editor_state(indoc! {"
7619            |fox jumps over
7620            the lazy dog|"});
7621    }
7622
7623    #[gpui::test]
7624    async fn test_delete(cx: &mut gpui::TestAppContext) {
7625        let mut cx = EditorTestContext::new(cx).await;
7626
7627        cx.set_state(indoc! {"
7628            on|e two three
7629            fou[r} five six
7630            seven {eight nine
7631            ]ten"});
7632        cx.update_editor(|e, cx| e.delete(&Delete, cx));
7633        cx.assert_editor_state(indoc! {"
7634            on| two three
7635            fou| five six
7636            seven |ten"});
7637
7638        // Test backspace with line_mode set to true
7639        cx.update_editor(|e, _| e.selections.line_mode = true);
7640        cx.set_state(indoc! {"
7641            The |quick |brown
7642            fox {jum]ps over
7643            the lazy dog
7644            |The qu[ick b}rown"});
7645        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
7646        cx.assert_editor_state("|the lazy dog|");
7647    }
7648
7649    #[gpui::test]
7650    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
7651        cx.set_global(Settings::test(cx));
7652        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7653        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7654        view.update(cx, |view, cx| {
7655            view.change_selections(None, cx, |s| {
7656                s.select_display_ranges([
7657                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7658                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7659                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7660                ])
7661            });
7662            view.delete_line(&DeleteLine, cx);
7663            assert_eq!(view.display_text(cx), "ghi");
7664            assert_eq!(
7665                view.selections.display_ranges(cx),
7666                vec![
7667                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
7668                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
7669                ]
7670            );
7671        });
7672
7673        cx.set_global(Settings::test(cx));
7674        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7675        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7676        view.update(cx, |view, cx| {
7677            view.change_selections(None, cx, |s| {
7678                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
7679            });
7680            view.delete_line(&DeleteLine, cx);
7681            assert_eq!(view.display_text(cx), "ghi\n");
7682            assert_eq!(
7683                view.selections.display_ranges(cx),
7684                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
7685            );
7686        });
7687    }
7688
7689    #[gpui::test]
7690    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
7691        cx.set_global(Settings::test(cx));
7692        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7693        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7694        view.update(cx, |view, cx| {
7695            view.change_selections(None, cx, |s| {
7696                s.select_display_ranges([
7697                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
7698                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
7699                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
7700                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7701                ])
7702            });
7703            view.duplicate_line(&DuplicateLine, cx);
7704            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
7705            assert_eq!(
7706                view.selections.display_ranges(cx),
7707                vec![
7708                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
7709                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
7710                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
7711                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
7712                ]
7713            );
7714        });
7715
7716        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
7717        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7718        view.update(cx, |view, cx| {
7719            view.change_selections(None, cx, |s| {
7720                s.select_display_ranges([
7721                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
7722                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
7723                ])
7724            });
7725            view.duplicate_line(&DuplicateLine, cx);
7726            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
7727            assert_eq!(
7728                view.selections.display_ranges(cx),
7729                vec![
7730                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
7731                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
7732                ]
7733            );
7734        });
7735    }
7736
7737    #[gpui::test]
7738    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
7739        cx.set_global(Settings::test(cx));
7740        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7741        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7742        view.update(cx, |view, cx| {
7743            view.fold_ranges(
7744                vec![
7745                    Point::new(0, 2)..Point::new(1, 2),
7746                    Point::new(2, 3)..Point::new(4, 1),
7747                    Point::new(7, 0)..Point::new(8, 4),
7748                ],
7749                cx,
7750            );
7751            view.change_selections(None, cx, |s| {
7752                s.select_display_ranges([
7753                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7754                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7755                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7756                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
7757                ])
7758            });
7759            assert_eq!(
7760                view.display_text(cx),
7761                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
7762            );
7763
7764            view.move_line_up(&MoveLineUp, cx);
7765            assert_eq!(
7766                view.display_text(cx),
7767                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
7768            );
7769            assert_eq!(
7770                view.selections.display_ranges(cx),
7771                vec![
7772                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
7773                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7774                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7775                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7776                ]
7777            );
7778        });
7779
7780        view.update(cx, |view, cx| {
7781            view.move_line_down(&MoveLineDown, cx);
7782            assert_eq!(
7783                view.display_text(cx),
7784                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
7785            );
7786            assert_eq!(
7787                view.selections.display_ranges(cx),
7788                vec![
7789                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7790                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7791                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7792                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7793                ]
7794            );
7795        });
7796
7797        view.update(cx, |view, cx| {
7798            view.move_line_down(&MoveLineDown, cx);
7799            assert_eq!(
7800                view.display_text(cx),
7801                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
7802            );
7803            assert_eq!(
7804                view.selections.display_ranges(cx),
7805                vec![
7806                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7807                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
7808                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
7809                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
7810                ]
7811            );
7812        });
7813
7814        view.update(cx, |view, cx| {
7815            view.move_line_up(&MoveLineUp, cx);
7816            assert_eq!(
7817                view.display_text(cx),
7818                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
7819            );
7820            assert_eq!(
7821                view.selections.display_ranges(cx),
7822                vec![
7823                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
7824                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
7825                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
7826                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
7827                ]
7828            );
7829        });
7830    }
7831
7832    #[gpui::test]
7833    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
7834        cx.set_global(Settings::test(cx));
7835        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
7836        let snapshot = buffer.read(cx).snapshot(cx);
7837        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
7838        editor.update(cx, |editor, cx| {
7839            editor.insert_blocks(
7840                [BlockProperties {
7841                    position: snapshot.anchor_after(Point::new(2, 0)),
7842                    disposition: BlockDisposition::Below,
7843                    height: 1,
7844                    render: Arc::new(|_| Empty::new().boxed()),
7845                }],
7846                cx,
7847            );
7848            editor.change_selections(None, cx, |s| {
7849                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
7850            });
7851            editor.move_line_down(&MoveLineDown, cx);
7852        });
7853    }
7854
7855    #[gpui::test]
7856    fn test_transpose(cx: &mut gpui::MutableAppContext) {
7857        cx.set_global(Settings::test(cx));
7858
7859        cx.add_window(Default::default(), |cx| {
7860            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
7861
7862            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
7863            editor.transpose(&Default::default(), cx);
7864            assert_eq!(editor.text(cx), "bac");
7865            assert_eq!(editor.selections.ranges(cx), [2..2]);
7866
7867            editor.transpose(&Default::default(), cx);
7868            assert_eq!(editor.text(cx), "bca");
7869            assert_eq!(editor.selections.ranges(cx), [3..3]);
7870
7871            editor.transpose(&Default::default(), cx);
7872            assert_eq!(editor.text(cx), "bac");
7873            assert_eq!(editor.selections.ranges(cx), [3..3]);
7874
7875            editor
7876        })
7877        .1;
7878
7879        cx.add_window(Default::default(), |cx| {
7880            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
7881
7882            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
7883            editor.transpose(&Default::default(), cx);
7884            assert_eq!(editor.text(cx), "acb\nde");
7885            assert_eq!(editor.selections.ranges(cx), [3..3]);
7886
7887            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
7888            editor.transpose(&Default::default(), cx);
7889            assert_eq!(editor.text(cx), "acbd\ne");
7890            assert_eq!(editor.selections.ranges(cx), [5..5]);
7891
7892            editor.transpose(&Default::default(), cx);
7893            assert_eq!(editor.text(cx), "acbde\n");
7894            assert_eq!(editor.selections.ranges(cx), [6..6]);
7895
7896            editor.transpose(&Default::default(), cx);
7897            assert_eq!(editor.text(cx), "acbd\ne");
7898            assert_eq!(editor.selections.ranges(cx), [6..6]);
7899
7900            editor
7901        })
7902        .1;
7903
7904        cx.add_window(Default::default(), |cx| {
7905            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
7906
7907            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
7908            editor.transpose(&Default::default(), cx);
7909            assert_eq!(editor.text(cx), "bacd\ne");
7910            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
7911
7912            editor.transpose(&Default::default(), cx);
7913            assert_eq!(editor.text(cx), "bcade\n");
7914            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
7915
7916            editor.transpose(&Default::default(), cx);
7917            assert_eq!(editor.text(cx), "bcda\ne");
7918            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
7919
7920            editor.transpose(&Default::default(), cx);
7921            assert_eq!(editor.text(cx), "bcade\n");
7922            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
7923
7924            editor.transpose(&Default::default(), cx);
7925            assert_eq!(editor.text(cx), "bcaed\n");
7926            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
7927
7928            editor
7929        })
7930        .1;
7931
7932        cx.add_window(Default::default(), |cx| {
7933            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
7934
7935            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
7936            editor.transpose(&Default::default(), cx);
7937            assert_eq!(editor.text(cx), "🏀🍐✋");
7938            assert_eq!(editor.selections.ranges(cx), [8..8]);
7939
7940            editor.transpose(&Default::default(), cx);
7941            assert_eq!(editor.text(cx), "🏀✋🍐");
7942            assert_eq!(editor.selections.ranges(cx), [11..11]);
7943
7944            editor.transpose(&Default::default(), cx);
7945            assert_eq!(editor.text(cx), "🏀🍐✋");
7946            assert_eq!(editor.selections.ranges(cx), [11..11]);
7947
7948            editor
7949        })
7950        .1;
7951    }
7952
7953    #[gpui::test]
7954    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
7955        let mut cx = EditorTestContext::new(cx).await;
7956
7957        cx.set_state("[one✅ }two [three }four [five }six ");
7958        cx.update_editor(|e, cx| e.cut(&Cut, cx));
7959        cx.assert_editor_state("|two |four |six ");
7960
7961        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
7962        cx.set_state("two |four |six |");
7963        cx.update_editor(|e, cx| e.paste(&Paste, cx));
7964        cx.assert_editor_state("two one✅ |four three |six five |");
7965
7966        // Paste again but with only two cursors. Since the number of cursors doesn't
7967        // match the number of slices in the clipboard, the entire clipboard text
7968        // is pasted at each cursor.
7969        cx.set_state("|two one✅ four three six five |");
7970        cx.update_editor(|e, cx| {
7971            e.handle_input(&Input("( ".into()), cx);
7972            e.paste(&Paste, cx);
7973            e.handle_input(&Input(") ".into()), cx);
7974        });
7975        cx.assert_editor_state(indoc! {"
7976            ( one✅ 
7977            three 
7978            five ) |two one✅ four three six five ( one✅ 
7979            three 
7980            five ) |"});
7981
7982        // Cut with three selections, one of which is full-line.
7983        cx.set_state(indoc! {"
7984            1[2}3
7985            4|567
7986            [8}9"});
7987        cx.update_editor(|e, cx| e.cut(&Cut, cx));
7988        cx.assert_editor_state(indoc! {"
7989            1|3
7990            |9"});
7991
7992        // Paste with three selections, noticing how the copied selection that was full-line
7993        // gets inserted before the second cursor.
7994        cx.set_state(indoc! {"
7995            1|3
7996            9|
7997            [o}ne"});
7998        cx.update_editor(|e, cx| e.paste(&Paste, cx));
7999        cx.assert_editor_state(indoc! {"
8000            12|3
8001            4567
8002            9|
8003            8|ne"});
8004
8005        // Copy with a single cursor only, which writes the whole line into the clipboard.
8006        cx.set_state(indoc! {"
8007            The quick brown
8008            fox ju|mps over
8009            the lazy dog"});
8010        cx.update_editor(|e, cx| e.copy(&Copy, cx));
8011        cx.assert_clipboard_content(Some("fox jumps over\n"));
8012
8013        // Paste with three selections, noticing how the copied full-line selection is inserted
8014        // before the empty selections but replaces the selection that is non-empty.
8015        cx.set_state(indoc! {"
8016            T|he quick brown
8017            [fo}x jumps over
8018            t|he lazy dog"});
8019        cx.update_editor(|e, cx| e.paste(&Paste, cx));
8020        cx.assert_editor_state(indoc! {"
8021            fox jumps over
8022            T|he quick brown
8023            fox jumps over
8024            |x jumps over
8025            fox jumps over
8026            t|he lazy dog"});
8027    }
8028
8029    #[gpui::test]
8030    fn test_select_all(cx: &mut gpui::MutableAppContext) {
8031        cx.set_global(Settings::test(cx));
8032        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
8033        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8034        view.update(cx, |view, cx| {
8035            view.select_all(&SelectAll, cx);
8036            assert_eq!(
8037                view.selections.display_ranges(cx),
8038                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
8039            );
8040        });
8041    }
8042
8043    #[gpui::test]
8044    fn test_select_line(cx: &mut gpui::MutableAppContext) {
8045        cx.set_global(Settings::test(cx));
8046        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
8047        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8048        view.update(cx, |view, cx| {
8049            view.change_selections(None, cx, |s| {
8050                s.select_display_ranges([
8051                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8052                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8053                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8054                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
8055                ])
8056            });
8057            view.select_line(&SelectLine, cx);
8058            assert_eq!(
8059                view.selections.display_ranges(cx),
8060                vec![
8061                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
8062                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
8063                ]
8064            );
8065        });
8066
8067        view.update(cx, |view, cx| {
8068            view.select_line(&SelectLine, cx);
8069            assert_eq!(
8070                view.selections.display_ranges(cx),
8071                vec![
8072                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
8073                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
8074                ]
8075            );
8076        });
8077
8078        view.update(cx, |view, cx| {
8079            view.select_line(&SelectLine, cx);
8080            assert_eq!(
8081                view.selections.display_ranges(cx),
8082                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
8083            );
8084        });
8085    }
8086
8087    #[gpui::test]
8088    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
8089        cx.set_global(Settings::test(cx));
8090        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
8091        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8092        view.update(cx, |view, cx| {
8093            view.fold_ranges(
8094                vec![
8095                    Point::new(0, 2)..Point::new(1, 2),
8096                    Point::new(2, 3)..Point::new(4, 1),
8097                    Point::new(7, 0)..Point::new(8, 4),
8098                ],
8099                cx,
8100            );
8101            view.change_selections(None, cx, |s| {
8102                s.select_display_ranges([
8103                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8104                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8105                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8106                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
8107                ])
8108            });
8109            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
8110        });
8111
8112        view.update(cx, |view, cx| {
8113            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8114            assert_eq!(
8115                view.display_text(cx),
8116                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
8117            );
8118            assert_eq!(
8119                view.selections.display_ranges(cx),
8120                [
8121                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
8122                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
8123                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
8124                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
8125                ]
8126            );
8127        });
8128
8129        view.update(cx, |view, cx| {
8130            view.change_selections(None, cx, |s| {
8131                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
8132            });
8133            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
8134            assert_eq!(
8135                view.display_text(cx),
8136                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
8137            );
8138            assert_eq!(
8139                view.selections.display_ranges(cx),
8140                [
8141                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
8142                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
8143                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
8144                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
8145                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
8146                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
8147                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
8148                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
8149                ]
8150            );
8151        });
8152    }
8153
8154    #[gpui::test]
8155    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
8156        cx.set_global(Settings::test(cx));
8157        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
8158        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8159
8160        view.update(cx, |view, cx| {
8161            view.change_selections(None, cx, |s| {
8162                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
8163            });
8164        });
8165        view.update(cx, |view, cx| {
8166            view.add_selection_above(&AddSelectionAbove, cx);
8167            assert_eq!(
8168                view.selections.display_ranges(cx),
8169                vec![
8170                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8171                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8172                ]
8173            );
8174        });
8175
8176        view.update(cx, |view, cx| {
8177            view.add_selection_above(&AddSelectionAbove, cx);
8178            assert_eq!(
8179                view.selections.display_ranges(cx),
8180                vec![
8181                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8182                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8183                ]
8184            );
8185        });
8186
8187        view.update(cx, |view, cx| {
8188            view.add_selection_below(&AddSelectionBelow, cx);
8189            assert_eq!(
8190                view.selections.display_ranges(cx),
8191                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
8192            );
8193
8194            view.undo_selection(&UndoSelection, cx);
8195            assert_eq!(
8196                view.selections.display_ranges(cx),
8197                vec![
8198                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
8199                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
8200                ]
8201            );
8202
8203            view.redo_selection(&RedoSelection, cx);
8204            assert_eq!(
8205                view.selections.display_ranges(cx),
8206                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
8207            );
8208        });
8209
8210        view.update(cx, |view, cx| {
8211            view.add_selection_below(&AddSelectionBelow, cx);
8212            assert_eq!(
8213                view.selections.display_ranges(cx),
8214                vec![
8215                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8216                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8217                ]
8218            );
8219        });
8220
8221        view.update(cx, |view, cx| {
8222            view.add_selection_below(&AddSelectionBelow, cx);
8223            assert_eq!(
8224                view.selections.display_ranges(cx),
8225                vec![
8226                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
8227                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
8228                ]
8229            );
8230        });
8231
8232        view.update(cx, |view, cx| {
8233            view.change_selections(None, cx, |s| {
8234                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
8235            });
8236        });
8237        view.update(cx, |view, cx| {
8238            view.add_selection_below(&AddSelectionBelow, cx);
8239            assert_eq!(
8240                view.selections.display_ranges(cx),
8241                vec![
8242                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8243                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8244                ]
8245            );
8246        });
8247
8248        view.update(cx, |view, cx| {
8249            view.add_selection_below(&AddSelectionBelow, cx);
8250            assert_eq!(
8251                view.selections.display_ranges(cx),
8252                vec![
8253                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
8254                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
8255                ]
8256            );
8257        });
8258
8259        view.update(cx, |view, cx| {
8260            view.add_selection_above(&AddSelectionAbove, cx);
8261            assert_eq!(
8262                view.selections.display_ranges(cx),
8263                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8264            );
8265        });
8266
8267        view.update(cx, |view, cx| {
8268            view.add_selection_above(&AddSelectionAbove, cx);
8269            assert_eq!(
8270                view.selections.display_ranges(cx),
8271                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
8272            );
8273        });
8274
8275        view.update(cx, |view, cx| {
8276            view.change_selections(None, cx, |s| {
8277                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
8278            });
8279            view.add_selection_below(&AddSelectionBelow, cx);
8280            assert_eq!(
8281                view.selections.display_ranges(cx),
8282                vec![
8283                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8284                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8285                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8286                ]
8287            );
8288        });
8289
8290        view.update(cx, |view, cx| {
8291            view.add_selection_below(&AddSelectionBelow, cx);
8292            assert_eq!(
8293                view.selections.display_ranges(cx),
8294                vec![
8295                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8296                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8297                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8298                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
8299                ]
8300            );
8301        });
8302
8303        view.update(cx, |view, cx| {
8304            view.add_selection_above(&AddSelectionAbove, cx);
8305            assert_eq!(
8306                view.selections.display_ranges(cx),
8307                vec![
8308                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
8309                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
8310                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
8311                ]
8312            );
8313        });
8314
8315        view.update(cx, |view, cx| {
8316            view.change_selections(None, cx, |s| {
8317                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
8318            });
8319        });
8320        view.update(cx, |view, cx| {
8321            view.add_selection_above(&AddSelectionAbove, cx);
8322            assert_eq!(
8323                view.selections.display_ranges(cx),
8324                vec![
8325                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
8326                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8327                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8328                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8329                ]
8330            );
8331        });
8332
8333        view.update(cx, |view, cx| {
8334            view.add_selection_below(&AddSelectionBelow, cx);
8335            assert_eq!(
8336                view.selections.display_ranges(cx),
8337                vec![
8338                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
8339                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
8340                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
8341                ]
8342            );
8343        });
8344    }
8345
8346    #[gpui::test]
8347    fn test_select_next(cx: &mut gpui::MutableAppContext) {
8348        cx.set_global(Settings::test(cx));
8349
8350        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
8351        let buffer = MultiBuffer::build_simple(&text, cx);
8352        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
8353
8354        view.update(cx, |view, cx| {
8355            view.change_selections(None, cx, |s| {
8356                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
8357            });
8358            view.select_next(
8359                &SelectNext {
8360                    replace_newest: false,
8361                },
8362                cx,
8363            );
8364            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
8365
8366            view.select_next(
8367                &SelectNext {
8368                    replace_newest: false,
8369                },
8370                cx,
8371            );
8372            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
8373
8374            view.undo_selection(&UndoSelection, cx);
8375            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
8376
8377            view.redo_selection(&RedoSelection, cx);
8378            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
8379
8380            view.select_next(
8381                &SelectNext {
8382                    replace_newest: false,
8383                },
8384                cx,
8385            );
8386            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
8387
8388            view.select_next(
8389                &SelectNext {
8390                    replace_newest: false,
8391                },
8392                cx,
8393            );
8394            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
8395        });
8396    }
8397
8398    #[gpui::test]
8399    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
8400        cx.update(|cx| cx.set_global(Settings::test(cx)));
8401        let language = Arc::new(Language::new(
8402            LanguageConfig::default(),
8403            Some(tree_sitter_rust::language()),
8404        ));
8405
8406        let text = r#"
8407            use mod1::mod2::{mod3, mod4};
8408
8409            fn fn_1(param1: bool, param2: &str) {
8410                let var1 = "text";
8411            }
8412        "#
8413        .unindent();
8414
8415        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8416        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8417        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8418        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8419            .await;
8420
8421        view.update(cx, |view, cx| {
8422            view.change_selections(None, cx, |s| {
8423                s.select_display_ranges([
8424                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8425                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8426                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8427                ]);
8428            });
8429            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8430        });
8431        assert_eq!(
8432            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
8433            &[
8434                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8435                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8436                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8437            ]
8438        );
8439
8440        view.update(cx, |view, cx| {
8441            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8442        });
8443        assert_eq!(
8444            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8445            &[
8446                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8447                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8448            ]
8449        );
8450
8451        view.update(cx, |view, cx| {
8452            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8453        });
8454        assert_eq!(
8455            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8456            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8457        );
8458
8459        // Trying to expand the selected syntax node one more time has no effect.
8460        view.update(cx, |view, cx| {
8461            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8462        });
8463        assert_eq!(
8464            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8465            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
8466        );
8467
8468        view.update(cx, |view, cx| {
8469            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8470        });
8471        assert_eq!(
8472            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8473            &[
8474                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8475                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
8476            ]
8477        );
8478
8479        view.update(cx, |view, cx| {
8480            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8481        });
8482        assert_eq!(
8483            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8484            &[
8485                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
8486                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8487                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
8488            ]
8489        );
8490
8491        view.update(cx, |view, cx| {
8492            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8493        });
8494        assert_eq!(
8495            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8496            &[
8497                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8498                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8499                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8500            ]
8501        );
8502
8503        // Trying to shrink the selected syntax node one more time has no effect.
8504        view.update(cx, |view, cx| {
8505            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
8506        });
8507        assert_eq!(
8508            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8509            &[
8510                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
8511                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
8512                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
8513            ]
8514        );
8515
8516        // Ensure that we keep expanding the selection if the larger selection starts or ends within
8517        // a fold.
8518        view.update(cx, |view, cx| {
8519            view.fold_ranges(
8520                vec![
8521                    Point::new(0, 21)..Point::new(0, 24),
8522                    Point::new(3, 20)..Point::new(3, 22),
8523                ],
8524                cx,
8525            );
8526            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
8527        });
8528        assert_eq!(
8529            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
8530            &[
8531                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
8532                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
8533                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
8534            ]
8535        );
8536    }
8537
8538    #[gpui::test]
8539    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
8540        cx.update(|cx| cx.set_global(Settings::test(cx)));
8541        let language = Arc::new(
8542            Language::new(
8543                LanguageConfig {
8544                    brackets: vec![
8545                        BracketPair {
8546                            start: "{".to_string(),
8547                            end: "}".to_string(),
8548                            close: false,
8549                            newline: true,
8550                        },
8551                        BracketPair {
8552                            start: "(".to_string(),
8553                            end: ")".to_string(),
8554                            close: false,
8555                            newline: true,
8556                        },
8557                    ],
8558                    ..Default::default()
8559                },
8560                Some(tree_sitter_rust::language()),
8561            )
8562            .with_indents_query(
8563                r#"
8564                (_ "(" ")" @end) @indent
8565                (_ "{" "}" @end) @indent
8566                "#,
8567            )
8568            .unwrap(),
8569        );
8570
8571        let text = "fn a() {}";
8572
8573        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8574        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8575        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8576        editor
8577            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
8578            .await;
8579
8580        editor.update(cx, |editor, cx| {
8581            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
8582            editor.newline(&Newline, cx);
8583            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
8584            assert_eq!(
8585                editor.selections.ranges(cx),
8586                &[
8587                    Point::new(1, 4)..Point::new(1, 4),
8588                    Point::new(3, 4)..Point::new(3, 4),
8589                    Point::new(5, 0)..Point::new(5, 0)
8590                ]
8591            );
8592        });
8593    }
8594
8595    #[gpui::test]
8596    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
8597        cx.update(|cx| cx.set_global(Settings::test(cx)));
8598        let language = Arc::new(Language::new(
8599            LanguageConfig {
8600                brackets: vec![
8601                    BracketPair {
8602                        start: "{".to_string(),
8603                        end: "}".to_string(),
8604                        close: true,
8605                        newline: true,
8606                    },
8607                    BracketPair {
8608                        start: "/*".to_string(),
8609                        end: " */".to_string(),
8610                        close: true,
8611                        newline: true,
8612                    },
8613                ],
8614                autoclose_before: "})]".to_string(),
8615                ..Default::default()
8616            },
8617            Some(tree_sitter_rust::language()),
8618        ));
8619
8620        let text = r#"
8621            a
8622
8623            /
8624
8625        "#
8626        .unindent();
8627
8628        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
8629        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8630        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
8631        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
8632            .await;
8633
8634        view.update(cx, |view, cx| {
8635            view.change_selections(None, cx, |s| {
8636                s.select_display_ranges([
8637                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
8638                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
8639                ])
8640            });
8641
8642            view.handle_input(&Input("{".to_string()), cx);
8643            view.handle_input(&Input("{".to_string()), cx);
8644            view.handle_input(&Input("{".to_string()), cx);
8645            assert_eq!(
8646                view.text(cx),
8647                "
8648                {{{}}}
8649                {{{}}}
8650                /
8651
8652                "
8653                .unindent()
8654            );
8655
8656            view.move_right(&MoveRight, cx);
8657            view.handle_input(&Input("}".to_string()), cx);
8658            view.handle_input(&Input("}".to_string()), cx);
8659            view.handle_input(&Input("}".to_string()), cx);
8660            assert_eq!(
8661                view.text(cx),
8662                "
8663                {{{}}}}
8664                {{{}}}}
8665                /
8666
8667                "
8668                .unindent()
8669            );
8670
8671            view.undo(&Undo, cx);
8672            view.handle_input(&Input("/".to_string()), cx);
8673            view.handle_input(&Input("*".to_string()), cx);
8674            assert_eq!(
8675                view.text(cx),
8676                "
8677                /* */
8678                /* */
8679                /
8680
8681                "
8682                .unindent()
8683            );
8684
8685            view.undo(&Undo, cx);
8686            view.change_selections(None, cx, |s| {
8687                s.select_display_ranges([
8688                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
8689                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
8690                ])
8691            });
8692            view.handle_input(&Input("*".to_string()), cx);
8693            assert_eq!(
8694                view.text(cx),
8695                "
8696                a
8697
8698                /*
8699                *
8700                "
8701                .unindent()
8702            );
8703
8704            // Don't autoclose if the next character isn't whitespace and isn't
8705            // listed in the language's "autoclose_before" section.
8706            view.finalize_last_transaction(cx);
8707            view.change_selections(None, cx, |s| {
8708                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
8709            });
8710            view.handle_input(&Input("{".to_string()), cx);
8711            assert_eq!(
8712                view.text(cx),
8713                "
8714                {a
8715
8716                /*
8717                *
8718                "
8719                .unindent()
8720            );
8721
8722            view.undo(&Undo, cx);
8723            view.change_selections(None, cx, |s| {
8724                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
8725            });
8726            view.handle_input(&Input("{".to_string()), cx);
8727            assert_eq!(
8728                view.text(cx),
8729                "
8730                {a}
8731
8732                /*
8733                *
8734                "
8735                .unindent()
8736            );
8737            assert_eq!(
8738                view.selections.display_ranges(cx),
8739                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
8740            );
8741        });
8742    }
8743
8744    #[gpui::test]
8745    async fn test_snippets(cx: &mut gpui::TestAppContext) {
8746        cx.update(|cx| cx.set_global(Settings::test(cx)));
8747
8748        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
8749            a.| b
8750            a.| b
8751            a.| b"});
8752        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
8753        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8754
8755        editor.update(cx, |editor, cx| {
8756            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
8757
8758            editor
8759                .insert_snippet(&insertion_ranges, snippet, cx)
8760                .unwrap();
8761
8762            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
8763                let range_markers = ('<', '>');
8764                let (expected_text, mut selection_ranges_lookup) =
8765                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
8766                let selection_ranges = selection_ranges_lookup
8767                    .remove(&range_markers.into())
8768                    .unwrap();
8769                assert_eq!(editor.text(cx), expected_text);
8770                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
8771            }
8772            assert(
8773                editor,
8774                cx,
8775                indoc! {"
8776                    a.f(<one>, two, <three>) b
8777                    a.f(<one>, two, <three>) b
8778                    a.f(<one>, two, <three>) b"},
8779            );
8780
8781            // Can't move earlier than the first tab stop
8782            assert!(!editor.move_to_prev_snippet_tabstop(cx));
8783            assert(
8784                editor,
8785                cx,
8786                indoc! {"
8787                    a.f(<one>, two, <three>) b
8788                    a.f(<one>, two, <three>) b
8789                    a.f(<one>, two, <three>) b"},
8790            );
8791
8792            assert!(editor.move_to_next_snippet_tabstop(cx));
8793            assert(
8794                editor,
8795                cx,
8796                indoc! {"
8797                    a.f(one, <two>, three) b
8798                    a.f(one, <two>, three) b
8799                    a.f(one, <two>, three) b"},
8800            );
8801
8802            editor.move_to_prev_snippet_tabstop(cx);
8803            assert(
8804                editor,
8805                cx,
8806                indoc! {"
8807                    a.f(<one>, two, <three>) b
8808                    a.f(<one>, two, <three>) b
8809                    a.f(<one>, two, <three>) b"},
8810            );
8811
8812            assert!(editor.move_to_next_snippet_tabstop(cx));
8813            assert(
8814                editor,
8815                cx,
8816                indoc! {"
8817                    a.f(one, <two>, three) b
8818                    a.f(one, <two>, three) b
8819                    a.f(one, <two>, three) b"},
8820            );
8821            assert!(editor.move_to_next_snippet_tabstop(cx));
8822            assert(
8823                editor,
8824                cx,
8825                indoc! {"
8826                    a.f(one, two, three)<> b
8827                    a.f(one, two, three)<> b
8828                    a.f(one, two, three)<> b"},
8829            );
8830
8831            // As soon as the last tab stop is reached, snippet state is gone
8832            editor.move_to_prev_snippet_tabstop(cx);
8833            assert(
8834                editor,
8835                cx,
8836                indoc! {"
8837                    a.f(one, two, three)<> b
8838                    a.f(one, two, three)<> b
8839                    a.f(one, two, three)<> b"},
8840            );
8841        });
8842    }
8843
8844    #[gpui::test]
8845    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
8846        cx.foreground().forbid_parking();
8847        cx.update(|cx| cx.set_global(Settings::test(cx)));
8848
8849        let mut language = Language::new(
8850            LanguageConfig {
8851                name: "Rust".into(),
8852                path_suffixes: vec!["rs".to_string()],
8853                ..Default::default()
8854            },
8855            Some(tree_sitter_rust::language()),
8856        );
8857        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
8858            capabilities: lsp::ServerCapabilities {
8859                document_formatting_provider: Some(lsp::OneOf::Left(true)),
8860                ..Default::default()
8861            },
8862            ..Default::default()
8863        });
8864
8865        let fs = FakeFs::new(cx.background().clone());
8866        fs.insert_file("/file.rs", Default::default()).await;
8867
8868        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
8869        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
8870        let buffer = project
8871            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
8872            .await
8873            .unwrap();
8874
8875        cx.foreground().start_waiting();
8876        let fake_server = fake_servers.next().await.unwrap();
8877
8878        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8879        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
8880        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
8881        assert!(cx.read(|cx| editor.is_dirty(cx)));
8882
8883        let save = cx.update(|cx| editor.save(project.clone(), cx));
8884        fake_server
8885            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
8886                assert_eq!(
8887                    params.text_document.uri,
8888                    lsp::Url::from_file_path("/file.rs").unwrap()
8889                );
8890                assert_eq!(params.options.tab_size, 4);
8891                Ok(Some(vec![lsp::TextEdit::new(
8892                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
8893                    ", ".to_string(),
8894                )]))
8895            })
8896            .next()
8897            .await;
8898        cx.foreground().start_waiting();
8899        save.await.unwrap();
8900        assert_eq!(
8901            editor.read_with(cx, |editor, cx| editor.text(cx)),
8902            "one, two\nthree\n"
8903        );
8904        assert!(!cx.read(|cx| editor.is_dirty(cx)));
8905
8906        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
8907        assert!(cx.read(|cx| editor.is_dirty(cx)));
8908
8909        // Ensure we can still save even if formatting hangs.
8910        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
8911            assert_eq!(
8912                params.text_document.uri,
8913                lsp::Url::from_file_path("/file.rs").unwrap()
8914            );
8915            futures::future::pending::<()>().await;
8916            unreachable!()
8917        });
8918        let save = cx.update(|cx| editor.save(project.clone(), cx));
8919        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
8920        cx.foreground().start_waiting();
8921        save.await.unwrap();
8922        assert_eq!(
8923            editor.read_with(cx, |editor, cx| editor.text(cx)),
8924            "one\ntwo\nthree\n"
8925        );
8926        assert!(!cx.read(|cx| editor.is_dirty(cx)));
8927
8928        // Set rust language override and assert overriden tabsize is sent to language server
8929        cx.update(|cx| {
8930            cx.update_global::<Settings, _, _>(|settings, _| {
8931                settings.language_overrides.insert(
8932                    "Rust".into(),
8933                    LanguageOverride {
8934                        tab_size: Some(8),
8935                        ..Default::default()
8936                    },
8937                );
8938            })
8939        });
8940
8941        let save = cx.update(|cx| editor.save(project.clone(), cx));
8942        fake_server
8943            .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                assert_eq!(params.options.tab_size, 8);
8949                Ok(Some(vec![]))
8950            })
8951            .next()
8952            .await;
8953        cx.foreground().start_waiting();
8954        save.await.unwrap();
8955    }
8956
8957    #[gpui::test]
8958    async fn test_completion(cx: &mut gpui::TestAppContext) {
8959        cx.update(|cx| cx.set_global(Settings::test(cx)));
8960
8961        let mut language = Language::new(
8962            LanguageConfig {
8963                name: "Rust".into(),
8964                path_suffixes: vec!["rs".to_string()],
8965                ..Default::default()
8966            },
8967            Some(tree_sitter_rust::language()),
8968        );
8969        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
8970            capabilities: lsp::ServerCapabilities {
8971                completion_provider: Some(lsp::CompletionOptions {
8972                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
8973                    ..Default::default()
8974                }),
8975                ..Default::default()
8976            },
8977            ..Default::default()
8978        });
8979
8980        let text = "
8981            one
8982            two
8983            three
8984        "
8985        .unindent();
8986
8987        let fs = FakeFs::new(cx.background().clone());
8988        fs.insert_file("/file.rs", text).await;
8989
8990        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
8991        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
8992        let buffer = project
8993            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
8994            .await
8995            .unwrap();
8996        let mut fake_server = fake_servers.next().await.unwrap();
8997
8998        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
8999        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
9000
9001        editor.update(cx, |editor, cx| {
9002            editor.project = Some(project);
9003            editor.change_selections(None, cx, |s| {
9004                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
9005            });
9006            editor.handle_input(&Input(".".to_string()), cx);
9007        });
9008
9009        handle_completion_request(
9010            &mut fake_server,
9011            "/file.rs",
9012            Point::new(0, 4),
9013            vec![
9014                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
9015                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
9016            ],
9017        )
9018        .await;
9019        editor
9020            .condition(&cx, |editor, _| editor.context_menu_visible())
9021            .await;
9022
9023        let apply_additional_edits = editor.update(cx, |editor, cx| {
9024            editor.move_down(&MoveDown, cx);
9025            let apply_additional_edits = editor
9026                .confirm_completion(&ConfirmCompletion::default(), cx)
9027                .unwrap();
9028            assert_eq!(
9029                editor.text(cx),
9030                "
9031                    one.second_completion
9032                    two
9033                    three
9034                "
9035                .unindent()
9036            );
9037            apply_additional_edits
9038        });
9039
9040        handle_resolve_completion_request(
9041            &mut fake_server,
9042            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
9043        )
9044        .await;
9045        apply_additional_edits.await.unwrap();
9046        assert_eq!(
9047            editor.read_with(cx, |editor, cx| editor.text(cx)),
9048            "
9049                one.second_completion
9050                two
9051                three
9052                additional edit
9053            "
9054            .unindent()
9055        );
9056
9057        editor.update(cx, |editor, cx| {
9058            editor.change_selections(None, cx, |s| {
9059                s.select_ranges([
9060                    Point::new(1, 3)..Point::new(1, 3),
9061                    Point::new(2, 5)..Point::new(2, 5),
9062                ])
9063            });
9064
9065            editor.handle_input(&Input(" ".to_string()), cx);
9066            assert!(editor.context_menu.is_none());
9067            editor.handle_input(&Input("s".to_string()), cx);
9068            assert!(editor.context_menu.is_none());
9069        });
9070
9071        handle_completion_request(
9072            &mut fake_server,
9073            "/file.rs",
9074            Point::new(2, 7),
9075            vec![
9076                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
9077                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
9078                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
9079            ],
9080        )
9081        .await;
9082        editor
9083            .condition(&cx, |editor, _| editor.context_menu_visible())
9084            .await;
9085
9086        editor.update(cx, |editor, cx| {
9087            editor.handle_input(&Input("i".to_string()), cx);
9088        });
9089
9090        handle_completion_request(
9091            &mut fake_server,
9092            "/file.rs",
9093            Point::new(2, 8),
9094            vec![
9095                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
9096                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
9097                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
9098            ],
9099        )
9100        .await;
9101        editor
9102            .condition(&cx, |editor, _| editor.context_menu_visible())
9103            .await;
9104
9105        let apply_additional_edits = editor.update(cx, |editor, cx| {
9106            let apply_additional_edits = editor
9107                .confirm_completion(&ConfirmCompletion::default(), cx)
9108                .unwrap();
9109            assert_eq!(
9110                editor.text(cx),
9111                "
9112                    one.second_completion
9113                    two sixth_completion
9114                    three sixth_completion
9115                    additional edit
9116                "
9117                .unindent()
9118            );
9119            apply_additional_edits
9120        });
9121        handle_resolve_completion_request(&mut fake_server, None).await;
9122        apply_additional_edits.await.unwrap();
9123
9124        async fn handle_completion_request(
9125            fake: &mut FakeLanguageServer,
9126            path: &'static str,
9127            position: Point,
9128            completions: Vec<(Range<Point>, &'static str)>,
9129        ) {
9130            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
9131                let completions = completions.clone();
9132                async move {
9133                    assert_eq!(
9134                        params.text_document_position.text_document.uri,
9135                        lsp::Url::from_file_path(path).unwrap()
9136                    );
9137                    assert_eq!(
9138                        params.text_document_position.position,
9139                        lsp::Position::new(position.row, position.column)
9140                    );
9141                    Ok(Some(lsp::CompletionResponse::Array(
9142                        completions
9143                            .iter()
9144                            .map(|(range, new_text)| lsp::CompletionItem {
9145                                label: new_text.to_string(),
9146                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
9147                                    range: lsp::Range::new(
9148                                        lsp::Position::new(range.start.row, range.start.column),
9149                                        lsp::Position::new(range.start.row, range.start.column),
9150                                    ),
9151                                    new_text: new_text.to_string(),
9152                                })),
9153                                ..Default::default()
9154                            })
9155                            .collect(),
9156                    )))
9157                }
9158            })
9159            .next()
9160            .await;
9161        }
9162
9163        async fn handle_resolve_completion_request(
9164            fake: &mut FakeLanguageServer,
9165            edit: Option<(Range<Point>, &'static str)>,
9166        ) {
9167            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
9168                let edit = edit.clone();
9169                async move {
9170                    Ok(lsp::CompletionItem {
9171                        additional_text_edits: edit.map(|(range, new_text)| {
9172                            vec![lsp::TextEdit::new(
9173                                lsp::Range::new(
9174                                    lsp::Position::new(range.start.row, range.start.column),
9175                                    lsp::Position::new(range.end.row, range.end.column),
9176                                ),
9177                                new_text.to_string(),
9178                            )]
9179                        }),
9180                        ..Default::default()
9181                    })
9182                }
9183            })
9184            .next()
9185            .await;
9186        }
9187    }
9188
9189    #[gpui::test]
9190    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
9191        cx.update(|cx| cx.set_global(Settings::test(cx)));
9192        let language = Arc::new(Language::new(
9193            LanguageConfig {
9194                line_comment: Some("// ".to_string()),
9195                ..Default::default()
9196            },
9197            Some(tree_sitter_rust::language()),
9198        ));
9199
9200        let text = "
9201            fn a() {
9202                //b();
9203                // c();
9204                //  d();
9205            }
9206        "
9207        .unindent();
9208
9209        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
9210        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9211        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
9212
9213        view.update(cx, |editor, cx| {
9214            // If multiple selections intersect a line, the line is only
9215            // toggled once.
9216            editor.change_selections(None, cx, |s| {
9217                s.select_display_ranges([
9218                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
9219                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
9220                ])
9221            });
9222            editor.toggle_comments(&ToggleComments, cx);
9223            assert_eq!(
9224                editor.text(cx),
9225                "
9226                    fn a() {
9227                        b();
9228                        c();
9229                         d();
9230                    }
9231                "
9232                .unindent()
9233            );
9234
9235            // The comment prefix is inserted at the same column for every line
9236            // in a selection.
9237            editor.change_selections(None, cx, |s| {
9238                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
9239            });
9240            editor.toggle_comments(&ToggleComments, cx);
9241            assert_eq!(
9242                editor.text(cx),
9243                "
9244                    fn a() {
9245                        // b();
9246                        // c();
9247                        //  d();
9248                    }
9249                "
9250                .unindent()
9251            );
9252
9253            // If a selection ends at the beginning of a line, that line is not toggled.
9254            editor.change_selections(None, cx, |s| {
9255                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
9256            });
9257            editor.toggle_comments(&ToggleComments, cx);
9258            assert_eq!(
9259                editor.text(cx),
9260                "
9261                        fn a() {
9262                            // b();
9263                            c();
9264                            //  d();
9265                        }
9266                    "
9267                .unindent()
9268            );
9269        });
9270    }
9271
9272    #[gpui::test]
9273    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
9274        cx.set_global(Settings::test(cx));
9275        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9276        let multibuffer = cx.add_model(|cx| {
9277            let mut multibuffer = MultiBuffer::new(0);
9278            multibuffer.push_excerpts(
9279                buffer.clone(),
9280                [
9281                    Point::new(0, 0)..Point::new(0, 4),
9282                    Point::new(1, 0)..Point::new(1, 4),
9283                ],
9284                cx,
9285            );
9286            multibuffer
9287        });
9288
9289        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
9290
9291        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9292        view.update(cx, |view, cx| {
9293            assert_eq!(view.text(cx), "aaaa\nbbbb");
9294            view.change_selections(None, cx, |s| {
9295                s.select_ranges([
9296                    Point::new(0, 0)..Point::new(0, 0),
9297                    Point::new(1, 0)..Point::new(1, 0),
9298                ])
9299            });
9300
9301            view.handle_input(&Input("X".to_string()), cx);
9302            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
9303            assert_eq!(
9304                view.selections.ranges(cx),
9305                [
9306                    Point::new(0, 1)..Point::new(0, 1),
9307                    Point::new(1, 1)..Point::new(1, 1),
9308                ]
9309            )
9310        });
9311    }
9312
9313    #[gpui::test]
9314    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
9315        cx.set_global(Settings::test(cx));
9316        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
9317                [aaaa
9318                (bbbb]
9319                cccc)"});
9320        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
9321        let multibuffer = cx.add_model(|cx| {
9322            let mut multibuffer = MultiBuffer::new(0);
9323            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
9324            multibuffer
9325        });
9326
9327        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
9328        view.update(cx, |view, cx| {
9329            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
9330                aaaa
9331                b|bbb
9332                b|bb|b
9333                cccc"});
9334            assert_eq!(view.text(cx), expected_text);
9335            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
9336
9337            view.handle_input(&Input("X".to_string()), cx);
9338
9339            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
9340                aaaa
9341                bX|bbXb
9342                bX|bbX|b
9343                cccc"});
9344            assert_eq!(view.text(cx), expected_text);
9345            assert_eq!(view.selections.ranges(cx), expected_selections);
9346
9347            view.newline(&Newline, cx);
9348            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
9349                aaaa
9350                bX
9351                |bbX
9352                b
9353                bX
9354                |bbX
9355                |b
9356                cccc"});
9357            assert_eq!(view.text(cx), expected_text);
9358            assert_eq!(view.selections.ranges(cx), expected_selections);
9359        });
9360    }
9361
9362    #[gpui::test]
9363    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
9364        cx.set_global(Settings::test(cx));
9365        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9366        let mut excerpt1_id = None;
9367        let multibuffer = cx.add_model(|cx| {
9368            let mut multibuffer = MultiBuffer::new(0);
9369            excerpt1_id = multibuffer
9370                .push_excerpts(
9371                    buffer.clone(),
9372                    [
9373                        Point::new(0, 0)..Point::new(1, 4),
9374                        Point::new(1, 0)..Point::new(2, 4),
9375                    ],
9376                    cx,
9377                )
9378                .into_iter()
9379                .next();
9380            multibuffer
9381        });
9382        assert_eq!(
9383            multibuffer.read(cx).read(cx).text(),
9384            "aaaa\nbbbb\nbbbb\ncccc"
9385        );
9386        let (_, editor) = cx.add_window(Default::default(), |cx| {
9387            let mut editor = build_editor(multibuffer.clone(), cx);
9388            let snapshot = editor.snapshot(cx);
9389            editor.change_selections(None, cx, |s| {
9390                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
9391            });
9392            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
9393            assert_eq!(
9394                editor.selections.ranges(cx),
9395                [
9396                    Point::new(1, 3)..Point::new(1, 3),
9397                    Point::new(2, 1)..Point::new(2, 1),
9398                ]
9399            );
9400            editor
9401        });
9402
9403        // Refreshing selections is a no-op when excerpts haven't changed.
9404        editor.update(cx, |editor, cx| {
9405            editor.change_selections(None, cx, |s| {
9406                s.refresh();
9407            });
9408            assert_eq!(
9409                editor.selections.ranges(cx),
9410                [
9411                    Point::new(1, 3)..Point::new(1, 3),
9412                    Point::new(2, 1)..Point::new(2, 1),
9413                ]
9414            );
9415        });
9416
9417        multibuffer.update(cx, |multibuffer, cx| {
9418            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9419        });
9420        editor.update(cx, |editor, cx| {
9421            // Removing an excerpt causes the first selection to become degenerate.
9422            assert_eq!(
9423                editor.selections.ranges(cx),
9424                [
9425                    Point::new(0, 0)..Point::new(0, 0),
9426                    Point::new(0, 1)..Point::new(0, 1)
9427                ]
9428            );
9429
9430            // Refreshing selections will relocate the first selection to the original buffer
9431            // location.
9432            editor.change_selections(None, cx, |s| {
9433                s.refresh();
9434            });
9435            assert_eq!(
9436                editor.selections.ranges(cx),
9437                [
9438                    Point::new(0, 1)..Point::new(0, 1),
9439                    Point::new(0, 3)..Point::new(0, 3)
9440                ]
9441            );
9442            assert!(editor.selections.pending_anchor().is_some());
9443        });
9444    }
9445
9446    #[gpui::test]
9447    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
9448        cx.set_global(Settings::test(cx));
9449        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
9450        let mut excerpt1_id = None;
9451        let multibuffer = cx.add_model(|cx| {
9452            let mut multibuffer = MultiBuffer::new(0);
9453            excerpt1_id = multibuffer
9454                .push_excerpts(
9455                    buffer.clone(),
9456                    [
9457                        Point::new(0, 0)..Point::new(1, 4),
9458                        Point::new(1, 0)..Point::new(2, 4),
9459                    ],
9460                    cx,
9461                )
9462                .into_iter()
9463                .next();
9464            multibuffer
9465        });
9466        assert_eq!(
9467            multibuffer.read(cx).read(cx).text(),
9468            "aaaa\nbbbb\nbbbb\ncccc"
9469        );
9470        let (_, editor) = cx.add_window(Default::default(), |cx| {
9471            let mut editor = build_editor(multibuffer.clone(), cx);
9472            let snapshot = editor.snapshot(cx);
9473            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
9474            assert_eq!(
9475                editor.selections.ranges(cx),
9476                [Point::new(1, 3)..Point::new(1, 3)]
9477            );
9478            editor
9479        });
9480
9481        multibuffer.update(cx, |multibuffer, cx| {
9482            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
9483        });
9484        editor.update(cx, |editor, cx| {
9485            assert_eq!(
9486                editor.selections.ranges(cx),
9487                [Point::new(0, 0)..Point::new(0, 0)]
9488            );
9489
9490            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
9491            editor.change_selections(None, cx, |s| {
9492                s.refresh();
9493            });
9494            assert_eq!(
9495                editor.selections.ranges(cx),
9496                [Point::new(0, 3)..Point::new(0, 3)]
9497            );
9498            assert!(editor.selections.pending_anchor().is_some());
9499        });
9500    }
9501
9502    #[gpui::test]
9503    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
9504        cx.update(|cx| cx.set_global(Settings::test(cx)));
9505        let language = Arc::new(Language::new(
9506            LanguageConfig {
9507                brackets: vec![
9508                    BracketPair {
9509                        start: "{".to_string(),
9510                        end: "}".to_string(),
9511                        close: true,
9512                        newline: true,
9513                    },
9514                    BracketPair {
9515                        start: "/* ".to_string(),
9516                        end: " */".to_string(),
9517                        close: true,
9518                        newline: true,
9519                    },
9520                ],
9521                ..Default::default()
9522            },
9523            Some(tree_sitter_rust::language()),
9524        ));
9525
9526        let text = concat!(
9527            "{   }\n",     // Suppress rustfmt
9528            "  x\n",       //
9529            "  /*   */\n", //
9530            "x\n",         //
9531            "{{} }\n",     //
9532        );
9533
9534        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
9535        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
9536        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
9537        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
9538            .await;
9539
9540        view.update(cx, |view, cx| {
9541            view.change_selections(None, cx, |s| {
9542                s.select_display_ranges([
9543                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
9544                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
9545                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
9546                ])
9547            });
9548            view.newline(&Newline, cx);
9549
9550            assert_eq!(
9551                view.buffer().read(cx).read(cx).text(),
9552                concat!(
9553                    "{ \n",    // Suppress rustfmt
9554                    "\n",      //
9555                    "}\n",     //
9556                    "  x\n",   //
9557                    "  /* \n", //
9558                    "  \n",    //
9559                    "  */\n",  //
9560                    "x\n",     //
9561                    "{{} \n",  //
9562                    "}\n",     //
9563                )
9564            );
9565        });
9566    }
9567
9568    #[gpui::test]
9569    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
9570        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9571
9572        cx.set_global(Settings::test(cx));
9573        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9574
9575        editor.update(cx, |editor, cx| {
9576            struct Type1;
9577            struct Type2;
9578
9579            let buffer = buffer.read(cx).snapshot(cx);
9580
9581            let anchor_range = |range: Range<Point>| {
9582                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
9583            };
9584
9585            editor.highlight_background::<Type1>(
9586                vec![
9587                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
9588                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
9589                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
9590                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
9591                ],
9592                |_| Color::red(),
9593                cx,
9594            );
9595            editor.highlight_background::<Type2>(
9596                vec![
9597                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
9598                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
9599                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
9600                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
9601                ],
9602                |_| Color::green(),
9603                cx,
9604            );
9605
9606            let snapshot = editor.snapshot(cx);
9607            let mut highlighted_ranges = editor.background_highlights_in_range(
9608                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
9609                &snapshot,
9610                cx.global::<Settings>().theme.as_ref(),
9611            );
9612            // Enforce a consistent ordering based on color without relying on the ordering of the
9613            // highlight's `TypeId` which is non-deterministic.
9614            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
9615            assert_eq!(
9616                highlighted_ranges,
9617                &[
9618                    (
9619                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
9620                        Color::green(),
9621                    ),
9622                    (
9623                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
9624                        Color::green(),
9625                    ),
9626                    (
9627                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
9628                        Color::red(),
9629                    ),
9630                    (
9631                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9632                        Color::red(),
9633                    ),
9634                ]
9635            );
9636            assert_eq!(
9637                editor.background_highlights_in_range(
9638                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
9639                    &snapshot,
9640                    cx.global::<Settings>().theme.as_ref(),
9641                ),
9642                &[(
9643                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
9644                    Color::red(),
9645                )]
9646            );
9647        });
9648    }
9649
9650    #[gpui::test]
9651    fn test_following(cx: &mut gpui::MutableAppContext) {
9652        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
9653
9654        cx.set_global(Settings::test(cx));
9655
9656        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
9657        let (_, follower) = cx.add_window(
9658            WindowOptions {
9659                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
9660                ..Default::default()
9661            },
9662            |cx| build_editor(buffer.clone(), cx),
9663        );
9664
9665        let pending_update = Rc::new(RefCell::new(None));
9666        follower.update(cx, {
9667            let update = pending_update.clone();
9668            |_, cx| {
9669                cx.subscribe(&leader, move |_, leader, event, cx| {
9670                    leader
9671                        .read(cx)
9672                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
9673                })
9674                .detach();
9675            }
9676        });
9677
9678        // Update the selections only
9679        leader.update(cx, |leader, cx| {
9680            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
9681        });
9682        follower.update(cx, |follower, cx| {
9683            follower
9684                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9685                .unwrap();
9686        });
9687        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
9688
9689        // Update the scroll position only
9690        leader.update(cx, |leader, cx| {
9691            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9692        });
9693        follower.update(cx, |follower, cx| {
9694            follower
9695                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9696                .unwrap();
9697        });
9698        assert_eq!(
9699            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
9700            vec2f(1.5, 3.5)
9701        );
9702
9703        // Update the selections and scroll position
9704        leader.update(cx, |leader, cx| {
9705            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
9706            leader.request_autoscroll(Autoscroll::Newest, cx);
9707            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
9708        });
9709        follower.update(cx, |follower, cx| {
9710            let initial_scroll_position = follower.scroll_position(cx);
9711            follower
9712                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9713                .unwrap();
9714            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
9715            assert!(follower.autoscroll_request.is_some());
9716        });
9717        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
9718
9719        // Creating a pending selection that precedes another selection
9720        leader.update(cx, |leader, cx| {
9721            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
9722            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
9723        });
9724        follower.update(cx, |follower, cx| {
9725            follower
9726                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9727                .unwrap();
9728        });
9729        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
9730
9731        // Extend the pending selection so that it surrounds another selection
9732        leader.update(cx, |leader, cx| {
9733            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
9734        });
9735        follower.update(cx, |follower, cx| {
9736            follower
9737                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
9738                .unwrap();
9739        });
9740        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
9741    }
9742
9743    #[test]
9744    fn test_combine_syntax_and_fuzzy_match_highlights() {
9745        let string = "abcdefghijklmnop";
9746        let syntax_ranges = [
9747            (
9748                0..3,
9749                HighlightStyle {
9750                    color: Some(Color::red()),
9751                    ..Default::default()
9752                },
9753            ),
9754            (
9755                4..8,
9756                HighlightStyle {
9757                    color: Some(Color::green()),
9758                    ..Default::default()
9759                },
9760            ),
9761        ];
9762        let match_indices = [4, 6, 7, 8];
9763        assert_eq!(
9764            combine_syntax_and_fuzzy_match_highlights(
9765                &string,
9766                Default::default(),
9767                syntax_ranges.into_iter(),
9768                &match_indices,
9769            ),
9770            &[
9771                (
9772                    0..3,
9773                    HighlightStyle {
9774                        color: Some(Color::red()),
9775                        ..Default::default()
9776                    },
9777                ),
9778                (
9779                    4..5,
9780                    HighlightStyle {
9781                        color: Some(Color::green()),
9782                        weight: Some(fonts::Weight::BOLD),
9783                        ..Default::default()
9784                    },
9785                ),
9786                (
9787                    5..6,
9788                    HighlightStyle {
9789                        color: Some(Color::green()),
9790                        ..Default::default()
9791                    },
9792                ),
9793                (
9794                    6..8,
9795                    HighlightStyle {
9796                        color: Some(Color::green()),
9797                        weight: Some(fonts::Weight::BOLD),
9798                        ..Default::default()
9799                    },
9800                ),
9801                (
9802                    8..9,
9803                    HighlightStyle {
9804                        weight: Some(fonts::Weight::BOLD),
9805                        ..Default::default()
9806                    },
9807                ),
9808            ]
9809        );
9810    }
9811
9812    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
9813        let point = DisplayPoint::new(row as u32, column as u32);
9814        point..point
9815    }
9816
9817    fn assert_selection_ranges(
9818        marked_text: &str,
9819        selection_marker_pairs: Vec<(char, char)>,
9820        view: &mut Editor,
9821        cx: &mut ViewContext<Editor>,
9822    ) {
9823        let snapshot = view.snapshot(cx).display_snapshot;
9824        let mut marker_chars = Vec::new();
9825        for (start, end) in selection_marker_pairs.iter() {
9826            marker_chars.push(*start);
9827            marker_chars.push(*end);
9828        }
9829        let (_, markers) = marked_text_by(marked_text, marker_chars);
9830        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
9831            .iter()
9832            .map(|(start, end)| {
9833                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
9834                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
9835                start..end
9836            })
9837            .collect();
9838        assert_eq!(
9839            view.selections.display_ranges(cx),
9840            &asserted_ranges[..],
9841            "Assert selections are {}",
9842            marked_text
9843        );
9844    }
9845}
9846
9847trait RangeExt<T> {
9848    fn sorted(&self) -> Range<T>;
9849    fn to_inclusive(&self) -> RangeInclusive<T>;
9850}
9851
9852impl<T: Ord + Clone> RangeExt<T> for Range<T> {
9853    fn sorted(&self) -> Self {
9854        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
9855    }
9856
9857    fn to_inclusive(&self) -> RangeInclusive<T> {
9858        self.start.clone()..=self.end.clone()
9859    }
9860}