editor.rs

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