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