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