editor.rs

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