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