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