editor.rs

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