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