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