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