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