editor.rs

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