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