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                // TODO kb wrong?
7244                false
7245            }
7246            multi_buffer::Event::ExcerptsRemoved { ids } => {
7247                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() });
7248                false
7249            }
7250            multi_buffer::Event::Reparsed => {
7251                cx.emit(Event::Reparsed);
7252                true
7253            }
7254            multi_buffer::Event::DirtyChanged => {
7255                cx.emit(Event::DirtyChanged);
7256                true
7257            }
7258            multi_buffer::Event::Saved => {
7259                cx.emit(Event::Saved);
7260                false
7261            }
7262            multi_buffer::Event::FileHandleChanged => {
7263                cx.emit(Event::TitleChanged);
7264                true
7265            }
7266            multi_buffer::Event::Reloaded => {
7267                cx.emit(Event::TitleChanged);
7268                true
7269            }
7270            multi_buffer::Event::DiffBaseChanged => {
7271                cx.emit(Event::DiffBaseChanged);
7272                true
7273            }
7274            multi_buffer::Event::Closed => {
7275                cx.emit(Event::Closed);
7276                false
7277            }
7278            multi_buffer::Event::DiagnosticsUpdated => {
7279                self.refresh_active_diagnostics(cx);
7280                false
7281            }
7282            _ => true,
7283        };
7284
7285        if update_inlay_hints {
7286            self.try_update_inlay_hints(cx);
7287        }
7288    }
7289
7290    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7291        cx.notify();
7292    }
7293
7294    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7295        self.refresh_copilot_suggestions(true, cx);
7296    }
7297
7298    pub fn set_searchable(&mut self, searchable: bool) {
7299        self.searchable = searchable;
7300    }
7301
7302    pub fn searchable(&self) -> bool {
7303        self.searchable
7304    }
7305
7306    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7307        let active_item = workspace.active_item(cx);
7308        let editor_handle = if let Some(editor) = active_item
7309            .as_ref()
7310            .and_then(|item| item.act_as::<Self>(cx))
7311        {
7312            editor
7313        } else {
7314            cx.propagate_action();
7315            return;
7316        };
7317
7318        let editor = editor_handle.read(cx);
7319        let buffer = editor.buffer.read(cx);
7320        if buffer.is_singleton() {
7321            cx.propagate_action();
7322            return;
7323        }
7324
7325        let mut new_selections_by_buffer = HashMap::default();
7326        for selection in editor.selections.all::<usize>(cx) {
7327            for (buffer, mut range, _) in
7328                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7329            {
7330                if selection.reversed {
7331                    mem::swap(&mut range.start, &mut range.end);
7332                }
7333                new_selections_by_buffer
7334                    .entry(buffer)
7335                    .or_insert(Vec::new())
7336                    .push(range)
7337            }
7338        }
7339
7340        editor_handle.update(cx, |editor, cx| {
7341            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7342        });
7343        let pane = workspace.active_pane().clone();
7344        pane.update(cx, |pane, _| pane.disable_history());
7345
7346        // We defer the pane interaction because we ourselves are a workspace item
7347        // and activating a new item causes the pane to call a method on us reentrantly,
7348        // which panics if we're on the stack.
7349        cx.defer(move |workspace, cx| {
7350            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7351                let editor = workspace.open_project_item::<Self>(buffer, cx);
7352                editor.update(cx, |editor, cx| {
7353                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7354                        s.select_ranges(ranges);
7355                    });
7356                });
7357            }
7358
7359            pane.update(cx, |pane, _| pane.enable_history());
7360        });
7361    }
7362
7363    fn jump(
7364        workspace: &mut Workspace,
7365        path: ProjectPath,
7366        position: Point,
7367        anchor: language::Anchor,
7368        cx: &mut ViewContext<Workspace>,
7369    ) {
7370        let editor = workspace.open_path(path, None, true, cx);
7371        cx.spawn(|_, mut cx| async move {
7372            let editor = editor
7373                .await?
7374                .downcast::<Editor>()
7375                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7376                .downgrade();
7377            editor.update(&mut cx, |editor, cx| {
7378                let buffer = editor
7379                    .buffer()
7380                    .read(cx)
7381                    .as_singleton()
7382                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7383                let buffer = buffer.read(cx);
7384                let cursor = if buffer.can_resolve(&anchor) {
7385                    language::ToPoint::to_point(&anchor, buffer)
7386                } else {
7387                    buffer.clip_point(position, Bias::Left)
7388                };
7389
7390                let nav_history = editor.nav_history.take();
7391                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7392                    s.select_ranges([cursor..cursor]);
7393                });
7394                editor.nav_history = nav_history;
7395
7396                anyhow::Ok(())
7397            })??;
7398
7399            anyhow::Ok(())
7400        })
7401        .detach_and_log_err(cx);
7402    }
7403
7404    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7405        let snapshot = self.buffer.read(cx).read(cx);
7406        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7407        Some(
7408            ranges
7409                .iter()
7410                .map(move |range| {
7411                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7412                })
7413                .collect(),
7414        )
7415    }
7416
7417    fn selection_replacement_ranges(
7418        &self,
7419        range: Range<OffsetUtf16>,
7420        cx: &AppContext,
7421    ) -> Vec<Range<OffsetUtf16>> {
7422        let selections = self.selections.all::<OffsetUtf16>(cx);
7423        let newest_selection = selections
7424            .iter()
7425            .max_by_key(|selection| selection.id)
7426            .unwrap();
7427        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7428        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7429        let snapshot = self.buffer.read(cx).read(cx);
7430        selections
7431            .into_iter()
7432            .map(|mut selection| {
7433                selection.start.0 =
7434                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7435                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7436                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7437                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7438            })
7439            .collect()
7440    }
7441
7442    fn report_copilot_event(
7443        &self,
7444        suggestion_id: Option<String>,
7445        suggestion_accepted: bool,
7446        cx: &AppContext,
7447    ) {
7448        let Some(project) = &self.project else {
7449            return
7450        };
7451
7452        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7453        let file_extension = self
7454            .buffer
7455            .read(cx)
7456            .as_singleton()
7457            .and_then(|b| b.read(cx).file())
7458            .and_then(|file| Path::new(file.file_name(cx)).extension())
7459            .and_then(|e| e.to_str())
7460            .map(|a| a.to_string());
7461
7462        let telemetry = project.read(cx).client().telemetry().clone();
7463        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7464
7465        let event = ClickhouseEvent::Copilot {
7466            suggestion_id,
7467            suggestion_accepted,
7468            file_extension,
7469        };
7470        telemetry.report_clickhouse_event(event, telemetry_settings);
7471    }
7472
7473    fn report_editor_event(
7474        &self,
7475        name: &'static str,
7476        file_extension: Option<String>,
7477        cx: &AppContext,
7478    ) {
7479        let Some(project) = &self.project else {
7480            return
7481        };
7482
7483        // If None, we are in a file without an extension
7484        let file = self
7485            .buffer
7486            .read(cx)
7487            .as_singleton()
7488            .and_then(|b| b.read(cx).file());
7489        let file_extension = file_extension.or(file
7490            .as_ref()
7491            .and_then(|file| Path::new(file.file_name(cx)).extension())
7492            .and_then(|e| e.to_str())
7493            .map(|a| a.to_string()));
7494
7495        let vim_mode = cx
7496            .global::<SettingsStore>()
7497            .raw_user_settings()
7498            .get("vim_mode")
7499            == Some(&serde_json::Value::Bool(true));
7500        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7501        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7502        let copilot_enabled_for_language = self
7503            .buffer
7504            .read(cx)
7505            .settings_at(0, cx)
7506            .show_copilot_suggestions;
7507
7508        let telemetry = project.read(cx).client().telemetry().clone();
7509        let event = ClickhouseEvent::Editor {
7510            file_extension,
7511            vim_mode,
7512            operation: name,
7513            copilot_enabled,
7514            copilot_enabled_for_language,
7515        };
7516        telemetry.report_clickhouse_event(event, telemetry_settings)
7517    }
7518
7519    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7520    /// with each line being an array of {text, highlight} objects.
7521    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7522        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7523            return;
7524        };
7525
7526        #[derive(Serialize)]
7527        struct Chunk<'a> {
7528            text: String,
7529            highlight: Option<&'a str>,
7530        }
7531
7532        let snapshot = buffer.read(cx).snapshot();
7533        let range = self
7534            .selected_text_range(cx)
7535            .and_then(|selected_range| {
7536                if selected_range.is_empty() {
7537                    None
7538                } else {
7539                    Some(selected_range)
7540                }
7541            })
7542            .unwrap_or_else(|| 0..snapshot.len());
7543
7544        let chunks = snapshot.chunks(range, true);
7545        let mut lines = Vec::new();
7546        let mut line: VecDeque<Chunk> = VecDeque::new();
7547
7548        let theme = &theme::current(cx).editor.syntax;
7549
7550        for chunk in chunks {
7551            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7552            let mut chunk_lines = chunk.text.split("\n").peekable();
7553            while let Some(text) = chunk_lines.next() {
7554                let mut merged_with_last_token = false;
7555                if let Some(last_token) = line.back_mut() {
7556                    if last_token.highlight == highlight {
7557                        last_token.text.push_str(text);
7558                        merged_with_last_token = true;
7559                    }
7560                }
7561
7562                if !merged_with_last_token {
7563                    line.push_back(Chunk {
7564                        text: text.into(),
7565                        highlight,
7566                    });
7567                }
7568
7569                if chunk_lines.peek().is_some() {
7570                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7571                        line.pop_front();
7572                    }
7573                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7574                        line.pop_back();
7575                    }
7576
7577                    lines.push(mem::take(&mut line));
7578                }
7579            }
7580        }
7581
7582        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7583        cx.write_to_clipboard(ClipboardItem::new(lines));
7584    }
7585}
7586
7587fn consume_contiguous_rows(
7588    contiguous_row_selections: &mut Vec<Selection<Point>>,
7589    selection: &Selection<Point>,
7590    display_map: &DisplaySnapshot,
7591    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7592) -> (u32, u32) {
7593    contiguous_row_selections.push(selection.clone());
7594    let start_row = selection.start.row;
7595    let mut end_row = ending_row(selection, display_map);
7596
7597    while let Some(next_selection) = selections.peek() {
7598        if next_selection.start.row <= end_row {
7599            end_row = ending_row(next_selection, display_map);
7600            contiguous_row_selections.push(selections.next().unwrap().clone());
7601        } else {
7602            break;
7603        }
7604    }
7605    (start_row, end_row)
7606}
7607
7608fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7609    if next_selection.end.column > 0 || next_selection.is_empty() {
7610        display_map.next_line_boundary(next_selection.end).0.row + 1
7611    } else {
7612        next_selection.end.row
7613    }
7614}
7615
7616impl EditorSnapshot {
7617    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7618        self.display_snapshot.buffer_snapshot.language_at(position)
7619    }
7620
7621    pub fn is_focused(&self) -> bool {
7622        self.is_focused
7623    }
7624
7625    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7626        self.placeholder_text.as_ref()
7627    }
7628
7629    pub fn scroll_position(&self) -> Vector2F {
7630        self.scroll_anchor.scroll_position(&self.display_snapshot)
7631    }
7632}
7633
7634impl Deref for EditorSnapshot {
7635    type Target = DisplaySnapshot;
7636
7637    fn deref(&self) -> &Self::Target {
7638        &self.display_snapshot
7639    }
7640}
7641
7642#[derive(Clone, Debug, PartialEq, Eq)]
7643pub enum Event {
7644    InputIgnored {
7645        text: Arc<str>,
7646    },
7647    ExcerptsAdded {
7648        buffer: ModelHandle<Buffer>,
7649        predecessor: ExcerptId,
7650        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7651    },
7652    ExcerptsRemoved {
7653        ids: Vec<ExcerptId>,
7654    },
7655    BufferEdited,
7656    Edited,
7657    Reparsed,
7658    Focused,
7659    Blurred,
7660    DirtyChanged,
7661    Saved,
7662    TitleChanged,
7663    DiffBaseChanged,
7664    SelectionsChanged {
7665        local: bool,
7666    },
7667    ScrollPositionChanged {
7668        local: bool,
7669        autoscroll: bool,
7670    },
7671    Closed,
7672}
7673
7674pub struct EditorFocused(pub ViewHandle<Editor>);
7675pub struct EditorBlurred(pub ViewHandle<Editor>);
7676pub struct EditorReleased(pub WeakViewHandle<Editor>);
7677
7678impl Entity for Editor {
7679    type Event = Event;
7680
7681    fn release(&mut self, cx: &mut AppContext) {
7682        cx.emit_global(EditorReleased(self.handle.clone()));
7683    }
7684}
7685
7686impl View for Editor {
7687    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7688        let style = self.style(cx);
7689        let font_changed = self.display_map.update(cx, |map, cx| {
7690            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7691            map.set_font(style.text.font_id, style.text.font_size, cx)
7692        });
7693
7694        if font_changed {
7695            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7696                hide_hover(editor, cx);
7697                hide_link_definition(editor, cx);
7698            });
7699        }
7700
7701        Stack::new()
7702            .with_child(EditorElement::new(style.clone()))
7703            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7704            .into_any()
7705    }
7706
7707    fn ui_name() -> &'static str {
7708        "Editor"
7709    }
7710
7711    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7712        if cx.is_self_focused() {
7713            let focused_event = EditorFocused(cx.handle());
7714            cx.emit(Event::Focused);
7715            cx.emit_global(focused_event);
7716        }
7717        if let Some(rename) = self.pending_rename.as_ref() {
7718            cx.focus(&rename.editor);
7719        } else {
7720            if !self.focused {
7721                self.blink_manager.update(cx, BlinkManager::enable);
7722            }
7723            self.focused = true;
7724            self.buffer.update(cx, |buffer, cx| {
7725                buffer.finalize_last_transaction(cx);
7726                if self.leader_replica_id.is_none() {
7727                    buffer.set_active_selections(
7728                        &self.selections.disjoint_anchors(),
7729                        self.selections.line_mode,
7730                        self.cursor_shape,
7731                        cx,
7732                    );
7733                }
7734            });
7735        }
7736    }
7737
7738    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7739        let blurred_event = EditorBlurred(cx.handle());
7740        cx.emit_global(blurred_event);
7741        self.focused = false;
7742        self.blink_manager.update(cx, BlinkManager::disable);
7743        self.buffer
7744            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7745        self.hide_context_menu(cx);
7746        hide_hover(self, cx);
7747        cx.emit(Event::Blurred);
7748        cx.notify();
7749    }
7750
7751    fn modifiers_changed(
7752        &mut self,
7753        event: &gpui::platform::ModifiersChangedEvent,
7754        cx: &mut ViewContext<Self>,
7755    ) -> bool {
7756        let pending_selection = self.has_pending_selection();
7757
7758        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7759            if event.cmd && !pending_selection {
7760                let snapshot = self.snapshot(cx);
7761                let kind = if event.shift {
7762                    LinkDefinitionKind::Type
7763                } else {
7764                    LinkDefinitionKind::Symbol
7765                };
7766
7767                show_link_definition(kind, self, point, snapshot, cx);
7768                return false;
7769            }
7770        }
7771
7772        {
7773            if self.link_go_to_definition_state.symbol_range.is_some()
7774                || !self.link_go_to_definition_state.definitions.is_empty()
7775            {
7776                self.link_go_to_definition_state.symbol_range.take();
7777                self.link_go_to_definition_state.definitions.clear();
7778                cx.notify();
7779            }
7780
7781            self.link_go_to_definition_state.task = None;
7782
7783            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7784        }
7785
7786        false
7787    }
7788
7789    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7790        Self::reset_to_default_keymap_context(keymap);
7791        let mode = match self.mode {
7792            EditorMode::SingleLine => "single_line",
7793            EditorMode::AutoHeight { .. } => "auto_height",
7794            EditorMode::Full => "full",
7795        };
7796        keymap.add_key("mode", mode);
7797        if self.pending_rename.is_some() {
7798            keymap.add_identifier("renaming");
7799        }
7800        match self.context_menu.as_ref() {
7801            Some(ContextMenu::Completions(_)) => {
7802                keymap.add_identifier("menu");
7803                keymap.add_identifier("showing_completions")
7804            }
7805            Some(ContextMenu::CodeActions(_)) => {
7806                keymap.add_identifier("menu");
7807                keymap.add_identifier("showing_code_actions")
7808            }
7809            None => {}
7810        }
7811        for layer in self.keymap_context_layers.values() {
7812            keymap.extend(layer);
7813        }
7814
7815        if let Some(extension) = self
7816            .buffer
7817            .read(cx)
7818            .as_singleton()
7819            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7820        {
7821            keymap.add_key("extension", extension.to_string());
7822        }
7823    }
7824
7825    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7826        Some(
7827            self.buffer
7828                .read(cx)
7829                .read(cx)
7830                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7831                .collect(),
7832        )
7833    }
7834
7835    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7836        // Prevent the IME menu from appearing when holding down an alphabetic key
7837        // while input is disabled.
7838        if !self.input_enabled {
7839            return None;
7840        }
7841
7842        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7843        Some(range.start.0..range.end.0)
7844    }
7845
7846    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7847        let snapshot = self.buffer.read(cx).read(cx);
7848        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7849        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7850    }
7851
7852    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7853        self.clear_text_highlights::<InputComposition>(cx);
7854        self.ime_transaction.take();
7855    }
7856
7857    fn replace_text_in_range(
7858        &mut self,
7859        range_utf16: Option<Range<usize>>,
7860        text: &str,
7861        cx: &mut ViewContext<Self>,
7862    ) {
7863        self.transact(cx, |this, cx| {
7864            if this.input_enabled {
7865                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7866                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7867                    Some(this.selection_replacement_ranges(range_utf16, cx))
7868                } else {
7869                    this.marked_text_ranges(cx)
7870                };
7871
7872                if let Some(new_selected_ranges) = new_selected_ranges {
7873                    this.change_selections(None, cx, |selections| {
7874                        selections.select_ranges(new_selected_ranges)
7875                    });
7876                }
7877            }
7878
7879            this.handle_input(text, cx);
7880        });
7881
7882        if !self.input_enabled {
7883            return;
7884        }
7885
7886        if let Some(transaction) = self.ime_transaction {
7887            self.buffer.update(cx, |buffer, cx| {
7888                buffer.group_until_transaction(transaction, cx);
7889            });
7890        }
7891
7892        self.unmark_text(cx);
7893    }
7894
7895    fn replace_and_mark_text_in_range(
7896        &mut self,
7897        range_utf16: Option<Range<usize>>,
7898        text: &str,
7899        new_selected_range_utf16: Option<Range<usize>>,
7900        cx: &mut ViewContext<Self>,
7901    ) {
7902        if !self.input_enabled {
7903            return;
7904        }
7905
7906        let transaction = self.transact(cx, |this, cx| {
7907            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7908                let snapshot = this.buffer.read(cx).read(cx);
7909                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7910                    for marked_range in &mut marked_ranges {
7911                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7912                        marked_range.start.0 += relative_range_utf16.start;
7913                        marked_range.start =
7914                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7915                        marked_range.end =
7916                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7917                    }
7918                }
7919                Some(marked_ranges)
7920            } else if let Some(range_utf16) = range_utf16 {
7921                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7922                Some(this.selection_replacement_ranges(range_utf16, cx))
7923            } else {
7924                None
7925            };
7926
7927            if let Some(ranges) = ranges_to_replace {
7928                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7929            }
7930
7931            let marked_ranges = {
7932                let snapshot = this.buffer.read(cx).read(cx);
7933                this.selections
7934                    .disjoint_anchors()
7935                    .iter()
7936                    .map(|selection| {
7937                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7938                    })
7939                    .collect::<Vec<_>>()
7940            };
7941
7942            if text.is_empty() {
7943                this.unmark_text(cx);
7944            } else {
7945                this.highlight_text::<InputComposition>(
7946                    marked_ranges.clone(),
7947                    this.style(cx).composition_mark,
7948                    cx,
7949                );
7950            }
7951
7952            this.handle_input(text, cx);
7953
7954            if let Some(new_selected_range) = new_selected_range_utf16 {
7955                let snapshot = this.buffer.read(cx).read(cx);
7956                let new_selected_ranges = marked_ranges
7957                    .into_iter()
7958                    .map(|marked_range| {
7959                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7960                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7961                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7962                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7963                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7964                    })
7965                    .collect::<Vec<_>>();
7966
7967                drop(snapshot);
7968                this.change_selections(None, cx, |selections| {
7969                    selections.select_ranges(new_selected_ranges)
7970                });
7971            }
7972        });
7973
7974        self.ime_transaction = self.ime_transaction.or(transaction);
7975        if let Some(transaction) = self.ime_transaction {
7976            self.buffer.update(cx, |buffer, cx| {
7977                buffer.group_until_transaction(transaction, cx);
7978            });
7979        }
7980
7981        if self.text_highlights::<InputComposition>(cx).is_none() {
7982            self.ime_transaction.take();
7983        }
7984    }
7985}
7986
7987fn build_style(
7988    settings: &ThemeSettings,
7989    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7990    override_text_style: Option<&OverrideTextStyle>,
7991    cx: &AppContext,
7992) -> EditorStyle {
7993    let font_cache = cx.font_cache();
7994
7995    let theme_id = settings.theme.meta.id;
7996    let mut theme = settings.theme.editor.clone();
7997    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7998        let field_editor_theme = get_field_editor_theme(&settings.theme);
7999        theme.text_color = field_editor_theme.text.color;
8000        theme.selection = field_editor_theme.selection;
8001        theme.background = field_editor_theme
8002            .container
8003            .background_color
8004            .unwrap_or_default();
8005        EditorStyle {
8006            text: field_editor_theme.text,
8007            placeholder_text: field_editor_theme.placeholder_text,
8008            theme,
8009            theme_id,
8010        }
8011    } else {
8012        let font_family_id = settings.buffer_font_family;
8013        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8014        let font_properties = Default::default();
8015        let font_id = font_cache
8016            .select_font(font_family_id, &font_properties)
8017            .unwrap();
8018        let font_size = settings.buffer_font_size(cx);
8019        EditorStyle {
8020            text: TextStyle {
8021                color: settings.theme.editor.text_color,
8022                font_family_name,
8023                font_family_id,
8024                font_id,
8025                font_size,
8026                font_properties,
8027                underline: Default::default(),
8028            },
8029            placeholder_text: None,
8030            theme,
8031            theme_id,
8032        }
8033    };
8034
8035    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8036        if let Some(highlighted) = style
8037            .text
8038            .clone()
8039            .highlight(highlight_style, font_cache)
8040            .log_err()
8041        {
8042            style.text = highlighted;
8043        }
8044    }
8045
8046    style
8047}
8048
8049trait SelectionExt {
8050    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8051    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8052    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8053    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8054        -> Range<u32>;
8055}
8056
8057impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8058    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8059        let start = self.start.to_point(buffer);
8060        let end = self.end.to_point(buffer);
8061        if self.reversed {
8062            end..start
8063        } else {
8064            start..end
8065        }
8066    }
8067
8068    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8069        let start = self.start.to_offset(buffer);
8070        let end = self.end.to_offset(buffer);
8071        if self.reversed {
8072            end..start
8073        } else {
8074            start..end
8075        }
8076    }
8077
8078    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8079        let start = self
8080            .start
8081            .to_point(&map.buffer_snapshot)
8082            .to_display_point(map);
8083        let end = self
8084            .end
8085            .to_point(&map.buffer_snapshot)
8086            .to_display_point(map);
8087        if self.reversed {
8088            end..start
8089        } else {
8090            start..end
8091        }
8092    }
8093
8094    fn spanned_rows(
8095        &self,
8096        include_end_if_at_line_start: bool,
8097        map: &DisplaySnapshot,
8098    ) -> Range<u32> {
8099        let start = self.start.to_point(&map.buffer_snapshot);
8100        let mut end = self.end.to_point(&map.buffer_snapshot);
8101        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8102            end.row -= 1;
8103        }
8104
8105        let buffer_start = map.prev_line_boundary(start).0;
8106        let buffer_end = map.next_line_boundary(end).0;
8107        buffer_start.row..buffer_end.row + 1
8108    }
8109}
8110
8111impl<T: InvalidationRegion> InvalidationStack<T> {
8112    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8113    where
8114        S: Clone + ToOffset,
8115    {
8116        while let Some(region) = self.last() {
8117            let all_selections_inside_invalidation_ranges =
8118                if selections.len() == region.ranges().len() {
8119                    selections
8120                        .iter()
8121                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8122                        .all(|(selection, invalidation_range)| {
8123                            let head = selection.head().to_offset(buffer);
8124                            invalidation_range.start <= head && invalidation_range.end >= head
8125                        })
8126                } else {
8127                    false
8128                };
8129
8130            if all_selections_inside_invalidation_ranges {
8131                break;
8132            } else {
8133                self.pop();
8134            }
8135        }
8136    }
8137}
8138
8139impl<T> Default for InvalidationStack<T> {
8140    fn default() -> Self {
8141        Self(Default::default())
8142    }
8143}
8144
8145impl<T> Deref for InvalidationStack<T> {
8146    type Target = Vec<T>;
8147
8148    fn deref(&self) -> &Self::Target {
8149        &self.0
8150    }
8151}
8152
8153impl<T> DerefMut for InvalidationStack<T> {
8154    fn deref_mut(&mut self) -> &mut Self::Target {
8155        &mut self.0
8156    }
8157}
8158
8159impl InvalidationRegion for SnippetState {
8160    fn ranges(&self) -> &[Range<Anchor>] {
8161        &self.ranges[self.active_index]
8162    }
8163}
8164
8165impl Deref for EditorStyle {
8166    type Target = theme::Editor;
8167
8168    fn deref(&self) -> &Self::Target {
8169        &self.theme
8170    }
8171}
8172
8173pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8174    let mut highlighted_lines = Vec::new();
8175
8176    for (index, line) in diagnostic.message.lines().enumerate() {
8177        let line = match &diagnostic.source {
8178            Some(source) if index == 0 => {
8179                let source_highlight = Vec::from_iter(0..source.len());
8180                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8181            }
8182
8183            _ => highlight_diagnostic_message(Vec::new(), line),
8184        };
8185        highlighted_lines.push(line);
8186    }
8187    let message = diagnostic.message;
8188    Arc::new(move |cx: &mut BlockContext| {
8189        let message = message.clone();
8190        let settings = settings::get::<ThemeSettings>(cx);
8191        let tooltip_style = settings.theme.tooltip.clone();
8192        let theme = &settings.theme.editor;
8193        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8194        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8195        let anchor_x = cx.anchor_x;
8196        enum BlockContextToolip {}
8197        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
8198            Flex::column()
8199                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8200                    Label::new(
8201                        line.clone(),
8202                        style.message.clone().with_font_size(font_size),
8203                    )
8204                    .with_highlights(highlights.clone())
8205                    .contained()
8206                    .with_margin_left(anchor_x)
8207                }))
8208                .aligned()
8209                .left()
8210                .into_any()
8211        })
8212        .with_cursor_style(CursorStyle::PointingHand)
8213        .on_click(MouseButton::Left, move |_, _, cx| {
8214            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8215        })
8216        // We really need to rethink this ID system...
8217        .with_tooltip::<BlockContextToolip>(
8218            cx.block_id,
8219            "Copy diagnostic message".to_string(),
8220            None,
8221            tooltip_style,
8222            cx,
8223        )
8224        .into_any()
8225    })
8226}
8227
8228pub fn highlight_diagnostic_message(
8229    initial_highlights: Vec<usize>,
8230    message: &str,
8231) -> (String, Vec<usize>) {
8232    let mut message_without_backticks = String::new();
8233    let mut prev_offset = 0;
8234    let mut inside_block = false;
8235    let mut highlights = initial_highlights;
8236    for (match_ix, (offset, _)) in message
8237        .match_indices('`')
8238        .chain([(message.len(), "")])
8239        .enumerate()
8240    {
8241        message_without_backticks.push_str(&message[prev_offset..offset]);
8242        if inside_block {
8243            highlights.extend(prev_offset - match_ix..offset - match_ix);
8244        }
8245
8246        inside_block = !inside_block;
8247        prev_offset = offset + 1;
8248    }
8249
8250    (message_without_backticks, highlights)
8251}
8252
8253pub fn diagnostic_style(
8254    severity: DiagnosticSeverity,
8255    valid: bool,
8256    theme: &theme::Editor,
8257) -> DiagnosticStyle {
8258    match (severity, valid) {
8259        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8260        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8261        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8262        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8263        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8264        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8265        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8266        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8267        _ => theme.invalid_hint_diagnostic.clone(),
8268    }
8269}
8270
8271pub fn combine_syntax_and_fuzzy_match_highlights(
8272    text: &str,
8273    default_style: HighlightStyle,
8274    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8275    match_indices: &[usize],
8276) -> Vec<(Range<usize>, HighlightStyle)> {
8277    let mut result = Vec::new();
8278    let mut match_indices = match_indices.iter().copied().peekable();
8279
8280    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8281    {
8282        syntax_highlight.weight = None;
8283
8284        // Add highlights for any fuzzy match characters before the next
8285        // syntax highlight range.
8286        while let Some(&match_index) = match_indices.peek() {
8287            if match_index >= range.start {
8288                break;
8289            }
8290            match_indices.next();
8291            let end_index = char_ix_after(match_index, text);
8292            let mut match_style = default_style;
8293            match_style.weight = Some(fonts::Weight::BOLD);
8294            result.push((match_index..end_index, match_style));
8295        }
8296
8297        if range.start == usize::MAX {
8298            break;
8299        }
8300
8301        // Add highlights for any fuzzy match characters within the
8302        // syntax highlight range.
8303        let mut offset = range.start;
8304        while let Some(&match_index) = match_indices.peek() {
8305            if match_index >= range.end {
8306                break;
8307            }
8308
8309            match_indices.next();
8310            if match_index > offset {
8311                result.push((offset..match_index, syntax_highlight));
8312            }
8313
8314            let mut end_index = char_ix_after(match_index, text);
8315            while let Some(&next_match_index) = match_indices.peek() {
8316                if next_match_index == end_index && next_match_index < range.end {
8317                    end_index = char_ix_after(next_match_index, text);
8318                    match_indices.next();
8319                } else {
8320                    break;
8321                }
8322            }
8323
8324            let mut match_style = syntax_highlight;
8325            match_style.weight = Some(fonts::Weight::BOLD);
8326            result.push((match_index..end_index, match_style));
8327            offset = end_index;
8328        }
8329
8330        if offset < range.end {
8331            result.push((offset..range.end, syntax_highlight));
8332        }
8333    }
8334
8335    fn char_ix_after(ix: usize, text: &str) -> usize {
8336        ix + text[ix..].chars().next().unwrap().len_utf8()
8337    }
8338
8339    result
8340}
8341
8342pub fn styled_runs_for_code_label<'a>(
8343    label: &'a CodeLabel,
8344    syntax_theme: &'a theme::SyntaxTheme,
8345) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8346    let fade_out = HighlightStyle {
8347        fade_out: Some(0.35),
8348        ..Default::default()
8349    };
8350
8351    let mut prev_end = label.filter_range.end;
8352    label
8353        .runs
8354        .iter()
8355        .enumerate()
8356        .flat_map(move |(ix, (range, highlight_id))| {
8357            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8358                style
8359            } else {
8360                return Default::default();
8361            };
8362            let mut muted_style = style;
8363            muted_style.highlight(fade_out);
8364
8365            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8366            if range.start >= label.filter_range.end {
8367                if range.start > prev_end {
8368                    runs.push((prev_end..range.start, fade_out));
8369                }
8370                runs.push((range.clone(), muted_style));
8371            } else if range.end <= label.filter_range.end {
8372                runs.push((range.clone(), style));
8373            } else {
8374                runs.push((range.start..label.filter_range.end, style));
8375                runs.push((label.filter_range.end..range.end, muted_style));
8376            }
8377            prev_end = cmp::max(prev_end, range.end);
8378
8379            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8380                runs.push((prev_end..label.text.len(), fade_out));
8381            }
8382
8383            runs
8384        })
8385}
8386
8387pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8388    let mut index = 0;
8389    let mut codepoints = text.char_indices().peekable();
8390
8391    std::iter::from_fn(move || {
8392        let start_index = index;
8393        while let Some((new_index, codepoint)) = codepoints.next() {
8394            index = new_index + codepoint.len_utf8();
8395            let current_upper = codepoint.is_uppercase();
8396            let next_upper = codepoints
8397                .peek()
8398                .map(|(_, c)| c.is_uppercase())
8399                .unwrap_or(false);
8400
8401            if !current_upper && next_upper {
8402                return Some(&text[start_index..index]);
8403            }
8404        }
8405
8406        index = text.len();
8407        if start_index < text.len() {
8408            return Some(&text[start_index..]);
8409        }
8410        None
8411    })
8412    .flat_map(|word| word.split_inclusive('_'))
8413}
8414
8415trait RangeToAnchorExt {
8416    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8417}
8418
8419impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8420    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8421        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8422    }
8423}