editor.rs

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