editor.rs

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