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, RangeInclusive},
  81    path::Path,
  82    sync::Arc,
  83    time::{Duration, Instant},
  84};
  85pub use sum_tree::Bias;
  86use theme::{DiagnosticStyle, Theme};
  87use util::{post_inc, 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 { return; };
4794                
4795                let mut best_length = usize::MAX;
4796                let mut best_inside = false;
4797                let mut best_in_bracket_range = false;
4798                let mut best_destination = None;
4799                for (open, close) in enclosing_bracket_ranges {
4800                    let close = close.to_inclusive();
4801                    let length = close.end() - open.start;
4802                    let inside = selection.start >= open.end && selection.end <= *close.start();
4803                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
4804                    
4805                    // If best is next to a bracket and current isn't, skip
4806                    if !in_bracket_range && best_in_bracket_range {
4807                        continue;
4808                    }
4809                    
4810                    // Prefer smaller lengths unless best is inside and current isn't
4811                    if length > best_length && (best_inside || !inside) {
4812                        continue;
4813                    }
4814                    
4815                    best_length = length;
4816                    best_inside = inside;
4817                    best_in_bracket_range = in_bracket_range;
4818                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
4819                        if inside {
4820                            open.end
4821                        } else {
4822                            open.start
4823                        }
4824                    } else {
4825                        if inside {
4826                            *close.start()
4827                        } else {
4828                            *close.end()
4829                        }
4830                    });
4831                }
4832                
4833                if let Some(destination) = best_destination {
4834                    selection.collapse_to(destination, SelectionGoal::None);
4835                }
4836            })
4837        });
4838    }
4839
4840    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4841        self.end_selection(cx);
4842        self.selection_history.mode = SelectionHistoryMode::Undoing;
4843        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4844            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4845            self.select_next_state = entry.select_next_state;
4846            self.add_selections_state = entry.add_selections_state;
4847            self.request_autoscroll(Autoscroll::newest(), cx);
4848        }
4849        self.selection_history.mode = SelectionHistoryMode::Normal;
4850    }
4851
4852    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4853        self.end_selection(cx);
4854        self.selection_history.mode = SelectionHistoryMode::Redoing;
4855        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4856            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4857            self.select_next_state = entry.select_next_state;
4858            self.add_selections_state = entry.add_selections_state;
4859            self.request_autoscroll(Autoscroll::newest(), cx);
4860        }
4861        self.selection_history.mode = SelectionHistoryMode::Normal;
4862    }
4863
4864    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
4865        self.go_to_diagnostic_impl(Direction::Next, cx)
4866    }
4867
4868    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4869        self.go_to_diagnostic_impl(Direction::Prev, cx)
4870    }
4871
4872    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4873        let buffer = self.buffer.read(cx).snapshot(cx);
4874        let selection = self.selections.newest::<usize>(cx);
4875
4876        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
4877        if direction == Direction::Next {
4878            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
4879                let (group_id, jump_to) = popover.activation_info();
4880                if self.activate_diagnostics(group_id, cx) {
4881                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4882                        let mut new_selection = s.newest_anchor().clone();
4883                        new_selection.collapse_to(jump_to, SelectionGoal::None);
4884                        s.select_anchors(vec![new_selection.clone()]);
4885                    });
4886                }
4887                return;
4888            }
4889        }
4890
4891        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4892            active_diagnostics
4893                .primary_range
4894                .to_offset(&buffer)
4895                .to_inclusive()
4896        });
4897        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4898            if active_primary_range.contains(&selection.head()) {
4899                *active_primary_range.end()
4900            } else {
4901                selection.head()
4902            }
4903        } else {
4904            selection.head()
4905        };
4906
4907        loop {
4908            let mut diagnostics = if direction == Direction::Prev {
4909                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4910            } else {
4911                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4912            };
4913            let group = diagnostics.find_map(|entry| {
4914                if entry.diagnostic.is_primary
4915                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4916                    && !entry.range.is_empty()
4917                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4918                {
4919                    Some((entry.range, entry.diagnostic.group_id))
4920                } else {
4921                    None
4922                }
4923            });
4924
4925            if let Some((primary_range, group_id)) = group {
4926                if self.activate_diagnostics(group_id, cx) {
4927                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4928                        s.select(vec![Selection {
4929                            id: selection.id,
4930                            start: primary_range.start,
4931                            end: primary_range.start,
4932                            reversed: false,
4933                            goal: SelectionGoal::None,
4934                        }]);
4935                    });
4936                }
4937                break;
4938            } else {
4939                // Cycle around to the start of the buffer, potentially moving back to the start of
4940                // the currently active diagnostic.
4941                active_primary_range.take();
4942                if direction == Direction::Prev {
4943                    if search_start == buffer.len() {
4944                        break;
4945                    } else {
4946                        search_start = buffer.len();
4947                    }
4948                } else if search_start == 0 {
4949                    break;
4950                } else {
4951                    search_start = 0;
4952                }
4953            }
4954        }
4955    }
4956
4957    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
4958        self.go_to_hunk_impl(Direction::Next, cx)
4959    }
4960
4961    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
4962        self.go_to_hunk_impl(Direction::Prev, cx)
4963    }
4964
4965    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4966        let snapshot = self
4967            .display_map
4968            .update(cx, |display_map, cx| display_map.snapshot(cx));
4969        let selection = self.selections.newest::<Point>(cx);
4970
4971        fn seek_in_direction(
4972            this: &mut Editor,
4973            snapshot: &DisplaySnapshot,
4974            initial_point: Point,
4975            is_wrapped: bool,
4976            direction: Direction,
4977            cx: &mut ViewContext<Editor>,
4978        ) -> bool {
4979            let hunks = if direction == Direction::Next {
4980                snapshot
4981                    .buffer_snapshot
4982                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
4983            } else {
4984                snapshot
4985                    .buffer_snapshot
4986                    .git_diff_hunks_in_range(0..initial_point.row, true)
4987            };
4988
4989            let display_point = initial_point.to_display_point(snapshot);
4990            let mut hunks = hunks
4991                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
4992                .skip_while(|hunk| {
4993                    if is_wrapped {
4994                        false
4995                    } else {
4996                        hunk.contains_display_row(display_point.row())
4997                    }
4998                })
4999                .dedup();
5000
5001            if let Some(hunk) = hunks.next() {
5002                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5003                    let row = hunk.start_display_row();
5004                    let point = DisplayPoint::new(row, 0);
5005                    s.select_display_ranges([point..point]);
5006                });
5007
5008                true
5009            } else {
5010                false
5011            }
5012        }
5013
5014        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5015            let wrapped_point = match direction {
5016                Direction::Next => Point::zero(),
5017                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5018            };
5019            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5020        }
5021    }
5022
5023    pub fn go_to_definition(
5024        workspace: &mut Workspace,
5025        _: &GoToDefinition,
5026        cx: &mut ViewContext<Workspace>,
5027    ) {
5028        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5029    }
5030
5031    pub fn go_to_type_definition(
5032        workspace: &mut Workspace,
5033        _: &GoToTypeDefinition,
5034        cx: &mut ViewContext<Workspace>,
5035    ) {
5036        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5037    }
5038
5039    fn go_to_definition_of_kind(
5040        kind: GotoDefinitionKind,
5041        workspace: &mut Workspace,
5042        cx: &mut ViewContext<Workspace>,
5043    ) {
5044        let active_item = workspace.active_item(cx);
5045        let editor_handle = if let Some(editor) = active_item
5046            .as_ref()
5047            .and_then(|item| item.act_as::<Self>(cx))
5048        {
5049            editor
5050        } else {
5051            return;
5052        };
5053
5054        let editor = editor_handle.read(cx);
5055        let buffer = editor.buffer.read(cx);
5056        let head = editor.selections.newest::<usize>(cx).head();
5057        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5058            text_anchor
5059        } else {
5060            return;
5061        };
5062
5063        let project = workspace.project().clone();
5064        let definitions = project.update(cx, |project, cx| match kind {
5065            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5066            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5067        });
5068
5069        cx.spawn(|workspace, mut cx| async move {
5070            let definitions = definitions.await?;
5071            workspace.update(&mut cx, |workspace, cx| {
5072                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5073            });
5074
5075            Ok::<(), anyhow::Error>(())
5076        })
5077        .detach_and_log_err(cx);
5078    }
5079
5080    pub fn navigate_to_definitions(
5081        workspace: &mut Workspace,
5082        editor_handle: ViewHandle<Editor>,
5083        definitions: Vec<LocationLink>,
5084        cx: &mut ViewContext<Workspace>,
5085    ) {
5086        let pane = workspace.active_pane().clone();
5087        // If there is one definition, just open it directly
5088        if let [definition] = definitions.as_slice() {
5089            let range = definition
5090                .target
5091                .range
5092                .to_offset(definition.target.buffer.read(cx));
5093
5094            let target_editor_handle =
5095                workspace.open_project_item(definition.target.buffer.clone(), cx);
5096            target_editor_handle.update(cx, |target_editor, cx| {
5097                // When selecting a definition in a different buffer, disable the nav history
5098                // to avoid creating a history entry at the previous cursor location.
5099                if editor_handle != target_editor_handle {
5100                    pane.update(cx, |pane, _| pane.disable_history());
5101                }
5102                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5103                    s.select_ranges([range]);
5104                });
5105
5106                pane.update(cx, |pane, _| pane.enable_history());
5107            });
5108        } else if !definitions.is_empty() {
5109            let replica_id = editor_handle.read(cx).replica_id(cx);
5110            let title = definitions
5111                .iter()
5112                .find(|definition| definition.origin.is_some())
5113                .and_then(|definition| {
5114                    definition.origin.as_ref().map(|origin| {
5115                        let buffer = origin.buffer.read(cx);
5116                        format!(
5117                            "Definitions for {}",
5118                            buffer
5119                                .text_for_range(origin.range.clone())
5120                                .collect::<String>()
5121                        )
5122                    })
5123                })
5124                .unwrap_or("Definitions".to_owned());
5125            let locations = definitions
5126                .into_iter()
5127                .map(|definition| definition.target)
5128                .collect();
5129            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5130        }
5131    }
5132
5133    pub fn find_all_references(
5134        workspace: &mut Workspace,
5135        _: &FindAllReferences,
5136        cx: &mut ViewContext<Workspace>,
5137    ) -> Option<Task<Result<()>>> {
5138        let active_item = workspace.active_item(cx)?;
5139        let editor_handle = active_item.act_as::<Self>(cx)?;
5140
5141        let editor = editor_handle.read(cx);
5142        let buffer = editor.buffer.read(cx);
5143        let head = editor.selections.newest::<usize>(cx).head();
5144        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5145        let replica_id = editor.replica_id(cx);
5146
5147        let project = workspace.project().clone();
5148        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5149        Some(cx.spawn(|workspace, mut cx| async move {
5150            let locations = references.await?;
5151            if locations.is_empty() {
5152                return Ok(());
5153            }
5154
5155            workspace.update(&mut cx, |workspace, cx| {
5156                let title = locations
5157                    .first()
5158                    .as_ref()
5159                    .map(|location| {
5160                        let buffer = location.buffer.read(cx);
5161                        format!(
5162                            "References to `{}`",
5163                            buffer
5164                                .text_for_range(location.range.clone())
5165                                .collect::<String>()
5166                        )
5167                    })
5168                    .unwrap();
5169                Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx);
5170            });
5171
5172            Ok(())
5173        }))
5174    }
5175
5176    /// Opens a multibuffer with the given project locations in it
5177    pub fn open_locations_in_multibuffer(
5178        workspace: &mut Workspace,
5179        mut locations: Vec<Location>,
5180        replica_id: ReplicaId,
5181        title: String,
5182        cx: &mut ViewContext<Workspace>,
5183    ) {
5184        // If there are multiple definitions, open them in a multibuffer
5185        locations.sort_by_key(|location| location.buffer.id());
5186        let mut locations = locations.into_iter().peekable();
5187        let mut ranges_to_highlight = Vec::new();
5188
5189        let excerpt_buffer = cx.add_model(|cx| {
5190            let mut multibuffer = MultiBuffer::new(replica_id);
5191            while let Some(location) = locations.next() {
5192                let buffer = location.buffer.read(cx);
5193                let mut ranges_for_buffer = Vec::new();
5194                let range = location.range.to_offset(buffer);
5195                ranges_for_buffer.push(range.clone());
5196
5197                while let Some(next_location) = locations.peek() {
5198                    if next_location.buffer == location.buffer {
5199                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5200                        locations.next();
5201                    } else {
5202                        break;
5203                    }
5204                }
5205
5206                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5207                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5208                    location.buffer.clone(),
5209                    ranges_for_buffer,
5210                    1,
5211                    cx,
5212                ))
5213            }
5214
5215            multibuffer.with_title(title)
5216        });
5217
5218        let editor = cx.add_view(|cx| {
5219            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5220        });
5221        editor.update(cx, |editor, cx| {
5222            editor.highlight_background::<Self>(
5223                ranges_to_highlight,
5224                |theme| theme.editor.highlighted_line_background,
5225                cx,
5226            );
5227        });
5228        workspace.add_item(Box::new(editor), cx);
5229    }
5230
5231    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5232        use language::ToOffset as _;
5233
5234        let project = self.project.clone()?;
5235        let selection = self.selections.newest_anchor().clone();
5236        let (cursor_buffer, cursor_buffer_position) = self
5237            .buffer
5238            .read(cx)
5239            .text_anchor_for_position(selection.head(), cx)?;
5240        let (tail_buffer, _) = self
5241            .buffer
5242            .read(cx)
5243            .text_anchor_for_position(selection.tail(), cx)?;
5244        if tail_buffer != cursor_buffer {
5245            return None;
5246        }
5247
5248        let snapshot = cursor_buffer.read(cx).snapshot();
5249        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5250        let prepare_rename = project.update(cx, |project, cx| {
5251            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5252        });
5253
5254        Some(cx.spawn(|this, mut cx| async move {
5255            let rename_range = if let Some(range) = prepare_rename.await? {
5256                Some(range)
5257            } else {
5258                this.read_with(&cx, |this, cx| {
5259                    let buffer = this.buffer.read(cx).snapshot(cx);
5260                    let mut buffer_highlights = this
5261                        .document_highlights_for_position(selection.head(), &buffer)
5262                        .filter(|highlight| {
5263                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5264                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5265                        });
5266                    buffer_highlights
5267                        .next()
5268                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5269                })
5270            };
5271            if let Some(rename_range) = rename_range {
5272                let rename_buffer_range = rename_range.to_offset(&snapshot);
5273                let cursor_offset_in_rename_range =
5274                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5275
5276                this.update(&mut cx, |this, cx| {
5277                    this.take_rename(false, cx);
5278                    let style = this.style(cx);
5279                    let buffer = this.buffer.read(cx).read(cx);
5280                    let cursor_offset = selection.head().to_offset(&buffer);
5281                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5282                    let rename_end = rename_start + rename_buffer_range.len();
5283                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5284                    let mut old_highlight_id = None;
5285                    let old_name: Arc<str> = buffer
5286                        .chunks(rename_start..rename_end, true)
5287                        .map(|chunk| {
5288                            if old_highlight_id.is_none() {
5289                                old_highlight_id = chunk.syntax_highlight_id;
5290                            }
5291                            chunk.text
5292                        })
5293                        .collect::<String>()
5294                        .into();
5295
5296                    drop(buffer);
5297
5298                    // Position the selection in the rename editor so that it matches the current selection.
5299                    this.show_local_selections = false;
5300                    let rename_editor = cx.add_view(|cx| {
5301                        let mut editor = Editor::single_line(None, cx);
5302                        if let Some(old_highlight_id) = old_highlight_id {
5303                            editor.override_text_style =
5304                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5305                        }
5306                        editor.buffer.update(cx, |buffer, cx| {
5307                            buffer.edit([(0..0, old_name.clone())], None, cx)
5308                        });
5309                        editor.select_all(&SelectAll, cx);
5310                        editor
5311                    });
5312
5313                    let ranges = this
5314                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5315                        .into_iter()
5316                        .flat_map(|(_, ranges)| ranges)
5317                        .chain(
5318                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5319                                .into_iter()
5320                                .flat_map(|(_, ranges)| ranges),
5321                        )
5322                        .collect();
5323
5324                    this.highlight_text::<Rename>(
5325                        ranges,
5326                        HighlightStyle {
5327                            fade_out: Some(style.rename_fade),
5328                            ..Default::default()
5329                        },
5330                        cx,
5331                    );
5332                    cx.focus(&rename_editor);
5333                    let block_id = this.insert_blocks(
5334                        [BlockProperties {
5335                            style: BlockStyle::Flex,
5336                            position: range.start.clone(),
5337                            height: 1,
5338                            render: Arc::new({
5339                                let editor = rename_editor.clone();
5340                                move |cx: &mut BlockContext| {
5341                                    ChildView::new(editor.clone(), cx)
5342                                        .contained()
5343                                        .with_padding_left(cx.anchor_x)
5344                                        .boxed()
5345                                }
5346                            }),
5347                            disposition: BlockDisposition::Below,
5348                        }],
5349                        cx,
5350                    )[0];
5351                    this.pending_rename = Some(RenameState {
5352                        range,
5353                        old_name,
5354                        editor: rename_editor,
5355                        block_id,
5356                    });
5357                });
5358            }
5359
5360            Ok(())
5361        }))
5362    }
5363
5364    pub fn confirm_rename(
5365        workspace: &mut Workspace,
5366        _: &ConfirmRename,
5367        cx: &mut ViewContext<Workspace>,
5368    ) -> Option<Task<Result<()>>> {
5369        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5370
5371        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5372            let rename = editor.take_rename(false, cx)?;
5373            let buffer = editor.buffer.read(cx);
5374            let (start_buffer, start) =
5375                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5376            let (end_buffer, end) =
5377                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5378            if start_buffer == end_buffer {
5379                let new_name = rename.editor.read(cx).text(cx);
5380                Some((start_buffer, start..end, rename.old_name, new_name))
5381            } else {
5382                None
5383            }
5384        })?;
5385
5386        let rename = workspace.project().clone().update(cx, |project, cx| {
5387            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5388        });
5389
5390        Some(cx.spawn(|workspace, mut cx| async move {
5391            let project_transaction = rename.await?;
5392            Self::open_project_transaction(
5393                editor.clone(),
5394                workspace,
5395                project_transaction,
5396                format!("Rename: {}{}", old_name, new_name),
5397                cx.clone(),
5398            )
5399            .await?;
5400
5401            editor.update(&mut cx, |editor, cx| {
5402                editor.refresh_document_highlights(cx);
5403            });
5404            Ok(())
5405        }))
5406    }
5407
5408    fn take_rename(
5409        &mut self,
5410        moving_cursor: bool,
5411        cx: &mut ViewContext<Self>,
5412    ) -> Option<RenameState> {
5413        let rename = self.pending_rename.take()?;
5414        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5415        self.clear_text_highlights::<Rename>(cx);
5416        self.show_local_selections = true;
5417
5418        if moving_cursor {
5419            let rename_editor = rename.editor.read(cx);
5420            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5421
5422            // Update the selection to match the position of the selection inside
5423            // the rename editor.
5424            let snapshot = self.buffer.read(cx).read(cx);
5425            let rename_range = rename.range.to_offset(&snapshot);
5426            let cursor_in_editor = snapshot
5427                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5428                .min(rename_range.end);
5429            drop(snapshot);
5430
5431            self.change_selections(None, cx, |s| {
5432                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5433            });
5434        } else {
5435            self.refresh_document_highlights(cx);
5436        }
5437
5438        Some(rename)
5439    }
5440
5441    #[cfg(any(test, feature = "test-support"))]
5442    pub fn pending_rename(&self) -> Option<&RenameState> {
5443        self.pending_rename.as_ref()
5444    }
5445
5446    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5447        let project = match &self.project {
5448            Some(project) => project.clone(),
5449            None => return None,
5450        };
5451
5452        Some(self.perform_format(project, cx))
5453    }
5454
5455    fn perform_format(
5456        &mut self,
5457        project: ModelHandle<Project>,
5458        cx: &mut ViewContext<'_, Self>,
5459    ) -> Task<Result<()>> {
5460        let buffer = self.buffer().clone();
5461        let buffers = buffer.read(cx).all_buffers();
5462
5463        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5464        let format = project.update(cx, |project, cx| {
5465            project.format(buffers, true, FormatTrigger::Manual, cx)
5466        });
5467
5468        cx.spawn(|_, mut cx| async move {
5469            let transaction = futures::select_biased! {
5470                _ = timeout => {
5471                    log::warn!("timed out waiting for formatting");
5472                    None
5473                }
5474                transaction = format.log_err().fuse() => transaction,
5475            };
5476
5477            buffer.update(&mut cx, |buffer, cx| {
5478                if let Some(transaction) = transaction {
5479                    if !buffer.is_singleton() {
5480                        buffer.push_transaction(&transaction.0);
5481                    }
5482                }
5483
5484                cx.notify();
5485            });
5486
5487            Ok(())
5488        })
5489    }
5490
5491    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5492        if let Some(project) = self.project.clone() {
5493            self.buffer.update(cx, |multi_buffer, cx| {
5494                project.update(cx, |project, cx| {
5495                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5496                });
5497            })
5498        }
5499    }
5500
5501    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5502        cx.show_character_palette();
5503    }
5504
5505    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5506        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5507            let buffer = self.buffer.read(cx).snapshot(cx);
5508            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5509            let is_valid = buffer
5510                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5511                .any(|entry| {
5512                    entry.diagnostic.is_primary
5513                        && !entry.range.is_empty()
5514                        && entry.range.start == primary_range_start
5515                        && entry.diagnostic.message == active_diagnostics.primary_message
5516                });
5517
5518            if is_valid != active_diagnostics.is_valid {
5519                active_diagnostics.is_valid = is_valid;
5520                let mut new_styles = HashMap::default();
5521                for (block_id, diagnostic) in &active_diagnostics.blocks {
5522                    new_styles.insert(
5523                        *block_id,
5524                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5525                    );
5526                }
5527                self.display_map
5528                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5529            }
5530        }
5531    }
5532
5533    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5534        self.dismiss_diagnostics(cx);
5535        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5536            let buffer = self.buffer.read(cx).snapshot(cx);
5537
5538            let mut primary_range = None;
5539            let mut primary_message = None;
5540            let mut group_end = Point::zero();
5541            let diagnostic_group = buffer
5542                .diagnostic_group::<Point>(group_id)
5543                .map(|entry| {
5544                    if entry.range.end > group_end {
5545                        group_end = entry.range.end;
5546                    }
5547                    if entry.diagnostic.is_primary {
5548                        primary_range = Some(entry.range.clone());
5549                        primary_message = Some(entry.diagnostic.message.clone());
5550                    }
5551                    entry
5552                })
5553                .collect::<Vec<_>>();
5554            let primary_range = primary_range?;
5555            let primary_message = primary_message?;
5556            let primary_range =
5557                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5558
5559            let blocks = display_map
5560                .insert_blocks(
5561                    diagnostic_group.iter().map(|entry| {
5562                        let diagnostic = entry.diagnostic.clone();
5563                        let message_height = diagnostic.message.lines().count() as u8;
5564                        BlockProperties {
5565                            style: BlockStyle::Fixed,
5566                            position: buffer.anchor_after(entry.range.start),
5567                            height: message_height,
5568                            render: diagnostic_block_renderer(diagnostic, true),
5569                            disposition: BlockDisposition::Below,
5570                        }
5571                    }),
5572                    cx,
5573                )
5574                .into_iter()
5575                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5576                .collect();
5577
5578            Some(ActiveDiagnosticGroup {
5579                primary_range,
5580                primary_message,
5581                blocks,
5582                is_valid: true,
5583            })
5584        });
5585        self.active_diagnostics.is_some()
5586    }
5587
5588    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5589        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5590            self.display_map.update(cx, |display_map, cx| {
5591                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5592            });
5593            cx.notify();
5594        }
5595    }
5596
5597    pub fn set_selections_from_remote(
5598        &mut self,
5599        selections: Vec<Selection<Anchor>>,
5600        pending_selection: Option<Selection<Anchor>>,
5601        cx: &mut ViewContext<Self>,
5602    ) {
5603        let old_cursor_position = self.selections.newest_anchor().head();
5604        self.selections.change_with(cx, |s| {
5605            s.select_anchors(selections);
5606            if let Some(pending_selection) = pending_selection {
5607                s.set_pending(pending_selection, SelectMode::Character);
5608            } else {
5609                s.clear_pending();
5610            }
5611        });
5612        self.selections_did_change(false, &old_cursor_position, cx);
5613    }
5614
5615    fn push_to_selection_history(&mut self) {
5616        self.selection_history.push(SelectionHistoryEntry {
5617            selections: self.selections.disjoint_anchors(),
5618            select_next_state: self.select_next_state.clone(),
5619            add_selections_state: self.add_selections_state.clone(),
5620        });
5621    }
5622
5623    pub fn transact(
5624        &mut self,
5625        cx: &mut ViewContext<Self>,
5626        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5627    ) -> Option<TransactionId> {
5628        self.start_transaction_at(Instant::now(), cx);
5629        update(self, cx);
5630        self.end_transaction_at(Instant::now(), cx)
5631    }
5632
5633    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5634        self.end_selection(cx);
5635        if let Some(tx_id) = self
5636            .buffer
5637            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5638        {
5639            self.selection_history
5640                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5641        }
5642    }
5643
5644    fn end_transaction_at(
5645        &mut self,
5646        now: Instant,
5647        cx: &mut ViewContext<Self>,
5648    ) -> Option<TransactionId> {
5649        if let Some(tx_id) = self
5650            .buffer
5651            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5652        {
5653            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5654                *end_selections = Some(self.selections.disjoint_anchors());
5655            } else {
5656                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5657            }
5658
5659            cx.emit(Event::Edited);
5660            Some(tx_id)
5661        } else {
5662            None
5663        }
5664    }
5665
5666    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5667        let mut fold_ranges = Vec::new();
5668
5669        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5670        let selections = self.selections.all::<Point>(cx);
5671        for selection in selections {
5672            let range = selection.display_range(&display_map).sorted();
5673            let buffer_start_row = range.start.to_point(&display_map).row;
5674
5675            for row in (0..=range.end.row()).rev() {
5676                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5677                    let fold_range = self.foldable_range_for_line(&display_map, row);
5678                    if fold_range.end.row >= buffer_start_row {
5679                        fold_ranges.push(fold_range);
5680                        if row <= range.start.row() {
5681                            break;
5682                        }
5683                    }
5684                }
5685            }
5686        }
5687
5688        self.fold_ranges(fold_ranges, cx);
5689    }
5690
5691    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5692        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5693        let buffer = &display_map.buffer_snapshot;
5694        let selections = self.selections.all::<Point>(cx);
5695        let ranges = selections
5696            .iter()
5697            .map(|s| {
5698                let range = s.display_range(&display_map).sorted();
5699                let mut start = range.start.to_point(&display_map);
5700                let mut end = range.end.to_point(&display_map);
5701                start.column = 0;
5702                end.column = buffer.line_len(end.row);
5703                start..end
5704            })
5705            .collect::<Vec<_>>();
5706        self.unfold_ranges(ranges, true, cx);
5707    }
5708
5709    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5710        let max_point = display_map.max_point();
5711        if display_row >= max_point.row() {
5712            false
5713        } else {
5714            let (start_indent, is_blank) = display_map.line_indent(display_row);
5715            if is_blank {
5716                false
5717            } else {
5718                for display_row in display_row + 1..=max_point.row() {
5719                    let (indent, is_blank) = display_map.line_indent(display_row);
5720                    if !is_blank {
5721                        return indent > start_indent;
5722                    }
5723                }
5724                false
5725            }
5726        }
5727    }
5728
5729    fn foldable_range_for_line(
5730        &self,
5731        display_map: &DisplaySnapshot,
5732        start_row: u32,
5733    ) -> Range<Point> {
5734        let max_point = display_map.max_point();
5735
5736        let (start_indent, _) = display_map.line_indent(start_row);
5737        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5738        let mut end = None;
5739        for row in start_row + 1..=max_point.row() {
5740            let (indent, is_blank) = display_map.line_indent(row);
5741            if !is_blank && indent <= start_indent {
5742                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5743                break;
5744            }
5745        }
5746
5747        let end = end.unwrap_or(max_point);
5748        start.to_point(display_map)..end.to_point(display_map)
5749    }
5750
5751    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5752        let selections = self.selections.all::<Point>(cx);
5753        let ranges = selections.into_iter().map(|s| s.start..s.end);
5754        self.fold_ranges(ranges, cx);
5755    }
5756
5757    pub fn fold_ranges<T: ToOffset>(
5758        &mut self,
5759        ranges: impl IntoIterator<Item = Range<T>>,
5760        cx: &mut ViewContext<Self>,
5761    ) {
5762        let mut ranges = ranges.into_iter().peekable();
5763        if ranges.peek().is_some() {
5764            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5765            self.request_autoscroll(Autoscroll::fit(), cx);
5766            cx.notify();
5767        }
5768    }
5769
5770    pub fn unfold_ranges<T: ToOffset>(
5771        &mut self,
5772        ranges: impl IntoIterator<Item = Range<T>>,
5773        inclusive: bool,
5774        cx: &mut ViewContext<Self>,
5775    ) {
5776        let mut ranges = ranges.into_iter().peekable();
5777        if ranges.peek().is_some() {
5778            self.display_map
5779                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5780            self.request_autoscroll(Autoscroll::fit(), cx);
5781            cx.notify();
5782        }
5783    }
5784
5785    pub fn insert_blocks(
5786        &mut self,
5787        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5788        cx: &mut ViewContext<Self>,
5789    ) -> Vec<BlockId> {
5790        let blocks = self
5791            .display_map
5792            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5793        self.request_autoscroll(Autoscroll::fit(), cx);
5794        blocks
5795    }
5796
5797    pub fn replace_blocks(
5798        &mut self,
5799        blocks: HashMap<BlockId, RenderBlock>,
5800        cx: &mut ViewContext<Self>,
5801    ) {
5802        self.display_map
5803            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5804        self.request_autoscroll(Autoscroll::fit(), cx);
5805    }
5806
5807    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5808        self.display_map.update(cx, |display_map, cx| {
5809            display_map.remove_blocks(block_ids, cx)
5810        });
5811    }
5812
5813    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5814        self.display_map
5815            .update(cx, |map, cx| map.snapshot(cx))
5816            .longest_row()
5817    }
5818
5819    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5820        self.display_map
5821            .update(cx, |map, cx| map.snapshot(cx))
5822            .max_point()
5823    }
5824
5825    pub fn text(&self, cx: &AppContext) -> String {
5826        self.buffer.read(cx).read(cx).text()
5827    }
5828
5829    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5830        self.transact(cx, |this, cx| {
5831            this.buffer
5832                .read(cx)
5833                .as_singleton()
5834                .expect("you can only call set_text on editors for singleton buffers")
5835                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5836        });
5837    }
5838
5839    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5840        self.display_map
5841            .update(cx, |map, cx| map.snapshot(cx))
5842            .text()
5843    }
5844
5845    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5846        let language_name = self
5847            .buffer
5848            .read(cx)
5849            .as_singleton()
5850            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5851            .map(|l| l.name());
5852
5853        let settings = cx.global::<Settings>();
5854        let mode = self
5855            .soft_wrap_mode_override
5856            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5857        match mode {
5858            settings::SoftWrap::None => SoftWrap::None,
5859            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5860            settings::SoftWrap::PreferredLineLength => {
5861                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5862            }
5863        }
5864    }
5865
5866    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5867        self.soft_wrap_mode_override = Some(mode);
5868        cx.notify();
5869    }
5870
5871    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5872        self.display_map
5873            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5874    }
5875
5876    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
5877        if self.soft_wrap_mode_override.is_some() {
5878            self.soft_wrap_mode_override.take();
5879        } else {
5880            let soft_wrap = match self.soft_wrap_mode(cx) {
5881                SoftWrap::None => settings::SoftWrap::EditorWidth,
5882                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
5883            };
5884            self.soft_wrap_mode_override = Some(soft_wrap);
5885        }
5886        cx.notify();
5887    }
5888
5889    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5890        self.highlighted_rows = rows;
5891    }
5892
5893    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5894        self.highlighted_rows.clone()
5895    }
5896
5897    pub fn highlight_background<T: 'static>(
5898        &mut self,
5899        ranges: Vec<Range<Anchor>>,
5900        color_fetcher: fn(&Theme) -> Color,
5901        cx: &mut ViewContext<Self>,
5902    ) {
5903        self.background_highlights
5904            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5905        cx.notify();
5906    }
5907
5908    #[allow(clippy::type_complexity)]
5909    pub fn clear_background_highlights<T: 'static>(
5910        &mut self,
5911        cx: &mut ViewContext<Self>,
5912    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5913        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
5914        if highlights.is_some() {
5915            cx.notify();
5916        }
5917        highlights
5918    }
5919
5920    #[cfg(feature = "test-support")]
5921    pub fn all_background_highlights(
5922        &mut self,
5923        cx: &mut ViewContext<Self>,
5924    ) -> Vec<(Range<DisplayPoint>, Color)> {
5925        let snapshot = self.snapshot(cx);
5926        let buffer = &snapshot.buffer_snapshot;
5927        let start = buffer.anchor_before(0);
5928        let end = buffer.anchor_after(buffer.len());
5929        let theme = cx.global::<Settings>().theme.as_ref();
5930        self.background_highlights_in_range(start..end, &snapshot, theme)
5931    }
5932
5933    fn document_highlights_for_position<'a>(
5934        &'a self,
5935        position: Anchor,
5936        buffer: &'a MultiBufferSnapshot,
5937    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5938        let read_highlights = self
5939            .background_highlights
5940            .get(&TypeId::of::<DocumentHighlightRead>())
5941            .map(|h| &h.1);
5942        let write_highlights = self
5943            .background_highlights
5944            .get(&TypeId::of::<DocumentHighlightWrite>())
5945            .map(|h| &h.1);
5946        let left_position = position.bias_left(buffer);
5947        let right_position = position.bias_right(buffer);
5948        read_highlights
5949            .into_iter()
5950            .chain(write_highlights)
5951            .flat_map(move |ranges| {
5952                let start_ix = match ranges.binary_search_by(|probe| {
5953                    let cmp = probe.end.cmp(&left_position, buffer);
5954                    if cmp.is_ge() {
5955                        Ordering::Greater
5956                    } else {
5957                        Ordering::Less
5958                    }
5959                }) {
5960                    Ok(i) | Err(i) => i,
5961                };
5962
5963                let right_position = right_position.clone();
5964                ranges[start_ix..]
5965                    .iter()
5966                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5967            })
5968    }
5969
5970    pub fn background_highlights_in_range(
5971        &self,
5972        search_range: Range<Anchor>,
5973        display_snapshot: &DisplaySnapshot,
5974        theme: &Theme,
5975    ) -> Vec<(Range<DisplayPoint>, Color)> {
5976        let mut results = Vec::new();
5977        let buffer = &display_snapshot.buffer_snapshot;
5978        for (color_fetcher, ranges) in self.background_highlights.values() {
5979            let color = color_fetcher(theme);
5980            let start_ix = match ranges.binary_search_by(|probe| {
5981                let cmp = probe.end.cmp(&search_range.start, buffer);
5982                if cmp.is_gt() {
5983                    Ordering::Greater
5984                } else {
5985                    Ordering::Less
5986                }
5987            }) {
5988                Ok(i) | Err(i) => i,
5989            };
5990            for range in &ranges[start_ix..] {
5991                if range.start.cmp(&search_range.end, buffer).is_ge() {
5992                    break;
5993                }
5994                let start = range
5995                    .start
5996                    .to_point(buffer)
5997                    .to_display_point(display_snapshot);
5998                let end = range
5999                    .end
6000                    .to_point(buffer)
6001                    .to_display_point(display_snapshot);
6002                results.push((start..end, color))
6003            }
6004        }
6005        results
6006    }
6007
6008    pub fn highlight_text<T: 'static>(
6009        &mut self,
6010        ranges: Vec<Range<Anchor>>,
6011        style: HighlightStyle,
6012        cx: &mut ViewContext<Self>,
6013    ) {
6014        self.display_map.update(cx, |map, _| {
6015            map.highlight_text(TypeId::of::<T>(), ranges, style)
6016        });
6017        cx.notify();
6018    }
6019
6020    pub fn text_highlights<'a, T: 'static>(
6021        &'a self,
6022        cx: &'a AppContext,
6023    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6024        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6025    }
6026
6027    pub fn clear_text_highlights<T: 'static>(
6028        &mut self,
6029        cx: &mut ViewContext<Self>,
6030    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6031        let highlights = self
6032            .display_map
6033            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6034        if highlights.is_some() {
6035            cx.notify();
6036        }
6037        highlights
6038    }
6039
6040    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6041        self.blink_manager.read(cx).visible() && self.focused
6042    }
6043
6044    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6045        cx.notify();
6046    }
6047
6048    fn on_buffer_event(
6049        &mut self,
6050        _: ModelHandle<MultiBuffer>,
6051        event: &multi_buffer::Event,
6052        cx: &mut ViewContext<Self>,
6053    ) {
6054        match event {
6055            multi_buffer::Event::Edited => {
6056                self.refresh_active_diagnostics(cx);
6057                self.refresh_code_actions(cx);
6058                cx.emit(Event::BufferEdited);
6059            }
6060            multi_buffer::Event::ExcerptsAdded {
6061                buffer,
6062                predecessor,
6063                excerpts,
6064            } => cx.emit(Event::ExcerptsAdded {
6065                buffer: buffer.clone(),
6066                predecessor: *predecessor,
6067                excerpts: excerpts.clone(),
6068            }),
6069            multi_buffer::Event::ExcerptsRemoved { ids } => {
6070                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6071            }
6072            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6073            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6074            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6075            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6076            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6077            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6078            multi_buffer::Event::DiagnosticsUpdated => {
6079                self.refresh_active_diagnostics(cx);
6080            }
6081        }
6082    }
6083
6084    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6085        cx.notify();
6086    }
6087
6088    pub fn set_searchable(&mut self, searchable: bool) {
6089        self.searchable = searchable;
6090    }
6091
6092    pub fn searchable(&self) -> bool {
6093        self.searchable
6094    }
6095
6096    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6097        let active_item = workspace.active_item(cx);
6098        let editor_handle = if let Some(editor) = active_item
6099            .as_ref()
6100            .and_then(|item| item.act_as::<Self>(cx))
6101        {
6102            editor
6103        } else {
6104            cx.propagate_action();
6105            return;
6106        };
6107
6108        let editor = editor_handle.read(cx);
6109        let buffer = editor.buffer.read(cx);
6110        if buffer.is_singleton() {
6111            cx.propagate_action();
6112            return;
6113        }
6114
6115        let mut new_selections_by_buffer = HashMap::default();
6116        for selection in editor.selections.all::<usize>(cx) {
6117            for (buffer, mut range) in
6118                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6119            {
6120                if selection.reversed {
6121                    mem::swap(&mut range.start, &mut range.end);
6122                }
6123                new_selections_by_buffer
6124                    .entry(buffer)
6125                    .or_insert(Vec::new())
6126                    .push(range)
6127            }
6128        }
6129
6130        editor_handle.update(cx, |editor, cx| {
6131            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6132        });
6133        let pane = workspace.active_pane().clone();
6134        pane.update(cx, |pane, _| pane.disable_history());
6135
6136        // We defer the pane interaction because we ourselves are a workspace item
6137        // and activating a new item causes the pane to call a method on us reentrantly,
6138        // which panics if we're on the stack.
6139        cx.defer(move |workspace, cx| {
6140            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6141                let editor = workspace.open_project_item::<Self>(buffer, cx);
6142                editor.update(cx, |editor, cx| {
6143                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6144                        s.select_ranges(ranges);
6145                    });
6146                });
6147            }
6148
6149            pane.update(cx, |pane, _| pane.enable_history());
6150        });
6151    }
6152
6153    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6154        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6155        let position = action.position;
6156        let anchor = action.anchor;
6157        cx.spawn_weak(|_, mut cx| async move {
6158            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6159            editor.update(&mut cx, |editor, cx| {
6160                let buffer = editor.buffer().read(cx).as_singleton()?;
6161                let buffer = buffer.read(cx);
6162                let cursor = if buffer.can_resolve(&anchor) {
6163                    language::ToPoint::to_point(&anchor, buffer)
6164                } else {
6165                    buffer.clip_point(position, Bias::Left)
6166                };
6167
6168                let nav_history = editor.nav_history.take();
6169                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6170                    s.select_ranges([cursor..cursor]);
6171                });
6172                editor.nav_history = nav_history;
6173
6174                Some(())
6175            })?;
6176            Some(())
6177        })
6178        .detach()
6179    }
6180
6181    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6182        let snapshot = self.buffer.read(cx).read(cx);
6183        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6184        Some(
6185            ranges
6186                .iter()
6187                .map(move |range| {
6188                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6189                })
6190                .collect(),
6191        )
6192    }
6193
6194    fn selection_replacement_ranges(
6195        &self,
6196        range: Range<OffsetUtf16>,
6197        cx: &AppContext,
6198    ) -> Vec<Range<OffsetUtf16>> {
6199        let selections = self.selections.all::<OffsetUtf16>(cx);
6200        let newest_selection = selections
6201            .iter()
6202            .max_by_key(|selection| selection.id)
6203            .unwrap();
6204        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6205        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6206        let snapshot = self.buffer.read(cx).read(cx);
6207        selections
6208            .into_iter()
6209            .map(|mut selection| {
6210                selection.start.0 =
6211                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6212                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6213                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6214                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6215            })
6216            .collect()
6217    }
6218
6219    fn report_event(&self, name: &str, cx: &AppContext) {
6220        if let Some((project, file)) = self.project.as_ref().zip(
6221            self.buffer
6222                .read(cx)
6223                .as_singleton()
6224                .and_then(|b| b.read(cx).file()),
6225        ) {
6226            let extension = Path::new(file.file_name(cx))
6227                .extension()
6228                .and_then(|e| e.to_str());
6229            project.read(cx).client().report_event(
6230                name,
6231                json!({ "File Extension": extension }),
6232                cx.global::<Settings>().telemetry(),
6233            );
6234        }
6235    }
6236}
6237
6238impl EditorSnapshot {
6239    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6240        self.display_snapshot.buffer_snapshot.language_at(position)
6241    }
6242
6243    pub fn is_focused(&self) -> bool {
6244        self.is_focused
6245    }
6246
6247    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6248        self.placeholder_text.as_ref()
6249    }
6250
6251    pub fn scroll_position(&self) -> Vector2F {
6252        self.scroll_anchor.scroll_position(&self.display_snapshot)
6253    }
6254}
6255
6256impl Deref for EditorSnapshot {
6257    type Target = DisplaySnapshot;
6258
6259    fn deref(&self) -> &Self::Target {
6260        &self.display_snapshot
6261    }
6262}
6263
6264#[derive(Clone, Debug, PartialEq, Eq)]
6265pub enum Event {
6266    InputIgnored {
6267        text: Arc<str>,
6268    },
6269    ExcerptsAdded {
6270        buffer: ModelHandle<Buffer>,
6271        predecessor: ExcerptId,
6272        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6273    },
6274    ExcerptsRemoved {
6275        ids: Vec<ExcerptId>,
6276    },
6277    BufferEdited,
6278    Edited,
6279    Reparsed,
6280    Blurred,
6281    DirtyChanged,
6282    Saved,
6283    TitleChanged,
6284    SelectionsChanged {
6285        local: bool,
6286    },
6287    ScrollPositionChanged {
6288        local: bool,
6289    },
6290    Closed,
6291}
6292
6293pub struct EditorFocused(pub ViewHandle<Editor>);
6294pub struct EditorBlurred(pub ViewHandle<Editor>);
6295pub struct EditorReleased(pub WeakViewHandle<Editor>);
6296
6297impl Entity for Editor {
6298    type Event = Event;
6299
6300    fn release(&mut self, cx: &mut MutableAppContext) {
6301        cx.emit_global(EditorReleased(self.handle.clone()));
6302    }
6303}
6304
6305impl View for Editor {
6306    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6307        let style = self.style(cx);
6308        let font_changed = self.display_map.update(cx, |map, cx| {
6309            map.set_font(style.text.font_id, style.text.font_size, cx)
6310        });
6311
6312        if font_changed {
6313            let handle = self.handle.clone();
6314            cx.defer(move |cx| {
6315                if let Some(editor) = handle.upgrade(cx) {
6316                    editor.update(cx, |editor, cx| {
6317                        hide_hover(editor, &HideHover, cx);
6318                        hide_link_definition(editor, cx);
6319                    })
6320                }
6321            });
6322        }
6323
6324        Stack::new()
6325            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6326            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6327            .boxed()
6328    }
6329
6330    fn ui_name() -> &'static str {
6331        "Editor"
6332    }
6333
6334    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6335        if cx.is_self_focused() {
6336            let focused_event = EditorFocused(cx.handle());
6337            cx.emit_global(focused_event);
6338        }
6339        if let Some(rename) = self.pending_rename.as_ref() {
6340            cx.focus(&rename.editor);
6341        } else {
6342            if !self.focused {
6343                self.blink_manager.update(cx, BlinkManager::enable);
6344            }
6345            self.focused = true;
6346            self.buffer.update(cx, |buffer, cx| {
6347                buffer.finalize_last_transaction(cx);
6348                if self.leader_replica_id.is_none() {
6349                    buffer.set_active_selections(
6350                        &self.selections.disjoint_anchors(),
6351                        self.selections.line_mode,
6352                        self.cursor_shape,
6353                        cx,
6354                    );
6355                }
6356            });
6357        }
6358    }
6359
6360    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6361        let blurred_event = EditorBlurred(cx.handle());
6362        cx.emit_global(blurred_event);
6363        self.focused = false;
6364        self.blink_manager.update(cx, BlinkManager::disable);
6365        self.buffer
6366            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6367        self.hide_context_menu(cx);
6368        hide_hover(self, &HideHover, cx);
6369        cx.emit(Event::Blurred);
6370        cx.notify();
6371    }
6372
6373    fn modifiers_changed(
6374        &mut self,
6375        event: &gpui::ModifiersChangedEvent,
6376        cx: &mut ViewContext<Self>,
6377    ) -> bool {
6378        let pending_selection = self.has_pending_selection();
6379
6380        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6381            if event.cmd && !pending_selection {
6382                let snapshot = self.snapshot(cx);
6383                let kind = if event.shift {
6384                    LinkDefinitionKind::Type
6385                } else {
6386                    LinkDefinitionKind::Symbol
6387                };
6388
6389                show_link_definition(kind, self, point, snapshot, cx);
6390                return false;
6391            }
6392        }
6393
6394        {
6395            if self.link_go_to_definition_state.symbol_range.is_some()
6396                || !self.link_go_to_definition_state.definitions.is_empty()
6397            {
6398                self.link_go_to_definition_state.symbol_range.take();
6399                self.link_go_to_definition_state.definitions.clear();
6400                cx.notify();
6401            }
6402
6403            self.link_go_to_definition_state.task = None;
6404
6405            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6406        }
6407
6408        false
6409    }
6410
6411    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6412        let mut context = Self::default_keymap_context();
6413        let mode = match self.mode {
6414            EditorMode::SingleLine => "single_line",
6415            EditorMode::AutoHeight { .. } => "auto_height",
6416            EditorMode::Full => "full",
6417        };
6418        context.map.insert("mode".into(), mode.into());
6419        if self.pending_rename.is_some() {
6420            context.set.insert("renaming".into());
6421        }
6422        match self.context_menu.as_ref() {
6423            Some(ContextMenu::Completions(_)) => {
6424                context.set.insert("showing_completions".into());
6425            }
6426            Some(ContextMenu::CodeActions(_)) => {
6427                context.set.insert("showing_code_actions".into());
6428            }
6429            None => {}
6430        }
6431
6432        for layer in self.keymap_context_layers.values() {
6433            context.extend(layer);
6434        }
6435
6436        context
6437    }
6438
6439    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6440        Some(
6441            self.buffer
6442                .read(cx)
6443                .read(cx)
6444                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6445                .collect(),
6446        )
6447    }
6448
6449    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6450        // Prevent the IME menu from appearing when holding down an alphabetic key
6451        // while input is disabled.
6452        if !self.input_enabled {
6453            return None;
6454        }
6455
6456        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6457        Some(range.start.0..range.end.0)
6458    }
6459
6460    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6461        let snapshot = self.buffer.read(cx).read(cx);
6462        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6463        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6464    }
6465
6466    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6467        self.clear_text_highlights::<InputComposition>(cx);
6468        self.ime_transaction.take();
6469    }
6470
6471    fn replace_text_in_range(
6472        &mut self,
6473        range_utf16: Option<Range<usize>>,
6474        text: &str,
6475        cx: &mut ViewContext<Self>,
6476    ) {
6477        self.transact(cx, |this, cx| {
6478            if this.input_enabled {
6479                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6480                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6481                    Some(this.selection_replacement_ranges(range_utf16, cx))
6482                } else {
6483                    this.marked_text_ranges(cx)
6484                };
6485
6486                if let Some(new_selected_ranges) = new_selected_ranges {
6487                    this.change_selections(None, cx, |selections| {
6488                        selections.select_ranges(new_selected_ranges)
6489                    });
6490                }
6491            }
6492
6493            this.handle_input(text, cx);
6494        });
6495
6496        if !self.input_enabled {
6497            return;
6498        }
6499
6500        if let Some(transaction) = self.ime_transaction {
6501            self.buffer.update(cx, |buffer, cx| {
6502                buffer.group_until_transaction(transaction, cx);
6503            });
6504        }
6505
6506        self.unmark_text(cx);
6507    }
6508
6509    fn replace_and_mark_text_in_range(
6510        &mut self,
6511        range_utf16: Option<Range<usize>>,
6512        text: &str,
6513        new_selected_range_utf16: Option<Range<usize>>,
6514        cx: &mut ViewContext<Self>,
6515    ) {
6516        if !self.input_enabled {
6517            return;
6518        }
6519
6520        let transaction = self.transact(cx, |this, cx| {
6521            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6522                let snapshot = this.buffer.read(cx).read(cx);
6523                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6524                    for marked_range in &mut marked_ranges {
6525                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6526                        marked_range.start.0 += relative_range_utf16.start;
6527                        marked_range.start =
6528                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6529                        marked_range.end =
6530                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6531                    }
6532                }
6533                Some(marked_ranges)
6534            } else if let Some(range_utf16) = range_utf16 {
6535                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6536                Some(this.selection_replacement_ranges(range_utf16, cx))
6537            } else {
6538                None
6539            };
6540
6541            if let Some(ranges) = ranges_to_replace {
6542                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6543            }
6544
6545            let marked_ranges = {
6546                let snapshot = this.buffer.read(cx).read(cx);
6547                this.selections
6548                    .disjoint_anchors()
6549                    .iter()
6550                    .map(|selection| {
6551                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6552                    })
6553                    .collect::<Vec<_>>()
6554            };
6555
6556            if text.is_empty() {
6557                this.unmark_text(cx);
6558            } else {
6559                this.highlight_text::<InputComposition>(
6560                    marked_ranges.clone(),
6561                    this.style(cx).composition_mark,
6562                    cx,
6563                );
6564            }
6565
6566            this.handle_input(text, cx);
6567
6568            if let Some(new_selected_range) = new_selected_range_utf16 {
6569                let snapshot = this.buffer.read(cx).read(cx);
6570                let new_selected_ranges = marked_ranges
6571                    .into_iter()
6572                    .map(|marked_range| {
6573                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6574                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6575                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6576                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6577                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6578                    })
6579                    .collect::<Vec<_>>();
6580
6581                drop(snapshot);
6582                this.change_selections(None, cx, |selections| {
6583                    selections.select_ranges(new_selected_ranges)
6584                });
6585            }
6586        });
6587
6588        self.ime_transaction = self.ime_transaction.or(transaction);
6589        if let Some(transaction) = self.ime_transaction {
6590            self.buffer.update(cx, |buffer, cx| {
6591                buffer.group_until_transaction(transaction, cx);
6592            });
6593        }
6594
6595        if self.text_highlights::<InputComposition>(cx).is_none() {
6596            self.ime_transaction.take();
6597        }
6598    }
6599}
6600
6601fn build_style(
6602    settings: &Settings,
6603    get_field_editor_theme: Option<&GetFieldEditorTheme>,
6604    override_text_style: Option<&OverrideTextStyle>,
6605    cx: &AppContext,
6606) -> EditorStyle {
6607    let font_cache = cx.font_cache();
6608
6609    let mut theme = settings.theme.editor.clone();
6610    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6611        let field_editor_theme = get_field_editor_theme(&settings.theme);
6612        theme.text_color = field_editor_theme.text.color;
6613        theme.selection = field_editor_theme.selection;
6614        theme.background = field_editor_theme
6615            .container
6616            .background_color
6617            .unwrap_or_default();
6618        EditorStyle {
6619            text: field_editor_theme.text,
6620            placeholder_text: field_editor_theme.placeholder_text,
6621            theme,
6622        }
6623    } else {
6624        let font_family_id = settings.buffer_font_family;
6625        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6626        let font_properties = Default::default();
6627        let font_id = font_cache
6628            .select_font(font_family_id, &font_properties)
6629            .unwrap();
6630        let font_size = settings.buffer_font_size;
6631        EditorStyle {
6632            text: TextStyle {
6633                color: settings.theme.editor.text_color,
6634                font_family_name,
6635                font_family_id,
6636                font_id,
6637                font_size,
6638                font_properties,
6639                underline: Default::default(),
6640            },
6641            placeholder_text: None,
6642            theme,
6643        }
6644    };
6645
6646    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6647        if let Some(highlighted) = style
6648            .text
6649            .clone()
6650            .highlight(highlight_style, font_cache)
6651            .log_err()
6652        {
6653            style.text = highlighted;
6654        }
6655    }
6656
6657    style
6658}
6659
6660trait SelectionExt {
6661    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6662    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6663    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6664    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6665        -> Range<u32>;
6666}
6667
6668impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6669    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6670        let start = self.start.to_point(buffer);
6671        let end = self.end.to_point(buffer);
6672        if self.reversed {
6673            end..start
6674        } else {
6675            start..end
6676        }
6677    }
6678
6679    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6680        let start = self.start.to_offset(buffer);
6681        let end = self.end.to_offset(buffer);
6682        if self.reversed {
6683            end..start
6684        } else {
6685            start..end
6686        }
6687    }
6688
6689    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6690        let start = self
6691            .start
6692            .to_point(&map.buffer_snapshot)
6693            .to_display_point(map);
6694        let end = self
6695            .end
6696            .to_point(&map.buffer_snapshot)
6697            .to_display_point(map);
6698        if self.reversed {
6699            end..start
6700        } else {
6701            start..end
6702        }
6703    }
6704
6705    fn spanned_rows(
6706        &self,
6707        include_end_if_at_line_start: bool,
6708        map: &DisplaySnapshot,
6709    ) -> Range<u32> {
6710        let start = self.start.to_point(&map.buffer_snapshot);
6711        let mut end = self.end.to_point(&map.buffer_snapshot);
6712        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6713            end.row -= 1;
6714        }
6715
6716        let buffer_start = map.prev_line_boundary(start).0;
6717        let buffer_end = map.next_line_boundary(end).0;
6718        buffer_start.row..buffer_end.row + 1
6719    }
6720}
6721
6722impl<T: InvalidationRegion> InvalidationStack<T> {
6723    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6724    where
6725        S: Clone + ToOffset,
6726    {
6727        while let Some(region) = self.last() {
6728            let all_selections_inside_invalidation_ranges =
6729                if selections.len() == region.ranges().len() {
6730                    selections
6731                        .iter()
6732                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6733                        .all(|(selection, invalidation_range)| {
6734                            let head = selection.head().to_offset(buffer);
6735                            invalidation_range.start <= head && invalidation_range.end >= head
6736                        })
6737                } else {
6738                    false
6739                };
6740
6741            if all_selections_inside_invalidation_ranges {
6742                break;
6743            } else {
6744                self.pop();
6745            }
6746        }
6747    }
6748}
6749
6750impl<T> Default for InvalidationStack<T> {
6751    fn default() -> Self {
6752        Self(Default::default())
6753    }
6754}
6755
6756impl<T> Deref for InvalidationStack<T> {
6757    type Target = Vec<T>;
6758
6759    fn deref(&self) -> &Self::Target {
6760        &self.0
6761    }
6762}
6763
6764impl<T> DerefMut for InvalidationStack<T> {
6765    fn deref_mut(&mut self) -> &mut Self::Target {
6766        &mut self.0
6767    }
6768}
6769
6770impl InvalidationRegion for SnippetState {
6771    fn ranges(&self) -> &[Range<Anchor>] {
6772        &self.ranges[self.active_index]
6773    }
6774}
6775
6776impl Deref for EditorStyle {
6777    type Target = theme::Editor;
6778
6779    fn deref(&self) -> &Self::Target {
6780        &self.theme
6781    }
6782}
6783
6784pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6785    let mut highlighted_lines = Vec::new();
6786    for line in diagnostic.message.lines() {
6787        highlighted_lines.push(highlight_diagnostic_message(line));
6788    }
6789
6790    Arc::new(move |cx: &mut BlockContext| {
6791        let settings = cx.global::<Settings>();
6792        let theme = &settings.theme.editor;
6793        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6794        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6795        Flex::column()
6796            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6797                Label::new(
6798                    line.clone(),
6799                    style.message.clone().with_font_size(font_size),
6800                )
6801                .with_highlights(highlights.clone())
6802                .contained()
6803                .with_margin_left(cx.anchor_x)
6804                .boxed()
6805            }))
6806            .aligned()
6807            .left()
6808            .boxed()
6809    })
6810}
6811
6812pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6813    let mut message_without_backticks = String::new();
6814    let mut prev_offset = 0;
6815    let mut inside_block = false;
6816    let mut highlights = Vec::new();
6817    for (match_ix, (offset, _)) in message
6818        .match_indices('`')
6819        .chain([(message.len(), "")])
6820        .enumerate()
6821    {
6822        message_without_backticks.push_str(&message[prev_offset..offset]);
6823        if inside_block {
6824            highlights.extend(prev_offset - match_ix..offset - match_ix);
6825        }
6826
6827        inside_block = !inside_block;
6828        prev_offset = offset + 1;
6829    }
6830
6831    (message_without_backticks, highlights)
6832}
6833
6834pub fn diagnostic_style(
6835    severity: DiagnosticSeverity,
6836    valid: bool,
6837    theme: &theme::Editor,
6838) -> DiagnosticStyle {
6839    match (severity, valid) {
6840        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6841        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6842        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6843        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6844        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6845        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6846        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6847        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6848        _ => theme.invalid_hint_diagnostic.clone(),
6849    }
6850}
6851
6852pub fn combine_syntax_and_fuzzy_match_highlights(
6853    text: &str,
6854    default_style: HighlightStyle,
6855    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6856    match_indices: &[usize],
6857) -> Vec<(Range<usize>, HighlightStyle)> {
6858    let mut result = Vec::new();
6859    let mut match_indices = match_indices.iter().copied().peekable();
6860
6861    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6862    {
6863        syntax_highlight.weight = None;
6864
6865        // Add highlights for any fuzzy match characters before the next
6866        // syntax highlight range.
6867        while let Some(&match_index) = match_indices.peek() {
6868            if match_index >= range.start {
6869                break;
6870            }
6871            match_indices.next();
6872            let end_index = char_ix_after(match_index, text);
6873            let mut match_style = default_style;
6874            match_style.weight = Some(fonts::Weight::BOLD);
6875            result.push((match_index..end_index, match_style));
6876        }
6877
6878        if range.start == usize::MAX {
6879            break;
6880        }
6881
6882        // Add highlights for any fuzzy match characters within the
6883        // syntax highlight range.
6884        let mut offset = range.start;
6885        while let Some(&match_index) = match_indices.peek() {
6886            if match_index >= range.end {
6887                break;
6888            }
6889
6890            match_indices.next();
6891            if match_index > offset {
6892                result.push((offset..match_index, syntax_highlight));
6893            }
6894
6895            let mut end_index = char_ix_after(match_index, text);
6896            while let Some(&next_match_index) = match_indices.peek() {
6897                if next_match_index == end_index && next_match_index < range.end {
6898                    end_index = char_ix_after(next_match_index, text);
6899                    match_indices.next();
6900                } else {
6901                    break;
6902                }
6903            }
6904
6905            let mut match_style = syntax_highlight;
6906            match_style.weight = Some(fonts::Weight::BOLD);
6907            result.push((match_index..end_index, match_style));
6908            offset = end_index;
6909        }
6910
6911        if offset < range.end {
6912            result.push((offset..range.end, syntax_highlight));
6913        }
6914    }
6915
6916    fn char_ix_after(ix: usize, text: &str) -> usize {
6917        ix + text[ix..].chars().next().unwrap().len_utf8()
6918    }
6919
6920    result
6921}
6922
6923pub fn styled_runs_for_code_label<'a>(
6924    label: &'a CodeLabel,
6925    syntax_theme: &'a theme::SyntaxTheme,
6926) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6927    let fade_out = HighlightStyle {
6928        fade_out: Some(0.35),
6929        ..Default::default()
6930    };
6931
6932    let mut prev_end = label.filter_range.end;
6933    label
6934        .runs
6935        .iter()
6936        .enumerate()
6937        .flat_map(move |(ix, (range, highlight_id))| {
6938            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6939                style
6940            } else {
6941                return Default::default();
6942            };
6943            let mut muted_style = style;
6944            muted_style.highlight(fade_out);
6945
6946            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6947            if range.start >= label.filter_range.end {
6948                if range.start > prev_end {
6949                    runs.push((prev_end..range.start, fade_out));
6950                }
6951                runs.push((range.clone(), muted_style));
6952            } else if range.end <= label.filter_range.end {
6953                runs.push((range.clone(), style));
6954            } else {
6955                runs.push((range.start..label.filter_range.end, style));
6956                runs.push((label.filter_range.end..range.end, muted_style));
6957            }
6958            prev_end = cmp::max(prev_end, range.end);
6959
6960            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6961                runs.push((prev_end..label.text.len(), fade_out));
6962            }
6963
6964            runs
6965        })
6966}
6967
6968pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
6969    let mut index = 0;
6970    let mut codepoints = text.char_indices().peekable();
6971
6972    std::iter::from_fn(move || {
6973        let start_index = index;
6974        while let Some((new_index, codepoint)) = codepoints.next() {
6975            index = new_index + codepoint.len_utf8();
6976            let current_upper = codepoint.is_uppercase();
6977            let next_upper = codepoints
6978                .peek()
6979                .map(|(_, c)| c.is_uppercase())
6980                .unwrap_or(false);
6981
6982            if !current_upper && next_upper {
6983                return Some(&text[start_index..index]);
6984            }
6985        }
6986
6987        index = text.len();
6988        if start_index < text.len() {
6989            return Some(&text[start_index..]);
6990        }
6991        None
6992    })
6993    .flat_map(|word| word.split_inclusive('_'))
6994}
6995
6996trait RangeExt<T> {
6997    fn sorted(&self) -> Range<T>;
6998    fn to_inclusive(&self) -> RangeInclusive<T>;
6999}
7000
7001impl<T: Ord + Clone> RangeExt<T> for Range<T> {
7002    fn sorted(&self) -> Self {
7003        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
7004    }
7005
7006    fn to_inclusive(&self) -> RangeInclusive<T> {
7007        self.start.clone()..=self.end.clone()
7008    }
7009}
7010
7011trait RangeToAnchorExt {
7012    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7013}
7014
7015impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7016    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7017        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7018    }
7019}