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