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