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