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