editor.rs

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