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