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