editor.rs

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