editor.rs

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