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