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