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