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