editor.rs

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