editor.rs

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