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