editor.rs

   1mod blink_manager;
   2pub mod display_map;
   3mod element;
   4mod git;
   5mod highlight_matching_bracket;
   6mod hover_popover;
   7pub mod items;
   8mod link_go_to_definition;
   9mod mouse_context_menu;
  10pub mod movement;
  11mod multi_buffer;
  12mod persistence;
  13pub mod scroll;
  14pub mod selections_collection;
  15
  16#[cfg(test)]
  17mod editor_tests;
  18#[cfg(any(test, feature = "test-support"))]
  19pub mod test;
  20
  21use aho_corasick::AhoCorasick;
  22use anyhow::Result;
  23use blink_manager::BlinkManager;
  24use clock::ReplicaId;
  25use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  26pub use display_map::DisplayPoint;
  27use display_map::*;
  28pub use element::*;
  29use futures::FutureExt;
  30use fuzzy::{StringMatch, StringMatchCandidate};
  31use gpui::{
  32    actions,
  33    color::Color,
  34    elements::*,
  35    executor,
  36    fonts::{self, HighlightStyle, TextStyle},
  37    geometry::vector::Vector2F,
  38    impl_actions, impl_internal_actions,
  39    keymap_matcher::KeymapContext,
  40    platform::CursorStyle,
  41    serde_json::json,
  42    AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
  43    ModelHandle, MouseButton, MutableAppContext, RenderContext, Subscription, Task, View,
  44    ViewContext, ViewHandle, WeakViewHandle,
  45};
  46use highlight_matching_bracket::refresh_matching_bracket_highlights;
  47use hover_popover::{hide_hover, HideHover, HoverState};
  48pub use items::MAX_TAB_TITLE_LEN;
  49use itertools::Itertools;
  50pub use language::{char_kind, CharKind};
  51use language::{
  52    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  53    Diagnostic, DiagnosticSeverity, IndentKind, IndentSize, Language, OffsetRangeExt, OffsetUtf16,
  54    Point, Selection, SelectionGoal, TransactionId,
  55};
  56use link_go_to_definition::{
  57    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  58};
  59pub use multi_buffer::{
  60    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  61    ToPoint,
  62};
  63use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  64use ordered_float::OrderedFloat;
  65use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  66use scroll::{
  67    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  68};
  69use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  70use serde::{Deserialize, Serialize};
  71use settings::Settings;
  72use smallvec::SmallVec;
  73use snippet::Snippet;
  74use std::{
  75    any::TypeId,
  76    borrow::Cow,
  77    cmp::{self, Ordering, Reverse},
  78    mem,
  79    num::NonZeroU32,
  80    ops::{Deref, DerefMut, Range},
  81    path::Path,
  82    sync::Arc,
  83    time::{Duration, Instant},
  84};
  85pub use sum_tree::Bias;
  86use theme::{DiagnosticStyle, Theme};
  87use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  88use workspace::{ItemNavHistory, ViewId, Workspace, WorkspaceId};
  89
  90use crate::git::diff_hunk_to_display;
  91
  92const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  93const MAX_LINE_LEN: usize = 1024;
  94const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  95const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  96
  97pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  98
  99#[derive(Clone, Deserialize, PartialEq, Default)]
 100pub struct SelectNext {
 101    #[serde(default)]
 102    pub replace_newest: bool,
 103}
 104
 105#[derive(Clone, PartialEq)]
 106pub struct Select(pub SelectPhase);
 107
 108#[derive(Clone, Debug, PartialEq)]
 109pub struct Jump {
 110    path: ProjectPath,
 111    position: Point,
 112    anchor: language::Anchor,
 113}
 114
 115#[derive(Clone, Deserialize, PartialEq)]
 116pub struct SelectToBeginningOfLine {
 117    #[serde(default)]
 118    stop_at_soft_wraps: bool,
 119}
 120
 121#[derive(Clone, Default, Deserialize, PartialEq)]
 122pub struct MovePageUp {
 123    #[serde(default)]
 124    center_cursor: bool,
 125}
 126
 127#[derive(Clone, Default, Deserialize, PartialEq)]
 128pub struct MovePageDown {
 129    #[serde(default)]
 130    center_cursor: bool,
 131}
 132
 133#[derive(Clone, Deserialize, PartialEq)]
 134pub struct SelectToEndOfLine {
 135    #[serde(default)]
 136    stop_at_soft_wraps: bool,
 137}
 138
 139#[derive(Clone, Deserialize, PartialEq)]
 140pub struct ToggleCodeActions {
 141    #[serde(default)]
 142    pub deployed_from_indicator: bool,
 143}
 144
 145#[derive(Clone, Default, Deserialize, PartialEq)]
 146pub struct ConfirmCompletion {
 147    #[serde(default)]
 148    pub item_ix: Option<usize>,
 149}
 150
 151#[derive(Clone, Default, Deserialize, PartialEq)]
 152pub struct ConfirmCodeAction {
 153    #[serde(default)]
 154    pub item_ix: Option<usize>,
 155}
 156
 157#[derive(Clone, Default, Deserialize, PartialEq)]
 158pub struct ToggleComments {
 159    #[serde(default)]
 160    pub advance_downwards: bool,
 161}
 162
 163actions!(
 164    editor,
 165    [
 166        Cancel,
 167        Backspace,
 168        Delete,
 169        Newline,
 170        NewlineBelow,
 171        GoToDiagnostic,
 172        GoToPrevDiagnostic,
 173        GoToHunk,
 174        GoToPrevHunk,
 175        Indent,
 176        Outdent,
 177        DeleteLine,
 178        DeleteToPreviousWordStart,
 179        DeleteToPreviousSubwordStart,
 180        DeleteToNextWordEnd,
 181        DeleteToNextSubwordEnd,
 182        DeleteToBeginningOfLine,
 183        DeleteToEndOfLine,
 184        CutToEndOfLine,
 185        DuplicateLine,
 186        MoveLineUp,
 187        MoveLineDown,
 188        Transpose,
 189        Cut,
 190        Copy,
 191        Paste,
 192        Undo,
 193        Redo,
 194        MoveUp,
 195        PageUp,
 196        MoveDown,
 197        PageDown,
 198        MoveLeft,
 199        MoveRight,
 200        MoveToPreviousWordStart,
 201        MoveToPreviousSubwordStart,
 202        MoveToNextWordEnd,
 203        MoveToNextSubwordEnd,
 204        MoveToBeginningOfLine,
 205        MoveToEndOfLine,
 206        MoveToBeginning,
 207        MoveToEnd,
 208        SelectUp,
 209        SelectDown,
 210        SelectLeft,
 211        SelectRight,
 212        SelectToPreviousWordStart,
 213        SelectToPreviousSubwordStart,
 214        SelectToNextWordEnd,
 215        SelectToNextSubwordEnd,
 216        SelectToBeginning,
 217        SelectToEnd,
 218        SelectAll,
 219        SelectLine,
 220        SplitSelectionIntoLines,
 221        AddSelectionAbove,
 222        AddSelectionBelow,
 223        Tab,
 224        TabPrev,
 225        ShowCharacterPalette,
 226        SelectLargerSyntaxNode,
 227        SelectSmallerSyntaxNode,
 228        GoToDefinition,
 229        GoToTypeDefinition,
 230        MoveToEnclosingBracket,
 231        UndoSelection,
 232        RedoSelection,
 233        FindAllReferences,
 234        Rename,
 235        ConfirmRename,
 236        Fold,
 237        UnfoldLines,
 238        FoldSelectedRanges,
 239        ShowCompletions,
 240        OpenExcerpts,
 241        RestartLanguageServer,
 242        Hover,
 243        Format,
 244        ToggleSoftWrap
 245    ]
 246);
 247
 248impl_actions!(
 249    editor,
 250    [
 251        SelectNext,
 252        SelectToBeginningOfLine,
 253        SelectToEndOfLine,
 254        ToggleCodeActions,
 255        MovePageUp,
 256        MovePageDown,
 257        ConfirmCompletion,
 258        ConfirmCodeAction,
 259        ToggleComments,
 260    ]
 261);
 262
 263impl_internal_actions!(editor, [Select, Jump]);
 264
 265enum DocumentHighlightRead {}
 266enum DocumentHighlightWrite {}
 267enum InputComposition {}
 268
 269#[derive(Copy, Clone, PartialEq, Eq)]
 270pub enum Direction {
 271    Prev,
 272    Next,
 273}
 274
 275pub fn init(cx: &mut MutableAppContext) {
 276    cx.add_action(Editor::new_file);
 277    cx.add_action(Editor::select);
 278    cx.add_action(Editor::cancel);
 279    cx.add_action(Editor::newline);
 280    cx.add_action(Editor::newline_below);
 281    cx.add_action(Editor::backspace);
 282    cx.add_action(Editor::delete);
 283    cx.add_action(Editor::tab);
 284    cx.add_action(Editor::tab_prev);
 285    cx.add_action(Editor::indent);
 286    cx.add_action(Editor::outdent);
 287    cx.add_action(Editor::delete_line);
 288    cx.add_action(Editor::delete_to_previous_word_start);
 289    cx.add_action(Editor::delete_to_previous_subword_start);
 290    cx.add_action(Editor::delete_to_next_word_end);
 291    cx.add_action(Editor::delete_to_next_subword_end);
 292    cx.add_action(Editor::delete_to_beginning_of_line);
 293    cx.add_action(Editor::delete_to_end_of_line);
 294    cx.add_action(Editor::cut_to_end_of_line);
 295    cx.add_action(Editor::duplicate_line);
 296    cx.add_action(Editor::move_line_up);
 297    cx.add_action(Editor::move_line_down);
 298    cx.add_action(Editor::transpose);
 299    cx.add_action(Editor::cut);
 300    cx.add_action(Editor::copy);
 301    cx.add_action(Editor::paste);
 302    cx.add_action(Editor::undo);
 303    cx.add_action(Editor::redo);
 304    cx.add_action(Editor::move_up);
 305    cx.add_action(Editor::move_page_up);
 306    cx.add_action(Editor::move_down);
 307    cx.add_action(Editor::move_page_down);
 308    cx.add_action(Editor::next_screen);
 309    cx.add_action(Editor::move_left);
 310    cx.add_action(Editor::move_right);
 311    cx.add_action(Editor::move_to_previous_word_start);
 312    cx.add_action(Editor::move_to_previous_subword_start);
 313    cx.add_action(Editor::move_to_next_word_end);
 314    cx.add_action(Editor::move_to_next_subword_end);
 315    cx.add_action(Editor::move_to_beginning_of_line);
 316    cx.add_action(Editor::move_to_end_of_line);
 317    cx.add_action(Editor::move_to_beginning);
 318    cx.add_action(Editor::move_to_end);
 319    cx.add_action(Editor::select_up);
 320    cx.add_action(Editor::select_down);
 321    cx.add_action(Editor::select_left);
 322    cx.add_action(Editor::select_right);
 323    cx.add_action(Editor::select_to_previous_word_start);
 324    cx.add_action(Editor::select_to_previous_subword_start);
 325    cx.add_action(Editor::select_to_next_word_end);
 326    cx.add_action(Editor::select_to_next_subword_end);
 327    cx.add_action(Editor::select_to_beginning_of_line);
 328    cx.add_action(Editor::select_to_end_of_line);
 329    cx.add_action(Editor::select_to_beginning);
 330    cx.add_action(Editor::select_to_end);
 331    cx.add_action(Editor::select_all);
 332    cx.add_action(Editor::select_line);
 333    cx.add_action(Editor::split_selection_into_lines);
 334    cx.add_action(Editor::add_selection_above);
 335    cx.add_action(Editor::add_selection_below);
 336    cx.add_action(Editor::select_next);
 337    cx.add_action(Editor::toggle_comments);
 338    cx.add_action(Editor::select_larger_syntax_node);
 339    cx.add_action(Editor::select_smaller_syntax_node);
 340    cx.add_action(Editor::move_to_enclosing_bracket);
 341    cx.add_action(Editor::undo_selection);
 342    cx.add_action(Editor::redo_selection);
 343    cx.add_action(Editor::go_to_diagnostic);
 344    cx.add_action(Editor::go_to_prev_diagnostic);
 345    cx.add_action(Editor::go_to_hunk);
 346    cx.add_action(Editor::go_to_prev_hunk);
 347    cx.add_action(Editor::go_to_definition);
 348    cx.add_action(Editor::go_to_type_definition);
 349    cx.add_action(Editor::fold);
 350    cx.add_action(Editor::unfold_lines);
 351    cx.add_action(Editor::fold_selected_ranges);
 352    cx.add_action(Editor::show_completions);
 353    cx.add_action(Editor::toggle_code_actions);
 354    cx.add_action(Editor::open_excerpts);
 355    cx.add_action(Editor::jump);
 356    cx.add_action(Editor::toggle_soft_wrap);
 357    cx.add_async_action(Editor::format);
 358    cx.add_action(Editor::restart_language_server);
 359    cx.add_action(Editor::show_character_palette);
 360    cx.add_async_action(Editor::confirm_completion);
 361    cx.add_async_action(Editor::confirm_code_action);
 362    cx.add_async_action(Editor::rename);
 363    cx.add_async_action(Editor::confirm_rename);
 364    cx.add_async_action(Editor::find_all_references);
 365
 366    hover_popover::init(cx);
 367    link_go_to_definition::init(cx);
 368    mouse_context_menu::init(cx);
 369    scroll::actions::init(cx);
 370
 371    workspace::register_project_item::<Editor>(cx);
 372    workspace::register_followable_item::<Editor>(cx);
 373    workspace::register_deserializable_item::<Editor>(cx);
 374}
 375
 376trait InvalidationRegion {
 377    fn ranges(&self) -> &[Range<Anchor>];
 378}
 379
 380#[derive(Clone, Debug, PartialEq)]
 381pub enum SelectPhase {
 382    Begin {
 383        position: DisplayPoint,
 384        add: bool,
 385        click_count: usize,
 386    },
 387    BeginColumnar {
 388        position: DisplayPoint,
 389        goal_column: u32,
 390    },
 391    Extend {
 392        position: DisplayPoint,
 393        click_count: usize,
 394    },
 395    Update {
 396        position: DisplayPoint,
 397        goal_column: u32,
 398        scroll_position: Vector2F,
 399    },
 400    End,
 401}
 402
 403#[derive(Clone, Debug)]
 404pub enum SelectMode {
 405    Character,
 406    Word(Range<Anchor>),
 407    Line(Range<Anchor>),
 408    All,
 409}
 410
 411#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 412pub enum EditorMode {
 413    SingleLine,
 414    AutoHeight { max_lines: usize },
 415    Full,
 416}
 417
 418#[derive(Clone)]
 419pub enum SoftWrap {
 420    None,
 421    EditorWidth,
 422    Column(u32),
 423}
 424
 425#[derive(Clone)]
 426pub struct EditorStyle {
 427    pub text: TextStyle,
 428    pub placeholder_text: Option<TextStyle>,
 429    pub theme: theme::Editor,
 430}
 431
 432type CompletionId = usize;
 433
 434type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 435type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 436
 437pub struct Editor {
 438    handle: WeakViewHandle<Self>,
 439    buffer: ModelHandle<MultiBuffer>,
 440    display_map: ModelHandle<DisplayMap>,
 441    pub selections: SelectionsCollection,
 442    pub scroll_manager: ScrollManager,
 443    columnar_selection_tail: Option<Anchor>,
 444    add_selections_state: Option<AddSelectionsState>,
 445    select_next_state: Option<SelectNextState>,
 446    selection_history: SelectionHistory,
 447    autoclose_regions: Vec<AutocloseRegion>,
 448    snippet_stack: InvalidationStack<SnippetState>,
 449    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 450    ime_transaction: Option<TransactionId>,
 451    active_diagnostics: Option<ActiveDiagnosticGroup>,
 452    soft_wrap_mode_override: Option<settings::SoftWrap>,
 453    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 454    override_text_style: Option<Box<OverrideTextStyle>>,
 455    project: Option<ModelHandle<Project>>,
 456    focused: bool,
 457    blink_manager: ModelHandle<BlinkManager>,
 458    show_local_selections: bool,
 459    mode: EditorMode,
 460    placeholder_text: Option<Arc<str>>,
 461    highlighted_rows: Option<Range<u32>>,
 462    #[allow(clippy::type_complexity)]
 463    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 464    nav_history: Option<ItemNavHistory>,
 465    context_menu: Option<ContextMenu>,
 466    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 467    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 468    next_completion_id: CompletionId,
 469    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 470    code_actions_task: Option<Task<()>>,
 471    document_highlights_task: Option<Task<()>>,
 472    pending_rename: Option<RenameState>,
 473    searchable: bool,
 474    cursor_shape: CursorShape,
 475    workspace_id: Option<WorkspaceId>,
 476    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 477    input_enabled: bool,
 478    leader_replica_id: Option<u16>,
 479    remote_id: Option<ViewId>,
 480    hover_state: HoverState,
 481    link_go_to_definition_state: LinkGoToDefinitionState,
 482    _subscriptions: Vec<Subscription>,
 483}
 484
 485pub struct EditorSnapshot {
 486    pub mode: EditorMode,
 487    pub display_snapshot: DisplaySnapshot,
 488    pub placeholder_text: Option<Arc<str>>,
 489    is_focused: bool,
 490    scroll_anchor: ScrollAnchor,
 491    ongoing_scroll: OngoingScroll,
 492}
 493
 494#[derive(Clone, Debug)]
 495struct SelectionHistoryEntry {
 496    selections: Arc<[Selection<Anchor>]>,
 497    select_next_state: Option<SelectNextState>,
 498    add_selections_state: Option<AddSelectionsState>,
 499}
 500
 501enum SelectionHistoryMode {
 502    Normal,
 503    Undoing,
 504    Redoing,
 505}
 506
 507impl Default for SelectionHistoryMode {
 508    fn default() -> Self {
 509        Self::Normal
 510    }
 511}
 512
 513#[derive(Default)]
 514struct SelectionHistory {
 515    #[allow(clippy::type_complexity)]
 516    selections_by_transaction:
 517        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 518    mode: SelectionHistoryMode,
 519    undo_stack: VecDeque<SelectionHistoryEntry>,
 520    redo_stack: VecDeque<SelectionHistoryEntry>,
 521}
 522
 523impl SelectionHistory {
 524    fn insert_transaction(
 525        &mut self,
 526        transaction_id: TransactionId,
 527        selections: Arc<[Selection<Anchor>]>,
 528    ) {
 529        self.selections_by_transaction
 530            .insert(transaction_id, (selections, None));
 531    }
 532
 533    #[allow(clippy::type_complexity)]
 534    fn transaction(
 535        &self,
 536        transaction_id: TransactionId,
 537    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 538        self.selections_by_transaction.get(&transaction_id)
 539    }
 540
 541    #[allow(clippy::type_complexity)]
 542    fn transaction_mut(
 543        &mut self,
 544        transaction_id: TransactionId,
 545    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 546        self.selections_by_transaction.get_mut(&transaction_id)
 547    }
 548
 549    fn push(&mut self, entry: SelectionHistoryEntry) {
 550        if !entry.selections.is_empty() {
 551            match self.mode {
 552                SelectionHistoryMode::Normal => {
 553                    self.push_undo(entry);
 554                    self.redo_stack.clear();
 555                }
 556                SelectionHistoryMode::Undoing => self.push_redo(entry),
 557                SelectionHistoryMode::Redoing => self.push_undo(entry),
 558            }
 559        }
 560    }
 561
 562    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 563        if self
 564            .undo_stack
 565            .back()
 566            .map_or(true, |e| e.selections != entry.selections)
 567        {
 568            self.undo_stack.push_back(entry);
 569            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 570                self.undo_stack.pop_front();
 571            }
 572        }
 573    }
 574
 575    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 576        if self
 577            .redo_stack
 578            .back()
 579            .map_or(true, |e| e.selections != entry.selections)
 580        {
 581            self.redo_stack.push_back(entry);
 582            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 583                self.redo_stack.pop_front();
 584            }
 585        }
 586    }
 587}
 588
 589#[derive(Clone, Debug)]
 590struct AddSelectionsState {
 591    above: bool,
 592    stack: Vec<usize>,
 593}
 594
 595#[derive(Clone, Debug)]
 596struct SelectNextState {
 597    query: AhoCorasick,
 598    wordwise: bool,
 599    done: bool,
 600}
 601
 602#[derive(Debug)]
 603struct AutocloseRegion {
 604    selection_id: usize,
 605    range: Range<Anchor>,
 606    pair: BracketPair,
 607}
 608
 609#[derive(Debug)]
 610struct SnippetState {
 611    ranges: Vec<Vec<Range<Anchor>>>,
 612    active_index: usize,
 613}
 614
 615pub struct RenameState {
 616    pub range: Range<Anchor>,
 617    pub old_name: Arc<str>,
 618    pub editor: ViewHandle<Editor>,
 619    block_id: BlockId,
 620}
 621
 622struct InvalidationStack<T>(Vec<T>);
 623
 624enum ContextMenu {
 625    Completions(CompletionsMenu),
 626    CodeActions(CodeActionsMenu),
 627}
 628
 629impl ContextMenu {
 630    fn select_first(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 631        if self.visible() {
 632            match self {
 633                ContextMenu::Completions(menu) => menu.select_first(cx),
 634                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 635            }
 636            true
 637        } else {
 638            false
 639        }
 640    }
 641
 642    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 643        if self.visible() {
 644            match self {
 645                ContextMenu::Completions(menu) => menu.select_prev(cx),
 646                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 647            }
 648            true
 649        } else {
 650            false
 651        }
 652    }
 653
 654    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 655        if self.visible() {
 656            match self {
 657                ContextMenu::Completions(menu) => menu.select_next(cx),
 658                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 659            }
 660            true
 661        } else {
 662            false
 663        }
 664    }
 665
 666    fn select_last(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 667        if self.visible() {
 668            match self {
 669                ContextMenu::Completions(menu) => menu.select_last(cx),
 670                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 671            }
 672            true
 673        } else {
 674            false
 675        }
 676    }
 677
 678    fn visible(&self) -> bool {
 679        match self {
 680            ContextMenu::Completions(menu) => menu.visible(),
 681            ContextMenu::CodeActions(menu) => menu.visible(),
 682        }
 683    }
 684
 685    fn render(
 686        &self,
 687        cursor_position: DisplayPoint,
 688        style: EditorStyle,
 689        cx: &mut RenderContext<Editor>,
 690    ) -> (DisplayPoint, ElementBox) {
 691        match self {
 692            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 693            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 694        }
 695    }
 696}
 697
 698struct CompletionsMenu {
 699    id: CompletionId,
 700    initial_position: Anchor,
 701    buffer: ModelHandle<Buffer>,
 702    completions: Arc<[Completion]>,
 703    match_candidates: Vec<StringMatchCandidate>,
 704    matches: Arc<[StringMatch]>,
 705    selected_item: usize,
 706    list: UniformListState,
 707}
 708
 709impl CompletionsMenu {
 710    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 711        self.selected_item = 0;
 712        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 713        cx.notify();
 714    }
 715
 716    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 717        if self.selected_item > 0 {
 718            self.selected_item -= 1;
 719            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 720        }
 721        cx.notify();
 722    }
 723
 724    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 725        if self.selected_item + 1 < self.matches.len() {
 726            self.selected_item += 1;
 727            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 728        }
 729        cx.notify();
 730    }
 731
 732    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 733        self.selected_item = self.matches.len() - 1;
 734        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 735        cx.notify();
 736    }
 737
 738    fn visible(&self) -> bool {
 739        !self.matches.is_empty()
 740    }
 741
 742    fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
 743        enum CompletionTag {}
 744
 745        let completions = self.completions.clone();
 746        let matches = self.matches.clone();
 747        let selected_item = self.selected_item;
 748        let container_style = style.autocomplete.container;
 749        UniformList::new(
 750            self.list.clone(),
 751            matches.len(),
 752            cx,
 753            move |_, range, items, cx| {
 754                let start_ix = range.start;
 755                for (ix, mat) in matches[range].iter().enumerate() {
 756                    let completion = &completions[mat.candidate_id];
 757                    let item_ix = start_ix + ix;
 758                    items.push(
 759                        MouseEventHandler::<CompletionTag>::new(
 760                            mat.candidate_id,
 761                            cx,
 762                            |state, _| {
 763                                let item_style = if item_ix == selected_item {
 764                                    style.autocomplete.selected_item
 765                                } else if state.hovered() {
 766                                    style.autocomplete.hovered_item
 767                                } else {
 768                                    style.autocomplete.item
 769                                };
 770
 771                                Text::new(completion.label.text.clone(), style.text.clone())
 772                                    .with_soft_wrap(false)
 773                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 774                                        &completion.label.text,
 775                                        style.text.color.into(),
 776                                        styled_runs_for_code_label(
 777                                            &completion.label,
 778                                            &style.syntax,
 779                                        ),
 780                                        &mat.positions,
 781                                    ))
 782                                    .contained()
 783                                    .with_style(item_style)
 784                                    .boxed()
 785                            },
 786                        )
 787                        .with_cursor_style(CursorStyle::PointingHand)
 788                        .on_down(MouseButton::Left, move |_, cx| {
 789                            cx.dispatch_action(ConfirmCompletion {
 790                                item_ix: Some(item_ix),
 791                            });
 792                        })
 793                        .boxed(),
 794                    );
 795                }
 796            },
 797        )
 798        .with_width_from_item(
 799            self.matches
 800                .iter()
 801                .enumerate()
 802                .max_by_key(|(_, mat)| {
 803                    self.completions[mat.candidate_id]
 804                        .label
 805                        .text
 806                        .chars()
 807                        .count()
 808                })
 809                .map(|(ix, _)| ix),
 810        )
 811        .contained()
 812        .with_style(container_style)
 813        .boxed()
 814    }
 815
 816    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 817        let mut matches = if let Some(query) = query {
 818            fuzzy::match_strings(
 819                &self.match_candidates,
 820                query,
 821                query.chars().any(|c| c.is_uppercase()),
 822                100,
 823                &Default::default(),
 824                executor,
 825            )
 826            .await
 827        } else {
 828            self.match_candidates
 829                .iter()
 830                .enumerate()
 831                .map(|(candidate_id, candidate)| StringMatch {
 832                    candidate_id,
 833                    score: Default::default(),
 834                    positions: Default::default(),
 835                    string: candidate.string.clone(),
 836                })
 837                .collect()
 838        };
 839
 840        //Remove all candidates where the query's start does not match the start of any word in the candidate
 841        if let Some(query) = query {
 842            if let Some(query_start) = query.chars().next() {
 843                matches.retain(|string_match| {
 844                    split_words(&string_match.string).any(|word| {
 845                        //Check that the first codepoint of the word as lowercase matches the first
 846                        //codepoint of the query as lowercase
 847                        word.chars()
 848                            .flat_map(|codepoint| codepoint.to_lowercase())
 849                            .zip(query_start.to_lowercase())
 850                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 851                    })
 852                });
 853            }
 854        }
 855
 856        matches.sort_unstable_by_key(|mat| {
 857            let completion = &self.completions[mat.candidate_id];
 858            (
 859                completion.lsp_completion.sort_text.as_ref(),
 860                Reverse(OrderedFloat(mat.score)),
 861                completion.sort_key(),
 862            )
 863        });
 864
 865        for mat in &mut matches {
 866            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 867            for position in &mut mat.positions {
 868                *position += filter_start;
 869            }
 870        }
 871
 872        self.matches = matches.into();
 873    }
 874}
 875
 876#[derive(Clone)]
 877struct CodeActionsMenu {
 878    actions: Arc<[CodeAction]>,
 879    buffer: ModelHandle<Buffer>,
 880    selected_item: usize,
 881    list: UniformListState,
 882    deployed_from_indicator: bool,
 883}
 884
 885impl CodeActionsMenu {
 886    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 887        self.selected_item = 0;
 888        cx.notify()
 889    }
 890
 891    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 892        if self.selected_item > 0 {
 893            self.selected_item -= 1;
 894            cx.notify()
 895        }
 896    }
 897
 898    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 899        if self.selected_item + 1 < self.actions.len() {
 900            self.selected_item += 1;
 901            cx.notify()
 902        }
 903    }
 904
 905    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 906        self.selected_item = self.actions.len() - 1;
 907        cx.notify()
 908    }
 909
 910    fn visible(&self) -> bool {
 911        !self.actions.is_empty()
 912    }
 913
 914    fn render(
 915        &self,
 916        mut cursor_position: DisplayPoint,
 917        style: EditorStyle,
 918        cx: &mut RenderContext<Editor>,
 919    ) -> (DisplayPoint, ElementBox) {
 920        enum ActionTag {}
 921
 922        let container_style = style.autocomplete.container;
 923        let actions = self.actions.clone();
 924        let selected_item = self.selected_item;
 925        let element = UniformList::new(
 926            self.list.clone(),
 927            actions.len(),
 928            cx,
 929            move |_, range, items, cx| {
 930                let start_ix = range.start;
 931                for (ix, action) in actions[range].iter().enumerate() {
 932                    let item_ix = start_ix + ix;
 933                    items.push(
 934                        MouseEventHandler::<ActionTag>::new(item_ix, cx, |state, _| {
 935                            let item_style = if item_ix == selected_item {
 936                                style.autocomplete.selected_item
 937                            } else if state.hovered() {
 938                                style.autocomplete.hovered_item
 939                            } else {
 940                                style.autocomplete.item
 941                            };
 942
 943                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 944                                .with_soft_wrap(false)
 945                                .contained()
 946                                .with_style(item_style)
 947                                .boxed()
 948                        })
 949                        .with_cursor_style(CursorStyle::PointingHand)
 950                        .on_down(MouseButton::Left, move |_, cx| {
 951                            cx.dispatch_action(ConfirmCodeAction {
 952                                item_ix: Some(item_ix),
 953                            });
 954                        })
 955                        .boxed(),
 956                    );
 957                }
 958            },
 959        )
 960        .with_width_from_item(
 961            self.actions
 962                .iter()
 963                .enumerate()
 964                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 965                .map(|(ix, _)| ix),
 966        )
 967        .contained()
 968        .with_style(container_style)
 969        .boxed();
 970
 971        if self.deployed_from_indicator {
 972            *cursor_position.column_mut() = 0;
 973        }
 974
 975        (cursor_position, element)
 976    }
 977}
 978
 979#[derive(Debug)]
 980struct ActiveDiagnosticGroup {
 981    primary_range: Range<Anchor>,
 982    primary_message: String,
 983    blocks: HashMap<BlockId, Diagnostic>,
 984    is_valid: bool,
 985}
 986
 987#[derive(Serialize, Deserialize)]
 988pub struct ClipboardSelection {
 989    pub len: usize,
 990    pub is_entire_line: bool,
 991    pub first_line_indent: u32,
 992}
 993
 994#[derive(Debug)]
 995pub struct NavigationData {
 996    cursor_anchor: Anchor,
 997    cursor_position: Point,
 998    scroll_anchor: ScrollAnchor,
 999    scroll_top_row: u32,
1000}
1001
1002pub struct EditorCreated(pub ViewHandle<Editor>);
1003
1004enum GotoDefinitionKind {
1005    Symbol,
1006    Type,
1007}
1008
1009impl Editor {
1010    pub fn single_line(
1011        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1012        cx: &mut ViewContext<Self>,
1013    ) -> Self {
1014        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1015        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1016        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1017    }
1018
1019    pub fn multi_line(
1020        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1021        cx: &mut ViewContext<Self>,
1022    ) -> Self {
1023        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1024        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1025        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1026    }
1027
1028    pub fn auto_height(
1029        max_lines: usize,
1030        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1031        cx: &mut ViewContext<Self>,
1032    ) -> Self {
1033        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1034        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1035        Self::new(
1036            EditorMode::AutoHeight { max_lines },
1037            buffer,
1038            None,
1039            field_editor_style,
1040            cx,
1041        )
1042    }
1043
1044    pub fn for_buffer(
1045        buffer: ModelHandle<Buffer>,
1046        project: Option<ModelHandle<Project>>,
1047        cx: &mut ViewContext<Self>,
1048    ) -> Self {
1049        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1050        Self::new(EditorMode::Full, buffer, project, None, cx)
1051    }
1052
1053    pub fn for_multibuffer(
1054        buffer: ModelHandle<MultiBuffer>,
1055        project: Option<ModelHandle<Project>>,
1056        cx: &mut ViewContext<Self>,
1057    ) -> Self {
1058        Self::new(EditorMode::Full, buffer, project, None, cx)
1059    }
1060
1061    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1062        let mut clone = Self::new(
1063            self.mode,
1064            self.buffer.clone(),
1065            self.project.clone(),
1066            self.get_field_editor_theme.clone(),
1067            cx,
1068        );
1069        self.display_map.update(cx, |display_map, cx| {
1070            let snapshot = display_map.snapshot(cx);
1071            clone.display_map.update(cx, |display_map, cx| {
1072                display_map.set_state(&snapshot, cx);
1073            });
1074        });
1075        clone.selections.clone_state(&self.selections);
1076        clone.scroll_manager.clone_state(&self.scroll_manager);
1077        clone.searchable = self.searchable;
1078        clone
1079    }
1080
1081    fn new(
1082        mode: EditorMode,
1083        buffer: ModelHandle<MultiBuffer>,
1084        project: Option<ModelHandle<Project>>,
1085        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1086        cx: &mut ViewContext<Self>,
1087    ) -> Self {
1088        let display_map = cx.add_model(|cx| {
1089            let settings = cx.global::<Settings>();
1090            let style = build_style(&*settings, get_field_editor_theme.as_deref(), None, cx);
1091            DisplayMap::new(
1092                buffer.clone(),
1093                style.text.font_id,
1094                style.text.font_size,
1095                None,
1096                2,
1097                1,
1098                cx,
1099            )
1100        });
1101
1102        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1103
1104        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1105
1106        let soft_wrap_mode_override =
1107            (mode == EditorMode::SingleLine).then(|| settings::SoftWrap::None);
1108        let mut this = Self {
1109            handle: cx.weak_handle(),
1110            buffer: buffer.clone(),
1111            display_map: display_map.clone(),
1112            selections,
1113            scroll_manager: ScrollManager::new(),
1114            columnar_selection_tail: None,
1115            add_selections_state: None,
1116            select_next_state: None,
1117            selection_history: Default::default(),
1118            autoclose_regions: Default::default(),
1119            snippet_stack: Default::default(),
1120            select_larger_syntax_node_stack: Vec::new(),
1121            ime_transaction: Default::default(),
1122            active_diagnostics: None,
1123            soft_wrap_mode_override,
1124            get_field_editor_theme,
1125            project,
1126            focused: false,
1127            blink_manager: blink_manager.clone(),
1128            show_local_selections: true,
1129            mode,
1130            placeholder_text: None,
1131            highlighted_rows: None,
1132            background_highlights: Default::default(),
1133            nav_history: None,
1134            context_menu: None,
1135            mouse_context_menu: cx.add_view(context_menu::ContextMenu::new),
1136            completion_tasks: Default::default(),
1137            next_completion_id: 0,
1138            available_code_actions: Default::default(),
1139            code_actions_task: Default::default(),
1140            document_highlights_task: Default::default(),
1141            pending_rename: Default::default(),
1142            searchable: true,
1143            override_text_style: None,
1144            cursor_shape: Default::default(),
1145            workspace_id: None,
1146            keymap_context_layers: Default::default(),
1147            input_enabled: true,
1148            leader_replica_id: None,
1149            remote_id: None,
1150            hover_state: Default::default(),
1151            link_go_to_definition_state: Default::default(),
1152            _subscriptions: vec![
1153                cx.observe(&buffer, Self::on_buffer_changed),
1154                cx.subscribe(&buffer, Self::on_buffer_event),
1155                cx.observe(&display_map, Self::on_display_map_changed),
1156                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1157            ],
1158        };
1159        this.end_selection(cx);
1160        this.scroll_manager.show_scrollbar(cx);
1161
1162        let editor_created_event = EditorCreated(cx.handle());
1163        cx.emit_global(editor_created_event);
1164
1165        if mode == EditorMode::Full {
1166            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1167            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1168        }
1169
1170        this.report_event("open editor", cx);
1171        this
1172    }
1173
1174    pub fn new_file(
1175        workspace: &mut Workspace,
1176        _: &workspace::NewFile,
1177        cx: &mut ViewContext<Workspace>,
1178    ) {
1179        let project = workspace.project().clone();
1180        if project.read(cx).is_remote() {
1181            cx.propagate_action();
1182        } else if let Some(buffer) = project
1183            .update(cx, |project, cx| project.create_buffer("", None, cx))
1184            .log_err()
1185        {
1186            workspace.add_item(
1187                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1188                cx,
1189            );
1190        }
1191    }
1192
1193    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1194        self.buffer.read(cx).replica_id()
1195    }
1196
1197    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1198        self.leader_replica_id
1199    }
1200
1201    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1202        &self.buffer
1203    }
1204
1205    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1206        self.buffer().read(cx).title(cx)
1207    }
1208
1209    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
1210        EditorSnapshot {
1211            mode: self.mode,
1212            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1213            scroll_anchor: self.scroll_manager.anchor(),
1214            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1215            placeholder_text: self.placeholder_text.clone(),
1216            is_focused: self
1217                .handle
1218                .upgrade(cx)
1219                .map_or(false, |handle| handle.is_focused(cx)),
1220        }
1221    }
1222
1223    pub fn language_at<'a, T: ToOffset>(
1224        &self,
1225        point: T,
1226        cx: &'a AppContext,
1227    ) -> Option<Arc<Language>> {
1228        self.buffer.read(cx).language_at(point, cx)
1229    }
1230
1231    fn style(&self, cx: &AppContext) -> EditorStyle {
1232        build_style(
1233            cx.global::<Settings>(),
1234            self.get_field_editor_theme.as_deref(),
1235            self.override_text_style.as_deref(),
1236            cx,
1237        )
1238    }
1239
1240    pub fn mode(&self) -> EditorMode {
1241        self.mode
1242    }
1243
1244    pub fn set_placeholder_text(
1245        &mut self,
1246        placeholder_text: impl Into<Arc<str>>,
1247        cx: &mut ViewContext<Self>,
1248    ) {
1249        self.placeholder_text = Some(placeholder_text.into());
1250        cx.notify();
1251    }
1252
1253    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1254        self.cursor_shape = cursor_shape;
1255        cx.notify();
1256    }
1257
1258    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1259        if self.display_map.read(cx).clip_at_line_ends != clip {
1260            self.display_map
1261                .update(cx, |map, _| map.clip_at_line_ends = clip);
1262        }
1263    }
1264
1265    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: KeymapContext) {
1266        self.keymap_context_layers
1267            .insert(TypeId::of::<Tag>(), context);
1268    }
1269
1270    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
1271        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1272    }
1273
1274    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1275        self.input_enabled = input_enabled;
1276    }
1277
1278    fn selections_did_change(
1279        &mut self,
1280        local: bool,
1281        old_cursor_position: &Anchor,
1282        cx: &mut ViewContext<Self>,
1283    ) {
1284        if self.focused && self.leader_replica_id.is_none() {
1285            self.buffer.update(cx, |buffer, cx| {
1286                buffer.set_active_selections(
1287                    &self.selections.disjoint_anchors(),
1288                    self.selections.line_mode,
1289                    self.cursor_shape,
1290                    cx,
1291                )
1292            });
1293        }
1294
1295        let display_map = self
1296            .display_map
1297            .update(cx, |display_map, cx| display_map.snapshot(cx));
1298        let buffer = &display_map.buffer_snapshot;
1299        self.add_selections_state = None;
1300        self.select_next_state = None;
1301        self.select_larger_syntax_node_stack.clear();
1302        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1303        self.snippet_stack
1304            .invalidate(&self.selections.disjoint_anchors(), buffer);
1305        self.take_rename(false, cx);
1306
1307        let new_cursor_position = self.selections.newest_anchor().head();
1308
1309        self.push_to_nav_history(
1310            old_cursor_position.clone(),
1311            Some(new_cursor_position.to_point(buffer)),
1312            cx,
1313        );
1314
1315        if local {
1316            let new_cursor_position = self.selections.newest_anchor().head();
1317            let completion_menu = match self.context_menu.as_mut() {
1318                Some(ContextMenu::Completions(menu)) => Some(menu),
1319                _ => {
1320                    self.context_menu.take();
1321                    None
1322                }
1323            };
1324
1325            if let Some(completion_menu) = completion_menu {
1326                let cursor_position = new_cursor_position.to_offset(buffer);
1327                let (word_range, kind) =
1328                    buffer.surrounding_word(completion_menu.initial_position.clone());
1329                if kind == Some(CharKind::Word)
1330                    && word_range.to_inclusive().contains(&cursor_position)
1331                {
1332                    let query = Self::completion_query(buffer, cursor_position);
1333                    cx.background()
1334                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1335                    self.show_completions(&ShowCompletions, cx);
1336                } else {
1337                    self.hide_context_menu(cx);
1338                }
1339            }
1340
1341            hide_hover(self, &HideHover, cx);
1342
1343            if old_cursor_position.to_display_point(&display_map).row()
1344                != new_cursor_position.to_display_point(&display_map).row()
1345            {
1346                self.available_code_actions.take();
1347            }
1348            self.refresh_code_actions(cx);
1349            self.refresh_document_highlights(cx);
1350            refresh_matching_bracket_highlights(self, cx);
1351        }
1352
1353        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1354        cx.emit(Event::SelectionsChanged { local });
1355        cx.notify();
1356    }
1357
1358    pub fn change_selections<R>(
1359        &mut self,
1360        autoscroll: Option<Autoscroll>,
1361        cx: &mut ViewContext<Self>,
1362        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1363    ) -> R {
1364        let old_cursor_position = self.selections.newest_anchor().head();
1365        self.push_to_selection_history();
1366
1367        let (changed, result) = self.selections.change_with(cx, change);
1368
1369        if changed {
1370            if let Some(autoscroll) = autoscroll {
1371                self.request_autoscroll(autoscroll, cx);
1372            }
1373            self.selections_did_change(true, &old_cursor_position, cx);
1374        }
1375
1376        result
1377    }
1378
1379    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1380    where
1381        I: IntoIterator<Item = (Range<S>, T)>,
1382        S: ToOffset,
1383        T: Into<Arc<str>>,
1384    {
1385        self.buffer
1386            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1387    }
1388
1389    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1390    where
1391        I: IntoIterator<Item = (Range<S>, T)>,
1392        S: ToOffset,
1393        T: Into<Arc<str>>,
1394    {
1395        self.buffer.update(cx, |buffer, cx| {
1396            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
1397        });
1398    }
1399
1400    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
1401        self.hide_context_menu(cx);
1402
1403        match phase {
1404            SelectPhase::Begin {
1405                position,
1406                add,
1407                click_count,
1408            } => self.begin_selection(*position, *add, *click_count, cx),
1409            SelectPhase::BeginColumnar {
1410                position,
1411                goal_column,
1412            } => self.begin_columnar_selection(*position, *goal_column, cx),
1413            SelectPhase::Extend {
1414                position,
1415                click_count,
1416            } => self.extend_selection(*position, *click_count, cx),
1417            SelectPhase::Update {
1418                position,
1419                goal_column,
1420                scroll_position,
1421            } => self.update_selection(*position, *goal_column, *scroll_position, cx),
1422            SelectPhase::End => self.end_selection(cx),
1423        }
1424    }
1425
1426    fn extend_selection(
1427        &mut self,
1428        position: DisplayPoint,
1429        click_count: usize,
1430        cx: &mut ViewContext<Self>,
1431    ) {
1432        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1433        let tail = self.selections.newest::<usize>(cx).tail();
1434        self.begin_selection(position, false, click_count, cx);
1435
1436        let position = position.to_offset(&display_map, Bias::Left);
1437        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1438
1439        let mut pending_selection = self
1440            .selections
1441            .pending_anchor()
1442            .expect("extend_selection not called with pending selection");
1443        if position >= tail {
1444            pending_selection.start = tail_anchor;
1445        } else {
1446            pending_selection.end = tail_anchor;
1447            pending_selection.reversed = true;
1448        }
1449
1450        let mut pending_mode = self.selections.pending_mode().unwrap();
1451        match &mut pending_mode {
1452            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1453            _ => {}
1454        }
1455
1456        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1457            s.set_pending(pending_selection, pending_mode)
1458        });
1459    }
1460
1461    fn begin_selection(
1462        &mut self,
1463        position: DisplayPoint,
1464        add: bool,
1465        click_count: usize,
1466        cx: &mut ViewContext<Self>,
1467    ) {
1468        if !self.focused {
1469            cx.focus_self();
1470        }
1471
1472        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1473        let buffer = &display_map.buffer_snapshot;
1474        let newest_selection = self.selections.newest_anchor().clone();
1475        let position = display_map.clip_point(position, Bias::Left);
1476
1477        let start;
1478        let end;
1479        let mode;
1480        let auto_scroll;
1481        match click_count {
1482            1 => {
1483                start = buffer.anchor_before(position.to_point(&display_map));
1484                end = start.clone();
1485                mode = SelectMode::Character;
1486                auto_scroll = true;
1487            }
1488            2 => {
1489                let range = movement::surrounding_word(&display_map, position);
1490                start = buffer.anchor_before(range.start.to_point(&display_map));
1491                end = buffer.anchor_before(range.end.to_point(&display_map));
1492                mode = SelectMode::Word(start.clone()..end.clone());
1493                auto_scroll = true;
1494            }
1495            3 => {
1496                let position = display_map
1497                    .clip_point(position, Bias::Left)
1498                    .to_point(&display_map);
1499                let line_start = display_map.prev_line_boundary(position).0;
1500                let next_line_start = buffer.clip_point(
1501                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1502                    Bias::Left,
1503                );
1504                start = buffer.anchor_before(line_start);
1505                end = buffer.anchor_before(next_line_start);
1506                mode = SelectMode::Line(start.clone()..end.clone());
1507                auto_scroll = true;
1508            }
1509            _ => {
1510                start = buffer.anchor_before(0);
1511                end = buffer.anchor_before(buffer.len());
1512                mode = SelectMode::All;
1513                auto_scroll = false;
1514            }
1515        }
1516
1517        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
1518            if !add {
1519                s.clear_disjoint();
1520            } else if click_count > 1 {
1521                s.delete(newest_selection.id)
1522            }
1523
1524            s.set_pending_anchor_range(start..end, mode);
1525        });
1526    }
1527
1528    fn begin_columnar_selection(
1529        &mut self,
1530        position: DisplayPoint,
1531        goal_column: u32,
1532        cx: &mut ViewContext<Self>,
1533    ) {
1534        if !self.focused {
1535            cx.focus_self();
1536        }
1537
1538        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1539        let tail = self.selections.newest::<Point>(cx).tail();
1540        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1541
1542        self.select_columns(
1543            tail.to_display_point(&display_map),
1544            position,
1545            goal_column,
1546            &display_map,
1547            cx,
1548        );
1549    }
1550
1551    fn update_selection(
1552        &mut self,
1553        position: DisplayPoint,
1554        goal_column: u32,
1555        scroll_position: Vector2F,
1556        cx: &mut ViewContext<Self>,
1557    ) {
1558        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1559
1560        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1561            let tail = tail.to_display_point(&display_map);
1562            self.select_columns(tail, position, goal_column, &display_map, cx);
1563        } else if let Some(mut pending) = self.selections.pending_anchor() {
1564            let buffer = self.buffer.read(cx).snapshot(cx);
1565            let head;
1566            let tail;
1567            let mode = self.selections.pending_mode().unwrap();
1568            match &mode {
1569                SelectMode::Character => {
1570                    head = position.to_point(&display_map);
1571                    tail = pending.tail().to_point(&buffer);
1572                }
1573                SelectMode::Word(original_range) => {
1574                    let original_display_range = original_range.start.to_display_point(&display_map)
1575                        ..original_range.end.to_display_point(&display_map);
1576                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1577                        ..original_display_range.end.to_point(&display_map);
1578                    if movement::is_inside_word(&display_map, position)
1579                        || original_display_range.contains(&position)
1580                    {
1581                        let word_range = movement::surrounding_word(&display_map, position);
1582                        if word_range.start < original_display_range.start {
1583                            head = word_range.start.to_point(&display_map);
1584                        } else {
1585                            head = word_range.end.to_point(&display_map);
1586                        }
1587                    } else {
1588                        head = position.to_point(&display_map);
1589                    }
1590
1591                    if head <= original_buffer_range.start {
1592                        tail = original_buffer_range.end;
1593                    } else {
1594                        tail = original_buffer_range.start;
1595                    }
1596                }
1597                SelectMode::Line(original_range) => {
1598                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1599
1600                    let position = display_map
1601                        .clip_point(position, Bias::Left)
1602                        .to_point(&display_map);
1603                    let line_start = display_map.prev_line_boundary(position).0;
1604                    let next_line_start = buffer.clip_point(
1605                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1606                        Bias::Left,
1607                    );
1608
1609                    if line_start < original_range.start {
1610                        head = line_start
1611                    } else {
1612                        head = next_line_start
1613                    }
1614
1615                    if head <= original_range.start {
1616                        tail = original_range.end;
1617                    } else {
1618                        tail = original_range.start;
1619                    }
1620                }
1621                SelectMode::All => {
1622                    return;
1623                }
1624            };
1625
1626            if head < tail {
1627                pending.start = buffer.anchor_before(head);
1628                pending.end = buffer.anchor_before(tail);
1629                pending.reversed = true;
1630            } else {
1631                pending.start = buffer.anchor_before(tail);
1632                pending.end = buffer.anchor_before(head);
1633                pending.reversed = false;
1634            }
1635
1636            self.change_selections(None, cx, |s| {
1637                s.set_pending(pending, mode);
1638            });
1639        } else {
1640            log::error!("update_selection dispatched with no pending selection");
1641            return;
1642        }
1643
1644        self.set_scroll_position(scroll_position, cx);
1645        cx.notify();
1646    }
1647
1648    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1649        self.columnar_selection_tail.take();
1650        if self.selections.pending_anchor().is_some() {
1651            let selections = self.selections.all::<usize>(cx);
1652            self.change_selections(None, cx, |s| {
1653                s.select(selections);
1654                s.clear_pending();
1655            });
1656        }
1657    }
1658
1659    fn select_columns(
1660        &mut self,
1661        tail: DisplayPoint,
1662        head: DisplayPoint,
1663        goal_column: u32,
1664        display_map: &DisplaySnapshot,
1665        cx: &mut ViewContext<Self>,
1666    ) {
1667        let start_row = cmp::min(tail.row(), head.row());
1668        let end_row = cmp::max(tail.row(), head.row());
1669        let start_column = cmp::min(tail.column(), goal_column);
1670        let end_column = cmp::max(tail.column(), goal_column);
1671        let reversed = start_column < tail.column();
1672
1673        let selection_ranges = (start_row..=end_row)
1674            .filter_map(|row| {
1675                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1676                    let start = display_map
1677                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1678                        .to_point(display_map);
1679                    let end = display_map
1680                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1681                        .to_point(display_map);
1682                    if reversed {
1683                        Some(end..start)
1684                    } else {
1685                        Some(start..end)
1686                    }
1687                } else {
1688                    None
1689                }
1690            })
1691            .collect::<Vec<_>>();
1692
1693        self.change_selections(None, cx, |s| {
1694            s.select_ranges(selection_ranges);
1695        });
1696        cx.notify();
1697    }
1698
1699    pub fn has_pending_nonempty_selection(&self) -> bool {
1700        let pending_nonempty_selection = match self.selections.pending_anchor() {
1701            Some(Selection { start, end, .. }) => start != end,
1702            None => false,
1703        };
1704        pending_nonempty_selection || self.columnar_selection_tail.is_some()
1705    }
1706
1707    pub fn has_pending_selection(&self) -> bool {
1708        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1709    }
1710
1711    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1712        if self.take_rename(false, cx).is_some() {
1713            return;
1714        }
1715
1716        if hide_hover(self, &HideHover, cx) {
1717            return;
1718        }
1719
1720        if self.hide_context_menu(cx).is_some() {
1721            return;
1722        }
1723
1724        if self.snippet_stack.pop().is_some() {
1725            return;
1726        }
1727
1728        if self.mode == EditorMode::Full {
1729            if self.active_diagnostics.is_some() {
1730                self.dismiss_diagnostics(cx);
1731                return;
1732            }
1733
1734            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
1735                return;
1736            }
1737        }
1738
1739        cx.propagate_action();
1740    }
1741
1742    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1743        let text: Arc<str> = text.into();
1744
1745        if !self.input_enabled {
1746            cx.emit(Event::InputIgnored { text });
1747            return;
1748        }
1749
1750        let selections = self.selections.all_adjusted(cx);
1751        let mut edits = Vec::new();
1752        let mut new_selections = Vec::with_capacity(selections.len());
1753        let mut new_autoclose_regions = Vec::new();
1754        let snapshot = self.buffer.read(cx).read(cx);
1755
1756        for (selection, autoclose_region) in
1757            self.selections_with_autoclose_regions(selections, &snapshot)
1758        {
1759            if let Some(language) = snapshot.language_scope_at(selection.head()) {
1760                // Determine if the inserted text matches the opening or closing
1761                // bracket of any of this language's bracket pairs.
1762                let mut bracket_pair = None;
1763                let mut is_bracket_pair_start = false;
1764                for pair in language.brackets() {
1765                    if pair.close && pair.start.ends_with(text.as_ref()) {
1766                        bracket_pair = Some(pair.clone());
1767                        is_bracket_pair_start = true;
1768                        break;
1769                    } else if pair.end.as_str() == text.as_ref() {
1770                        bracket_pair = Some(pair.clone());
1771                        break;
1772                    }
1773                }
1774
1775                if let Some(bracket_pair) = bracket_pair {
1776                    if selection.is_empty() {
1777                        if is_bracket_pair_start {
1778                            let prefix_len = bracket_pair.start.len() - text.len();
1779
1780                            // If the inserted text is a suffix of an opening bracket and the
1781                            // selection is preceded by the rest of the opening bracket, then
1782                            // insert the closing bracket.
1783                            let following_text_allows_autoclose = snapshot
1784                                .chars_at(selection.start)
1785                                .next()
1786                                .map_or(true, |c| language.should_autoclose_before(c));
1787                            let preceding_text_matches_prefix = prefix_len == 0
1788                                || (selection.start.column >= (prefix_len as u32)
1789                                    && snapshot.contains_str_at(
1790                                        Point::new(
1791                                            selection.start.row,
1792                                            selection.start.column - (prefix_len as u32),
1793                                        ),
1794                                        &bracket_pair.start[..prefix_len],
1795                                    ));
1796                            if following_text_allows_autoclose && preceding_text_matches_prefix {
1797                                let anchor = snapshot.anchor_before(selection.end);
1798                                new_selections.push((selection.map(|_| anchor), text.len()));
1799                                new_autoclose_regions.push((
1800                                    anchor,
1801                                    text.len(),
1802                                    selection.id,
1803                                    bracket_pair.clone(),
1804                                ));
1805                                edits.push((
1806                                    selection.range(),
1807                                    format!("{}{}", text, bracket_pair.end).into(),
1808                                ));
1809                                continue;
1810                            }
1811                        }
1812
1813                        if let Some(region) = autoclose_region {
1814                            // If the selection is followed by an auto-inserted closing bracket,
1815                            // then don't insert that closing bracket again; just move the selection
1816                            // past the closing bracket.
1817                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
1818                                && text.as_ref() == region.pair.end.as_str();
1819                            if should_skip {
1820                                let anchor = snapshot.anchor_after(selection.end);
1821                                new_selections
1822                                    .push((selection.map(|_| anchor), region.pair.end.len()));
1823                                continue;
1824                            }
1825                        }
1826                    }
1827                    // If an opening bracket is 1 character long and is typed while
1828                    // text is selected, then surround that text with the bracket pair.
1829                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
1830                        edits.push((selection.start..selection.start, text.clone()));
1831                        edits.push((
1832                            selection.end..selection.end,
1833                            bracket_pair.end.as_str().into(),
1834                        ));
1835                        new_selections.push((
1836                            Selection {
1837                                id: selection.id,
1838                                start: snapshot.anchor_after(selection.start),
1839                                end: snapshot.anchor_before(selection.end),
1840                                reversed: selection.reversed,
1841                                goal: selection.goal,
1842                            },
1843                            0,
1844                        ));
1845                        continue;
1846                    }
1847                }
1848            }
1849
1850            // If not handling any auto-close operation, then just replace the selected
1851            // text with the given input and move the selection to the end of the
1852            // newly inserted text.
1853            let anchor = snapshot.anchor_after(selection.end);
1854            new_selections.push((selection.map(|_| anchor), 0));
1855            edits.push((selection.start..selection.end, text.clone()));
1856        }
1857
1858        drop(snapshot);
1859        self.transact(cx, |this, cx| {
1860            this.buffer.update(cx, |buffer, cx| {
1861                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
1862            });
1863
1864            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
1865            let new_selection_deltas = new_selections.iter().map(|e| e.1);
1866            let snapshot = this.buffer.read(cx).read(cx);
1867            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
1868                .zip(new_selection_deltas)
1869                .map(|(selection, delta)| selection.map(|e| e + delta))
1870                .collect::<Vec<_>>();
1871
1872            let mut i = 0;
1873            for (position, delta, selection_id, pair) in new_autoclose_regions {
1874                let position = position.to_offset(&snapshot) + delta;
1875                let start = snapshot.anchor_before(position);
1876                let end = snapshot.anchor_after(position);
1877                while let Some(existing_state) = this.autoclose_regions.get(i) {
1878                    match existing_state.range.start.cmp(&start, &snapshot) {
1879                        Ordering::Less => i += 1,
1880                        Ordering::Greater => break,
1881                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
1882                            Ordering::Less => i += 1,
1883                            Ordering::Equal => break,
1884                            Ordering::Greater => break,
1885                        },
1886                    }
1887                }
1888                this.autoclose_regions.insert(
1889                    i,
1890                    AutocloseRegion {
1891                        selection_id,
1892                        range: start..end,
1893                        pair,
1894                    },
1895                );
1896            }
1897
1898            drop(snapshot);
1899            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
1900            this.trigger_completion_on_input(&text, cx);
1901        });
1902    }
1903
1904    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
1905        self.transact(cx, |this, cx| {
1906            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
1907                let selections = this.selections.all::<usize>(cx);
1908
1909                let buffer = this.buffer.read(cx).snapshot(cx);
1910                selections
1911                    .iter()
1912                    .map(|selection| {
1913                        let start_point = selection.start.to_point(&buffer);
1914                        let mut indent = buffer.indent_size_for_line(start_point.row);
1915                        indent.len = cmp::min(indent.len, start_point.column);
1916                        let start = selection.start;
1917                        let end = selection.end;
1918
1919                        let mut insert_extra_newline = false;
1920                        if let Some(language) = buffer.language_scope_at(start) {
1921                            let leading_whitespace_len = buffer
1922                                .reversed_chars_at(start)
1923                                .take_while(|c| c.is_whitespace() && *c != '\n')
1924                                .map(|c| c.len_utf8())
1925                                .sum::<usize>();
1926
1927                            let trailing_whitespace_len = buffer
1928                                .chars_at(end)
1929                                .take_while(|c| c.is_whitespace() && *c != '\n')
1930                                .map(|c| c.len_utf8())
1931                                .sum::<usize>();
1932
1933                            insert_extra_newline = language.brackets().iter().any(|pair| {
1934                                let pair_start = pair.start.trim_end();
1935                                let pair_end = pair.end.trim_start();
1936
1937                                pair.newline
1938                                    && buffer
1939                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
1940                                    && buffer.contains_str_at(
1941                                        (start - leading_whitespace_len)
1942                                            .saturating_sub(pair_start.len()),
1943                                        pair_start,
1944                                    )
1945                            });
1946                        }
1947
1948                        let mut new_text = String::with_capacity(1 + indent.len as usize);
1949                        new_text.push('\n');
1950                        new_text.extend(indent.chars());
1951                        if insert_extra_newline {
1952                            new_text = new_text.repeat(2);
1953                        }
1954
1955                        let anchor = buffer.anchor_after(end);
1956                        let new_selection = selection.map(|_| anchor);
1957                        (
1958                            (start..end, new_text),
1959                            (insert_extra_newline, new_selection),
1960                        )
1961                    })
1962                    .unzip()
1963            };
1964
1965            this.edit_with_autoindent(edits, cx);
1966            let buffer = this.buffer.read(cx).snapshot(cx);
1967            let new_selections = selection_fixup_info
1968                .into_iter()
1969                .map(|(extra_newline_inserted, new_selection)| {
1970                    let mut cursor = new_selection.end.to_point(&buffer);
1971                    if extra_newline_inserted {
1972                        cursor.row -= 1;
1973                        cursor.column = buffer.line_len(cursor.row);
1974                    }
1975                    new_selection.map(|_| cursor)
1976                })
1977                .collect();
1978
1979            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
1980        });
1981    }
1982
1983    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
1984        let buffer = self.buffer.read(cx);
1985        let snapshot = buffer.snapshot(cx);
1986
1987        let mut edits = Vec::new();
1988        let mut rows = Vec::new();
1989        let mut rows_inserted = 0;
1990
1991        for selection in self.selections.all_adjusted(cx) {
1992            let cursor = selection.head();
1993            let row = cursor.row;
1994
1995            let end_of_line = snapshot
1996                .clip_point(Point::new(row, snapshot.line_len(row)), Bias::Left)
1997                .to_point(&snapshot);
1998
1999            let newline = "\n".to_string();
2000            edits.push((end_of_line..end_of_line, newline));
2001
2002            rows_inserted += 1;
2003            rows.push(row + rows_inserted);
2004        }
2005
2006        self.transact(cx, |editor, cx| {
2007            editor.edit_with_autoindent(edits, cx);
2008
2009            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2010                let mut index = 0;
2011                s.move_cursors_with(|map, _, _| {
2012                    let row = rows[index];
2013                    index += 1;
2014
2015                    let point = Point::new(row, 0);
2016                    let boundary = map.next_line_boundary(point).1;
2017                    let clipped = map.clip_point(boundary, Bias::Left);
2018
2019                    (clipped, SelectionGoal::None)
2020                });
2021            });
2022        });
2023    }
2024
2025    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2026        let text: Arc<str> = text.into();
2027        self.transact(cx, |this, cx| {
2028            let old_selections = this.selections.all_adjusted(cx);
2029            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2030                let anchors = {
2031                    let snapshot = buffer.read(cx);
2032                    old_selections
2033                        .iter()
2034                        .map(|s| {
2035                            let anchor = snapshot.anchor_after(s.end);
2036                            s.map(|_| anchor)
2037                        })
2038                        .collect::<Vec<_>>()
2039                };
2040                buffer.edit(
2041                    old_selections
2042                        .iter()
2043                        .map(|s| (s.start..s.end, text.clone())),
2044                    Some(AutoindentMode::Block {
2045                        original_indent_columns: Vec::new(),
2046                    }),
2047                    cx,
2048                );
2049                anchors
2050            });
2051
2052            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2053                s.select_anchors(selection_anchors);
2054            })
2055        });
2056    }
2057
2058    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2059        if !cx.global::<Settings>().show_completions_on_input {
2060            return;
2061        }
2062
2063        let selection = self.selections.newest_anchor();
2064        if self
2065            .buffer
2066            .read(cx)
2067            .is_completion_trigger(selection.head(), text, cx)
2068        {
2069            self.show_completions(&ShowCompletions, cx);
2070        } else {
2071            self.hide_context_menu(cx);
2072        }
2073    }
2074
2075    /// If any empty selections is touching the start of its innermost containing autoclose
2076    /// region, expand it to select the brackets.
2077    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2078        let selections = self.selections.all::<usize>(cx);
2079        let buffer = self.buffer.read(cx).read(cx);
2080        let mut new_selections = Vec::new();
2081        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2082            if let (Some(region), true) = (region, selection.is_empty()) {
2083                let mut range = region.range.to_offset(&buffer);
2084                if selection.start == range.start {
2085                    if range.start >= region.pair.start.len() {
2086                        range.start -= region.pair.start.len();
2087                        if buffer.contains_str_at(range.start, &region.pair.start) {
2088                            if buffer.contains_str_at(range.end, &region.pair.end) {
2089                                range.end += region.pair.end.len();
2090                                selection.start = range.start;
2091                                selection.end = range.end;
2092                            }
2093                        }
2094                    }
2095                }
2096            }
2097            new_selections.push(selection);
2098        }
2099
2100        drop(buffer);
2101        self.change_selections(None, cx, |selections| selections.select(new_selections));
2102    }
2103
2104    /// Iterate the given selections, and for each one, find the smallest surrounding
2105    /// autoclose region. This uses the ordering of the selections and the autoclose
2106    /// regions to avoid repeated comparisons.
2107    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2108        &'a self,
2109        selections: impl IntoIterator<Item = Selection<D>>,
2110        buffer: &'a MultiBufferSnapshot,
2111    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2112        let mut i = 0;
2113        let mut regions = self.autoclose_regions.as_slice();
2114        selections.into_iter().map(move |selection| {
2115            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2116
2117            let mut enclosing = None;
2118            while let Some(pair_state) = regions.get(i) {
2119                if pair_state.range.end.to_offset(buffer) < range.start {
2120                    regions = &regions[i + 1..];
2121                    i = 0;
2122                } else if pair_state.range.start.to_offset(buffer) > range.end {
2123                    break;
2124                } else if pair_state.selection_id == selection.id {
2125                    enclosing = Some(pair_state);
2126                    i += 1;
2127                }
2128            }
2129
2130            (selection.clone(), enclosing)
2131        })
2132    }
2133
2134    /// Remove any autoclose regions that no longer contain their selection.
2135    fn invalidate_autoclose_regions(
2136        &mut self,
2137        mut selections: &[Selection<Anchor>],
2138        buffer: &MultiBufferSnapshot,
2139    ) {
2140        self.autoclose_regions.retain(|state| {
2141            let mut i = 0;
2142            while let Some(selection) = selections.get(i) {
2143                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2144                    selections = &selections[1..];
2145                    continue;
2146                }
2147                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2148                    break;
2149                }
2150                if selection.id == state.selection_id {
2151                    return true;
2152                } else {
2153                    i += 1;
2154                }
2155            }
2156            false
2157        });
2158    }
2159
2160    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2161        let offset = position.to_offset(buffer);
2162        let (word_range, kind) = buffer.surrounding_word(offset);
2163        if offset > word_range.start && kind == Some(CharKind::Word) {
2164            Some(
2165                buffer
2166                    .text_for_range(word_range.start..offset)
2167                    .collect::<String>(),
2168            )
2169        } else {
2170            None
2171        }
2172    }
2173
2174    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2175        if self.pending_rename.is_some() {
2176            return;
2177        }
2178
2179        let project = if let Some(project) = self.project.clone() {
2180            project
2181        } else {
2182            return;
2183        };
2184
2185        let position = self.selections.newest_anchor().head();
2186        let (buffer, buffer_position) = if let Some(output) = self
2187            .buffer
2188            .read(cx)
2189            .text_anchor_for_position(position.clone(), cx)
2190        {
2191            output
2192        } else {
2193            return;
2194        };
2195
2196        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2197        let completions = project.update(cx, |project, cx| {
2198            project.completions(&buffer, buffer_position, cx)
2199        });
2200
2201        let id = post_inc(&mut self.next_completion_id);
2202        let task = cx.spawn_weak(|this, mut cx| {
2203            async move {
2204                let completions = completions.await?;
2205                if completions.is_empty() {
2206                    return Ok(());
2207                }
2208
2209                let mut menu = CompletionsMenu {
2210                    id,
2211                    initial_position: position,
2212                    match_candidates: completions
2213                        .iter()
2214                        .enumerate()
2215                        .map(|(id, completion)| {
2216                            StringMatchCandidate::new(
2217                                id,
2218                                completion.label.text[completion.label.filter_range.clone()].into(),
2219                            )
2220                        })
2221                        .collect(),
2222                    buffer,
2223                    completions: completions.into(),
2224                    matches: Vec::new().into(),
2225                    selected_item: 0,
2226                    list: Default::default(),
2227                };
2228
2229                menu.filter(query.as_deref(), cx.background()).await;
2230
2231                if let Some(this) = this.upgrade(&cx) {
2232                    this.update(&mut cx, |this, cx| {
2233                        match this.context_menu.as_ref() {
2234                            None => {}
2235                            Some(ContextMenu::Completions(prev_menu)) => {
2236                                if prev_menu.id > menu.id {
2237                                    return;
2238                                }
2239                            }
2240                            _ => return,
2241                        }
2242
2243                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
2244                        if this.focused {
2245                            this.show_context_menu(ContextMenu::Completions(menu), cx);
2246                        }
2247
2248                        cx.notify();
2249                    });
2250                }
2251                Ok::<_, anyhow::Error>(())
2252            }
2253            .log_err()
2254        });
2255        self.completion_tasks.push((id, task));
2256    }
2257
2258    pub fn confirm_completion(
2259        &mut self,
2260        action: &ConfirmCompletion,
2261        cx: &mut ViewContext<Self>,
2262    ) -> Option<Task<Result<()>>> {
2263        use language::ToOffset as _;
2264
2265        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2266            menu
2267        } else {
2268            return None;
2269        };
2270
2271        let mat = completions_menu
2272            .matches
2273            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2274        let buffer_handle = completions_menu.buffer;
2275        let completion = completions_menu.completions.get(mat.candidate_id)?;
2276
2277        let snippet;
2278        let text;
2279        if completion.is_snippet() {
2280            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2281            text = snippet.as_ref().unwrap().text.clone();
2282        } else {
2283            snippet = None;
2284            text = completion.new_text.clone();
2285        };
2286        let selections = self.selections.all::<usize>(cx);
2287        let buffer = buffer_handle.read(cx);
2288        let old_range = completion.old_range.to_offset(buffer);
2289        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2290
2291        let newest_selection = self.selections.newest_anchor();
2292        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
2293            return None;
2294        }
2295
2296        let lookbehind = newest_selection
2297            .start
2298            .text_anchor
2299            .to_offset(buffer)
2300            .saturating_sub(old_range.start);
2301        let lookahead = old_range
2302            .end
2303            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2304        let mut common_prefix_len = old_text
2305            .bytes()
2306            .zip(text.bytes())
2307            .take_while(|(a, b)| a == b)
2308            .count();
2309
2310        let snapshot = self.buffer.read(cx).snapshot(cx);
2311        let mut ranges = Vec::new();
2312        for selection in &selections {
2313            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2314                let start = selection.start.saturating_sub(lookbehind);
2315                let end = selection.end + lookahead;
2316                ranges.push(start + common_prefix_len..end);
2317            } else {
2318                common_prefix_len = 0;
2319                ranges.clear();
2320                ranges.extend(selections.iter().map(|s| {
2321                    if s.id == newest_selection.id {
2322                        old_range.clone()
2323                    } else {
2324                        s.start..s.end
2325                    }
2326                }));
2327                break;
2328            }
2329        }
2330        let text = &text[common_prefix_len..];
2331
2332        self.transact(cx, |this, cx| {
2333            if let Some(mut snippet) = snippet {
2334                snippet.text = text.to_string();
2335                for tabstop in snippet.tabstops.iter_mut().flatten() {
2336                    tabstop.start -= common_prefix_len as isize;
2337                    tabstop.end -= common_prefix_len as isize;
2338                }
2339
2340                this.insert_snippet(&ranges, snippet, cx).log_err();
2341            } else {
2342                this.buffer.update(cx, |buffer, cx| {
2343                    buffer.edit(
2344                        ranges.iter().map(|range| (range.clone(), text)),
2345                        Some(AutoindentMode::EachLine),
2346                        cx,
2347                    );
2348                });
2349            }
2350        });
2351
2352        let project = self.project.clone()?;
2353        let apply_edits = project.update(cx, |project, cx| {
2354            project.apply_additional_edits_for_completion(
2355                buffer_handle,
2356                completion.clone(),
2357                true,
2358                cx,
2359            )
2360        });
2361        Some(cx.foreground().spawn(async move {
2362            apply_edits.await?;
2363            Ok(())
2364        }))
2365    }
2366
2367    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2368        if matches!(
2369            self.context_menu.as_ref(),
2370            Some(ContextMenu::CodeActions(_))
2371        ) {
2372            self.context_menu.take();
2373            cx.notify();
2374            return;
2375        }
2376
2377        let deployed_from_indicator = action.deployed_from_indicator;
2378        let mut task = self.code_actions_task.take();
2379        cx.spawn_weak(|this, mut cx| async move {
2380            while let Some(prev_task) = task {
2381                prev_task.await;
2382                task = this
2383                    .upgrade(&cx)
2384                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
2385            }
2386
2387            if let Some(this) = this.upgrade(&cx) {
2388                this.update(&mut cx, |this, cx| {
2389                    if this.focused {
2390                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
2391                            this.show_context_menu(
2392                                ContextMenu::CodeActions(CodeActionsMenu {
2393                                    buffer,
2394                                    actions,
2395                                    selected_item: Default::default(),
2396                                    list: Default::default(),
2397                                    deployed_from_indicator,
2398                                }),
2399                                cx,
2400                            );
2401                        }
2402                    }
2403                })
2404            }
2405            Ok::<_, anyhow::Error>(())
2406        })
2407        .detach_and_log_err(cx);
2408    }
2409
2410    pub fn confirm_code_action(
2411        workspace: &mut Workspace,
2412        action: &ConfirmCodeAction,
2413        cx: &mut ViewContext<Workspace>,
2414    ) -> Option<Task<Result<()>>> {
2415        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2416        let actions_menu = if let ContextMenu::CodeActions(menu) =
2417            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2418        {
2419            menu
2420        } else {
2421            return None;
2422        };
2423        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2424        let action = actions_menu.actions.get(action_ix)?.clone();
2425        let title = action.lsp_action.title.clone();
2426        let buffer = actions_menu.buffer;
2427
2428        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2429            project.apply_code_action(buffer, action, true, cx)
2430        });
2431        Some(cx.spawn(|workspace, cx| async move {
2432            let project_transaction = apply_code_actions.await?;
2433            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
2434        }))
2435    }
2436
2437    async fn open_project_transaction(
2438        this: ViewHandle<Editor>,
2439        workspace: ViewHandle<Workspace>,
2440        transaction: ProjectTransaction,
2441        title: String,
2442        mut cx: AsyncAppContext,
2443    ) -> Result<()> {
2444        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
2445
2446        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2447        entries.sort_unstable_by_key(|(buffer, _)| {
2448            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2449        });
2450
2451        // If the project transaction's edits are all contained within this editor, then
2452        // avoid opening a new editor to display them.
2453
2454        if let Some((buffer, transaction)) = entries.first() {
2455            if entries.len() == 1 {
2456                let excerpt = this.read_with(&cx, |editor, cx| {
2457                    editor
2458                        .buffer()
2459                        .read(cx)
2460                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2461                });
2462                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2463                    if excerpted_buffer == *buffer {
2464                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2465                            let excerpt_range = excerpt_range.to_offset(buffer);
2466                            buffer
2467                                .edited_ranges_for_transaction::<usize>(transaction)
2468                                .all(|range| {
2469                                    excerpt_range.start <= range.start
2470                                        && excerpt_range.end >= range.end
2471                                })
2472                        });
2473
2474                        if all_edits_within_excerpt {
2475                            return Ok(());
2476                        }
2477                    }
2478                }
2479            }
2480        } else {
2481            return Ok(());
2482        }
2483
2484        let mut ranges_to_highlight = Vec::new();
2485        let excerpt_buffer = cx.add_model(|cx| {
2486            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2487            for (buffer_handle, transaction) in &entries {
2488                let buffer = buffer_handle.read(cx);
2489                ranges_to_highlight.extend(
2490                    multibuffer.push_excerpts_with_context_lines(
2491                        buffer_handle.clone(),
2492                        buffer
2493                            .edited_ranges_for_transaction::<usize>(transaction)
2494                            .collect(),
2495                        1,
2496                        cx,
2497                    ),
2498                );
2499            }
2500            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
2501            multibuffer
2502        });
2503
2504        workspace.update(&mut cx, |workspace, cx| {
2505            let project = workspace.project().clone();
2506            let editor =
2507                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2508            workspace.add_item(Box::new(editor.clone()), cx);
2509            editor.update(cx, |editor, cx| {
2510                editor.highlight_background::<Self>(
2511                    ranges_to_highlight,
2512                    |theme| theme.editor.highlighted_line_background,
2513                    cx,
2514                );
2515            });
2516        });
2517
2518        Ok(())
2519    }
2520
2521    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2522        let project = self.project.as_ref()?;
2523        let buffer = self.buffer.read(cx);
2524        let newest_selection = self.selections.newest_anchor().clone();
2525        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2526        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2527        if start_buffer != end_buffer {
2528            return None;
2529        }
2530
2531        let actions = project.update(cx, |project, cx| {
2532            project.code_actions(&start_buffer, start..end, cx)
2533        });
2534        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
2535            let actions = actions.await;
2536            if let Some(this) = this.upgrade(&cx) {
2537                this.update(&mut cx, |this, cx| {
2538                    this.available_code_actions = actions.log_err().and_then(|actions| {
2539                        if actions.is_empty() {
2540                            None
2541                        } else {
2542                            Some((start_buffer, actions.into()))
2543                        }
2544                    });
2545                    cx.notify();
2546                })
2547            }
2548        }));
2549        None
2550    }
2551
2552    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2553        if self.pending_rename.is_some() {
2554            return None;
2555        }
2556
2557        let project = self.project.as_ref()?;
2558        let buffer = self.buffer.read(cx);
2559        let newest_selection = self.selections.newest_anchor().clone();
2560        let cursor_position = newest_selection.head();
2561        let (cursor_buffer, cursor_buffer_position) =
2562            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2563        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2564        if cursor_buffer != tail_buffer {
2565            return None;
2566        }
2567
2568        let highlights = project.update(cx, |project, cx| {
2569            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2570        });
2571
2572        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
2573            let highlights = highlights.log_err().await;
2574            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
2575                this.update(&mut cx, |this, cx| {
2576                    if this.pending_rename.is_some() {
2577                        return;
2578                    }
2579
2580                    let buffer_id = cursor_position.buffer_id;
2581                    let buffer = this.buffer.read(cx);
2582                    if !buffer
2583                        .text_anchor_for_position(cursor_position, cx)
2584                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2585                    {
2586                        return;
2587                    }
2588
2589                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2590                    let mut write_ranges = Vec::new();
2591                    let mut read_ranges = Vec::new();
2592                    for highlight in highlights {
2593                        for (excerpt_id, excerpt_range) in
2594                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2595                        {
2596                            let start = highlight
2597                                .range
2598                                .start
2599                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
2600                            let end = highlight
2601                                .range
2602                                .end
2603                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
2604                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2605                                continue;
2606                            }
2607
2608                            let range = Anchor {
2609                                buffer_id,
2610                                excerpt_id: excerpt_id.clone(),
2611                                text_anchor: start,
2612                            }..Anchor {
2613                                buffer_id,
2614                                excerpt_id,
2615                                text_anchor: end,
2616                            };
2617                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2618                                write_ranges.push(range);
2619                            } else {
2620                                read_ranges.push(range);
2621                            }
2622                        }
2623                    }
2624
2625                    this.highlight_background::<DocumentHighlightRead>(
2626                        read_ranges,
2627                        |theme| theme.editor.document_highlight_read_background,
2628                        cx,
2629                    );
2630                    this.highlight_background::<DocumentHighlightWrite>(
2631                        write_ranges,
2632                        |theme| theme.editor.document_highlight_write_background,
2633                        cx,
2634                    );
2635                    cx.notify();
2636                });
2637            }
2638        }));
2639        None
2640    }
2641
2642    pub fn render_code_actions_indicator(
2643        &self,
2644        style: &EditorStyle,
2645        cx: &mut RenderContext<Self>,
2646    ) -> Option<ElementBox> {
2647        if self.available_code_actions.is_some() {
2648            enum Tag {}
2649            Some(
2650                MouseEventHandler::<Tag>::new(0, cx, |_, _| {
2651                    Svg::new("icons/bolt_8.svg")
2652                        .with_color(style.code_actions.indicator)
2653                        .boxed()
2654                })
2655                .with_cursor_style(CursorStyle::PointingHand)
2656                .with_padding(Padding::uniform(3.))
2657                .on_down(MouseButton::Left, |_, cx| {
2658                    cx.dispatch_action(ToggleCodeActions {
2659                        deployed_from_indicator: true,
2660                    });
2661                })
2662                .boxed(),
2663            )
2664        } else {
2665            None
2666        }
2667    }
2668
2669    pub fn context_menu_visible(&self) -> bool {
2670        self.context_menu
2671            .as_ref()
2672            .map_or(false, |menu| menu.visible())
2673    }
2674
2675    pub fn render_context_menu(
2676        &self,
2677        cursor_position: DisplayPoint,
2678        style: EditorStyle,
2679        cx: &mut RenderContext<Editor>,
2680    ) -> Option<(DisplayPoint, ElementBox)> {
2681        self.context_menu
2682            .as_ref()
2683            .map(|menu| menu.render(cursor_position, style, cx))
2684    }
2685
2686    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
2687        if !matches!(menu, ContextMenu::Completions(_)) {
2688            self.completion_tasks.clear();
2689        }
2690        self.context_menu = Some(menu);
2691        cx.notify();
2692    }
2693
2694    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
2695        cx.notify();
2696        self.completion_tasks.clear();
2697        self.context_menu.take()
2698    }
2699
2700    pub fn insert_snippet(
2701        &mut self,
2702        insertion_ranges: &[Range<usize>],
2703        snippet: Snippet,
2704        cx: &mut ViewContext<Self>,
2705    ) -> Result<()> {
2706        let tabstops = self.buffer.update(cx, |buffer, cx| {
2707            let snippet_text: Arc<str> = snippet.text.clone().into();
2708            buffer.edit(
2709                insertion_ranges
2710                    .iter()
2711                    .cloned()
2712                    .map(|range| (range, snippet_text.clone())),
2713                Some(AutoindentMode::EachLine),
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_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                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
2790                    s.select_anchor_ranges(current_ranges.iter().cloned())
2791                });
2792                // If snippet state is not at the last tabstop, push it back on the stack
2793                if snippet.active_index + 1 < snippet.ranges.len() {
2794                    self.snippet_stack.push(snippet);
2795                }
2796                return true;
2797            }
2798        }
2799
2800        false
2801    }
2802
2803    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
2804        self.transact(cx, |this, cx| {
2805            this.select_all(&SelectAll, cx);
2806            this.insert("", cx);
2807        });
2808    }
2809
2810    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
2811        self.transact(cx, |this, cx| {
2812            this.select_autoclose_pair(cx);
2813            let mut selections = this.selections.all::<Point>(cx);
2814            if !this.selections.line_mode {
2815                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
2816                for selection in &mut selections {
2817                    if selection.is_empty() {
2818                        let old_head = selection.head();
2819                        let mut new_head =
2820                            movement::left(&display_map, old_head.to_display_point(&display_map))
2821                                .to_point(&display_map);
2822                        if let Some((buffer, line_buffer_range)) = display_map
2823                            .buffer_snapshot
2824                            .buffer_line_for_row(old_head.row)
2825                        {
2826                            let indent_size =
2827                                buffer.indent_size_for_line(line_buffer_range.start.row);
2828                            let language_name = buffer
2829                                .language_at(line_buffer_range.start)
2830                                .map(|language| language.name());
2831                            let indent_len = match indent_size.kind {
2832                                IndentKind::Space => {
2833                                    cx.global::<Settings>().tab_size(language_name.as_deref())
2834                                }
2835                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
2836                            };
2837                            if old_head.column <= indent_size.len && old_head.column > 0 {
2838                                let indent_len = indent_len.get();
2839                                new_head = cmp::min(
2840                                    new_head,
2841                                    Point::new(
2842                                        old_head.row,
2843                                        ((old_head.column - 1) / indent_len) * indent_len,
2844                                    ),
2845                                );
2846                            }
2847                        }
2848
2849                        selection.set_head(new_head, SelectionGoal::None);
2850                    }
2851                }
2852            }
2853
2854            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
2855            this.insert("", cx);
2856        });
2857    }
2858
2859    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
2860        self.transact(cx, |this, cx| {
2861            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2862                let line_mode = s.line_mode;
2863                s.move_with(|map, selection| {
2864                    if selection.is_empty() && !line_mode {
2865                        let cursor = movement::right(map, selection.head());
2866                        selection.set_head(cursor, SelectionGoal::None);
2867                    }
2868                })
2869            });
2870            this.insert("", cx);
2871        });
2872    }
2873
2874    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
2875        if self.move_to_prev_snippet_tabstop(cx) {
2876            return;
2877        }
2878
2879        self.outdent(&Outdent, cx);
2880    }
2881
2882    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
2883        if self.move_to_next_snippet_tabstop(cx) {
2884            return;
2885        }
2886
2887        let mut selections = self.selections.all_adjusted(cx);
2888        let buffer = self.buffer.read(cx);
2889        let snapshot = buffer.snapshot(cx);
2890        let rows_iter = selections.iter().map(|s| s.head().row);
2891        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
2892
2893        let mut edits = Vec::new();
2894        let mut prev_edited_row = 0;
2895        let mut row_delta = 0;
2896        for selection in &mut selections {
2897            if selection.start.row != prev_edited_row {
2898                row_delta = 0;
2899            }
2900            prev_edited_row = selection.end.row;
2901
2902            // If the selection is non-empty, then increase the indentation of the selected lines.
2903            if !selection.is_empty() {
2904                row_delta =
2905                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
2906                continue;
2907            }
2908
2909            // If the selection is empty and the cursor is in the leading whitespace before the
2910            // suggested indentation, then auto-indent the line.
2911            let cursor = selection.head();
2912            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
2913                let current_indent = snapshot.indent_size_for_line(cursor.row);
2914                if cursor.column < suggested_indent.len
2915                    && cursor.column <= current_indent.len
2916                    && current_indent.len <= suggested_indent.len
2917                {
2918                    selection.start = Point::new(cursor.row, suggested_indent.len);
2919                    selection.end = selection.start;
2920                    if row_delta == 0 {
2921                        edits.extend(Buffer::edit_for_indent_size_adjustment(
2922                            cursor.row,
2923                            current_indent,
2924                            suggested_indent,
2925                        ));
2926                        row_delta = suggested_indent.len - current_indent.len;
2927                    }
2928                    continue;
2929                }
2930            }
2931
2932            // Otherwise, insert a hard or soft tab.
2933            let settings = cx.global::<Settings>();
2934            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
2935            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
2936                IndentSize::tab()
2937            } else {
2938                let tab_size = settings.tab_size(language_name.as_deref()).get();
2939                let char_column = snapshot
2940                    .text_for_range(Point::new(cursor.row, 0)..cursor)
2941                    .flat_map(str::chars)
2942                    .count()
2943                    + row_delta as usize;
2944                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
2945                IndentSize::spaces(chars_to_next_tab_stop)
2946            };
2947            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
2948            selection.end = selection.start;
2949            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
2950            row_delta += tab_size.len;
2951        }
2952
2953        self.transact(cx, |this, cx| {
2954            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
2955            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections))
2956        });
2957    }
2958
2959    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
2960        let mut selections = self.selections.all::<Point>(cx);
2961        let mut prev_edited_row = 0;
2962        let mut row_delta = 0;
2963        let mut edits = Vec::new();
2964        let buffer = self.buffer.read(cx);
2965        let snapshot = buffer.snapshot(cx);
2966        for selection in &mut selections {
2967            if selection.start.row != prev_edited_row {
2968                row_delta = 0;
2969            }
2970            prev_edited_row = selection.end.row;
2971
2972            row_delta =
2973                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
2974        }
2975
2976        self.transact(cx, |this, cx| {
2977            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
2978            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
2979        });
2980    }
2981
2982    fn indent_selection(
2983        buffer: &MultiBuffer,
2984        snapshot: &MultiBufferSnapshot,
2985        selection: &mut Selection<Point>,
2986        edits: &mut Vec<(Range<Point>, String)>,
2987        delta_for_start_row: u32,
2988        cx: &AppContext,
2989    ) -> u32 {
2990        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
2991        let settings = cx.global::<Settings>();
2992        let tab_size = settings.tab_size(language_name.as_deref()).get();
2993        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
2994            IndentKind::Tab
2995        } else {
2996            IndentKind::Space
2997        };
2998        let mut start_row = selection.start.row;
2999        let mut end_row = selection.end.row + 1;
3000
3001        // If a selection ends at the beginning of a line, don't indent
3002        // that last line.
3003        if selection.end.column == 0 {
3004            end_row -= 1;
3005        }
3006
3007        // Avoid re-indenting a row that has already been indented by a
3008        // previous selection, but still update this selection's column
3009        // to reflect that indentation.
3010        if delta_for_start_row > 0 {
3011            start_row += 1;
3012            selection.start.column += delta_for_start_row;
3013            if selection.end.row == selection.start.row {
3014                selection.end.column += delta_for_start_row;
3015            }
3016        }
3017
3018        let mut delta_for_end_row = 0;
3019        for row in start_row..end_row {
3020            let current_indent = snapshot.indent_size_for_line(row);
3021            let indent_delta = match (current_indent.kind, indent_kind) {
3022                (IndentKind::Space, IndentKind::Space) => {
3023                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3024                    IndentSize::spaces(columns_to_next_tab_stop)
3025                }
3026                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3027                (_, IndentKind::Tab) => IndentSize::tab(),
3028            };
3029
3030            let row_start = Point::new(row, 0);
3031            edits.push((
3032                row_start..row_start,
3033                indent_delta.chars().collect::<String>(),
3034            ));
3035
3036            // Update this selection's endpoints to reflect the indentation.
3037            if row == selection.start.row {
3038                selection.start.column += indent_delta.len;
3039            }
3040            if row == selection.end.row {
3041                selection.end.column += indent_delta.len;
3042                delta_for_end_row = indent_delta.len;
3043            }
3044        }
3045
3046        if selection.start.row == selection.end.row {
3047            delta_for_start_row + delta_for_end_row
3048        } else {
3049            delta_for_end_row
3050        }
3051    }
3052
3053    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3054        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3055        let selections = self.selections.all::<Point>(cx);
3056        let mut deletion_ranges = Vec::new();
3057        let mut last_outdent = None;
3058        {
3059            let buffer = self.buffer.read(cx);
3060            let snapshot = buffer.snapshot(cx);
3061            for selection in &selections {
3062                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3063                let tab_size = cx
3064                    .global::<Settings>()
3065                    .tab_size(language_name.as_deref())
3066                    .get();
3067                let mut rows = selection.spanned_rows(false, &display_map);
3068
3069                // Avoid re-outdenting a row that has already been outdented by a
3070                // previous selection.
3071                if let Some(last_row) = last_outdent {
3072                    if last_row == rows.start {
3073                        rows.start += 1;
3074                    }
3075                }
3076
3077                for row in rows {
3078                    let indent_size = snapshot.indent_size_for_line(row);
3079                    if indent_size.len > 0 {
3080                        let deletion_len = match indent_size.kind {
3081                            IndentKind::Space => {
3082                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3083                                if columns_to_prev_tab_stop == 0 {
3084                                    tab_size
3085                                } else {
3086                                    columns_to_prev_tab_stop
3087                                }
3088                            }
3089                            IndentKind::Tab => 1,
3090                        };
3091                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3092                        last_outdent = Some(row);
3093                    }
3094                }
3095            }
3096        }
3097
3098        self.transact(cx, |this, cx| {
3099            this.buffer.update(cx, |buffer, cx| {
3100                let empty_str: Arc<str> = "".into();
3101                buffer.edit(
3102                    deletion_ranges
3103                        .into_iter()
3104                        .map(|range| (range, empty_str.clone())),
3105                    None,
3106                    cx,
3107                );
3108            });
3109            let selections = this.selections.all::<usize>(cx);
3110            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3111        });
3112    }
3113
3114    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3115        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3116        let selections = self.selections.all::<Point>(cx);
3117
3118        let mut new_cursors = Vec::new();
3119        let mut edit_ranges = Vec::new();
3120        let mut selections = selections.iter().peekable();
3121        while let Some(selection) = selections.next() {
3122            let mut rows = selection.spanned_rows(false, &display_map);
3123            let goal_display_column = selection.head().to_display_point(&display_map).column();
3124
3125            // Accumulate contiguous regions of rows that we want to delete.
3126            while let Some(next_selection) = selections.peek() {
3127                let next_rows = next_selection.spanned_rows(false, &display_map);
3128                if next_rows.start <= rows.end {
3129                    rows.end = next_rows.end;
3130                    selections.next().unwrap();
3131                } else {
3132                    break;
3133                }
3134            }
3135
3136            let buffer = &display_map.buffer_snapshot;
3137            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3138            let edit_end;
3139            let cursor_buffer_row;
3140            if buffer.max_point().row >= rows.end {
3141                // If there's a line after the range, delete the \n from the end of the row range
3142                // and position the cursor on the next line.
3143                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3144                cursor_buffer_row = rows.end;
3145            } else {
3146                // If there isn't a line after the range, delete the \n from the line before the
3147                // start of the row range and position the cursor there.
3148                edit_start = edit_start.saturating_sub(1);
3149                edit_end = buffer.len();
3150                cursor_buffer_row = rows.start.saturating_sub(1);
3151            }
3152
3153            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3154            *cursor.column_mut() =
3155                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3156
3157            new_cursors.push((
3158                selection.id,
3159                buffer.anchor_after(cursor.to_point(&display_map)),
3160            ));
3161            edit_ranges.push(edit_start..edit_end);
3162        }
3163
3164        self.transact(cx, |this, cx| {
3165            let buffer = this.buffer.update(cx, |buffer, cx| {
3166                let empty_str: Arc<str> = "".into();
3167                buffer.edit(
3168                    edit_ranges
3169                        .into_iter()
3170                        .map(|range| (range, empty_str.clone())),
3171                    None,
3172                    cx,
3173                );
3174                buffer.snapshot(cx)
3175            });
3176            let new_selections = new_cursors
3177                .into_iter()
3178                .map(|(id, cursor)| {
3179                    let cursor = cursor.to_point(&buffer);
3180                    Selection {
3181                        id,
3182                        start: cursor,
3183                        end: cursor,
3184                        reversed: false,
3185                        goal: SelectionGoal::None,
3186                    }
3187                })
3188                .collect();
3189
3190            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3191                s.select(new_selections);
3192            });
3193        });
3194    }
3195
3196    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3197        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3198        let buffer = &display_map.buffer_snapshot;
3199        let selections = self.selections.all::<Point>(cx);
3200
3201        let mut edits = Vec::new();
3202        let mut selections_iter = selections.iter().peekable();
3203        while let Some(selection) = selections_iter.next() {
3204            // Avoid duplicating the same lines twice.
3205            let mut rows = selection.spanned_rows(false, &display_map);
3206
3207            while let Some(next_selection) = selections_iter.peek() {
3208                let next_rows = next_selection.spanned_rows(false, &display_map);
3209                if next_rows.start < rows.end {
3210                    rows.end = next_rows.end;
3211                    selections_iter.next().unwrap();
3212                } else {
3213                    break;
3214                }
3215            }
3216
3217            // Copy the text from the selected row region and splice it at the start of the region.
3218            let start = Point::new(rows.start, 0);
3219            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3220            let text = buffer
3221                .text_for_range(start..end)
3222                .chain(Some("\n"))
3223                .collect::<String>();
3224            edits.push((start..start, text));
3225        }
3226
3227        self.transact(cx, |this, cx| {
3228            this.buffer.update(cx, |buffer, cx| {
3229                buffer.edit(edits, None, cx);
3230            });
3231
3232            this.request_autoscroll(Autoscroll::fit(), cx);
3233        });
3234    }
3235
3236    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3237        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3238        let buffer = self.buffer.read(cx).snapshot(cx);
3239
3240        let mut edits = Vec::new();
3241        let mut unfold_ranges = Vec::new();
3242        let mut refold_ranges = Vec::new();
3243
3244        let selections = self.selections.all::<Point>(cx);
3245        let mut selections = selections.iter().peekable();
3246        let mut contiguous_row_selections = Vec::new();
3247        let mut new_selections = Vec::new();
3248
3249        while let Some(selection) = selections.next() {
3250            // Find all the selections that span a contiguous row range
3251            contiguous_row_selections.push(selection.clone());
3252            let start_row = selection.start.row;
3253            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3254                display_map.next_line_boundary(selection.end).0.row + 1
3255            } else {
3256                selection.end.row
3257            };
3258
3259            while let Some(next_selection) = selections.peek() {
3260                if next_selection.start.row <= end_row {
3261                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3262                        display_map.next_line_boundary(next_selection.end).0.row + 1
3263                    } else {
3264                        next_selection.end.row
3265                    };
3266                    contiguous_row_selections.push(selections.next().unwrap().clone());
3267                } else {
3268                    break;
3269                }
3270            }
3271
3272            // Move the text spanned by the row range to be before the line preceding the row range
3273            if start_row > 0 {
3274                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3275                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3276                let insertion_point = display_map
3277                    .prev_line_boundary(Point::new(start_row - 1, 0))
3278                    .0;
3279
3280                // Don't move lines across excerpts
3281                if buffer
3282                    .excerpt_boundaries_in_range((
3283                        Bound::Excluded(insertion_point),
3284                        Bound::Included(range_to_move.end),
3285                    ))
3286                    .next()
3287                    .is_none()
3288                {
3289                    let text = buffer
3290                        .text_for_range(range_to_move.clone())
3291                        .flat_map(|s| s.chars())
3292                        .skip(1)
3293                        .chain(['\n'])
3294                        .collect::<String>();
3295
3296                    edits.push((
3297                        buffer.anchor_after(range_to_move.start)
3298                            ..buffer.anchor_before(range_to_move.end),
3299                        String::new(),
3300                    ));
3301                    let insertion_anchor = buffer.anchor_after(insertion_point);
3302                    edits.push((insertion_anchor..insertion_anchor, text));
3303
3304                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3305
3306                    // Move selections up
3307                    new_selections.extend(contiguous_row_selections.drain(..).map(
3308                        |mut selection| {
3309                            selection.start.row -= row_delta;
3310                            selection.end.row -= row_delta;
3311                            selection
3312                        },
3313                    ));
3314
3315                    // Move folds up
3316                    unfold_ranges.push(range_to_move.clone());
3317                    for fold in display_map.folds_in_range(
3318                        buffer.anchor_before(range_to_move.start)
3319                            ..buffer.anchor_after(range_to_move.end),
3320                    ) {
3321                        let mut start = fold.start.to_point(&buffer);
3322                        let mut end = fold.end.to_point(&buffer);
3323                        start.row -= row_delta;
3324                        end.row -= row_delta;
3325                        refold_ranges.push(start..end);
3326                    }
3327                }
3328            }
3329
3330            // If we didn't move line(s), preserve the existing selections
3331            new_selections.append(&mut contiguous_row_selections);
3332        }
3333
3334        self.transact(cx, |this, cx| {
3335            this.unfold_ranges(unfold_ranges, true, cx);
3336            this.buffer.update(cx, |buffer, cx| {
3337                for (range, text) in edits {
3338                    buffer.edit([(range, text)], None, cx);
3339                }
3340            });
3341            this.fold_ranges(refold_ranges, cx);
3342            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3343                s.select(new_selections);
3344            })
3345        });
3346    }
3347
3348    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3349        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3350        let buffer = self.buffer.read(cx).snapshot(cx);
3351
3352        let mut edits = Vec::new();
3353        let mut unfold_ranges = Vec::new();
3354        let mut refold_ranges = Vec::new();
3355
3356        let selections = self.selections.all::<Point>(cx);
3357        let mut selections = selections.iter().peekable();
3358        let mut contiguous_row_selections = Vec::new();
3359        let mut new_selections = Vec::new();
3360
3361        while let Some(selection) = selections.next() {
3362            // Find all the selections that span a contiguous row range
3363            contiguous_row_selections.push(selection.clone());
3364            let start_row = selection.start.row;
3365            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3366                display_map.next_line_boundary(selection.end).0.row + 1
3367            } else {
3368                selection.end.row
3369            };
3370
3371            while let Some(next_selection) = selections.peek() {
3372                if next_selection.start.row <= end_row {
3373                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3374                        display_map.next_line_boundary(next_selection.end).0.row + 1
3375                    } else {
3376                        next_selection.end.row
3377                    };
3378                    contiguous_row_selections.push(selections.next().unwrap().clone());
3379                } else {
3380                    break;
3381                }
3382            }
3383
3384            // Move the text spanned by the row range to be after the last line of the row range
3385            if end_row <= buffer.max_point().row {
3386                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3387                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3388
3389                // Don't move lines across excerpt boundaries
3390                if buffer
3391                    .excerpt_boundaries_in_range((
3392                        Bound::Excluded(range_to_move.start),
3393                        Bound::Included(insertion_point),
3394                    ))
3395                    .next()
3396                    .is_none()
3397                {
3398                    let mut text = String::from("\n");
3399                    text.extend(buffer.text_for_range(range_to_move.clone()));
3400                    text.pop(); // Drop trailing newline
3401                    edits.push((
3402                        buffer.anchor_after(range_to_move.start)
3403                            ..buffer.anchor_before(range_to_move.end),
3404                        String::new(),
3405                    ));
3406                    let insertion_anchor = buffer.anchor_after(insertion_point);
3407                    edits.push((insertion_anchor..insertion_anchor, text));
3408
3409                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3410
3411                    // Move selections down
3412                    new_selections.extend(contiguous_row_selections.drain(..).map(
3413                        |mut selection| {
3414                            selection.start.row += row_delta;
3415                            selection.end.row += row_delta;
3416                            selection
3417                        },
3418                    ));
3419
3420                    // Move folds down
3421                    unfold_ranges.push(range_to_move.clone());
3422                    for fold in display_map.folds_in_range(
3423                        buffer.anchor_before(range_to_move.start)
3424                            ..buffer.anchor_after(range_to_move.end),
3425                    ) {
3426                        let mut start = fold.start.to_point(&buffer);
3427                        let mut end = fold.end.to_point(&buffer);
3428                        start.row += row_delta;
3429                        end.row += row_delta;
3430                        refold_ranges.push(start..end);
3431                    }
3432                }
3433            }
3434
3435            // If we didn't move line(s), preserve the existing selections
3436            new_selections.append(&mut contiguous_row_selections);
3437        }
3438
3439        self.transact(cx, |this, cx| {
3440            this.unfold_ranges(unfold_ranges, true, cx);
3441            this.buffer.update(cx, |buffer, cx| {
3442                for (range, text) in edits {
3443                    buffer.edit([(range, text)], None, cx);
3444                }
3445            });
3446            this.fold_ranges(refold_ranges, cx);
3447            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
3448        });
3449    }
3450
3451    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3452        self.transact(cx, |this, cx| {
3453            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3454                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3455                let line_mode = s.line_mode;
3456                s.move_with(|display_map, selection| {
3457                    if !selection.is_empty() || line_mode {
3458                        return;
3459                    }
3460
3461                    let mut head = selection.head();
3462                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3463                    if head.column() == display_map.line_len(head.row()) {
3464                        transpose_offset = display_map
3465                            .buffer_snapshot
3466                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3467                    }
3468
3469                    if transpose_offset == 0 {
3470                        return;
3471                    }
3472
3473                    *head.column_mut() += 1;
3474                    head = display_map.clip_point(head, Bias::Right);
3475                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3476
3477                    let transpose_start = display_map
3478                        .buffer_snapshot
3479                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3480                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3481                        let transpose_end = display_map
3482                            .buffer_snapshot
3483                            .clip_offset(transpose_offset + 1, Bias::Right);
3484                        if let Some(ch) =
3485                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3486                        {
3487                            edits.push((transpose_start..transpose_offset, String::new()));
3488                            edits.push((transpose_end..transpose_end, ch.to_string()));
3489                        }
3490                    }
3491                });
3492                edits
3493            });
3494            this.buffer
3495                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3496            let selections = this.selections.all::<usize>(cx);
3497            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3498                s.select(selections);
3499            });
3500        });
3501    }
3502
3503    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3504        let mut text = String::new();
3505        let buffer = self.buffer.read(cx).snapshot(cx);
3506        let mut selections = self.selections.all::<Point>(cx);
3507        let mut clipboard_selections = Vec::with_capacity(selections.len());
3508        {
3509            let max_point = buffer.max_point();
3510            for selection in &mut selections {
3511                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3512                if is_entire_line {
3513                    selection.start = Point::new(selection.start.row, 0);
3514                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3515                    selection.goal = SelectionGoal::None;
3516                }
3517                let mut len = 0;
3518                for chunk in buffer.text_for_range(selection.start..selection.end) {
3519                    text.push_str(chunk);
3520                    len += chunk.len();
3521                }
3522                clipboard_selections.push(ClipboardSelection {
3523                    len,
3524                    is_entire_line,
3525                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3526                });
3527            }
3528        }
3529
3530        self.transact(cx, |this, cx| {
3531            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3532                s.select(selections);
3533            });
3534            this.insert("", cx);
3535            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3536        });
3537    }
3538
3539    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3540        let selections = self.selections.all::<Point>(cx);
3541        let buffer = self.buffer.read(cx).read(cx);
3542        let mut text = String::new();
3543
3544        let mut clipboard_selections = Vec::with_capacity(selections.len());
3545        {
3546            let max_point = buffer.max_point();
3547            for selection in selections.iter() {
3548                let mut start = selection.start;
3549                let mut end = selection.end;
3550                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3551                if is_entire_line {
3552                    start = Point::new(start.row, 0);
3553                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3554                }
3555                let mut len = 0;
3556                for chunk in buffer.text_for_range(start..end) {
3557                    text.push_str(chunk);
3558                    len += chunk.len();
3559                }
3560                clipboard_selections.push(ClipboardSelection {
3561                    len,
3562                    is_entire_line,
3563                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3564                });
3565            }
3566        }
3567
3568        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3569    }
3570
3571    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3572        self.transact(cx, |this, cx| {
3573            if let Some(item) = cx.as_mut().read_from_clipboard() {
3574                let mut clipboard_text = Cow::Borrowed(item.text());
3575                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3576                    let old_selections = this.selections.all::<usize>(cx);
3577                    let all_selections_were_entire_line =
3578                        clipboard_selections.iter().all(|s| s.is_entire_line);
3579                    let first_selection_indent_column =
3580                        clipboard_selections.first().map(|s| s.first_line_indent);
3581                    if clipboard_selections.len() != old_selections.len() {
3582                        let mut newline_separated_text = String::new();
3583                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3584                        let mut ix = 0;
3585                        while let Some(clipboard_selection) = clipboard_selections.next() {
3586                            newline_separated_text
3587                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3588                            ix += clipboard_selection.len;
3589                            if clipboard_selections.peek().is_some() {
3590                                newline_separated_text.push('\n');
3591                            }
3592                        }
3593                        clipboard_text = Cow::Owned(newline_separated_text);
3594                    }
3595
3596                    this.buffer.update(cx, |buffer, cx| {
3597                        let snapshot = buffer.read(cx);
3598                        let mut start_offset = 0;
3599                        let mut edits = Vec::new();
3600                        let mut original_indent_columns = Vec::new();
3601                        let line_mode = this.selections.line_mode;
3602                        for (ix, selection) in old_selections.iter().enumerate() {
3603                            let to_insert;
3604                            let entire_line;
3605                            let original_indent_column;
3606                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3607                                let end_offset = start_offset + clipboard_selection.len;
3608                                to_insert = &clipboard_text[start_offset..end_offset];
3609                                entire_line = clipboard_selection.is_entire_line;
3610                                start_offset = end_offset;
3611                                original_indent_column =
3612                                    Some(clipboard_selection.first_line_indent);
3613                            } else {
3614                                to_insert = clipboard_text.as_str();
3615                                entire_line = all_selections_were_entire_line;
3616                                original_indent_column = first_selection_indent_column
3617                            }
3618
3619                            // If the corresponding selection was empty when this slice of the
3620                            // clipboard text was written, then the entire line containing the
3621                            // selection was copied. If this selection is also currently empty,
3622                            // then paste the line before the current line of the buffer.
3623                            let range = if selection.is_empty() && !line_mode && entire_line {
3624                                let column = selection.start.to_point(&snapshot).column as usize;
3625                                let line_start = selection.start - column;
3626                                line_start..line_start
3627                            } else {
3628                                selection.range()
3629                            };
3630
3631                            edits.push((range, to_insert));
3632                            original_indent_columns.extend(original_indent_column);
3633                        }
3634                        drop(snapshot);
3635
3636                        buffer.edit(
3637                            edits,
3638                            Some(AutoindentMode::Block {
3639                                original_indent_columns,
3640                            }),
3641                            cx,
3642                        );
3643                    });
3644
3645                    let selections = this.selections.all::<usize>(cx);
3646                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3647                } else {
3648                    this.insert(&clipboard_text, cx);
3649                }
3650            }
3651        });
3652    }
3653
3654    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3655        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3656            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3657                self.change_selections(None, cx, |s| {
3658                    s.select_anchors(selections.to_vec());
3659                });
3660            }
3661            self.request_autoscroll(Autoscroll::fit(), cx);
3662            self.unmark_text(cx);
3663            cx.emit(Event::Edited);
3664        }
3665    }
3666
3667    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3668        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3669            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3670            {
3671                self.change_selections(None, cx, |s| {
3672                    s.select_anchors(selections.to_vec());
3673                });
3674            }
3675            self.request_autoscroll(Autoscroll::fit(), cx);
3676            self.unmark_text(cx);
3677            cx.emit(Event::Edited);
3678        }
3679    }
3680
3681    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3682        self.buffer
3683            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3684    }
3685
3686    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3687        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3688            let line_mode = s.line_mode;
3689            s.move_with(|map, selection| {
3690                let cursor = if selection.is_empty() && !line_mode {
3691                    movement::left(map, selection.start)
3692                } else {
3693                    selection.start
3694                };
3695                selection.collapse_to(cursor, SelectionGoal::None);
3696            });
3697        })
3698    }
3699
3700    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3701        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3702            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3703        })
3704    }
3705
3706    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3707        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3708            let line_mode = s.line_mode;
3709            s.move_with(|map, selection| {
3710                let cursor = if selection.is_empty() && !line_mode {
3711                    movement::right(map, selection.end)
3712                } else {
3713                    selection.end
3714                };
3715                selection.collapse_to(cursor, SelectionGoal::None)
3716            });
3717        })
3718    }
3719
3720    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3721        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3722            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3723        })
3724    }
3725
3726    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3727        if self.take_rename(true, cx).is_some() {
3728            return;
3729        }
3730
3731        if let Some(context_menu) = self.context_menu.as_mut() {
3732            if context_menu.select_prev(cx) {
3733                return;
3734            }
3735        }
3736
3737        if matches!(self.mode, EditorMode::SingleLine) {
3738            cx.propagate_action();
3739            return;
3740        }
3741
3742        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3743            let line_mode = s.line_mode;
3744            s.move_with(|map, selection| {
3745                if !selection.is_empty() && !line_mode {
3746                    selection.goal = SelectionGoal::None;
3747                }
3748                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
3749                selection.collapse_to(cursor, goal);
3750            });
3751        })
3752    }
3753
3754    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
3755        if self.take_rename(true, cx).is_some() {
3756            return;
3757        }
3758
3759        if self
3760            .context_menu
3761            .as_mut()
3762            .map(|menu| menu.select_first(cx))
3763            .unwrap_or(false)
3764        {
3765            return;
3766        }
3767
3768        if matches!(self.mode, EditorMode::SingleLine) {
3769            cx.propagate_action();
3770            return;
3771        }
3772
3773        let row_count = if let Some(row_count) = self.visible_line_count() {
3774            row_count as u32 - 1
3775        } else {
3776            return;
3777        };
3778
3779        let autoscroll = if action.center_cursor {
3780            Autoscroll::center()
3781        } else {
3782            Autoscroll::fit()
3783        };
3784
3785        self.change_selections(Some(autoscroll), cx, |s| {
3786            let line_mode = s.line_mode;
3787            s.move_with(|map, selection| {
3788                if !selection.is_empty() && !line_mode {
3789                    selection.goal = SelectionGoal::None;
3790                }
3791                let (cursor, goal) =
3792                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
3793                selection.collapse_to(cursor, goal);
3794            });
3795        });
3796    }
3797
3798    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3799        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3800            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3801        })
3802    }
3803
3804    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3805        self.take_rename(true, cx);
3806
3807        if let Some(context_menu) = self.context_menu.as_mut() {
3808            if context_menu.select_next(cx) {
3809                return;
3810            }
3811        }
3812
3813        if self.mode == EditorMode::SingleLine {
3814            cx.propagate_action();
3815            return;
3816        }
3817
3818        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3819            let line_mode = s.line_mode;
3820            s.move_with(|map, selection| {
3821                if !selection.is_empty() && !line_mode {
3822                    selection.goal = SelectionGoal::None;
3823                }
3824                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
3825                selection.collapse_to(cursor, goal);
3826            });
3827        });
3828    }
3829
3830    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
3831        if self.take_rename(true, cx).is_some() {
3832            return;
3833        }
3834
3835        if self
3836            .context_menu
3837            .as_mut()
3838            .map(|menu| menu.select_last(cx))
3839            .unwrap_or(false)
3840        {
3841            return;
3842        }
3843
3844        if matches!(self.mode, EditorMode::SingleLine) {
3845            cx.propagate_action();
3846            return;
3847        }
3848
3849        let row_count = if let Some(row_count) = self.visible_line_count() {
3850            row_count as u32 - 1
3851        } else {
3852            return;
3853        };
3854
3855        let autoscroll = if action.center_cursor {
3856            Autoscroll::center()
3857        } else {
3858            Autoscroll::fit()
3859        };
3860
3861        self.change_selections(Some(autoscroll), cx, |s| {
3862            let line_mode = s.line_mode;
3863            s.move_with(|map, selection| {
3864                if !selection.is_empty() && !line_mode {
3865                    selection.goal = SelectionGoal::None;
3866                }
3867                let (cursor, goal) =
3868                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
3869                selection.collapse_to(cursor, goal);
3870            });
3871        });
3872    }
3873
3874    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3875        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3876            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3877        });
3878    }
3879
3880    pub fn move_to_previous_word_start(
3881        &mut self,
3882        _: &MoveToPreviousWordStart,
3883        cx: &mut ViewContext<Self>,
3884    ) {
3885        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3886            s.move_cursors_with(|map, head, _| {
3887                (
3888                    movement::previous_word_start(map, head),
3889                    SelectionGoal::None,
3890                )
3891            });
3892        })
3893    }
3894
3895    pub fn move_to_previous_subword_start(
3896        &mut self,
3897        _: &MoveToPreviousSubwordStart,
3898        cx: &mut ViewContext<Self>,
3899    ) {
3900        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3901            s.move_cursors_with(|map, head, _| {
3902                (
3903                    movement::previous_subword_start(map, head),
3904                    SelectionGoal::None,
3905                )
3906            });
3907        })
3908    }
3909
3910    pub fn select_to_previous_word_start(
3911        &mut self,
3912        _: &SelectToPreviousWordStart,
3913        cx: &mut ViewContext<Self>,
3914    ) {
3915        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3916            s.move_heads_with(|map, head, _| {
3917                (
3918                    movement::previous_word_start(map, head),
3919                    SelectionGoal::None,
3920                )
3921            });
3922        })
3923    }
3924
3925    pub fn select_to_previous_subword_start(
3926        &mut self,
3927        _: &SelectToPreviousSubwordStart,
3928        cx: &mut ViewContext<Self>,
3929    ) {
3930        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3931            s.move_heads_with(|map, head, _| {
3932                (
3933                    movement::previous_subword_start(map, head),
3934                    SelectionGoal::None,
3935                )
3936            });
3937        })
3938    }
3939
3940    pub fn delete_to_previous_word_start(
3941        &mut self,
3942        _: &DeleteToPreviousWordStart,
3943        cx: &mut ViewContext<Self>,
3944    ) {
3945        self.transact(cx, |this, cx| {
3946            this.select_autoclose_pair(cx);
3947            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3948                let line_mode = s.line_mode;
3949                s.move_with(|map, selection| {
3950                    if selection.is_empty() && !line_mode {
3951                        let cursor = movement::previous_word_start(map, selection.head());
3952                        selection.set_head(cursor, SelectionGoal::None);
3953                    }
3954                });
3955            });
3956            this.insert("", cx);
3957        });
3958    }
3959
3960    pub fn delete_to_previous_subword_start(
3961        &mut self,
3962        _: &DeleteToPreviousSubwordStart,
3963        cx: &mut ViewContext<Self>,
3964    ) {
3965        self.transact(cx, |this, cx| {
3966            this.select_autoclose_pair(cx);
3967            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3968                let line_mode = s.line_mode;
3969                s.move_with(|map, selection| {
3970                    if selection.is_empty() && !line_mode {
3971                        let cursor = movement::previous_subword_start(map, selection.head());
3972                        selection.set_head(cursor, SelectionGoal::None);
3973                    }
3974                });
3975            });
3976            this.insert("", cx);
3977        });
3978    }
3979
3980    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3981        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3982            s.move_cursors_with(|map, head, _| {
3983                (movement::next_word_end(map, head), SelectionGoal::None)
3984            });
3985        })
3986    }
3987
3988    pub fn move_to_next_subword_end(
3989        &mut self,
3990        _: &MoveToNextSubwordEnd,
3991        cx: &mut ViewContext<Self>,
3992    ) {
3993        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3994            s.move_cursors_with(|map, head, _| {
3995                (movement::next_subword_end(map, head), SelectionGoal::None)
3996            });
3997        })
3998    }
3999
4000    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4001        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4002            s.move_heads_with(|map, head, _| {
4003                (movement::next_word_end(map, head), SelectionGoal::None)
4004            });
4005        })
4006    }
4007
4008    pub fn select_to_next_subword_end(
4009        &mut self,
4010        _: &SelectToNextSubwordEnd,
4011        cx: &mut ViewContext<Self>,
4012    ) {
4013        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4014            s.move_heads_with(|map, head, _| {
4015                (movement::next_subword_end(map, head), SelectionGoal::None)
4016            });
4017        })
4018    }
4019
4020    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4021        self.transact(cx, |this, cx| {
4022            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4023                let line_mode = s.line_mode;
4024                s.move_with(|map, selection| {
4025                    if selection.is_empty() && !line_mode {
4026                        let cursor = movement::next_word_end(map, selection.head());
4027                        selection.set_head(cursor, SelectionGoal::None);
4028                    }
4029                });
4030            });
4031            this.insert("", cx);
4032        });
4033    }
4034
4035    pub fn delete_to_next_subword_end(
4036        &mut self,
4037        _: &DeleteToNextSubwordEnd,
4038        cx: &mut ViewContext<Self>,
4039    ) {
4040        self.transact(cx, |this, cx| {
4041            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4042                s.move_with(|map, selection| {
4043                    if selection.is_empty() {
4044                        let cursor = movement::next_subword_end(map, selection.head());
4045                        selection.set_head(cursor, SelectionGoal::None);
4046                    }
4047                });
4048            });
4049            this.insert("", cx);
4050        });
4051    }
4052
4053    pub fn move_to_beginning_of_line(
4054        &mut self,
4055        _: &MoveToBeginningOfLine,
4056        cx: &mut ViewContext<Self>,
4057    ) {
4058        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4059            s.move_cursors_with(|map, head, _| {
4060                (
4061                    movement::indented_line_beginning(map, head, true),
4062                    SelectionGoal::None,
4063                )
4064            });
4065        })
4066    }
4067
4068    pub fn select_to_beginning_of_line(
4069        &mut self,
4070        action: &SelectToBeginningOfLine,
4071        cx: &mut ViewContext<Self>,
4072    ) {
4073        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4074            s.move_heads_with(|map, head, _| {
4075                (
4076                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4077                    SelectionGoal::None,
4078                )
4079            });
4080        });
4081    }
4082
4083    pub fn delete_to_beginning_of_line(
4084        &mut self,
4085        _: &DeleteToBeginningOfLine,
4086        cx: &mut ViewContext<Self>,
4087    ) {
4088        self.transact(cx, |this, cx| {
4089            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4090                s.move_with(|_, selection| {
4091                    selection.reversed = true;
4092                });
4093            });
4094
4095            this.select_to_beginning_of_line(
4096                &SelectToBeginningOfLine {
4097                    stop_at_soft_wraps: false,
4098                },
4099                cx,
4100            );
4101            this.backspace(&Backspace, cx);
4102        });
4103    }
4104
4105    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4106        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4107            s.move_cursors_with(|map, head, _| {
4108                (movement::line_end(map, head, true), SelectionGoal::None)
4109            });
4110        })
4111    }
4112
4113    pub fn select_to_end_of_line(
4114        &mut self,
4115        action: &SelectToEndOfLine,
4116        cx: &mut ViewContext<Self>,
4117    ) {
4118        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4119            s.move_heads_with(|map, head, _| {
4120                (
4121                    movement::line_end(map, head, action.stop_at_soft_wraps),
4122                    SelectionGoal::None,
4123                )
4124            });
4125        })
4126    }
4127
4128    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4129        self.transact(cx, |this, cx| {
4130            this.select_to_end_of_line(
4131                &SelectToEndOfLine {
4132                    stop_at_soft_wraps: false,
4133                },
4134                cx,
4135            );
4136            this.delete(&Delete, cx);
4137        });
4138    }
4139
4140    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4141        self.transact(cx, |this, cx| {
4142            this.select_to_end_of_line(
4143                &SelectToEndOfLine {
4144                    stop_at_soft_wraps: false,
4145                },
4146                cx,
4147            );
4148            this.cut(&Cut, cx);
4149        });
4150    }
4151
4152    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4153        if matches!(self.mode, EditorMode::SingleLine) {
4154            cx.propagate_action();
4155            return;
4156        }
4157
4158        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4159            s.select_ranges(vec![0..0]);
4160        });
4161    }
4162
4163    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4164        let mut selection = self.selections.last::<Point>(cx);
4165        selection.set_head(Point::zero(), SelectionGoal::None);
4166
4167        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4168            s.select(vec![selection]);
4169        });
4170    }
4171
4172    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4173        if matches!(self.mode, EditorMode::SingleLine) {
4174            cx.propagate_action();
4175            return;
4176        }
4177
4178        let cursor = self.buffer.read(cx).read(cx).len();
4179        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4180            s.select_ranges(vec![cursor..cursor])
4181        });
4182    }
4183
4184    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4185        self.nav_history = nav_history;
4186    }
4187
4188    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4189        self.nav_history.as_ref()
4190    }
4191
4192    fn push_to_nav_history(
4193        &self,
4194        cursor_anchor: Anchor,
4195        new_position: Option<Point>,
4196        cx: &mut ViewContext<Self>,
4197    ) {
4198        if let Some(nav_history) = &self.nav_history {
4199            let buffer = self.buffer.read(cx).read(cx);
4200            let cursor_position = cursor_anchor.to_point(&buffer);
4201            let scroll_state = self.scroll_manager.anchor();
4202            let scroll_top_row = scroll_state.top_row(&buffer);
4203            drop(buffer);
4204
4205            if let Some(new_position) = new_position {
4206                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4207                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4208                    return;
4209                }
4210            }
4211
4212            nav_history.push(
4213                Some(NavigationData {
4214                    cursor_anchor,
4215                    cursor_position,
4216                    scroll_anchor: scroll_state,
4217                    scroll_top_row,
4218                }),
4219                cx,
4220            );
4221        }
4222    }
4223
4224    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4225        let buffer = self.buffer.read(cx).snapshot(cx);
4226        let mut selection = self.selections.first::<usize>(cx);
4227        selection.set_head(buffer.len(), SelectionGoal::None);
4228        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4229            s.select(vec![selection]);
4230        });
4231    }
4232
4233    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4234        let end = self.buffer.read(cx).read(cx).len();
4235        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4236            s.select_ranges(vec![0..end]);
4237        });
4238    }
4239
4240    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4241        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4242        let mut selections = self.selections.all::<Point>(cx);
4243        let max_point = display_map.buffer_snapshot.max_point();
4244        for selection in &mut selections {
4245            let rows = selection.spanned_rows(true, &display_map);
4246            selection.start = Point::new(rows.start, 0);
4247            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4248            selection.reversed = false;
4249        }
4250        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4251            s.select(selections);
4252        });
4253    }
4254
4255    pub fn split_selection_into_lines(
4256        &mut self,
4257        _: &SplitSelectionIntoLines,
4258        cx: &mut ViewContext<Self>,
4259    ) {
4260        let mut to_unfold = Vec::new();
4261        let mut new_selection_ranges = Vec::new();
4262        {
4263            let selections = self.selections.all::<Point>(cx);
4264            let buffer = self.buffer.read(cx).read(cx);
4265            for selection in selections {
4266                for row in selection.start.row..selection.end.row {
4267                    let cursor = Point::new(row, buffer.line_len(row));
4268                    new_selection_ranges.push(cursor..cursor);
4269                }
4270                new_selection_ranges.push(selection.end..selection.end);
4271                to_unfold.push(selection.start..selection.end);
4272            }
4273        }
4274        self.unfold_ranges(to_unfold, true, cx);
4275        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4276            s.select_ranges(new_selection_ranges);
4277        });
4278    }
4279
4280    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4281        self.add_selection(true, cx);
4282    }
4283
4284    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4285        self.add_selection(false, cx);
4286    }
4287
4288    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4289        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4290        let mut selections = self.selections.all::<Point>(cx);
4291        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4292            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4293            let range = oldest_selection.display_range(&display_map).sorted();
4294            let columns = cmp::min(range.start.column(), range.end.column())
4295                ..cmp::max(range.start.column(), range.end.column());
4296
4297            selections.clear();
4298            let mut stack = Vec::new();
4299            for row in range.start.row()..=range.end.row() {
4300                if let Some(selection) = self.selections.build_columnar_selection(
4301                    &display_map,
4302                    row,
4303                    &columns,
4304                    oldest_selection.reversed,
4305                ) {
4306                    stack.push(selection.id);
4307                    selections.push(selection);
4308                }
4309            }
4310
4311            if above {
4312                stack.reverse();
4313            }
4314
4315            AddSelectionsState { above, stack }
4316        });
4317
4318        let last_added_selection = *state.stack.last().unwrap();
4319        let mut new_selections = Vec::new();
4320        if above == state.above {
4321            let end_row = if above {
4322                0
4323            } else {
4324                display_map.max_point().row()
4325            };
4326
4327            'outer: for selection in selections {
4328                if selection.id == last_added_selection {
4329                    let range = selection.display_range(&display_map).sorted();
4330                    debug_assert_eq!(range.start.row(), range.end.row());
4331                    let mut row = range.start.row();
4332                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4333                    {
4334                        start..end
4335                    } else {
4336                        cmp::min(range.start.column(), range.end.column())
4337                            ..cmp::max(range.start.column(), range.end.column())
4338                    };
4339
4340                    while row != end_row {
4341                        if above {
4342                            row -= 1;
4343                        } else {
4344                            row += 1;
4345                        }
4346
4347                        if let Some(new_selection) = self.selections.build_columnar_selection(
4348                            &display_map,
4349                            row,
4350                            &columns,
4351                            selection.reversed,
4352                        ) {
4353                            state.stack.push(new_selection.id);
4354                            if above {
4355                                new_selections.push(new_selection);
4356                                new_selections.push(selection);
4357                            } else {
4358                                new_selections.push(selection);
4359                                new_selections.push(new_selection);
4360                            }
4361
4362                            continue 'outer;
4363                        }
4364                    }
4365                }
4366
4367                new_selections.push(selection);
4368            }
4369        } else {
4370            new_selections = selections;
4371            new_selections.retain(|s| s.id != last_added_selection);
4372            state.stack.pop();
4373        }
4374
4375        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4376            s.select(new_selections);
4377        });
4378        if state.stack.len() > 1 {
4379            self.add_selections_state = Some(state);
4380        }
4381    }
4382
4383    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4384        self.push_to_selection_history();
4385        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4386        let buffer = &display_map.buffer_snapshot;
4387        let mut selections = self.selections.all::<usize>(cx);
4388        if let Some(mut select_next_state) = self.select_next_state.take() {
4389            let query = &select_next_state.query;
4390            if !select_next_state.done {
4391                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4392                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4393                let mut next_selected_range = None;
4394
4395                let bytes_after_last_selection =
4396                    buffer.bytes_in_range(last_selection.end..buffer.len());
4397                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4398                let query_matches = query
4399                    .stream_find_iter(bytes_after_last_selection)
4400                    .map(|result| (last_selection.end, result))
4401                    .chain(
4402                        query
4403                            .stream_find_iter(bytes_before_first_selection)
4404                            .map(|result| (0, result)),
4405                    );
4406                for (start_offset, query_match) in query_matches {
4407                    let query_match = query_match.unwrap(); // can only fail due to I/O
4408                    let offset_range =
4409                        start_offset + query_match.start()..start_offset + query_match.end();
4410                    let display_range = offset_range.start.to_display_point(&display_map)
4411                        ..offset_range.end.to_display_point(&display_map);
4412
4413                    if !select_next_state.wordwise
4414                        || (!movement::is_inside_word(&display_map, display_range.start)
4415                            && !movement::is_inside_word(&display_map, display_range.end))
4416                    {
4417                        next_selected_range = Some(offset_range);
4418                        break;
4419                    }
4420                }
4421
4422                if let Some(next_selected_range) = next_selected_range {
4423                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4424                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4425                        if action.replace_newest {
4426                            s.delete(s.newest_anchor().id);
4427                        }
4428                        s.insert_range(next_selected_range);
4429                    });
4430                } else {
4431                    select_next_state.done = true;
4432                }
4433            }
4434
4435            self.select_next_state = Some(select_next_state);
4436        } else if selections.len() == 1 {
4437            let selection = selections.last_mut().unwrap();
4438            if selection.start == selection.end {
4439                let word_range = movement::surrounding_word(
4440                    &display_map,
4441                    selection.start.to_display_point(&display_map),
4442                );
4443                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4444                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4445                selection.goal = SelectionGoal::None;
4446                selection.reversed = false;
4447
4448                let query = buffer
4449                    .text_for_range(selection.start..selection.end)
4450                    .collect::<String>();
4451                let select_state = SelectNextState {
4452                    query: AhoCorasick::new_auto_configured(&[query]),
4453                    wordwise: true,
4454                    done: false,
4455                };
4456                self.unfold_ranges([selection.start..selection.end], false, cx);
4457                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4458                    s.select(selections);
4459                });
4460                self.select_next_state = Some(select_state);
4461            } else {
4462                let query = buffer
4463                    .text_for_range(selection.start..selection.end)
4464                    .collect::<String>();
4465                self.select_next_state = Some(SelectNextState {
4466                    query: AhoCorasick::new_auto_configured(&[query]),
4467                    wordwise: false,
4468                    done: false,
4469                });
4470                self.select_next(action, cx);
4471            }
4472        }
4473    }
4474
4475    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
4476        self.transact(cx, |this, cx| {
4477            let mut selections = this.selections.all::<Point>(cx);
4478            let mut edits = Vec::new();
4479            let mut selection_edit_ranges = Vec::new();
4480            let mut last_toggled_row = None;
4481            let snapshot = this.buffer.read(cx).read(cx);
4482            let empty_str: Arc<str> = "".into();
4483            let mut suffixes_inserted = Vec::new();
4484
4485            fn comment_prefix_range(
4486                snapshot: &MultiBufferSnapshot,
4487                row: u32,
4488                comment_prefix: &str,
4489                comment_prefix_whitespace: &str,
4490            ) -> Range<Point> {
4491                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4492
4493                let mut line_bytes = snapshot
4494                    .bytes_in_range(start..snapshot.max_point())
4495                    .flatten()
4496                    .copied();
4497
4498                // If this line currently begins with the line comment prefix, then record
4499                // the range containing the prefix.
4500                if line_bytes
4501                    .by_ref()
4502                    .take(comment_prefix.len())
4503                    .eq(comment_prefix.bytes())
4504                {
4505                    // Include any whitespace that matches the comment prefix.
4506                    let matching_whitespace_len = line_bytes
4507                        .zip(comment_prefix_whitespace.bytes())
4508                        .take_while(|(a, b)| a == b)
4509                        .count() as u32;
4510                    let end = Point::new(
4511                        start.row,
4512                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4513                    );
4514                    start..end
4515                } else {
4516                    start..start
4517                }
4518            }
4519
4520            fn comment_suffix_range(
4521                snapshot: &MultiBufferSnapshot,
4522                row: u32,
4523                comment_suffix: &str,
4524                comment_suffix_has_leading_space: bool,
4525            ) -> Range<Point> {
4526                let end = Point::new(row, snapshot.line_len(row));
4527                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4528
4529                let mut line_end_bytes = snapshot
4530                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4531                    .flatten()
4532                    .copied();
4533
4534                let leading_space_len = if suffix_start_column > 0
4535                    && line_end_bytes.next() == Some(b' ')
4536                    && comment_suffix_has_leading_space
4537                {
4538                    1
4539                } else {
4540                    0
4541                };
4542
4543                // If this line currently begins with the line comment prefix, then record
4544                // the range containing the prefix.
4545                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4546                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4547                    start..end
4548                } else {
4549                    end..end
4550                }
4551            }
4552
4553            // TODO: Handle selections that cross excerpts
4554            for selection in &mut selections {
4555                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
4556                let language = if let Some(language) =
4557                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
4558                {
4559                    language
4560                } else {
4561                    continue;
4562                };
4563
4564                selection_edit_ranges.clear();
4565
4566                // If multiple selections contain a given row, avoid processing that
4567                // row more than once.
4568                let mut start_row = selection.start.row;
4569                if last_toggled_row == Some(start_row) {
4570                    start_row += 1;
4571                }
4572                let end_row =
4573                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4574                        selection.end.row - 1
4575                    } else {
4576                        selection.end.row
4577                    };
4578                last_toggled_row = Some(end_row);
4579
4580                if start_row > end_row {
4581                    continue;
4582                }
4583
4584                // If the language has line comments, toggle those.
4585                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4586                    // Split the comment prefix's trailing whitespace into a separate string,
4587                    // as that portion won't be used for detecting if a line is a comment.
4588                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4589                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4590                    let mut all_selection_lines_are_comments = true;
4591
4592                    for row in start_row..=end_row {
4593                        if snapshot.is_line_blank(row) {
4594                            continue;
4595                        }
4596
4597                        let prefix_range = comment_prefix_range(
4598                            snapshot.deref(),
4599                            row,
4600                            comment_prefix,
4601                            comment_prefix_whitespace,
4602                        );
4603                        if prefix_range.is_empty() {
4604                            all_selection_lines_are_comments = false;
4605                        }
4606                        selection_edit_ranges.push(prefix_range);
4607                    }
4608
4609                    if all_selection_lines_are_comments {
4610                        edits.extend(
4611                            selection_edit_ranges
4612                                .iter()
4613                                .cloned()
4614                                .map(|range| (range, empty_str.clone())),
4615                        );
4616                    } else {
4617                        let min_column = selection_edit_ranges
4618                            .iter()
4619                            .map(|r| r.start.column)
4620                            .min()
4621                            .unwrap_or(0);
4622                        edits.extend(selection_edit_ranges.iter().map(|range| {
4623                            let position = Point::new(range.start.row, min_column);
4624                            (position..position, full_comment_prefix.clone())
4625                        }));
4626                    }
4627                } else if let Some((full_comment_prefix, comment_suffix)) =
4628                    language.block_comment_delimiters()
4629                {
4630                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4631                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4632                    let prefix_range = comment_prefix_range(
4633                        snapshot.deref(),
4634                        start_row,
4635                        comment_prefix,
4636                        comment_prefix_whitespace,
4637                    );
4638                    let suffix_range = comment_suffix_range(
4639                        snapshot.deref(),
4640                        end_row,
4641                        comment_suffix.trim_start_matches(' '),
4642                        comment_suffix.starts_with(' '),
4643                    );
4644
4645                    if prefix_range.is_empty() || suffix_range.is_empty() {
4646                        edits.push((
4647                            prefix_range.start..prefix_range.start,
4648                            full_comment_prefix.clone(),
4649                        ));
4650                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4651                        suffixes_inserted.push((end_row, comment_suffix.len()));
4652                    } else {
4653                        edits.push((prefix_range, empty_str.clone()));
4654                        edits.push((suffix_range, empty_str.clone()));
4655                    }
4656                } else {
4657                    continue;
4658                }
4659            }
4660
4661            drop(snapshot);
4662            this.buffer.update(cx, |buffer, cx| {
4663                buffer.edit(edits, None, cx);
4664            });
4665
4666            // Adjust selections so that they end before any comment suffixes that
4667            // were inserted.
4668            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4669            let mut selections = this.selections.all::<Point>(cx);
4670            let snapshot = this.buffer.read(cx).read(cx);
4671            for selection in &mut selections {
4672                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
4673                    match row.cmp(&selection.end.row) {
4674                        Ordering::Less => {
4675                            suffixes_inserted.next();
4676                            continue;
4677                        }
4678                        Ordering::Greater => break,
4679                        Ordering::Equal => {
4680                            if selection.end.column == snapshot.line_len(row) {
4681                                if selection.is_empty() {
4682                                    selection.start.column -= suffix_len as u32;
4683                                }
4684                                selection.end.column -= suffix_len as u32;
4685                            }
4686                            break;
4687                        }
4688                    }
4689                }
4690            }
4691
4692            drop(snapshot);
4693            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4694
4695            let selections = this.selections.all::<Point>(cx);
4696            let selections_on_single_row = selections.windows(2).all(|selections| {
4697                selections[0].start.row == selections[1].start.row
4698                    && selections[0].end.row == selections[1].end.row
4699                    && selections[0].start.row == selections[0].end.row
4700            });
4701            let selections_selecting = selections
4702                .iter()
4703                .any(|selection| selection.start != selection.end);
4704            let advance_downwards = action.advance_downwards
4705                && selections_on_single_row
4706                && !selections_selecting
4707                && this.mode != EditorMode::SingleLine;
4708
4709            if advance_downwards {
4710                let snapshot = this.buffer.read(cx).snapshot(cx);
4711
4712                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4713                    s.move_cursors_with(|display_snapshot, display_point, _| {
4714                        let mut point = display_point.to_point(display_snapshot);
4715                        point.row += 1;
4716                        point = snapshot.clip_point(point, Bias::Left);
4717                        let display_point = point.to_display_point(display_snapshot);
4718                        (display_point, SelectionGoal::Column(display_point.column()))
4719                    })
4720                });
4721            }
4722        });
4723    }
4724
4725    pub fn select_larger_syntax_node(
4726        &mut self,
4727        _: &SelectLargerSyntaxNode,
4728        cx: &mut ViewContext<Self>,
4729    ) {
4730        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4731        let buffer = self.buffer.read(cx).snapshot(cx);
4732        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4733
4734        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4735        let mut selected_larger_node = false;
4736        let new_selections = old_selections
4737            .iter()
4738            .map(|selection| {
4739                let old_range = selection.start..selection.end;
4740                let mut new_range = old_range.clone();
4741                while let Some(containing_range) =
4742                    buffer.range_for_syntax_ancestor(new_range.clone())
4743                {
4744                    new_range = containing_range;
4745                    if !display_map.intersects_fold(new_range.start)
4746                        && !display_map.intersects_fold(new_range.end)
4747                    {
4748                        break;
4749                    }
4750                }
4751
4752                selected_larger_node |= new_range != old_range;
4753                Selection {
4754                    id: selection.id,
4755                    start: new_range.start,
4756                    end: new_range.end,
4757                    goal: SelectionGoal::None,
4758                    reversed: selection.reversed,
4759                }
4760            })
4761            .collect::<Vec<_>>();
4762
4763        if selected_larger_node {
4764            stack.push(old_selections);
4765            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4766                s.select(new_selections);
4767            });
4768        }
4769        self.select_larger_syntax_node_stack = stack;
4770    }
4771
4772    pub fn select_smaller_syntax_node(
4773        &mut self,
4774        _: &SelectSmallerSyntaxNode,
4775        cx: &mut ViewContext<Self>,
4776    ) {
4777        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4778        if let Some(selections) = stack.pop() {
4779            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4780                s.select(selections.to_vec());
4781            });
4782        }
4783        self.select_larger_syntax_node_stack = stack;
4784    }
4785
4786    pub fn move_to_enclosing_bracket(
4787        &mut self,
4788        _: &MoveToEnclosingBracket,
4789        cx: &mut ViewContext<Self>,
4790    ) {
4791        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4792            s.move_offsets_with(|snapshot, selection| {
4793                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
4794                    return;
4795                };
4796
4797                let mut best_length = usize::MAX;
4798                let mut best_inside = false;
4799                let mut best_in_bracket_range = false;
4800                let mut best_destination = None;
4801                for (open, close) in enclosing_bracket_ranges {
4802                    let close = close.to_inclusive();
4803                    let length = close.end() - open.start;
4804                    let inside = selection.start >= open.end && selection.end <= *close.start();
4805                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
4806
4807                    // If best is next to a bracket and current isn't, skip
4808                    if !in_bracket_range && best_in_bracket_range {
4809                        continue;
4810                    }
4811
4812                    // Prefer smaller lengths unless best is inside and current isn't
4813                    if length > best_length && (best_inside || !inside) {
4814                        continue;
4815                    }
4816
4817                    best_length = length;
4818                    best_inside = inside;
4819                    best_in_bracket_range = in_bracket_range;
4820                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
4821                        if inside {
4822                            open.end
4823                        } else {
4824                            open.start
4825                        }
4826                    } else {
4827                        if inside {
4828                            *close.start()
4829                        } else {
4830                            *close.end()
4831                        }
4832                    });
4833                }
4834
4835                if let Some(destination) = best_destination {
4836                    selection.collapse_to(destination, SelectionGoal::None);
4837                }
4838            })
4839        });
4840    }
4841
4842    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4843        self.end_selection(cx);
4844        self.selection_history.mode = SelectionHistoryMode::Undoing;
4845        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4846            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4847            self.select_next_state = entry.select_next_state;
4848            self.add_selections_state = entry.add_selections_state;
4849            self.request_autoscroll(Autoscroll::newest(), cx);
4850        }
4851        self.selection_history.mode = SelectionHistoryMode::Normal;
4852    }
4853
4854    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4855        self.end_selection(cx);
4856        self.selection_history.mode = SelectionHistoryMode::Redoing;
4857        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4858            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4859            self.select_next_state = entry.select_next_state;
4860            self.add_selections_state = entry.add_selections_state;
4861            self.request_autoscroll(Autoscroll::newest(), cx);
4862        }
4863        self.selection_history.mode = SelectionHistoryMode::Normal;
4864    }
4865
4866    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
4867        self.go_to_diagnostic_impl(Direction::Next, cx)
4868    }
4869
4870    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4871        self.go_to_diagnostic_impl(Direction::Prev, cx)
4872    }
4873
4874    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4875        let buffer = self.buffer.read(cx).snapshot(cx);
4876        let selection = self.selections.newest::<usize>(cx);
4877
4878        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
4879        if direction == Direction::Next {
4880            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
4881                let (group_id, jump_to) = popover.activation_info();
4882                if self.activate_diagnostics(group_id, cx) {
4883                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4884                        let mut new_selection = s.newest_anchor().clone();
4885                        new_selection.collapse_to(jump_to, SelectionGoal::None);
4886                        s.select_anchors(vec![new_selection.clone()]);
4887                    });
4888                }
4889                return;
4890            }
4891        }
4892
4893        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4894            active_diagnostics
4895                .primary_range
4896                .to_offset(&buffer)
4897                .to_inclusive()
4898        });
4899        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4900            if active_primary_range.contains(&selection.head()) {
4901                *active_primary_range.end()
4902            } else {
4903                selection.head()
4904            }
4905        } else {
4906            selection.head()
4907        };
4908
4909        loop {
4910            let mut diagnostics = if direction == Direction::Prev {
4911                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4912            } else {
4913                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4914            };
4915            let group = diagnostics.find_map(|entry| {
4916                if entry.diagnostic.is_primary
4917                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4918                    && !entry.range.is_empty()
4919                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4920                {
4921                    Some((entry.range, entry.diagnostic.group_id))
4922                } else {
4923                    None
4924                }
4925            });
4926
4927            if let Some((primary_range, group_id)) = group {
4928                if self.activate_diagnostics(group_id, cx) {
4929                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4930                        s.select(vec![Selection {
4931                            id: selection.id,
4932                            start: primary_range.start,
4933                            end: primary_range.start,
4934                            reversed: false,
4935                            goal: SelectionGoal::None,
4936                        }]);
4937                    });
4938                }
4939                break;
4940            } else {
4941                // Cycle around to the start of the buffer, potentially moving back to the start of
4942                // the currently active diagnostic.
4943                active_primary_range.take();
4944                if direction == Direction::Prev {
4945                    if search_start == buffer.len() {
4946                        break;
4947                    } else {
4948                        search_start = buffer.len();
4949                    }
4950                } else if search_start == 0 {
4951                    break;
4952                } else {
4953                    search_start = 0;
4954                }
4955            }
4956        }
4957    }
4958
4959    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
4960        self.go_to_hunk_impl(Direction::Next, cx)
4961    }
4962
4963    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
4964        self.go_to_hunk_impl(Direction::Prev, cx)
4965    }
4966
4967    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4968        let snapshot = self
4969            .display_map
4970            .update(cx, |display_map, cx| display_map.snapshot(cx));
4971        let selection = self.selections.newest::<Point>(cx);
4972
4973        fn seek_in_direction(
4974            this: &mut Editor,
4975            snapshot: &DisplaySnapshot,
4976            initial_point: Point,
4977            is_wrapped: bool,
4978            direction: Direction,
4979            cx: &mut ViewContext<Editor>,
4980        ) -> bool {
4981            let hunks = if direction == Direction::Next {
4982                snapshot
4983                    .buffer_snapshot
4984                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
4985            } else {
4986                snapshot
4987                    .buffer_snapshot
4988                    .git_diff_hunks_in_range(0..initial_point.row, true)
4989            };
4990
4991            let display_point = initial_point.to_display_point(snapshot);
4992            let mut hunks = hunks
4993                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
4994                .skip_while(|hunk| {
4995                    if is_wrapped {
4996                        false
4997                    } else {
4998                        hunk.contains_display_row(display_point.row())
4999                    }
5000                })
5001                .dedup();
5002
5003            if let Some(hunk) = hunks.next() {
5004                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5005                    let row = hunk.start_display_row();
5006                    let point = DisplayPoint::new(row, 0);
5007                    s.select_display_ranges([point..point]);
5008                });
5009
5010                true
5011            } else {
5012                false
5013            }
5014        }
5015
5016        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5017            let wrapped_point = match direction {
5018                Direction::Next => Point::zero(),
5019                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5020            };
5021            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5022        }
5023    }
5024
5025    pub fn go_to_definition(
5026        workspace: &mut Workspace,
5027        _: &GoToDefinition,
5028        cx: &mut ViewContext<Workspace>,
5029    ) {
5030        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5031    }
5032
5033    pub fn go_to_type_definition(
5034        workspace: &mut Workspace,
5035        _: &GoToTypeDefinition,
5036        cx: &mut ViewContext<Workspace>,
5037    ) {
5038        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5039    }
5040
5041    fn go_to_definition_of_kind(
5042        kind: GotoDefinitionKind,
5043        workspace: &mut Workspace,
5044        cx: &mut ViewContext<Workspace>,
5045    ) {
5046        let active_item = workspace.active_item(cx);
5047        let editor_handle = if let Some(editor) = active_item
5048            .as_ref()
5049            .and_then(|item| item.act_as::<Self>(cx))
5050        {
5051            editor
5052        } else {
5053            return;
5054        };
5055
5056        let editor = editor_handle.read(cx);
5057        let buffer = editor.buffer.read(cx);
5058        let head = editor.selections.newest::<usize>(cx).head();
5059        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5060            text_anchor
5061        } else {
5062            return;
5063        };
5064
5065        let project = workspace.project().clone();
5066        let definitions = project.update(cx, |project, cx| match kind {
5067            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5068            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5069        });
5070
5071        cx.spawn(|workspace, mut cx| async move {
5072            let definitions = definitions.await?;
5073            workspace.update(&mut cx, |workspace, cx| {
5074                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5075            });
5076
5077            Ok::<(), anyhow::Error>(())
5078        })
5079        .detach_and_log_err(cx);
5080    }
5081
5082    pub fn navigate_to_definitions(
5083        workspace: &mut Workspace,
5084        editor_handle: ViewHandle<Editor>,
5085        definitions: Vec<LocationLink>,
5086        cx: &mut ViewContext<Workspace>,
5087    ) {
5088        let pane = workspace.active_pane().clone();
5089        // If there is one definition, just open it directly
5090        if let [definition] = definitions.as_slice() {
5091            let range = definition
5092                .target
5093                .range
5094                .to_offset(definition.target.buffer.read(cx));
5095
5096            let target_editor_handle =
5097                workspace.open_project_item(definition.target.buffer.clone(), cx);
5098            target_editor_handle.update(cx, |target_editor, cx| {
5099                // When selecting a definition in a different buffer, disable the nav history
5100                // to avoid creating a history entry at the previous cursor location.
5101                if editor_handle != target_editor_handle {
5102                    pane.update(cx, |pane, _| pane.disable_history());
5103                }
5104                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5105                    s.select_ranges([range]);
5106                });
5107
5108                pane.update(cx, |pane, _| pane.enable_history());
5109            });
5110        } else if !definitions.is_empty() {
5111            let replica_id = editor_handle.read(cx).replica_id(cx);
5112            let title = definitions
5113                .iter()
5114                .find(|definition| definition.origin.is_some())
5115                .and_then(|definition| {
5116                    definition.origin.as_ref().map(|origin| {
5117                        let buffer = origin.buffer.read(cx);
5118                        format!(
5119                            "Definitions for {}",
5120                            buffer
5121                                .text_for_range(origin.range.clone())
5122                                .collect::<String>()
5123                        )
5124                    })
5125                })
5126                .unwrap_or("Definitions".to_owned());
5127            let locations = definitions
5128                .into_iter()
5129                .map(|definition| definition.target)
5130                .collect();
5131            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5132        }
5133    }
5134
5135    pub fn find_all_references(
5136        workspace: &mut Workspace,
5137        _: &FindAllReferences,
5138        cx: &mut ViewContext<Workspace>,
5139    ) -> Option<Task<Result<()>>> {
5140        let active_item = workspace.active_item(cx)?;
5141        let editor_handle = active_item.act_as::<Self>(cx)?;
5142
5143        let editor = editor_handle.read(cx);
5144        let buffer = editor.buffer.read(cx);
5145        let head = editor.selections.newest::<usize>(cx).head();
5146        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5147        let replica_id = editor.replica_id(cx);
5148
5149        let project = workspace.project().clone();
5150        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5151        Some(cx.spawn(|workspace, mut cx| async move {
5152            let locations = references.await?;
5153            if locations.is_empty() {
5154                return Ok(());
5155            }
5156
5157            workspace.update(&mut cx, |workspace, cx| {
5158                let title = locations
5159                    .first()
5160                    .as_ref()
5161                    .map(|location| {
5162                        let buffer = location.buffer.read(cx);
5163                        format!(
5164                            "References to `{}`",
5165                            buffer
5166                                .text_for_range(location.range.clone())
5167                                .collect::<String>()
5168                        )
5169                    })
5170                    .unwrap();
5171                Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx);
5172            });
5173
5174            Ok(())
5175        }))
5176    }
5177
5178    /// Opens a multibuffer with the given project locations in it
5179    pub fn open_locations_in_multibuffer(
5180        workspace: &mut Workspace,
5181        mut locations: Vec<Location>,
5182        replica_id: ReplicaId,
5183        title: String,
5184        cx: &mut ViewContext<Workspace>,
5185    ) {
5186        // If there are multiple definitions, open them in a multibuffer
5187        locations.sort_by_key(|location| location.buffer.id());
5188        let mut locations = locations.into_iter().peekable();
5189        let mut ranges_to_highlight = Vec::new();
5190
5191        let excerpt_buffer = cx.add_model(|cx| {
5192            let mut multibuffer = MultiBuffer::new(replica_id);
5193            while let Some(location) = locations.next() {
5194                let buffer = location.buffer.read(cx);
5195                let mut ranges_for_buffer = Vec::new();
5196                let range = location.range.to_offset(buffer);
5197                ranges_for_buffer.push(range.clone());
5198
5199                while let Some(next_location) = locations.peek() {
5200                    if next_location.buffer == location.buffer {
5201                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5202                        locations.next();
5203                    } else {
5204                        break;
5205                    }
5206                }
5207
5208                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5209                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5210                    location.buffer.clone(),
5211                    ranges_for_buffer,
5212                    1,
5213                    cx,
5214                ))
5215            }
5216
5217            multibuffer.with_title(title)
5218        });
5219
5220        let editor = cx.add_view(|cx| {
5221            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5222        });
5223        editor.update(cx, |editor, cx| {
5224            editor.highlight_background::<Self>(
5225                ranges_to_highlight,
5226                |theme| theme.editor.highlighted_line_background,
5227                cx,
5228            );
5229        });
5230        workspace.add_item(Box::new(editor), cx);
5231    }
5232
5233    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5234        use language::ToOffset as _;
5235
5236        let project = self.project.clone()?;
5237        let selection = self.selections.newest_anchor().clone();
5238        let (cursor_buffer, cursor_buffer_position) = self
5239            .buffer
5240            .read(cx)
5241            .text_anchor_for_position(selection.head(), cx)?;
5242        let (tail_buffer, _) = self
5243            .buffer
5244            .read(cx)
5245            .text_anchor_for_position(selection.tail(), cx)?;
5246        if tail_buffer != cursor_buffer {
5247            return None;
5248        }
5249
5250        let snapshot = cursor_buffer.read(cx).snapshot();
5251        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5252        let prepare_rename = project.update(cx, |project, cx| {
5253            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5254        });
5255
5256        Some(cx.spawn(|this, mut cx| async move {
5257            let rename_range = if let Some(range) = prepare_rename.await? {
5258                Some(range)
5259            } else {
5260                this.read_with(&cx, |this, cx| {
5261                    let buffer = this.buffer.read(cx).snapshot(cx);
5262                    let mut buffer_highlights = this
5263                        .document_highlights_for_position(selection.head(), &buffer)
5264                        .filter(|highlight| {
5265                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5266                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5267                        });
5268                    buffer_highlights
5269                        .next()
5270                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5271                })
5272            };
5273            if let Some(rename_range) = rename_range {
5274                let rename_buffer_range = rename_range.to_offset(&snapshot);
5275                let cursor_offset_in_rename_range =
5276                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5277
5278                this.update(&mut cx, |this, cx| {
5279                    this.take_rename(false, cx);
5280                    let style = this.style(cx);
5281                    let buffer = this.buffer.read(cx).read(cx);
5282                    let cursor_offset = selection.head().to_offset(&buffer);
5283                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5284                    let rename_end = rename_start + rename_buffer_range.len();
5285                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5286                    let mut old_highlight_id = None;
5287                    let old_name: Arc<str> = buffer
5288                        .chunks(rename_start..rename_end, true)
5289                        .map(|chunk| {
5290                            if old_highlight_id.is_none() {
5291                                old_highlight_id = chunk.syntax_highlight_id;
5292                            }
5293                            chunk.text
5294                        })
5295                        .collect::<String>()
5296                        .into();
5297
5298                    drop(buffer);
5299
5300                    // Position the selection in the rename editor so that it matches the current selection.
5301                    this.show_local_selections = false;
5302                    let rename_editor = cx.add_view(|cx| {
5303                        let mut editor = Editor::single_line(None, cx);
5304                        if let Some(old_highlight_id) = old_highlight_id {
5305                            editor.override_text_style =
5306                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5307                        }
5308                        editor.buffer.update(cx, |buffer, cx| {
5309                            buffer.edit([(0..0, old_name.clone())], None, cx)
5310                        });
5311                        editor.select_all(&SelectAll, cx);
5312                        editor
5313                    });
5314
5315                    let ranges = this
5316                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5317                        .into_iter()
5318                        .flat_map(|(_, ranges)| ranges)
5319                        .chain(
5320                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5321                                .into_iter()
5322                                .flat_map(|(_, ranges)| ranges),
5323                        )
5324                        .collect();
5325
5326                    this.highlight_text::<Rename>(
5327                        ranges,
5328                        HighlightStyle {
5329                            fade_out: Some(style.rename_fade),
5330                            ..Default::default()
5331                        },
5332                        cx,
5333                    );
5334                    cx.focus(&rename_editor);
5335                    let block_id = this.insert_blocks(
5336                        [BlockProperties {
5337                            style: BlockStyle::Flex,
5338                            position: range.start.clone(),
5339                            height: 1,
5340                            render: Arc::new({
5341                                let editor = rename_editor.clone();
5342                                move |cx: &mut BlockContext| {
5343                                    ChildView::new(editor.clone(), cx)
5344                                        .contained()
5345                                        .with_padding_left(cx.anchor_x)
5346                                        .boxed()
5347                                }
5348                            }),
5349                            disposition: BlockDisposition::Below,
5350                        }],
5351                        cx,
5352                    )[0];
5353                    this.pending_rename = Some(RenameState {
5354                        range,
5355                        old_name,
5356                        editor: rename_editor,
5357                        block_id,
5358                    });
5359                });
5360            }
5361
5362            Ok(())
5363        }))
5364    }
5365
5366    pub fn confirm_rename(
5367        workspace: &mut Workspace,
5368        _: &ConfirmRename,
5369        cx: &mut ViewContext<Workspace>,
5370    ) -> Option<Task<Result<()>>> {
5371        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5372
5373        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5374            let rename = editor.take_rename(false, cx)?;
5375            let buffer = editor.buffer.read(cx);
5376            let (start_buffer, start) =
5377                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5378            let (end_buffer, end) =
5379                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5380            if start_buffer == end_buffer {
5381                let new_name = rename.editor.read(cx).text(cx);
5382                Some((start_buffer, start..end, rename.old_name, new_name))
5383            } else {
5384                None
5385            }
5386        })?;
5387
5388        let rename = workspace.project().clone().update(cx, |project, cx| {
5389            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5390        });
5391
5392        Some(cx.spawn(|workspace, mut cx| async move {
5393            let project_transaction = rename.await?;
5394            Self::open_project_transaction(
5395                editor.clone(),
5396                workspace,
5397                project_transaction,
5398                format!("Rename: {}{}", old_name, new_name),
5399                cx.clone(),
5400            )
5401            .await?;
5402
5403            editor.update(&mut cx, |editor, cx| {
5404                editor.refresh_document_highlights(cx);
5405            });
5406            Ok(())
5407        }))
5408    }
5409
5410    fn take_rename(
5411        &mut self,
5412        moving_cursor: bool,
5413        cx: &mut ViewContext<Self>,
5414    ) -> Option<RenameState> {
5415        let rename = self.pending_rename.take()?;
5416        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5417        self.clear_text_highlights::<Rename>(cx);
5418        self.show_local_selections = true;
5419
5420        if moving_cursor {
5421            let rename_editor = rename.editor.read(cx);
5422            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5423
5424            // Update the selection to match the position of the selection inside
5425            // the rename editor.
5426            let snapshot = self.buffer.read(cx).read(cx);
5427            let rename_range = rename.range.to_offset(&snapshot);
5428            let cursor_in_editor = snapshot
5429                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5430                .min(rename_range.end);
5431            drop(snapshot);
5432
5433            self.change_selections(None, cx, |s| {
5434                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5435            });
5436        } else {
5437            self.refresh_document_highlights(cx);
5438        }
5439
5440        Some(rename)
5441    }
5442
5443    #[cfg(any(test, feature = "test-support"))]
5444    pub fn pending_rename(&self) -> Option<&RenameState> {
5445        self.pending_rename.as_ref()
5446    }
5447
5448    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5449        let project = match &self.project {
5450            Some(project) => project.clone(),
5451            None => return None,
5452        };
5453
5454        Some(self.perform_format(project, cx))
5455    }
5456
5457    fn perform_format(
5458        &mut self,
5459        project: ModelHandle<Project>,
5460        cx: &mut ViewContext<'_, Self>,
5461    ) -> Task<Result<()>> {
5462        let buffer = self.buffer().clone();
5463        let buffers = buffer.read(cx).all_buffers();
5464
5465        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5466        let format = project.update(cx, |project, cx| {
5467            project.format(buffers, true, FormatTrigger::Manual, cx)
5468        });
5469
5470        cx.spawn(|_, mut cx| async move {
5471            let transaction = futures::select_biased! {
5472                _ = timeout => {
5473                    log::warn!("timed out waiting for formatting");
5474                    None
5475                }
5476                transaction = format.log_err().fuse() => transaction,
5477            };
5478
5479            buffer.update(&mut cx, |buffer, cx| {
5480                if let Some(transaction) = transaction {
5481                    if !buffer.is_singleton() {
5482                        buffer.push_transaction(&transaction.0);
5483                    }
5484                }
5485
5486                cx.notify();
5487            });
5488
5489            Ok(())
5490        })
5491    }
5492
5493    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5494        if let Some(project) = self.project.clone() {
5495            self.buffer.update(cx, |multi_buffer, cx| {
5496                project.update(cx, |project, cx| {
5497                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5498                });
5499            })
5500        }
5501    }
5502
5503    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5504        cx.show_character_palette();
5505    }
5506
5507    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5508        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5509            let buffer = self.buffer.read(cx).snapshot(cx);
5510            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5511            let is_valid = buffer
5512                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5513                .any(|entry| {
5514                    entry.diagnostic.is_primary
5515                        && !entry.range.is_empty()
5516                        && entry.range.start == primary_range_start
5517                        && entry.diagnostic.message == active_diagnostics.primary_message
5518                });
5519
5520            if is_valid != active_diagnostics.is_valid {
5521                active_diagnostics.is_valid = is_valid;
5522                let mut new_styles = HashMap::default();
5523                for (block_id, diagnostic) in &active_diagnostics.blocks {
5524                    new_styles.insert(
5525                        *block_id,
5526                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5527                    );
5528                }
5529                self.display_map
5530                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5531            }
5532        }
5533    }
5534
5535    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5536        self.dismiss_diagnostics(cx);
5537        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5538            let buffer = self.buffer.read(cx).snapshot(cx);
5539
5540            let mut primary_range = None;
5541            let mut primary_message = None;
5542            let mut group_end = Point::zero();
5543            let diagnostic_group = buffer
5544                .diagnostic_group::<Point>(group_id)
5545                .map(|entry| {
5546                    if entry.range.end > group_end {
5547                        group_end = entry.range.end;
5548                    }
5549                    if entry.diagnostic.is_primary {
5550                        primary_range = Some(entry.range.clone());
5551                        primary_message = Some(entry.diagnostic.message.clone());
5552                    }
5553                    entry
5554                })
5555                .collect::<Vec<_>>();
5556            let primary_range = primary_range?;
5557            let primary_message = primary_message?;
5558            let primary_range =
5559                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5560
5561            let blocks = display_map
5562                .insert_blocks(
5563                    diagnostic_group.iter().map(|entry| {
5564                        let diagnostic = entry.diagnostic.clone();
5565                        let message_height = diagnostic.message.lines().count() as u8;
5566                        BlockProperties {
5567                            style: BlockStyle::Fixed,
5568                            position: buffer.anchor_after(entry.range.start),
5569                            height: message_height,
5570                            render: diagnostic_block_renderer(diagnostic, true),
5571                            disposition: BlockDisposition::Below,
5572                        }
5573                    }),
5574                    cx,
5575                )
5576                .into_iter()
5577                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5578                .collect();
5579
5580            Some(ActiveDiagnosticGroup {
5581                primary_range,
5582                primary_message,
5583                blocks,
5584                is_valid: true,
5585            })
5586        });
5587        self.active_diagnostics.is_some()
5588    }
5589
5590    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5591        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5592            self.display_map.update(cx, |display_map, cx| {
5593                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5594            });
5595            cx.notify();
5596        }
5597    }
5598
5599    pub fn set_selections_from_remote(
5600        &mut self,
5601        selections: Vec<Selection<Anchor>>,
5602        pending_selection: Option<Selection<Anchor>>,
5603        cx: &mut ViewContext<Self>,
5604    ) {
5605        let old_cursor_position = self.selections.newest_anchor().head();
5606        self.selections.change_with(cx, |s| {
5607            s.select_anchors(selections);
5608            if let Some(pending_selection) = pending_selection {
5609                s.set_pending(pending_selection, SelectMode::Character);
5610            } else {
5611                s.clear_pending();
5612            }
5613        });
5614        self.selections_did_change(false, &old_cursor_position, cx);
5615    }
5616
5617    fn push_to_selection_history(&mut self) {
5618        self.selection_history.push(SelectionHistoryEntry {
5619            selections: self.selections.disjoint_anchors(),
5620            select_next_state: self.select_next_state.clone(),
5621            add_selections_state: self.add_selections_state.clone(),
5622        });
5623    }
5624
5625    pub fn transact(
5626        &mut self,
5627        cx: &mut ViewContext<Self>,
5628        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5629    ) -> Option<TransactionId> {
5630        self.start_transaction_at(Instant::now(), cx);
5631        update(self, cx);
5632        self.end_transaction_at(Instant::now(), cx)
5633    }
5634
5635    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5636        self.end_selection(cx);
5637        if let Some(tx_id) = self
5638            .buffer
5639            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5640        {
5641            self.selection_history
5642                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5643        }
5644    }
5645
5646    fn end_transaction_at(
5647        &mut self,
5648        now: Instant,
5649        cx: &mut ViewContext<Self>,
5650    ) -> Option<TransactionId> {
5651        if let Some(tx_id) = self
5652            .buffer
5653            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5654        {
5655            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5656                *end_selections = Some(self.selections.disjoint_anchors());
5657            } else {
5658                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5659            }
5660
5661            cx.emit(Event::Edited);
5662            Some(tx_id)
5663        } else {
5664            None
5665        }
5666    }
5667
5668    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5669        let mut fold_ranges = Vec::new();
5670
5671        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5672        let selections = self.selections.all::<Point>(cx);
5673        for selection in selections {
5674            let range = selection.display_range(&display_map).sorted();
5675            let buffer_start_row = range.start.to_point(&display_map).row;
5676
5677            for row in (0..=range.end.row()).rev() {
5678                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5679                    let fold_range = self.foldable_range_for_line(&display_map, row);
5680                    if fold_range.end.row >= buffer_start_row {
5681                        fold_ranges.push(fold_range);
5682                        if row <= range.start.row() {
5683                            break;
5684                        }
5685                    }
5686                }
5687            }
5688        }
5689
5690        self.fold_ranges(fold_ranges, cx);
5691    }
5692
5693    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5694        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5695        let buffer = &display_map.buffer_snapshot;
5696        let selections = self.selections.all::<Point>(cx);
5697        let ranges = selections
5698            .iter()
5699            .map(|s| {
5700                let range = s.display_range(&display_map).sorted();
5701                let mut start = range.start.to_point(&display_map);
5702                let mut end = range.end.to_point(&display_map);
5703                start.column = 0;
5704                end.column = buffer.line_len(end.row);
5705                start..end
5706            })
5707            .collect::<Vec<_>>();
5708        self.unfold_ranges(ranges, true, cx);
5709    }
5710
5711    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5712        let max_point = display_map.max_point();
5713        if display_row >= max_point.row() {
5714            false
5715        } else {
5716            let (start_indent, is_blank) = display_map.line_indent(display_row);
5717            if is_blank {
5718                false
5719            } else {
5720                for display_row in display_row + 1..=max_point.row() {
5721                    let (indent, is_blank) = display_map.line_indent(display_row);
5722                    if !is_blank {
5723                        return indent > start_indent;
5724                    }
5725                }
5726                false
5727            }
5728        }
5729    }
5730
5731    fn foldable_range_for_line(
5732        &self,
5733        display_map: &DisplaySnapshot,
5734        start_row: u32,
5735    ) -> Range<Point> {
5736        let max_point = display_map.max_point();
5737
5738        let (start_indent, _) = display_map.line_indent(start_row);
5739        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5740        let mut end = None;
5741        for row in start_row + 1..=max_point.row() {
5742            let (indent, is_blank) = display_map.line_indent(row);
5743            if !is_blank && indent <= start_indent {
5744                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5745                break;
5746            }
5747        }
5748
5749        let end = end.unwrap_or(max_point);
5750        start.to_point(display_map)..end.to_point(display_map)
5751    }
5752
5753    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5754        let selections = self.selections.all::<Point>(cx);
5755        let ranges = selections.into_iter().map(|s| s.start..s.end);
5756        self.fold_ranges(ranges, cx);
5757    }
5758
5759    pub fn fold_ranges<T: ToOffset>(
5760        &mut self,
5761        ranges: impl IntoIterator<Item = Range<T>>,
5762        cx: &mut ViewContext<Self>,
5763    ) {
5764        let mut ranges = ranges.into_iter().peekable();
5765        if ranges.peek().is_some() {
5766            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5767            self.request_autoscroll(Autoscroll::fit(), cx);
5768            cx.notify();
5769        }
5770    }
5771
5772    pub fn unfold_ranges<T: ToOffset>(
5773        &mut self,
5774        ranges: impl IntoIterator<Item = Range<T>>,
5775        inclusive: bool,
5776        cx: &mut ViewContext<Self>,
5777    ) {
5778        let mut ranges = ranges.into_iter().peekable();
5779        if ranges.peek().is_some() {
5780            self.display_map
5781                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5782            self.request_autoscroll(Autoscroll::fit(), cx);
5783            cx.notify();
5784        }
5785    }
5786
5787    pub fn insert_blocks(
5788        &mut self,
5789        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5790        cx: &mut ViewContext<Self>,
5791    ) -> Vec<BlockId> {
5792        let blocks = self
5793            .display_map
5794            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5795        self.request_autoscroll(Autoscroll::fit(), cx);
5796        blocks
5797    }
5798
5799    pub fn replace_blocks(
5800        &mut self,
5801        blocks: HashMap<BlockId, RenderBlock>,
5802        cx: &mut ViewContext<Self>,
5803    ) {
5804        self.display_map
5805            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5806        self.request_autoscroll(Autoscroll::fit(), cx);
5807    }
5808
5809    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5810        self.display_map.update(cx, |display_map, cx| {
5811            display_map.remove_blocks(block_ids, cx)
5812        });
5813    }
5814
5815    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5816        self.display_map
5817            .update(cx, |map, cx| map.snapshot(cx))
5818            .longest_row()
5819    }
5820
5821    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5822        self.display_map
5823            .update(cx, |map, cx| map.snapshot(cx))
5824            .max_point()
5825    }
5826
5827    pub fn text(&self, cx: &AppContext) -> String {
5828        self.buffer.read(cx).read(cx).text()
5829    }
5830
5831    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5832        self.transact(cx, |this, cx| {
5833            this.buffer
5834                .read(cx)
5835                .as_singleton()
5836                .expect("you can only call set_text on editors for singleton buffers")
5837                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5838        });
5839    }
5840
5841    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5842        self.display_map
5843            .update(cx, |map, cx| map.snapshot(cx))
5844            .text()
5845    }
5846
5847    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5848        let language_name = self
5849            .buffer
5850            .read(cx)
5851            .as_singleton()
5852            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5853            .map(|l| l.name());
5854
5855        let settings = cx.global::<Settings>();
5856        let mode = self
5857            .soft_wrap_mode_override
5858            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5859        match mode {
5860            settings::SoftWrap::None => SoftWrap::None,
5861            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5862            settings::SoftWrap::PreferredLineLength => {
5863                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5864            }
5865        }
5866    }
5867
5868    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5869        self.soft_wrap_mode_override = Some(mode);
5870        cx.notify();
5871    }
5872
5873    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5874        self.display_map
5875            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5876    }
5877
5878    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
5879        if self.soft_wrap_mode_override.is_some() {
5880            self.soft_wrap_mode_override.take();
5881        } else {
5882            let soft_wrap = match self.soft_wrap_mode(cx) {
5883                SoftWrap::None => settings::SoftWrap::EditorWidth,
5884                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
5885            };
5886            self.soft_wrap_mode_override = Some(soft_wrap);
5887        }
5888        cx.notify();
5889    }
5890
5891    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5892        self.highlighted_rows = rows;
5893    }
5894
5895    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5896        self.highlighted_rows.clone()
5897    }
5898
5899    pub fn highlight_background<T: 'static>(
5900        &mut self,
5901        ranges: Vec<Range<Anchor>>,
5902        color_fetcher: fn(&Theme) -> Color,
5903        cx: &mut ViewContext<Self>,
5904    ) {
5905        self.background_highlights
5906            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5907        cx.notify();
5908    }
5909
5910    #[allow(clippy::type_complexity)]
5911    pub fn clear_background_highlights<T: 'static>(
5912        &mut self,
5913        cx: &mut ViewContext<Self>,
5914    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5915        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
5916        if highlights.is_some() {
5917            cx.notify();
5918        }
5919        highlights
5920    }
5921
5922    #[cfg(feature = "test-support")]
5923    pub fn all_background_highlights(
5924        &mut self,
5925        cx: &mut ViewContext<Self>,
5926    ) -> Vec<(Range<DisplayPoint>, Color)> {
5927        let snapshot = self.snapshot(cx);
5928        let buffer = &snapshot.buffer_snapshot;
5929        let start = buffer.anchor_before(0);
5930        let end = buffer.anchor_after(buffer.len());
5931        let theme = cx.global::<Settings>().theme.as_ref();
5932        self.background_highlights_in_range(start..end, &snapshot, theme)
5933    }
5934
5935    fn document_highlights_for_position<'a>(
5936        &'a self,
5937        position: Anchor,
5938        buffer: &'a MultiBufferSnapshot,
5939    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5940        let read_highlights = self
5941            .background_highlights
5942            .get(&TypeId::of::<DocumentHighlightRead>())
5943            .map(|h| &h.1);
5944        let write_highlights = self
5945            .background_highlights
5946            .get(&TypeId::of::<DocumentHighlightWrite>())
5947            .map(|h| &h.1);
5948        let left_position = position.bias_left(buffer);
5949        let right_position = position.bias_right(buffer);
5950        read_highlights
5951            .into_iter()
5952            .chain(write_highlights)
5953            .flat_map(move |ranges| {
5954                let start_ix = match ranges.binary_search_by(|probe| {
5955                    let cmp = probe.end.cmp(&left_position, buffer);
5956                    if cmp.is_ge() {
5957                        Ordering::Greater
5958                    } else {
5959                        Ordering::Less
5960                    }
5961                }) {
5962                    Ok(i) | Err(i) => i,
5963                };
5964
5965                let right_position = right_position.clone();
5966                ranges[start_ix..]
5967                    .iter()
5968                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5969            })
5970    }
5971
5972    pub fn background_highlights_in_range(
5973        &self,
5974        search_range: Range<Anchor>,
5975        display_snapshot: &DisplaySnapshot,
5976        theme: &Theme,
5977    ) -> Vec<(Range<DisplayPoint>, Color)> {
5978        let mut results = Vec::new();
5979        let buffer = &display_snapshot.buffer_snapshot;
5980        for (color_fetcher, ranges) in self.background_highlights.values() {
5981            let color = color_fetcher(theme);
5982            let start_ix = match ranges.binary_search_by(|probe| {
5983                let cmp = probe.end.cmp(&search_range.start, buffer);
5984                if cmp.is_gt() {
5985                    Ordering::Greater
5986                } else {
5987                    Ordering::Less
5988                }
5989            }) {
5990                Ok(i) | Err(i) => i,
5991            };
5992            for range in &ranges[start_ix..] {
5993                if range.start.cmp(&search_range.end, buffer).is_ge() {
5994                    break;
5995                }
5996                let start = range
5997                    .start
5998                    .to_point(buffer)
5999                    .to_display_point(display_snapshot);
6000                let end = range
6001                    .end
6002                    .to_point(buffer)
6003                    .to_display_point(display_snapshot);
6004                results.push((start..end, color))
6005            }
6006        }
6007        results
6008    }
6009
6010    pub fn highlight_text<T: 'static>(
6011        &mut self,
6012        ranges: Vec<Range<Anchor>>,
6013        style: HighlightStyle,
6014        cx: &mut ViewContext<Self>,
6015    ) {
6016        self.display_map.update(cx, |map, _| {
6017            map.highlight_text(TypeId::of::<T>(), ranges, style)
6018        });
6019        cx.notify();
6020    }
6021
6022    pub fn text_highlights<'a, T: 'static>(
6023        &'a self,
6024        cx: &'a AppContext,
6025    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6026        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6027    }
6028
6029    pub fn clear_text_highlights<T: 'static>(
6030        &mut self,
6031        cx: &mut ViewContext<Self>,
6032    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6033        let highlights = self
6034            .display_map
6035            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6036        if highlights.is_some() {
6037            cx.notify();
6038        }
6039        highlights
6040    }
6041
6042    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6043        self.blink_manager.read(cx).visible() && self.focused
6044    }
6045
6046    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6047        cx.notify();
6048    }
6049
6050    fn on_buffer_event(
6051        &mut self,
6052        _: ModelHandle<MultiBuffer>,
6053        event: &multi_buffer::Event,
6054        cx: &mut ViewContext<Self>,
6055    ) {
6056        match event {
6057            multi_buffer::Event::Edited => {
6058                self.refresh_active_diagnostics(cx);
6059                self.refresh_code_actions(cx);
6060                cx.emit(Event::BufferEdited);
6061            }
6062            multi_buffer::Event::ExcerptsAdded {
6063                buffer,
6064                predecessor,
6065                excerpts,
6066            } => cx.emit(Event::ExcerptsAdded {
6067                buffer: buffer.clone(),
6068                predecessor: *predecessor,
6069                excerpts: excerpts.clone(),
6070            }),
6071            multi_buffer::Event::ExcerptsRemoved { ids } => {
6072                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6073            }
6074            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6075            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6076            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6077            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6078            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6079            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6080            multi_buffer::Event::DiagnosticsUpdated => {
6081                self.refresh_active_diagnostics(cx);
6082            }
6083        }
6084    }
6085
6086    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6087        cx.notify();
6088    }
6089
6090    pub fn set_searchable(&mut self, searchable: bool) {
6091        self.searchable = searchable;
6092    }
6093
6094    pub fn searchable(&self) -> bool {
6095        self.searchable
6096    }
6097
6098    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6099        let active_item = workspace.active_item(cx);
6100        let editor_handle = if let Some(editor) = active_item
6101            .as_ref()
6102            .and_then(|item| item.act_as::<Self>(cx))
6103        {
6104            editor
6105        } else {
6106            cx.propagate_action();
6107            return;
6108        };
6109
6110        let editor = editor_handle.read(cx);
6111        let buffer = editor.buffer.read(cx);
6112        if buffer.is_singleton() {
6113            cx.propagate_action();
6114            return;
6115        }
6116
6117        let mut new_selections_by_buffer = HashMap::default();
6118        for selection in editor.selections.all::<usize>(cx) {
6119            for (buffer, mut range) in
6120                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6121            {
6122                if selection.reversed {
6123                    mem::swap(&mut range.start, &mut range.end);
6124                }
6125                new_selections_by_buffer
6126                    .entry(buffer)
6127                    .or_insert(Vec::new())
6128                    .push(range)
6129            }
6130        }
6131
6132        editor_handle.update(cx, |editor, cx| {
6133            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6134        });
6135        let pane = workspace.active_pane().clone();
6136        pane.update(cx, |pane, _| pane.disable_history());
6137
6138        // We defer the pane interaction because we ourselves are a workspace item
6139        // and activating a new item causes the pane to call a method on us reentrantly,
6140        // which panics if we're on the stack.
6141        cx.defer(move |workspace, cx| {
6142            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6143                let editor = workspace.open_project_item::<Self>(buffer, cx);
6144                editor.update(cx, |editor, cx| {
6145                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6146                        s.select_ranges(ranges);
6147                    });
6148                });
6149            }
6150
6151            pane.update(cx, |pane, _| pane.enable_history());
6152        });
6153    }
6154
6155    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6156        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6157        let position = action.position;
6158        let anchor = action.anchor;
6159        cx.spawn_weak(|_, mut cx| async move {
6160            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6161            editor.update(&mut cx, |editor, cx| {
6162                let buffer = editor.buffer().read(cx).as_singleton()?;
6163                let buffer = buffer.read(cx);
6164                let cursor = if buffer.can_resolve(&anchor) {
6165                    language::ToPoint::to_point(&anchor, buffer)
6166                } else {
6167                    buffer.clip_point(position, Bias::Left)
6168                };
6169
6170                let nav_history = editor.nav_history.take();
6171                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6172                    s.select_ranges([cursor..cursor]);
6173                });
6174                editor.nav_history = nav_history;
6175
6176                Some(())
6177            })?;
6178            Some(())
6179        })
6180        .detach()
6181    }
6182
6183    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6184        let snapshot = self.buffer.read(cx).read(cx);
6185        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6186        Some(
6187            ranges
6188                .iter()
6189                .map(move |range| {
6190                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6191                })
6192                .collect(),
6193        )
6194    }
6195
6196    fn selection_replacement_ranges(
6197        &self,
6198        range: Range<OffsetUtf16>,
6199        cx: &AppContext,
6200    ) -> Vec<Range<OffsetUtf16>> {
6201        let selections = self.selections.all::<OffsetUtf16>(cx);
6202        let newest_selection = selections
6203            .iter()
6204            .max_by_key(|selection| selection.id)
6205            .unwrap();
6206        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6207        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6208        let snapshot = self.buffer.read(cx).read(cx);
6209        selections
6210            .into_iter()
6211            .map(|mut selection| {
6212                selection.start.0 =
6213                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6214                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6215                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6216                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6217            })
6218            .collect()
6219    }
6220
6221    fn report_event(&self, name: &str, cx: &AppContext) {
6222        if let Some((project, file)) = self.project.as_ref().zip(
6223            self.buffer
6224                .read(cx)
6225                .as_singleton()
6226                .and_then(|b| b.read(cx).file()),
6227        ) {
6228            let extension = Path::new(file.file_name(cx))
6229                .extension()
6230                .and_then(|e| e.to_str());
6231            project.read(cx).client().report_event(
6232                name,
6233                json!({ "File Extension": extension }),
6234                cx.global::<Settings>().telemetry(),
6235            );
6236        }
6237    }
6238}
6239
6240impl EditorSnapshot {
6241    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6242        self.display_snapshot.buffer_snapshot.language_at(position)
6243    }
6244
6245    pub fn is_focused(&self) -> bool {
6246        self.is_focused
6247    }
6248
6249    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6250        self.placeholder_text.as_ref()
6251    }
6252
6253    pub fn scroll_position(&self) -> Vector2F {
6254        self.scroll_anchor.scroll_position(&self.display_snapshot)
6255    }
6256}
6257
6258impl Deref for EditorSnapshot {
6259    type Target = DisplaySnapshot;
6260
6261    fn deref(&self) -> &Self::Target {
6262        &self.display_snapshot
6263    }
6264}
6265
6266#[derive(Clone, Debug, PartialEq, Eq)]
6267pub enum Event {
6268    InputIgnored {
6269        text: Arc<str>,
6270    },
6271    ExcerptsAdded {
6272        buffer: ModelHandle<Buffer>,
6273        predecessor: ExcerptId,
6274        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6275    },
6276    ExcerptsRemoved {
6277        ids: Vec<ExcerptId>,
6278    },
6279    BufferEdited,
6280    Edited,
6281    Reparsed,
6282    Blurred,
6283    DirtyChanged,
6284    Saved,
6285    TitleChanged,
6286    SelectionsChanged {
6287        local: bool,
6288    },
6289    ScrollPositionChanged {
6290        local: bool,
6291    },
6292    Closed,
6293}
6294
6295pub struct EditorFocused(pub ViewHandle<Editor>);
6296pub struct EditorBlurred(pub ViewHandle<Editor>);
6297pub struct EditorReleased(pub WeakViewHandle<Editor>);
6298
6299impl Entity for Editor {
6300    type Event = Event;
6301
6302    fn release(&mut self, cx: &mut MutableAppContext) {
6303        cx.emit_global(EditorReleased(self.handle.clone()));
6304    }
6305}
6306
6307impl View for Editor {
6308    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6309        let style = self.style(cx);
6310        let font_changed = self.display_map.update(cx, |map, cx| {
6311            map.set_font(style.text.font_id, style.text.font_size, cx)
6312        });
6313
6314        if font_changed {
6315            let handle = self.handle.clone();
6316            cx.defer(move |cx| {
6317                if let Some(editor) = handle.upgrade(cx) {
6318                    editor.update(cx, |editor, cx| {
6319                        hide_hover(editor, &HideHover, cx);
6320                        hide_link_definition(editor, cx);
6321                    })
6322                }
6323            });
6324        }
6325
6326        Stack::new()
6327            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6328            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6329            .boxed()
6330    }
6331
6332    fn ui_name() -> &'static str {
6333        "Editor"
6334    }
6335
6336    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6337        if cx.is_self_focused() {
6338            let focused_event = EditorFocused(cx.handle());
6339            cx.emit_global(focused_event);
6340        }
6341        if let Some(rename) = self.pending_rename.as_ref() {
6342            cx.focus(&rename.editor);
6343        } else {
6344            if !self.focused {
6345                self.blink_manager.update(cx, BlinkManager::enable);
6346            }
6347            self.focused = true;
6348            self.buffer.update(cx, |buffer, cx| {
6349                buffer.finalize_last_transaction(cx);
6350                if self.leader_replica_id.is_none() {
6351                    buffer.set_active_selections(
6352                        &self.selections.disjoint_anchors(),
6353                        self.selections.line_mode,
6354                        self.cursor_shape,
6355                        cx,
6356                    );
6357                }
6358            });
6359        }
6360    }
6361
6362    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6363        let blurred_event = EditorBlurred(cx.handle());
6364        cx.emit_global(blurred_event);
6365        self.focused = false;
6366        self.blink_manager.update(cx, BlinkManager::disable);
6367        self.buffer
6368            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6369        self.hide_context_menu(cx);
6370        hide_hover(self, &HideHover, cx);
6371        cx.emit(Event::Blurred);
6372        cx.notify();
6373    }
6374
6375    fn modifiers_changed(
6376        &mut self,
6377        event: &gpui::ModifiersChangedEvent,
6378        cx: &mut ViewContext<Self>,
6379    ) -> bool {
6380        let pending_selection = self.has_pending_selection();
6381
6382        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6383            if event.cmd && !pending_selection {
6384                let snapshot = self.snapshot(cx);
6385                let kind = if event.shift {
6386                    LinkDefinitionKind::Type
6387                } else {
6388                    LinkDefinitionKind::Symbol
6389                };
6390
6391                show_link_definition(kind, self, point, snapshot, cx);
6392                return false;
6393            }
6394        }
6395
6396        {
6397            if self.link_go_to_definition_state.symbol_range.is_some()
6398                || !self.link_go_to_definition_state.definitions.is_empty()
6399            {
6400                self.link_go_to_definition_state.symbol_range.take();
6401                self.link_go_to_definition_state.definitions.clear();
6402                cx.notify();
6403            }
6404
6405            self.link_go_to_definition_state.task = None;
6406
6407            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6408        }
6409
6410        false
6411    }
6412
6413    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6414        let mut context = Self::default_keymap_context();
6415        let mode = match self.mode {
6416            EditorMode::SingleLine => "single_line",
6417            EditorMode::AutoHeight { .. } => "auto_height",
6418            EditorMode::Full => "full",
6419        };
6420        context.map.insert("mode".into(), mode.into());
6421        if self.pending_rename.is_some() {
6422            context.set.insert("renaming".into());
6423        }
6424        match self.context_menu.as_ref() {
6425            Some(ContextMenu::Completions(_)) => {
6426                context.set.insert("showing_completions".into());
6427            }
6428            Some(ContextMenu::CodeActions(_)) => {
6429                context.set.insert("showing_code_actions".into());
6430            }
6431            None => {}
6432        }
6433
6434        for layer in self.keymap_context_layers.values() {
6435            context.extend(layer);
6436        }
6437
6438        context
6439    }
6440
6441    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6442        Some(
6443            self.buffer
6444                .read(cx)
6445                .read(cx)
6446                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6447                .collect(),
6448        )
6449    }
6450
6451    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6452        // Prevent the IME menu from appearing when holding down an alphabetic key
6453        // while input is disabled.
6454        if !self.input_enabled {
6455            return None;
6456        }
6457
6458        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6459        Some(range.start.0..range.end.0)
6460    }
6461
6462    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6463        let snapshot = self.buffer.read(cx).read(cx);
6464        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6465        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6466    }
6467
6468    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6469        self.clear_text_highlights::<InputComposition>(cx);
6470        self.ime_transaction.take();
6471    }
6472
6473    fn replace_text_in_range(
6474        &mut self,
6475        range_utf16: Option<Range<usize>>,
6476        text: &str,
6477        cx: &mut ViewContext<Self>,
6478    ) {
6479        self.transact(cx, |this, cx| {
6480            if this.input_enabled {
6481                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6482                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6483                    Some(this.selection_replacement_ranges(range_utf16, cx))
6484                } else {
6485                    this.marked_text_ranges(cx)
6486                };
6487
6488                if let Some(new_selected_ranges) = new_selected_ranges {
6489                    this.change_selections(None, cx, |selections| {
6490                        selections.select_ranges(new_selected_ranges)
6491                    });
6492                }
6493            }
6494
6495            this.handle_input(text, cx);
6496        });
6497
6498        if !self.input_enabled {
6499            return;
6500        }
6501
6502        if let Some(transaction) = self.ime_transaction {
6503            self.buffer.update(cx, |buffer, cx| {
6504                buffer.group_until_transaction(transaction, cx);
6505            });
6506        }
6507
6508        self.unmark_text(cx);
6509    }
6510
6511    fn replace_and_mark_text_in_range(
6512        &mut self,
6513        range_utf16: Option<Range<usize>>,
6514        text: &str,
6515        new_selected_range_utf16: Option<Range<usize>>,
6516        cx: &mut ViewContext<Self>,
6517    ) {
6518        if !self.input_enabled {
6519            return;
6520        }
6521
6522        let transaction = self.transact(cx, |this, cx| {
6523            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6524                let snapshot = this.buffer.read(cx).read(cx);
6525                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6526                    for marked_range in &mut marked_ranges {
6527                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6528                        marked_range.start.0 += relative_range_utf16.start;
6529                        marked_range.start =
6530                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6531                        marked_range.end =
6532                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6533                    }
6534                }
6535                Some(marked_ranges)
6536            } else if let Some(range_utf16) = range_utf16 {
6537                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6538                Some(this.selection_replacement_ranges(range_utf16, cx))
6539            } else {
6540                None
6541            };
6542
6543            if let Some(ranges) = ranges_to_replace {
6544                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6545            }
6546
6547            let marked_ranges = {
6548                let snapshot = this.buffer.read(cx).read(cx);
6549                this.selections
6550                    .disjoint_anchors()
6551                    .iter()
6552                    .map(|selection| {
6553                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6554                    })
6555                    .collect::<Vec<_>>()
6556            };
6557
6558            if text.is_empty() {
6559                this.unmark_text(cx);
6560            } else {
6561                this.highlight_text::<InputComposition>(
6562                    marked_ranges.clone(),
6563                    this.style(cx).composition_mark,
6564                    cx,
6565                );
6566            }
6567
6568            this.handle_input(text, cx);
6569
6570            if let Some(new_selected_range) = new_selected_range_utf16 {
6571                let snapshot = this.buffer.read(cx).read(cx);
6572                let new_selected_ranges = marked_ranges
6573                    .into_iter()
6574                    .map(|marked_range| {
6575                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6576                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6577                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6578                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6579                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6580                    })
6581                    .collect::<Vec<_>>();
6582
6583                drop(snapshot);
6584                this.change_selections(None, cx, |selections| {
6585                    selections.select_ranges(new_selected_ranges)
6586                });
6587            }
6588        });
6589
6590        self.ime_transaction = self.ime_transaction.or(transaction);
6591        if let Some(transaction) = self.ime_transaction {
6592            self.buffer.update(cx, |buffer, cx| {
6593                buffer.group_until_transaction(transaction, cx);
6594            });
6595        }
6596
6597        if self.text_highlights::<InputComposition>(cx).is_none() {
6598            self.ime_transaction.take();
6599        }
6600    }
6601}
6602
6603fn build_style(
6604    settings: &Settings,
6605    get_field_editor_theme: Option<&GetFieldEditorTheme>,
6606    override_text_style: Option<&OverrideTextStyle>,
6607    cx: &AppContext,
6608) -> EditorStyle {
6609    let font_cache = cx.font_cache();
6610
6611    let mut theme = settings.theme.editor.clone();
6612    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6613        let field_editor_theme = get_field_editor_theme(&settings.theme);
6614        theme.text_color = field_editor_theme.text.color;
6615        theme.selection = field_editor_theme.selection;
6616        theme.background = field_editor_theme
6617            .container
6618            .background_color
6619            .unwrap_or_default();
6620        EditorStyle {
6621            text: field_editor_theme.text,
6622            placeholder_text: field_editor_theme.placeholder_text,
6623            theme,
6624        }
6625    } else {
6626        let font_family_id = settings.buffer_font_family;
6627        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6628        let font_properties = Default::default();
6629        let font_id = font_cache
6630            .select_font(font_family_id, &font_properties)
6631            .unwrap();
6632        let font_size = settings.buffer_font_size;
6633        EditorStyle {
6634            text: TextStyle {
6635                color: settings.theme.editor.text_color,
6636                font_family_name,
6637                font_family_id,
6638                font_id,
6639                font_size,
6640                font_properties,
6641                underline: Default::default(),
6642            },
6643            placeholder_text: None,
6644            theme,
6645        }
6646    };
6647
6648    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6649        if let Some(highlighted) = style
6650            .text
6651            .clone()
6652            .highlight(highlight_style, font_cache)
6653            .log_err()
6654        {
6655            style.text = highlighted;
6656        }
6657    }
6658
6659    style
6660}
6661
6662trait SelectionExt {
6663    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6664    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6665    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6666    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6667        -> Range<u32>;
6668}
6669
6670impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6671    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6672        let start = self.start.to_point(buffer);
6673        let end = self.end.to_point(buffer);
6674        if self.reversed {
6675            end..start
6676        } else {
6677            start..end
6678        }
6679    }
6680
6681    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6682        let start = self.start.to_offset(buffer);
6683        let end = self.end.to_offset(buffer);
6684        if self.reversed {
6685            end..start
6686        } else {
6687            start..end
6688        }
6689    }
6690
6691    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6692        let start = self
6693            .start
6694            .to_point(&map.buffer_snapshot)
6695            .to_display_point(map);
6696        let end = self
6697            .end
6698            .to_point(&map.buffer_snapshot)
6699            .to_display_point(map);
6700        if self.reversed {
6701            end..start
6702        } else {
6703            start..end
6704        }
6705    }
6706
6707    fn spanned_rows(
6708        &self,
6709        include_end_if_at_line_start: bool,
6710        map: &DisplaySnapshot,
6711    ) -> Range<u32> {
6712        let start = self.start.to_point(&map.buffer_snapshot);
6713        let mut end = self.end.to_point(&map.buffer_snapshot);
6714        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6715            end.row -= 1;
6716        }
6717
6718        let buffer_start = map.prev_line_boundary(start).0;
6719        let buffer_end = map.next_line_boundary(end).0;
6720        buffer_start.row..buffer_end.row + 1
6721    }
6722}
6723
6724impl<T: InvalidationRegion> InvalidationStack<T> {
6725    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6726    where
6727        S: Clone + ToOffset,
6728    {
6729        while let Some(region) = self.last() {
6730            let all_selections_inside_invalidation_ranges =
6731                if selections.len() == region.ranges().len() {
6732                    selections
6733                        .iter()
6734                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6735                        .all(|(selection, invalidation_range)| {
6736                            let head = selection.head().to_offset(buffer);
6737                            invalidation_range.start <= head && invalidation_range.end >= head
6738                        })
6739                } else {
6740                    false
6741                };
6742
6743            if all_selections_inside_invalidation_ranges {
6744                break;
6745            } else {
6746                self.pop();
6747            }
6748        }
6749    }
6750}
6751
6752impl<T> Default for InvalidationStack<T> {
6753    fn default() -> Self {
6754        Self(Default::default())
6755    }
6756}
6757
6758impl<T> Deref for InvalidationStack<T> {
6759    type Target = Vec<T>;
6760
6761    fn deref(&self) -> &Self::Target {
6762        &self.0
6763    }
6764}
6765
6766impl<T> DerefMut for InvalidationStack<T> {
6767    fn deref_mut(&mut self) -> &mut Self::Target {
6768        &mut self.0
6769    }
6770}
6771
6772impl InvalidationRegion for SnippetState {
6773    fn ranges(&self) -> &[Range<Anchor>] {
6774        &self.ranges[self.active_index]
6775    }
6776}
6777
6778impl Deref for EditorStyle {
6779    type Target = theme::Editor;
6780
6781    fn deref(&self) -> &Self::Target {
6782        &self.theme
6783    }
6784}
6785
6786pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6787    let mut highlighted_lines = Vec::new();
6788    for line in diagnostic.message.lines() {
6789        highlighted_lines.push(highlight_diagnostic_message(line));
6790    }
6791
6792    Arc::new(move |cx: &mut BlockContext| {
6793        let settings = cx.global::<Settings>();
6794        let theme = &settings.theme.editor;
6795        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6796        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6797        Flex::column()
6798            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6799                Label::new(
6800                    line.clone(),
6801                    style.message.clone().with_font_size(font_size),
6802                )
6803                .with_highlights(highlights.clone())
6804                .contained()
6805                .with_margin_left(cx.anchor_x)
6806                .boxed()
6807            }))
6808            .aligned()
6809            .left()
6810            .boxed()
6811    })
6812}
6813
6814pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6815    let mut message_without_backticks = String::new();
6816    let mut prev_offset = 0;
6817    let mut inside_block = false;
6818    let mut highlights = Vec::new();
6819    for (match_ix, (offset, _)) in message
6820        .match_indices('`')
6821        .chain([(message.len(), "")])
6822        .enumerate()
6823    {
6824        message_without_backticks.push_str(&message[prev_offset..offset]);
6825        if inside_block {
6826            highlights.extend(prev_offset - match_ix..offset - match_ix);
6827        }
6828
6829        inside_block = !inside_block;
6830        prev_offset = offset + 1;
6831    }
6832
6833    (message_without_backticks, highlights)
6834}
6835
6836pub fn diagnostic_style(
6837    severity: DiagnosticSeverity,
6838    valid: bool,
6839    theme: &theme::Editor,
6840) -> DiagnosticStyle {
6841    match (severity, valid) {
6842        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6843        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6844        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6845        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6846        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6847        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6848        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6849        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6850        _ => theme.invalid_hint_diagnostic.clone(),
6851    }
6852}
6853
6854pub fn combine_syntax_and_fuzzy_match_highlights(
6855    text: &str,
6856    default_style: HighlightStyle,
6857    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6858    match_indices: &[usize],
6859) -> Vec<(Range<usize>, HighlightStyle)> {
6860    let mut result = Vec::new();
6861    let mut match_indices = match_indices.iter().copied().peekable();
6862
6863    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6864    {
6865        syntax_highlight.weight = None;
6866
6867        // Add highlights for any fuzzy match characters before the next
6868        // syntax highlight range.
6869        while let Some(&match_index) = match_indices.peek() {
6870            if match_index >= range.start {
6871                break;
6872            }
6873            match_indices.next();
6874            let end_index = char_ix_after(match_index, text);
6875            let mut match_style = default_style;
6876            match_style.weight = Some(fonts::Weight::BOLD);
6877            result.push((match_index..end_index, match_style));
6878        }
6879
6880        if range.start == usize::MAX {
6881            break;
6882        }
6883
6884        // Add highlights for any fuzzy match characters within the
6885        // syntax highlight range.
6886        let mut offset = range.start;
6887        while let Some(&match_index) = match_indices.peek() {
6888            if match_index >= range.end {
6889                break;
6890            }
6891
6892            match_indices.next();
6893            if match_index > offset {
6894                result.push((offset..match_index, syntax_highlight));
6895            }
6896
6897            let mut end_index = char_ix_after(match_index, text);
6898            while let Some(&next_match_index) = match_indices.peek() {
6899                if next_match_index == end_index && next_match_index < range.end {
6900                    end_index = char_ix_after(next_match_index, text);
6901                    match_indices.next();
6902                } else {
6903                    break;
6904                }
6905            }
6906
6907            let mut match_style = syntax_highlight;
6908            match_style.weight = Some(fonts::Weight::BOLD);
6909            result.push((match_index..end_index, match_style));
6910            offset = end_index;
6911        }
6912
6913        if offset < range.end {
6914            result.push((offset..range.end, syntax_highlight));
6915        }
6916    }
6917
6918    fn char_ix_after(ix: usize, text: &str) -> usize {
6919        ix + text[ix..].chars().next().unwrap().len_utf8()
6920    }
6921
6922    result
6923}
6924
6925pub fn styled_runs_for_code_label<'a>(
6926    label: &'a CodeLabel,
6927    syntax_theme: &'a theme::SyntaxTheme,
6928) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6929    let fade_out = HighlightStyle {
6930        fade_out: Some(0.35),
6931        ..Default::default()
6932    };
6933
6934    let mut prev_end = label.filter_range.end;
6935    label
6936        .runs
6937        .iter()
6938        .enumerate()
6939        .flat_map(move |(ix, (range, highlight_id))| {
6940            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6941                style
6942            } else {
6943                return Default::default();
6944            };
6945            let mut muted_style = style;
6946            muted_style.highlight(fade_out);
6947
6948            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6949            if range.start >= label.filter_range.end {
6950                if range.start > prev_end {
6951                    runs.push((prev_end..range.start, fade_out));
6952                }
6953                runs.push((range.clone(), muted_style));
6954            } else if range.end <= label.filter_range.end {
6955                runs.push((range.clone(), style));
6956            } else {
6957                runs.push((range.start..label.filter_range.end, style));
6958                runs.push((label.filter_range.end..range.end, muted_style));
6959            }
6960            prev_end = cmp::max(prev_end, range.end);
6961
6962            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6963                runs.push((prev_end..label.text.len(), fade_out));
6964            }
6965
6966            runs
6967        })
6968}
6969
6970pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
6971    let mut index = 0;
6972    let mut codepoints = text.char_indices().peekable();
6973
6974    std::iter::from_fn(move || {
6975        let start_index = index;
6976        while let Some((new_index, codepoint)) = codepoints.next() {
6977            index = new_index + codepoint.len_utf8();
6978            let current_upper = codepoint.is_uppercase();
6979            let next_upper = codepoints
6980                .peek()
6981                .map(|(_, c)| c.is_uppercase())
6982                .unwrap_or(false);
6983
6984            if !current_upper && next_upper {
6985                return Some(&text[start_index..index]);
6986            }
6987        }
6988
6989        index = text.len();
6990        if start_index < text.len() {
6991            return Some(&text[start_index..]);
6992        }
6993        None
6994    })
6995    .flat_map(|word| word.split_inclusive('_'))
6996}
6997
6998trait RangeToAnchorExt {
6999    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7000}
7001
7002impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7003    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7004        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7005    }
7006}