editor.rs

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