editor.rs

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