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