editor.rs

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