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