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