editor.rs

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