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