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