editor.rs

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