editor.rs

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