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        if let Some(InlaySplice {
2676            to_remove,
2677            to_insert,
2678        }) = self.inlay_hint_cache.spawn_hint_refresh(
2679            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
2680            invalidate_cache,
2681            cx,
2682        ) {
2683            self.splice_inlay_hints(to_remove, to_insert, cx);
2684        }
2685    }
2686
2687    fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> {
2688        self.display_map
2689            .read(cx)
2690            .current_inlays()
2691            .filter(move |inlay| {
2692                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
2693            })
2694            .cloned()
2695            .collect()
2696    }
2697
2698    fn excerpt_visible_offsets(
2699        &self,
2700        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
2701        cx: &mut ViewContext<'_, '_, Editor>,
2702    ) -> HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)> {
2703        let multi_buffer = self.buffer().read(cx);
2704        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
2705        let multi_buffer_visible_start = self
2706            .scroll_manager
2707            .anchor()
2708            .anchor
2709            .to_point(&multi_buffer_snapshot);
2710        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
2711            multi_buffer_visible_start
2712                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
2713            Bias::Left,
2714        );
2715        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
2716        multi_buffer
2717            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
2718            .into_iter()
2719            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
2720            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
2721                let buffer = buffer_handle.read(cx);
2722                let language = buffer.language()?;
2723                if let Some(restrict_to_languages) = restrict_to_languages {
2724                    if !restrict_to_languages.contains(language) {
2725                        return None;
2726                    }
2727                }
2728                Some((
2729                    excerpt_id,
2730                    (
2731                        buffer_handle,
2732                        buffer.version().clone(),
2733                        excerpt_visible_range,
2734                    ),
2735                ))
2736            })
2737            .collect()
2738    }
2739
2740    fn splice_inlay_hints(
2741        &self,
2742        to_remove: Vec<InlayId>,
2743        to_insert: Vec<Inlay>,
2744        cx: &mut ViewContext<Self>,
2745    ) {
2746        self.display_map.update(cx, |display_map, cx| {
2747            display_map.splice_inlays(to_remove, to_insert, cx);
2748        });
2749    }
2750
2751    fn trigger_on_type_formatting(
2752        &self,
2753        input: String,
2754        cx: &mut ViewContext<Self>,
2755    ) -> Option<Task<Result<()>>> {
2756        if input.len() != 1 {
2757            return None;
2758        }
2759
2760        let project = self.project.as_ref()?;
2761        let position = self.selections.newest_anchor().head();
2762        let (buffer, buffer_position) = self
2763            .buffer
2764            .read(cx)
2765            .text_anchor_for_position(position.clone(), cx)?;
2766
2767        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
2768        // hence we do LSP request & edit on host side only — add formats to host's history.
2769        let push_to_lsp_host_history = true;
2770        // If this is not the host, append its history with new edits.
2771        let push_to_client_history = project.read(cx).is_remote();
2772
2773        let on_type_formatting = project.update(cx, |project, cx| {
2774            project.on_type_format(
2775                buffer.clone(),
2776                buffer_position,
2777                input,
2778                push_to_lsp_host_history,
2779                cx,
2780            )
2781        });
2782        Some(cx.spawn(|editor, mut cx| async move {
2783            if let Some(transaction) = on_type_formatting.await? {
2784                if push_to_client_history {
2785                    buffer.update(&mut cx, |buffer, _| {
2786                        buffer.push_transaction(transaction, Instant::now());
2787                    });
2788                }
2789                editor.update(&mut cx, |editor, cx| {
2790                    editor.refresh_document_highlights(cx);
2791                })?;
2792            }
2793            Ok(())
2794        }))
2795    }
2796
2797    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2798        if self.pending_rename.is_some() {
2799            return;
2800        }
2801
2802        let project = if let Some(project) = self.project.clone() {
2803            project
2804        } else {
2805            return;
2806        };
2807
2808        let position = self.selections.newest_anchor().head();
2809        let (buffer, buffer_position) = if let Some(output) = self
2810            .buffer
2811            .read(cx)
2812            .text_anchor_for_position(position.clone(), cx)
2813        {
2814            output
2815        } else {
2816            return;
2817        };
2818
2819        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2820        let completions = project.update(cx, |project, cx| {
2821            project.completions(&buffer, buffer_position, cx)
2822        });
2823
2824        let id = post_inc(&mut self.next_completion_id);
2825        let task = cx.spawn(|this, mut cx| {
2826            async move {
2827                let menu = if let Some(completions) = completions.await.log_err() {
2828                    let mut menu = CompletionsMenu {
2829                        id,
2830                        initial_position: position,
2831                        match_candidates: completions
2832                            .iter()
2833                            .enumerate()
2834                            .map(|(id, completion)| {
2835                                StringMatchCandidate::new(
2836                                    id,
2837                                    completion.label.text[completion.label.filter_range.clone()]
2838                                        .into(),
2839                                )
2840                            })
2841                            .collect(),
2842                        buffer,
2843                        completions: completions.into(),
2844                        matches: Vec::new().into(),
2845                        selected_item: 0,
2846                        list: Default::default(),
2847                    };
2848                    menu.filter(query.as_deref(), cx.background()).await;
2849                    if menu.matches.is_empty() {
2850                        None
2851                    } else {
2852                        Some(menu)
2853                    }
2854                } else {
2855                    None
2856                };
2857
2858                this.update(&mut cx, |this, cx| {
2859                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2860
2861                    match this.context_menu.as_ref() {
2862                        None => {}
2863                        Some(ContextMenu::Completions(prev_menu)) => {
2864                            if prev_menu.id > id {
2865                                return;
2866                            }
2867                        }
2868                        _ => return,
2869                    }
2870
2871                    if this.focused && menu.is_some() {
2872                        let menu = menu.unwrap();
2873                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2874                    } else if this.completion_tasks.is_empty() {
2875                        // If there are no more completion tasks and the last menu was
2876                        // empty, we should hide it. If it was already hidden, we should
2877                        // also show the copilot suggestion when available.
2878                        if this.hide_context_menu(cx).is_none() {
2879                            this.update_visible_copilot_suggestion(cx);
2880                        }
2881                    }
2882                })?;
2883
2884                Ok::<_, anyhow::Error>(())
2885            }
2886            .log_err()
2887        });
2888        self.completion_tasks.push((id, task));
2889    }
2890
2891    pub fn confirm_completion(
2892        &mut self,
2893        action: &ConfirmCompletion,
2894        cx: &mut ViewContext<Self>,
2895    ) -> Option<Task<Result<()>>> {
2896        use language::ToOffset as _;
2897
2898        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2899            menu
2900        } else {
2901            return None;
2902        };
2903
2904        let mat = completions_menu
2905            .matches
2906            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2907        let buffer_handle = completions_menu.buffer;
2908        let completion = completions_menu.completions.get(mat.candidate_id)?;
2909
2910        let snippet;
2911        let text;
2912        if completion.is_snippet() {
2913            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2914            text = snippet.as_ref().unwrap().text.clone();
2915        } else {
2916            snippet = None;
2917            text = completion.new_text.clone();
2918        };
2919        let selections = self.selections.all::<usize>(cx);
2920        let buffer = buffer_handle.read(cx);
2921        let old_range = completion.old_range.to_offset(buffer);
2922        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2923
2924        let newest_selection = self.selections.newest_anchor();
2925        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2926            return None;
2927        }
2928
2929        let lookbehind = newest_selection
2930            .start
2931            .text_anchor
2932            .to_offset(buffer)
2933            .saturating_sub(old_range.start);
2934        let lookahead = old_range
2935            .end
2936            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2937        let mut common_prefix_len = old_text
2938            .bytes()
2939            .zip(text.bytes())
2940            .take_while(|(a, b)| a == b)
2941            .count();
2942
2943        let snapshot = self.buffer.read(cx).snapshot(cx);
2944        let mut ranges = Vec::new();
2945        for selection in &selections {
2946            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2947                let start = selection.start.saturating_sub(lookbehind);
2948                let end = selection.end + lookahead;
2949                ranges.push(start + common_prefix_len..end);
2950            } else {
2951                common_prefix_len = 0;
2952                ranges.clear();
2953                ranges.extend(selections.iter().map(|s| {
2954                    if s.id == newest_selection.id {
2955                        old_range.clone()
2956                    } else {
2957                        s.start..s.end
2958                    }
2959                }));
2960                break;
2961            }
2962        }
2963        let text = &text[common_prefix_len..];
2964
2965        self.transact(cx, |this, cx| {
2966            if let Some(mut snippet) = snippet {
2967                snippet.text = text.to_string();
2968                for tabstop in snippet.tabstops.iter_mut().flatten() {
2969                    tabstop.start -= common_prefix_len as isize;
2970                    tabstop.end -= common_prefix_len as isize;
2971                }
2972
2973                this.insert_snippet(&ranges, snippet, cx).log_err();
2974            } else {
2975                this.buffer.update(cx, |buffer, cx| {
2976                    buffer.edit(
2977                        ranges.iter().map(|range| (range.clone(), text)),
2978                        Some(AutoindentMode::EachLine),
2979                        cx,
2980                    );
2981                });
2982            }
2983
2984            this.refresh_copilot_suggestions(true, cx);
2985        });
2986
2987        let project = self.project.clone()?;
2988        let apply_edits = project.update(cx, |project, cx| {
2989            project.apply_additional_edits_for_completion(
2990                buffer_handle,
2991                completion.clone(),
2992                true,
2993                cx,
2994            )
2995        });
2996        Some(cx.foreground().spawn(async move {
2997            apply_edits.await?;
2998            Ok(())
2999        }))
3000    }
3001
3002    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3003        if matches!(
3004            self.context_menu.as_ref(),
3005            Some(ContextMenu::CodeActions(_))
3006        ) {
3007            self.context_menu.take();
3008            cx.notify();
3009            return;
3010        }
3011
3012        let deployed_from_indicator = action.deployed_from_indicator;
3013        let mut task = self.code_actions_task.take();
3014        cx.spawn(|this, mut cx| async move {
3015            while let Some(prev_task) = task {
3016                prev_task.await;
3017                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3018            }
3019
3020            this.update(&mut cx, |this, cx| {
3021                if this.focused {
3022                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3023                        this.show_context_menu(
3024                            ContextMenu::CodeActions(CodeActionsMenu {
3025                                buffer,
3026                                actions,
3027                                selected_item: Default::default(),
3028                                list: Default::default(),
3029                                deployed_from_indicator,
3030                            }),
3031                            cx,
3032                        );
3033                    }
3034                }
3035            })?;
3036
3037            Ok::<_, anyhow::Error>(())
3038        })
3039        .detach_and_log_err(cx);
3040    }
3041
3042    pub fn confirm_code_action(
3043        workspace: &mut Workspace,
3044        action: &ConfirmCodeAction,
3045        cx: &mut ViewContext<Workspace>,
3046    ) -> Option<Task<Result<()>>> {
3047        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3048        let actions_menu = if let ContextMenu::CodeActions(menu) =
3049            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3050        {
3051            menu
3052        } else {
3053            return None;
3054        };
3055        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3056        let action = actions_menu.actions.get(action_ix)?.clone();
3057        let title = action.lsp_action.title.clone();
3058        let buffer = actions_menu.buffer;
3059
3060        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3061            project.apply_code_action(buffer, action, true, cx)
3062        });
3063        let editor = editor.downgrade();
3064        Some(cx.spawn(|workspace, cx| async move {
3065            let project_transaction = apply_code_actions.await?;
3066            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3067        }))
3068    }
3069
3070    async fn open_project_transaction(
3071        this: &WeakViewHandle<Editor>,
3072        workspace: WeakViewHandle<Workspace>,
3073        transaction: ProjectTransaction,
3074        title: String,
3075        mut cx: AsyncAppContext,
3076    ) -> Result<()> {
3077        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3078
3079        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3080        entries.sort_unstable_by_key(|(buffer, _)| {
3081            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3082        });
3083
3084        // If the project transaction's edits are all contained within this editor, then
3085        // avoid opening a new editor to display them.
3086
3087        if let Some((buffer, transaction)) = entries.first() {
3088            if entries.len() == 1 {
3089                let excerpt = this.read_with(&cx, |editor, cx| {
3090                    editor
3091                        .buffer()
3092                        .read(cx)
3093                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3094                })?;
3095                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3096                    if excerpted_buffer == *buffer {
3097                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3098                            let excerpt_range = excerpt_range.to_offset(buffer);
3099                            buffer
3100                                .edited_ranges_for_transaction::<usize>(transaction)
3101                                .all(|range| {
3102                                    excerpt_range.start <= range.start
3103                                        && excerpt_range.end >= range.end
3104                                })
3105                        });
3106
3107                        if all_edits_within_excerpt {
3108                            return Ok(());
3109                        }
3110                    }
3111                }
3112            }
3113        } else {
3114            return Ok(());
3115        }
3116
3117        let mut ranges_to_highlight = Vec::new();
3118        let excerpt_buffer = cx.add_model(|cx| {
3119            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3120            for (buffer_handle, transaction) in &entries {
3121                let buffer = buffer_handle.read(cx);
3122                ranges_to_highlight.extend(
3123                    multibuffer.push_excerpts_with_context_lines(
3124                        buffer_handle.clone(),
3125                        buffer
3126                            .edited_ranges_for_transaction::<usize>(transaction)
3127                            .collect(),
3128                        1,
3129                        cx,
3130                    ),
3131                );
3132            }
3133            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3134            multibuffer
3135        });
3136
3137        workspace.update(&mut cx, |workspace, cx| {
3138            let project = workspace.project().clone();
3139            let editor =
3140                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3141            workspace.add_item(Box::new(editor.clone()), cx);
3142            editor.update(cx, |editor, cx| {
3143                editor.highlight_background::<Self>(
3144                    ranges_to_highlight,
3145                    |theme| theme.editor.highlighted_line_background,
3146                    cx,
3147                );
3148            });
3149        })?;
3150
3151        Ok(())
3152    }
3153
3154    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3155        let project = self.project.as_ref()?;
3156        let buffer = self.buffer.read(cx);
3157        let newest_selection = self.selections.newest_anchor().clone();
3158        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3159        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3160        if start_buffer != end_buffer {
3161            return None;
3162        }
3163
3164        let actions = project.update(cx, |project, cx| {
3165            project.code_actions(&start_buffer, start..end, cx)
3166        });
3167        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3168            let actions = actions.await;
3169            this.update(&mut cx, |this, cx| {
3170                this.available_code_actions = actions.log_err().and_then(|actions| {
3171                    if actions.is_empty() {
3172                        None
3173                    } else {
3174                        Some((start_buffer, actions.into()))
3175                    }
3176                });
3177                cx.notify();
3178            })
3179            .log_err();
3180        }));
3181        None
3182    }
3183
3184    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3185        if self.pending_rename.is_some() {
3186            return None;
3187        }
3188
3189        let project = self.project.as_ref()?;
3190        let buffer = self.buffer.read(cx);
3191        let newest_selection = self.selections.newest_anchor().clone();
3192        let cursor_position = newest_selection.head();
3193        let (cursor_buffer, cursor_buffer_position) =
3194            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3195        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3196        if cursor_buffer != tail_buffer {
3197            return None;
3198        }
3199
3200        let highlights = project.update(cx, |project, cx| {
3201            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3202        });
3203
3204        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3205            if let Some(highlights) = highlights.await.log_err() {
3206                this.update(&mut cx, |this, cx| {
3207                    if this.pending_rename.is_some() {
3208                        return;
3209                    }
3210
3211                    let buffer_id = cursor_position.buffer_id;
3212                    let buffer = this.buffer.read(cx);
3213                    if !buffer
3214                        .text_anchor_for_position(cursor_position, cx)
3215                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3216                    {
3217                        return;
3218                    }
3219
3220                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3221                    let mut write_ranges = Vec::new();
3222                    let mut read_ranges = Vec::new();
3223                    for highlight in highlights {
3224                        for (excerpt_id, excerpt_range) in
3225                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3226                        {
3227                            let start = highlight
3228                                .range
3229                                .start
3230                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3231                            let end = highlight
3232                                .range
3233                                .end
3234                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3235                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3236                                continue;
3237                            }
3238
3239                            let range = Anchor {
3240                                buffer_id,
3241                                excerpt_id: excerpt_id.clone(),
3242                                text_anchor: start,
3243                            }..Anchor {
3244                                buffer_id,
3245                                excerpt_id,
3246                                text_anchor: end,
3247                            };
3248                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3249                                write_ranges.push(range);
3250                            } else {
3251                                read_ranges.push(range);
3252                            }
3253                        }
3254                    }
3255
3256                    this.highlight_background::<DocumentHighlightRead>(
3257                        read_ranges,
3258                        |theme| theme.editor.document_highlight_read_background,
3259                        cx,
3260                    );
3261                    this.highlight_background::<DocumentHighlightWrite>(
3262                        write_ranges,
3263                        |theme| theme.editor.document_highlight_write_background,
3264                        cx,
3265                    );
3266                    cx.notify();
3267                })
3268                .log_err();
3269            }
3270        }));
3271        None
3272    }
3273
3274    fn refresh_copilot_suggestions(
3275        &mut self,
3276        debounce: bool,
3277        cx: &mut ViewContext<Self>,
3278    ) -> Option<()> {
3279        let copilot = Copilot::global(cx)?;
3280        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3281            self.clear_copilot_suggestions(cx);
3282            return None;
3283        }
3284        self.update_visible_copilot_suggestion(cx);
3285
3286        let snapshot = self.buffer.read(cx).snapshot(cx);
3287        let cursor = self.selections.newest_anchor().head();
3288        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3289            self.clear_copilot_suggestions(cx);
3290            return None;
3291        }
3292
3293        let (buffer, buffer_position) =
3294            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3295        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3296            if debounce {
3297                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3298            }
3299
3300            let completions = copilot
3301                .update(&mut cx, |copilot, cx| {
3302                    copilot.completions(&buffer, buffer_position, cx)
3303                })
3304                .await
3305                .log_err()
3306                .into_iter()
3307                .flatten()
3308                .collect_vec();
3309
3310            this.update(&mut cx, |this, cx| {
3311                if !completions.is_empty() {
3312                    this.copilot_state.cycled = false;
3313                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3314                    this.copilot_state.completions.clear();
3315                    this.copilot_state.active_completion_index = 0;
3316                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3317                    for completion in completions {
3318                        this.copilot_state.push_completion(completion);
3319                    }
3320                    this.update_visible_copilot_suggestion(cx);
3321                }
3322            })
3323            .log_err()?;
3324            Some(())
3325        });
3326
3327        Some(())
3328    }
3329
3330    fn cycle_copilot_suggestions(
3331        &mut self,
3332        direction: Direction,
3333        cx: &mut ViewContext<Self>,
3334    ) -> Option<()> {
3335        let copilot = Copilot::global(cx)?;
3336        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3337            return None;
3338        }
3339
3340        if self.copilot_state.cycled {
3341            self.copilot_state.cycle_completions(direction);
3342            self.update_visible_copilot_suggestion(cx);
3343        } else {
3344            let cursor = self.selections.newest_anchor().head();
3345            let (buffer, buffer_position) =
3346                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3347            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3348                let completions = copilot
3349                    .update(&mut cx, |copilot, cx| {
3350                        copilot.completions_cycling(&buffer, buffer_position, cx)
3351                    })
3352                    .await;
3353
3354                this.update(&mut cx, |this, cx| {
3355                    this.copilot_state.cycled = true;
3356                    for completion in completions.log_err().into_iter().flatten() {
3357                        this.copilot_state.push_completion(completion);
3358                    }
3359                    this.copilot_state.cycle_completions(direction);
3360                    this.update_visible_copilot_suggestion(cx);
3361                })
3362                .log_err()?;
3363
3364                Some(())
3365            });
3366        }
3367
3368        Some(())
3369    }
3370
3371    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3372        if !self.has_active_copilot_suggestion(cx) {
3373            self.refresh_copilot_suggestions(false, cx);
3374            return;
3375        }
3376
3377        self.update_visible_copilot_suggestion(cx);
3378    }
3379
3380    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3381        if self.has_active_copilot_suggestion(cx) {
3382            self.cycle_copilot_suggestions(Direction::Next, cx);
3383        } else {
3384            self.refresh_copilot_suggestions(false, cx);
3385        }
3386    }
3387
3388    fn previous_copilot_suggestion(
3389        &mut self,
3390        _: &copilot::PreviousSuggestion,
3391        cx: &mut ViewContext<Self>,
3392    ) {
3393        if self.has_active_copilot_suggestion(cx) {
3394            self.cycle_copilot_suggestions(Direction::Prev, cx);
3395        } else {
3396            self.refresh_copilot_suggestions(false, cx);
3397        }
3398    }
3399
3400    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3401        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3402            if let Some((copilot, completion)) =
3403                Copilot::global(cx).zip(self.copilot_state.active_completion())
3404            {
3405                copilot
3406                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3407                    .detach_and_log_err(cx);
3408
3409                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3410            }
3411            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3412            cx.notify();
3413            true
3414        } else {
3415            false
3416        }
3417    }
3418
3419    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3420        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3421            if let Some(copilot) = Copilot::global(cx) {
3422                copilot
3423                    .update(cx, |copilot, cx| {
3424                        copilot.discard_completions(&self.copilot_state.completions, cx)
3425                    })
3426                    .detach_and_log_err(cx);
3427
3428                self.report_copilot_event(None, false, cx)
3429            }
3430
3431            self.display_map.update(cx, |map, cx| {
3432                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
3433            });
3434            cx.notify();
3435            true
3436        } else {
3437            false
3438        }
3439    }
3440
3441    fn is_copilot_enabled_at(
3442        &self,
3443        location: Anchor,
3444        snapshot: &MultiBufferSnapshot,
3445        cx: &mut ViewContext<Self>,
3446    ) -> bool {
3447        let file = snapshot.file_at(location);
3448        let language = snapshot.language_at(location);
3449        let settings = all_language_settings(file, cx);
3450        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3451    }
3452
3453    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3454        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3455            let buffer = self.buffer.read(cx).read(cx);
3456            suggestion.position.is_valid(&buffer)
3457        } else {
3458            false
3459        }
3460    }
3461
3462    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3463        let suggestion = self.copilot_state.suggestion.take()?;
3464        self.display_map.update(cx, |map, cx| {
3465            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
3466        });
3467        let buffer = self.buffer.read(cx).read(cx);
3468
3469        if suggestion.position.is_valid(&buffer) {
3470            Some(suggestion)
3471        } else {
3472            None
3473        }
3474    }
3475
3476    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3477        let snapshot = self.buffer.read(cx).snapshot(cx);
3478        let selection = self.selections.newest_anchor();
3479        let cursor = selection.head();
3480
3481        if self.context_menu.is_some()
3482            || !self.completion_tasks.is_empty()
3483            || selection.start != selection.end
3484        {
3485            self.discard_copilot_suggestion(cx);
3486        } else if let Some(text) = self
3487            .copilot_state
3488            .text_for_active_completion(cursor, &snapshot)
3489        {
3490            let text = Rope::from(text);
3491            let mut to_remove = Vec::new();
3492            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3493                to_remove.push(suggestion.id);
3494            }
3495
3496            let suggestion_inlay =
3497                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
3498            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
3499            self.display_map.update(cx, move |map, cx| {
3500                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
3501            });
3502            cx.notify();
3503        } else {
3504            self.discard_copilot_suggestion(cx);
3505        }
3506    }
3507
3508    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3509        self.copilot_state = Default::default();
3510        self.discard_copilot_suggestion(cx);
3511    }
3512
3513    pub fn render_code_actions_indicator(
3514        &self,
3515        style: &EditorStyle,
3516        is_active: bool,
3517        cx: &mut ViewContext<Self>,
3518    ) -> Option<AnyElement<Self>> {
3519        if self.available_code_actions.is_some() {
3520            enum CodeActions {}
3521            Some(
3522                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3523                    Svg::new("icons/bolt_8.svg").with_color(
3524                        style
3525                            .code_actions
3526                            .indicator
3527                            .in_state(is_active)
3528                            .style_for(state)
3529                            .color,
3530                    )
3531                })
3532                .with_cursor_style(CursorStyle::PointingHand)
3533                .with_padding(Padding::uniform(3.))
3534                .on_down(MouseButton::Left, |_, this, cx| {
3535                    this.toggle_code_actions(
3536                        &ToggleCodeActions {
3537                            deployed_from_indicator: true,
3538                        },
3539                        cx,
3540                    );
3541                })
3542                .into_any(),
3543            )
3544        } else {
3545            None
3546        }
3547    }
3548
3549    pub fn render_fold_indicators(
3550        &self,
3551        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3552        style: &EditorStyle,
3553        gutter_hovered: bool,
3554        line_height: f32,
3555        gutter_margin: f32,
3556        cx: &mut ViewContext<Self>,
3557    ) -> Vec<Option<AnyElement<Self>>> {
3558        enum FoldIndicators {}
3559
3560        let style = style.folds.clone();
3561
3562        fold_data
3563            .iter()
3564            .enumerate()
3565            .map(|(ix, fold_data)| {
3566                fold_data
3567                    .map(|(fold_status, buffer_row, active)| {
3568                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3569                            MouseEventHandler::<FoldIndicators, _>::new(
3570                                ix as usize,
3571                                cx,
3572                                |mouse_state, _| {
3573                                    Svg::new(match fold_status {
3574                                        FoldStatus::Folded => style.folded_icon.clone(),
3575                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3576                                    })
3577                                    .with_color(
3578                                        style
3579                                            .indicator
3580                                            .in_state(fold_status == FoldStatus::Folded)
3581                                            .style_for(mouse_state)
3582                                            .color,
3583                                    )
3584                                    .constrained()
3585                                    .with_width(gutter_margin * style.icon_margin_scale)
3586                                    .aligned()
3587                                    .constrained()
3588                                    .with_height(line_height)
3589                                    .with_width(gutter_margin)
3590                                    .aligned()
3591                                },
3592                            )
3593                            .with_cursor_style(CursorStyle::PointingHand)
3594                            .with_padding(Padding::uniform(3.))
3595                            .on_click(MouseButton::Left, {
3596                                move |_, editor, cx| match fold_status {
3597                                    FoldStatus::Folded => {
3598                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3599                                    }
3600                                    FoldStatus::Foldable => {
3601                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3602                                    }
3603                                }
3604                            })
3605                            .into_any()
3606                        })
3607                    })
3608                    .flatten()
3609            })
3610            .collect()
3611    }
3612
3613    pub fn context_menu_visible(&self) -> bool {
3614        self.context_menu
3615            .as_ref()
3616            .map_or(false, |menu| menu.visible())
3617    }
3618
3619    pub fn render_context_menu(
3620        &self,
3621        cursor_position: DisplayPoint,
3622        style: EditorStyle,
3623        cx: &mut ViewContext<Editor>,
3624    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3625        self.context_menu
3626            .as_ref()
3627            .map(|menu| menu.render(cursor_position, style, cx))
3628    }
3629
3630    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3631        if !matches!(menu, ContextMenu::Completions(_)) {
3632            self.completion_tasks.clear();
3633        }
3634        self.context_menu = Some(menu);
3635        self.discard_copilot_suggestion(cx);
3636        cx.notify();
3637    }
3638
3639    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3640        cx.notify();
3641        self.completion_tasks.clear();
3642        let context_menu = self.context_menu.take();
3643        if context_menu.is_some() {
3644            self.update_visible_copilot_suggestion(cx);
3645        }
3646        context_menu
3647    }
3648
3649    pub fn insert_snippet(
3650        &mut self,
3651        insertion_ranges: &[Range<usize>],
3652        snippet: Snippet,
3653        cx: &mut ViewContext<Self>,
3654    ) -> Result<()> {
3655        let tabstops = self.buffer.update(cx, |buffer, cx| {
3656            let snippet_text: Arc<str> = snippet.text.clone().into();
3657            buffer.edit(
3658                insertion_ranges
3659                    .iter()
3660                    .cloned()
3661                    .map(|range| (range, snippet_text.clone())),
3662                Some(AutoindentMode::EachLine),
3663                cx,
3664            );
3665
3666            let snapshot = &*buffer.read(cx);
3667            let snippet = &snippet;
3668            snippet
3669                .tabstops
3670                .iter()
3671                .map(|tabstop| {
3672                    let mut tabstop_ranges = tabstop
3673                        .iter()
3674                        .flat_map(|tabstop_range| {
3675                            let mut delta = 0_isize;
3676                            insertion_ranges.iter().map(move |insertion_range| {
3677                                let insertion_start = insertion_range.start as isize + delta;
3678                                delta +=
3679                                    snippet.text.len() as isize - insertion_range.len() as isize;
3680
3681                                let start = snapshot.anchor_before(
3682                                    (insertion_start + tabstop_range.start) as usize,
3683                                );
3684                                let end = snapshot
3685                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3686                                start..end
3687                            })
3688                        })
3689                        .collect::<Vec<_>>();
3690                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3691                    tabstop_ranges
3692                })
3693                .collect::<Vec<_>>()
3694        });
3695
3696        if let Some(tabstop) = tabstops.first() {
3697            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3698                s.select_ranges(tabstop.iter().cloned());
3699            });
3700            self.snippet_stack.push(SnippetState {
3701                active_index: 0,
3702                ranges: tabstops,
3703            });
3704        }
3705
3706        Ok(())
3707    }
3708
3709    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3710        self.move_to_snippet_tabstop(Bias::Right, cx)
3711    }
3712
3713    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3714        self.move_to_snippet_tabstop(Bias::Left, cx)
3715    }
3716
3717    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3718        if let Some(mut snippet) = self.snippet_stack.pop() {
3719            match bias {
3720                Bias::Left => {
3721                    if snippet.active_index > 0 {
3722                        snippet.active_index -= 1;
3723                    } else {
3724                        self.snippet_stack.push(snippet);
3725                        return false;
3726                    }
3727                }
3728                Bias::Right => {
3729                    if snippet.active_index + 1 < snippet.ranges.len() {
3730                        snippet.active_index += 1;
3731                    } else {
3732                        self.snippet_stack.push(snippet);
3733                        return false;
3734                    }
3735                }
3736            }
3737            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3738                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3739                    s.select_anchor_ranges(current_ranges.iter().cloned())
3740                });
3741                // If snippet state is not at the last tabstop, push it back on the stack
3742                if snippet.active_index + 1 < snippet.ranges.len() {
3743                    self.snippet_stack.push(snippet);
3744                }
3745                return true;
3746            }
3747        }
3748
3749        false
3750    }
3751
3752    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3753        self.transact(cx, |this, cx| {
3754            this.select_all(&SelectAll, cx);
3755            this.insert("", cx);
3756        });
3757    }
3758
3759    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3760        self.transact(cx, |this, cx| {
3761            this.select_autoclose_pair(cx);
3762            let mut selections = this.selections.all::<Point>(cx);
3763            if !this.selections.line_mode {
3764                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3765                for selection in &mut selections {
3766                    if selection.is_empty() {
3767                        let old_head = selection.head();
3768                        let mut new_head =
3769                            movement::left(&display_map, old_head.to_display_point(&display_map))
3770                                .to_point(&display_map);
3771                        if let Some((buffer, line_buffer_range)) = display_map
3772                            .buffer_snapshot
3773                            .buffer_line_for_row(old_head.row)
3774                        {
3775                            let indent_size =
3776                                buffer.indent_size_for_line(line_buffer_range.start.row);
3777                            let indent_len = match indent_size.kind {
3778                                IndentKind::Space => {
3779                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3780                                }
3781                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3782                            };
3783                            if old_head.column <= indent_size.len && old_head.column > 0 {
3784                                let indent_len = indent_len.get();
3785                                new_head = cmp::min(
3786                                    new_head,
3787                                    Point::new(
3788                                        old_head.row,
3789                                        ((old_head.column - 1) / indent_len) * indent_len,
3790                                    ),
3791                                );
3792                            }
3793                        }
3794
3795                        selection.set_head(new_head, SelectionGoal::None);
3796                    }
3797                }
3798            }
3799
3800            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3801            this.insert("", cx);
3802            this.refresh_copilot_suggestions(true, cx);
3803        });
3804    }
3805
3806    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3807        self.transact(cx, |this, cx| {
3808            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3809                let line_mode = s.line_mode;
3810                s.move_with(|map, selection| {
3811                    if selection.is_empty() && !line_mode {
3812                        let cursor = movement::right(map, selection.head());
3813                        selection.end = cursor;
3814                        selection.reversed = true;
3815                        selection.goal = SelectionGoal::None;
3816                    }
3817                })
3818            });
3819            this.insert("", cx);
3820            this.refresh_copilot_suggestions(true, cx);
3821        });
3822    }
3823
3824    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3825        if self.move_to_prev_snippet_tabstop(cx) {
3826            return;
3827        }
3828
3829        self.outdent(&Outdent, cx);
3830    }
3831
3832    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3833        if self.move_to_next_snippet_tabstop(cx) {
3834            return;
3835        }
3836
3837        let mut selections = self.selections.all_adjusted(cx);
3838        let buffer = self.buffer.read(cx);
3839        let snapshot = buffer.snapshot(cx);
3840        let rows_iter = selections.iter().map(|s| s.head().row);
3841        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3842
3843        let mut edits = Vec::new();
3844        let mut prev_edited_row = 0;
3845        let mut row_delta = 0;
3846        for selection in &mut selections {
3847            if selection.start.row != prev_edited_row {
3848                row_delta = 0;
3849            }
3850            prev_edited_row = selection.end.row;
3851
3852            // If the selection is non-empty, then increase the indentation of the selected lines.
3853            if !selection.is_empty() {
3854                row_delta =
3855                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3856                continue;
3857            }
3858
3859            // If the selection is empty and the cursor is in the leading whitespace before the
3860            // suggested indentation, then auto-indent the line.
3861            let cursor = selection.head();
3862            let current_indent = snapshot.indent_size_for_line(cursor.row);
3863            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3864                if cursor.column < suggested_indent.len
3865                    && cursor.column <= current_indent.len
3866                    && current_indent.len <= suggested_indent.len
3867                {
3868                    selection.start = Point::new(cursor.row, suggested_indent.len);
3869                    selection.end = selection.start;
3870                    if row_delta == 0 {
3871                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3872                            cursor.row,
3873                            current_indent,
3874                            suggested_indent,
3875                        ));
3876                        row_delta = suggested_indent.len - current_indent.len;
3877                    }
3878                    continue;
3879                }
3880            }
3881
3882            // Accept copilot suggestion if there is only one selection and the cursor is not
3883            // in the leading whitespace.
3884            if self.selections.count() == 1
3885                && cursor.column >= current_indent.len
3886                && self.has_active_copilot_suggestion(cx)
3887            {
3888                self.accept_copilot_suggestion(cx);
3889                return;
3890            }
3891
3892            // Otherwise, insert a hard or soft tab.
3893            let settings = buffer.settings_at(cursor, cx);
3894            let tab_size = if settings.hard_tabs {
3895                IndentSize::tab()
3896            } else {
3897                let tab_size = settings.tab_size.get();
3898                let char_column = snapshot
3899                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3900                    .flat_map(str::chars)
3901                    .count()
3902                    + row_delta as usize;
3903                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3904                IndentSize::spaces(chars_to_next_tab_stop)
3905            };
3906            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3907            selection.end = selection.start;
3908            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3909            row_delta += tab_size.len;
3910        }
3911
3912        self.transact(cx, |this, cx| {
3913            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3914            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3915            this.refresh_copilot_suggestions(true, cx);
3916        });
3917    }
3918
3919    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3920        let mut selections = self.selections.all::<Point>(cx);
3921        let mut prev_edited_row = 0;
3922        let mut row_delta = 0;
3923        let mut edits = Vec::new();
3924        let buffer = self.buffer.read(cx);
3925        let snapshot = buffer.snapshot(cx);
3926        for selection in &mut selections {
3927            if selection.start.row != prev_edited_row {
3928                row_delta = 0;
3929            }
3930            prev_edited_row = selection.end.row;
3931
3932            row_delta =
3933                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3934        }
3935
3936        self.transact(cx, |this, cx| {
3937            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3938            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3939        });
3940    }
3941
3942    fn indent_selection(
3943        buffer: &MultiBuffer,
3944        snapshot: &MultiBufferSnapshot,
3945        selection: &mut Selection<Point>,
3946        edits: &mut Vec<(Range<Point>, String)>,
3947        delta_for_start_row: u32,
3948        cx: &AppContext,
3949    ) -> u32 {
3950        let settings = buffer.settings_at(selection.start, cx);
3951        let tab_size = settings.tab_size.get();
3952        let indent_kind = if settings.hard_tabs {
3953            IndentKind::Tab
3954        } else {
3955            IndentKind::Space
3956        };
3957        let mut start_row = selection.start.row;
3958        let mut end_row = selection.end.row + 1;
3959
3960        // If a selection ends at the beginning of a line, don't indent
3961        // that last line.
3962        if selection.end.column == 0 {
3963            end_row -= 1;
3964        }
3965
3966        // Avoid re-indenting a row that has already been indented by a
3967        // previous selection, but still update this selection's column
3968        // to reflect that indentation.
3969        if delta_for_start_row > 0 {
3970            start_row += 1;
3971            selection.start.column += delta_for_start_row;
3972            if selection.end.row == selection.start.row {
3973                selection.end.column += delta_for_start_row;
3974            }
3975        }
3976
3977        let mut delta_for_end_row = 0;
3978        for row in start_row..end_row {
3979            let current_indent = snapshot.indent_size_for_line(row);
3980            let indent_delta = match (current_indent.kind, indent_kind) {
3981                (IndentKind::Space, IndentKind::Space) => {
3982                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3983                    IndentSize::spaces(columns_to_next_tab_stop)
3984                }
3985                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3986                (_, IndentKind::Tab) => IndentSize::tab(),
3987            };
3988
3989            let row_start = Point::new(row, 0);
3990            edits.push((
3991                row_start..row_start,
3992                indent_delta.chars().collect::<String>(),
3993            ));
3994
3995            // Update this selection's endpoints to reflect the indentation.
3996            if row == selection.start.row {
3997                selection.start.column += indent_delta.len;
3998            }
3999            if row == selection.end.row {
4000                selection.end.column += indent_delta.len;
4001                delta_for_end_row = indent_delta.len;
4002            }
4003        }
4004
4005        if selection.start.row == selection.end.row {
4006            delta_for_start_row + delta_for_end_row
4007        } else {
4008            delta_for_end_row
4009        }
4010    }
4011
4012    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4013        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4014        let selections = self.selections.all::<Point>(cx);
4015        let mut deletion_ranges = Vec::new();
4016        let mut last_outdent = None;
4017        {
4018            let buffer = self.buffer.read(cx);
4019            let snapshot = buffer.snapshot(cx);
4020            for selection in &selections {
4021                let settings = buffer.settings_at(selection.start, cx);
4022                let tab_size = settings.tab_size.get();
4023                let mut rows = selection.spanned_rows(false, &display_map);
4024
4025                // Avoid re-outdenting a row that has already been outdented by a
4026                // previous selection.
4027                if let Some(last_row) = last_outdent {
4028                    if last_row == rows.start {
4029                        rows.start += 1;
4030                    }
4031                }
4032
4033                for row in rows {
4034                    let indent_size = snapshot.indent_size_for_line(row);
4035                    if indent_size.len > 0 {
4036                        let deletion_len = match indent_size.kind {
4037                            IndentKind::Space => {
4038                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4039                                if columns_to_prev_tab_stop == 0 {
4040                                    tab_size
4041                                } else {
4042                                    columns_to_prev_tab_stop
4043                                }
4044                            }
4045                            IndentKind::Tab => 1,
4046                        };
4047                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4048                        last_outdent = Some(row);
4049                    }
4050                }
4051            }
4052        }
4053
4054        self.transact(cx, |this, cx| {
4055            this.buffer.update(cx, |buffer, cx| {
4056                let empty_str: Arc<str> = "".into();
4057                buffer.edit(
4058                    deletion_ranges
4059                        .into_iter()
4060                        .map(|range| (range, empty_str.clone())),
4061                    None,
4062                    cx,
4063                );
4064            });
4065            let selections = this.selections.all::<usize>(cx);
4066            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4067        });
4068    }
4069
4070    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4071        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4072        let selections = self.selections.all::<Point>(cx);
4073
4074        let mut new_cursors = Vec::new();
4075        let mut edit_ranges = Vec::new();
4076        let mut selections = selections.iter().peekable();
4077        while let Some(selection) = selections.next() {
4078            let mut rows = selection.spanned_rows(false, &display_map);
4079            let goal_display_column = selection.head().to_display_point(&display_map).column();
4080
4081            // Accumulate contiguous regions of rows that we want to delete.
4082            while let Some(next_selection) = selections.peek() {
4083                let next_rows = next_selection.spanned_rows(false, &display_map);
4084                if next_rows.start <= rows.end {
4085                    rows.end = next_rows.end;
4086                    selections.next().unwrap();
4087                } else {
4088                    break;
4089                }
4090            }
4091
4092            let buffer = &display_map.buffer_snapshot;
4093            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4094            let edit_end;
4095            let cursor_buffer_row;
4096            if buffer.max_point().row >= rows.end {
4097                // If there's a line after the range, delete the \n from the end of the row range
4098                // and position the cursor on the next line.
4099                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4100                cursor_buffer_row = rows.end;
4101            } else {
4102                // If there isn't a line after the range, delete the \n from the line before the
4103                // start of the row range and position the cursor there.
4104                edit_start = edit_start.saturating_sub(1);
4105                edit_end = buffer.len();
4106                cursor_buffer_row = rows.start.saturating_sub(1);
4107            }
4108
4109            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4110            *cursor.column_mut() =
4111                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4112
4113            new_cursors.push((
4114                selection.id,
4115                buffer.anchor_after(cursor.to_point(&display_map)),
4116            ));
4117            edit_ranges.push(edit_start..edit_end);
4118        }
4119
4120        self.transact(cx, |this, cx| {
4121            let buffer = this.buffer.update(cx, |buffer, cx| {
4122                let empty_str: Arc<str> = "".into();
4123                buffer.edit(
4124                    edit_ranges
4125                        .into_iter()
4126                        .map(|range| (range, empty_str.clone())),
4127                    None,
4128                    cx,
4129                );
4130                buffer.snapshot(cx)
4131            });
4132            let new_selections = new_cursors
4133                .into_iter()
4134                .map(|(id, cursor)| {
4135                    let cursor = cursor.to_point(&buffer);
4136                    Selection {
4137                        id,
4138                        start: cursor,
4139                        end: cursor,
4140                        reversed: false,
4141                        goal: SelectionGoal::None,
4142                    }
4143                })
4144                .collect();
4145
4146            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4147                s.select(new_selections);
4148            });
4149        });
4150    }
4151
4152    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4153        let mut row_ranges = Vec::<Range<u32>>::new();
4154        for selection in self.selections.all::<Point>(cx) {
4155            let start = selection.start.row;
4156            let end = if selection.start.row == selection.end.row {
4157                selection.start.row + 1
4158            } else {
4159                selection.end.row
4160            };
4161
4162            if let Some(last_row_range) = row_ranges.last_mut() {
4163                if start <= last_row_range.end {
4164                    last_row_range.end = end;
4165                    continue;
4166                }
4167            }
4168            row_ranges.push(start..end);
4169        }
4170
4171        let snapshot = self.buffer.read(cx).snapshot(cx);
4172        let mut cursor_positions = Vec::new();
4173        for row_range in &row_ranges {
4174            let anchor = snapshot.anchor_before(Point::new(
4175                row_range.end - 1,
4176                snapshot.line_len(row_range.end - 1),
4177            ));
4178            cursor_positions.push(anchor.clone()..anchor);
4179        }
4180
4181        self.transact(cx, |this, cx| {
4182            for row_range in row_ranges.into_iter().rev() {
4183                for row in row_range.rev() {
4184                    let end_of_line = Point::new(row, snapshot.line_len(row));
4185                    let indent = snapshot.indent_size_for_line(row + 1);
4186                    let start_of_next_line = Point::new(row + 1, indent.len);
4187
4188                    let replace = if snapshot.line_len(row + 1) > indent.len {
4189                        " "
4190                    } else {
4191                        ""
4192                    };
4193
4194                    this.buffer.update(cx, |buffer, cx| {
4195                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4196                    });
4197                }
4198            }
4199
4200            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4201                s.select_anchor_ranges(cursor_positions)
4202            });
4203        });
4204    }
4205
4206    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4207        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4208        let buffer = &display_map.buffer_snapshot;
4209        let selections = self.selections.all::<Point>(cx);
4210
4211        let mut edits = Vec::new();
4212        let mut selections_iter = selections.iter().peekable();
4213        while let Some(selection) = selections_iter.next() {
4214            // Avoid duplicating the same lines twice.
4215            let mut rows = selection.spanned_rows(false, &display_map);
4216
4217            while let Some(next_selection) = selections_iter.peek() {
4218                let next_rows = next_selection.spanned_rows(false, &display_map);
4219                if next_rows.start < rows.end {
4220                    rows.end = next_rows.end;
4221                    selections_iter.next().unwrap();
4222                } else {
4223                    break;
4224                }
4225            }
4226
4227            // Copy the text from the selected row region and splice it at the start of the region.
4228            let start = Point::new(rows.start, 0);
4229            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4230            let text = buffer
4231                .text_for_range(start..end)
4232                .chain(Some("\n"))
4233                .collect::<String>();
4234            edits.push((start..start, text));
4235        }
4236
4237        self.transact(cx, |this, cx| {
4238            this.buffer.update(cx, |buffer, cx| {
4239                buffer.edit(edits, None, cx);
4240            });
4241
4242            this.request_autoscroll(Autoscroll::fit(), cx);
4243        });
4244    }
4245
4246    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4247        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4248        let buffer = self.buffer.read(cx).snapshot(cx);
4249
4250        let mut edits = Vec::new();
4251        let mut unfold_ranges = Vec::new();
4252        let mut refold_ranges = Vec::new();
4253
4254        let selections = self.selections.all::<Point>(cx);
4255        let mut selections = selections.iter().peekable();
4256        let mut contiguous_row_selections = Vec::new();
4257        let mut new_selections = Vec::new();
4258
4259        while let Some(selection) = selections.next() {
4260            // Find all the selections that span a contiguous row range
4261            let (start_row, end_row) = consume_contiguous_rows(
4262                &mut contiguous_row_selections,
4263                selection,
4264                &display_map,
4265                &mut selections,
4266            );
4267
4268            // Move the text spanned by the row range to be before the line preceding the row range
4269            if start_row > 0 {
4270                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4271                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4272                let insertion_point = display_map
4273                    .prev_line_boundary(Point::new(start_row - 1, 0))
4274                    .0;
4275
4276                // Don't move lines across excerpts
4277                if buffer
4278                    .excerpt_boundaries_in_range((
4279                        Bound::Excluded(insertion_point),
4280                        Bound::Included(range_to_move.end),
4281                    ))
4282                    .next()
4283                    .is_none()
4284                {
4285                    let text = buffer
4286                        .text_for_range(range_to_move.clone())
4287                        .flat_map(|s| s.chars())
4288                        .skip(1)
4289                        .chain(['\n'])
4290                        .collect::<String>();
4291
4292                    edits.push((
4293                        buffer.anchor_after(range_to_move.start)
4294                            ..buffer.anchor_before(range_to_move.end),
4295                        String::new(),
4296                    ));
4297                    let insertion_anchor = buffer.anchor_after(insertion_point);
4298                    edits.push((insertion_anchor..insertion_anchor, text));
4299
4300                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4301
4302                    // Move selections up
4303                    new_selections.extend(contiguous_row_selections.drain(..).map(
4304                        |mut selection| {
4305                            selection.start.row -= row_delta;
4306                            selection.end.row -= row_delta;
4307                            selection
4308                        },
4309                    ));
4310
4311                    // Move folds up
4312                    unfold_ranges.push(range_to_move.clone());
4313                    for fold in display_map.folds_in_range(
4314                        buffer.anchor_before(range_to_move.start)
4315                            ..buffer.anchor_after(range_to_move.end),
4316                    ) {
4317                        let mut start = fold.start.to_point(&buffer);
4318                        let mut end = fold.end.to_point(&buffer);
4319                        start.row -= row_delta;
4320                        end.row -= row_delta;
4321                        refold_ranges.push(start..end);
4322                    }
4323                }
4324            }
4325
4326            // If we didn't move line(s), preserve the existing selections
4327            new_selections.append(&mut contiguous_row_selections);
4328        }
4329
4330        self.transact(cx, |this, cx| {
4331            this.unfold_ranges(unfold_ranges, true, true, cx);
4332            this.buffer.update(cx, |buffer, cx| {
4333                for (range, text) in edits {
4334                    buffer.edit([(range, text)], None, cx);
4335                }
4336            });
4337            this.fold_ranges(refold_ranges, true, cx);
4338            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4339                s.select(new_selections);
4340            })
4341        });
4342    }
4343
4344    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4345        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4346        let buffer = self.buffer.read(cx).snapshot(cx);
4347
4348        let mut edits = Vec::new();
4349        let mut unfold_ranges = Vec::new();
4350        let mut refold_ranges = Vec::new();
4351
4352        let selections = self.selections.all::<Point>(cx);
4353        let mut selections = selections.iter().peekable();
4354        let mut contiguous_row_selections = Vec::new();
4355        let mut new_selections = Vec::new();
4356
4357        while let Some(selection) = selections.next() {
4358            // Find all the selections that span a contiguous row range
4359            let (start_row, end_row) = consume_contiguous_rows(
4360                &mut contiguous_row_selections,
4361                selection,
4362                &display_map,
4363                &mut selections,
4364            );
4365
4366            // Move the text spanned by the row range to be after the last line of the row range
4367            if end_row <= buffer.max_point().row {
4368                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4369                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4370
4371                // Don't move lines across excerpt boundaries
4372                if buffer
4373                    .excerpt_boundaries_in_range((
4374                        Bound::Excluded(range_to_move.start),
4375                        Bound::Included(insertion_point),
4376                    ))
4377                    .next()
4378                    .is_none()
4379                {
4380                    let mut text = String::from("\n");
4381                    text.extend(buffer.text_for_range(range_to_move.clone()));
4382                    text.pop(); // Drop trailing newline
4383                    edits.push((
4384                        buffer.anchor_after(range_to_move.start)
4385                            ..buffer.anchor_before(range_to_move.end),
4386                        String::new(),
4387                    ));
4388                    let insertion_anchor = buffer.anchor_after(insertion_point);
4389                    edits.push((insertion_anchor..insertion_anchor, text));
4390
4391                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4392
4393                    // Move selections down
4394                    new_selections.extend(contiguous_row_selections.drain(..).map(
4395                        |mut selection| {
4396                            selection.start.row += row_delta;
4397                            selection.end.row += row_delta;
4398                            selection
4399                        },
4400                    ));
4401
4402                    // Move folds down
4403                    unfold_ranges.push(range_to_move.clone());
4404                    for fold in display_map.folds_in_range(
4405                        buffer.anchor_before(range_to_move.start)
4406                            ..buffer.anchor_after(range_to_move.end),
4407                    ) {
4408                        let mut start = fold.start.to_point(&buffer);
4409                        let mut end = fold.end.to_point(&buffer);
4410                        start.row += row_delta;
4411                        end.row += row_delta;
4412                        refold_ranges.push(start..end);
4413                    }
4414                }
4415            }
4416
4417            // If we didn't move line(s), preserve the existing selections
4418            new_selections.append(&mut contiguous_row_selections);
4419        }
4420
4421        self.transact(cx, |this, cx| {
4422            this.unfold_ranges(unfold_ranges, true, true, cx);
4423            this.buffer.update(cx, |buffer, cx| {
4424                for (range, text) in edits {
4425                    buffer.edit([(range, text)], None, cx);
4426                }
4427            });
4428            this.fold_ranges(refold_ranges, true, cx);
4429            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4430        });
4431    }
4432
4433    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4434        self.transact(cx, |this, cx| {
4435            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4436                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4437                let line_mode = s.line_mode;
4438                s.move_with(|display_map, selection| {
4439                    if !selection.is_empty() || line_mode {
4440                        return;
4441                    }
4442
4443                    let mut head = selection.head();
4444                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4445                    if head.column() == display_map.line_len(head.row()) {
4446                        transpose_offset = display_map
4447                            .buffer_snapshot
4448                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4449                    }
4450
4451                    if transpose_offset == 0 {
4452                        return;
4453                    }
4454
4455                    *head.column_mut() += 1;
4456                    head = display_map.clip_point(head, Bias::Right);
4457                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4458
4459                    let transpose_start = display_map
4460                        .buffer_snapshot
4461                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4462                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4463                        let transpose_end = display_map
4464                            .buffer_snapshot
4465                            .clip_offset(transpose_offset + 1, Bias::Right);
4466                        if let Some(ch) =
4467                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4468                        {
4469                            edits.push((transpose_start..transpose_offset, String::new()));
4470                            edits.push((transpose_end..transpose_end, ch.to_string()));
4471                        }
4472                    }
4473                });
4474                edits
4475            });
4476            this.buffer
4477                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4478            let selections = this.selections.all::<usize>(cx);
4479            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4480                s.select(selections);
4481            });
4482        });
4483    }
4484
4485    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4486        let mut text = String::new();
4487        let buffer = self.buffer.read(cx).snapshot(cx);
4488        let mut selections = self.selections.all::<Point>(cx);
4489        let mut clipboard_selections = Vec::with_capacity(selections.len());
4490        {
4491            let max_point = buffer.max_point();
4492            for selection in &mut selections {
4493                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4494                if is_entire_line {
4495                    selection.start = Point::new(selection.start.row, 0);
4496                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4497                    selection.goal = SelectionGoal::None;
4498                }
4499                let mut len = 0;
4500                for chunk in buffer.text_for_range(selection.start..selection.end) {
4501                    text.push_str(chunk);
4502                    len += chunk.len();
4503                }
4504                clipboard_selections.push(ClipboardSelection {
4505                    len,
4506                    is_entire_line,
4507                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4508                });
4509            }
4510        }
4511
4512        self.transact(cx, |this, cx| {
4513            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4514                s.select(selections);
4515            });
4516            this.insert("", cx);
4517            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4518        });
4519    }
4520
4521    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4522        let selections = self.selections.all::<Point>(cx);
4523        let buffer = self.buffer.read(cx).read(cx);
4524        let mut text = String::new();
4525
4526        let mut clipboard_selections = Vec::with_capacity(selections.len());
4527        {
4528            let max_point = buffer.max_point();
4529            for selection in selections.iter() {
4530                let mut start = selection.start;
4531                let mut end = selection.end;
4532                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4533                if is_entire_line {
4534                    start = Point::new(start.row, 0);
4535                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4536                }
4537                let mut len = 0;
4538                for chunk in buffer.text_for_range(start..end) {
4539                    text.push_str(chunk);
4540                    len += chunk.len();
4541                }
4542                clipboard_selections.push(ClipboardSelection {
4543                    len,
4544                    is_entire_line,
4545                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4546                });
4547            }
4548        }
4549
4550        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4551    }
4552
4553    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4554        self.transact(cx, |this, cx| {
4555            if let Some(item) = cx.read_from_clipboard() {
4556                let mut clipboard_text = Cow::Borrowed(item.text());
4557                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4558                    let old_selections = this.selections.all::<usize>(cx);
4559                    let all_selections_were_entire_line =
4560                        clipboard_selections.iter().all(|s| s.is_entire_line);
4561                    let first_selection_indent_column =
4562                        clipboard_selections.first().map(|s| s.first_line_indent);
4563                    if clipboard_selections.len() != old_selections.len() {
4564                        let mut newline_separated_text = String::new();
4565                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4566                        let mut ix = 0;
4567                        while let Some(clipboard_selection) = clipboard_selections.next() {
4568                            newline_separated_text
4569                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4570                            ix += clipboard_selection.len;
4571                            if clipboard_selections.peek().is_some() {
4572                                newline_separated_text.push('\n');
4573                            }
4574                        }
4575                        clipboard_text = Cow::Owned(newline_separated_text);
4576                    }
4577
4578                    this.buffer.update(cx, |buffer, cx| {
4579                        let snapshot = buffer.read(cx);
4580                        let mut start_offset = 0;
4581                        let mut edits = Vec::new();
4582                        let mut original_indent_columns = Vec::new();
4583                        let line_mode = this.selections.line_mode;
4584                        for (ix, selection) in old_selections.iter().enumerate() {
4585                            let to_insert;
4586                            let entire_line;
4587                            let original_indent_column;
4588                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4589                                let end_offset = start_offset + clipboard_selection.len;
4590                                to_insert = &clipboard_text[start_offset..end_offset];
4591                                entire_line = clipboard_selection.is_entire_line;
4592                                start_offset = end_offset;
4593                                original_indent_column =
4594                                    Some(clipboard_selection.first_line_indent);
4595                            } else {
4596                                to_insert = clipboard_text.as_str();
4597                                entire_line = all_selections_were_entire_line;
4598                                original_indent_column = first_selection_indent_column
4599                            }
4600
4601                            // If the corresponding selection was empty when this slice of the
4602                            // clipboard text was written, then the entire line containing the
4603                            // selection was copied. If this selection is also currently empty,
4604                            // then paste the line before the current line of the buffer.
4605                            let range = if selection.is_empty() && !line_mode && entire_line {
4606                                let column = selection.start.to_point(&snapshot).column as usize;
4607                                let line_start = selection.start - column;
4608                                line_start..line_start
4609                            } else {
4610                                selection.range()
4611                            };
4612
4613                            edits.push((range, to_insert));
4614                            original_indent_columns.extend(original_indent_column);
4615                        }
4616                        drop(snapshot);
4617
4618                        buffer.edit(
4619                            edits,
4620                            Some(AutoindentMode::Block {
4621                                original_indent_columns,
4622                            }),
4623                            cx,
4624                        );
4625                    });
4626
4627                    let selections = this.selections.all::<usize>(cx);
4628                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4629                } else {
4630                    this.insert(&clipboard_text, cx);
4631                }
4632            }
4633        });
4634    }
4635
4636    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4637        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4638            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4639                self.change_selections(None, cx, |s| {
4640                    s.select_anchors(selections.to_vec());
4641                });
4642            }
4643            self.request_autoscroll(Autoscroll::fit(), cx);
4644            self.unmark_text(cx);
4645            self.refresh_copilot_suggestions(true, cx);
4646            cx.emit(Event::Edited);
4647        }
4648    }
4649
4650    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4651        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4652            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4653            {
4654                self.change_selections(None, cx, |s| {
4655                    s.select_anchors(selections.to_vec());
4656                });
4657            }
4658            self.request_autoscroll(Autoscroll::fit(), cx);
4659            self.unmark_text(cx);
4660            self.refresh_copilot_suggestions(true, cx);
4661            cx.emit(Event::Edited);
4662        }
4663    }
4664
4665    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4666        self.buffer
4667            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4668    }
4669
4670    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4671        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4672            let line_mode = s.line_mode;
4673            s.move_with(|map, selection| {
4674                let cursor = if selection.is_empty() && !line_mode {
4675                    movement::left(map, selection.start)
4676                } else {
4677                    selection.start
4678                };
4679                selection.collapse_to(cursor, SelectionGoal::None);
4680            });
4681        })
4682    }
4683
4684    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4685        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4686            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4687        })
4688    }
4689
4690    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4691        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4692            let line_mode = s.line_mode;
4693            s.move_with(|map, selection| {
4694                let cursor = if selection.is_empty() && !line_mode {
4695                    movement::right(map, selection.end)
4696                } else {
4697                    selection.end
4698                };
4699                selection.collapse_to(cursor, SelectionGoal::None)
4700            });
4701        })
4702    }
4703
4704    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4705        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4706            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4707        })
4708    }
4709
4710    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4711        if self.take_rename(true, cx).is_some() {
4712            return;
4713        }
4714
4715        if let Some(context_menu) = self.context_menu.as_mut() {
4716            if context_menu.select_prev(cx) {
4717                return;
4718            }
4719        }
4720
4721        if matches!(self.mode, EditorMode::SingleLine) {
4722            cx.propagate_action();
4723            return;
4724        }
4725
4726        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4727            let line_mode = s.line_mode;
4728            s.move_with(|map, selection| {
4729                if !selection.is_empty() && !line_mode {
4730                    selection.goal = SelectionGoal::None;
4731                }
4732                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4733                selection.collapse_to(cursor, goal);
4734            });
4735        })
4736    }
4737
4738    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4739        if self.take_rename(true, cx).is_some() {
4740            return;
4741        }
4742
4743        if self
4744            .context_menu
4745            .as_mut()
4746            .map(|menu| menu.select_first(cx))
4747            .unwrap_or(false)
4748        {
4749            return;
4750        }
4751
4752        if matches!(self.mode, EditorMode::SingleLine) {
4753            cx.propagate_action();
4754            return;
4755        }
4756
4757        let row_count = if let Some(row_count) = self.visible_line_count() {
4758            row_count as u32 - 1
4759        } else {
4760            return;
4761        };
4762
4763        let autoscroll = if action.center_cursor {
4764            Autoscroll::center()
4765        } else {
4766            Autoscroll::fit()
4767        };
4768
4769        self.change_selections(Some(autoscroll), cx, |s| {
4770            let line_mode = s.line_mode;
4771            s.move_with(|map, selection| {
4772                if !selection.is_empty() && !line_mode {
4773                    selection.goal = SelectionGoal::None;
4774                }
4775                let (cursor, goal) =
4776                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4777                selection.collapse_to(cursor, goal);
4778            });
4779        });
4780    }
4781
4782    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4783        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4784            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4785        })
4786    }
4787
4788    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4789        self.take_rename(true, cx);
4790
4791        if let Some(context_menu) = self.context_menu.as_mut() {
4792            if context_menu.select_next(cx) {
4793                return;
4794            }
4795        }
4796
4797        if self.mode == EditorMode::SingleLine {
4798            cx.propagate_action();
4799            return;
4800        }
4801
4802        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4803            let line_mode = s.line_mode;
4804            s.move_with(|map, selection| {
4805                if !selection.is_empty() && !line_mode {
4806                    selection.goal = SelectionGoal::None;
4807                }
4808                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4809                selection.collapse_to(cursor, goal);
4810            });
4811        });
4812    }
4813
4814    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4815        if self.take_rename(true, cx).is_some() {
4816            return;
4817        }
4818
4819        if self
4820            .context_menu
4821            .as_mut()
4822            .map(|menu| menu.select_last(cx))
4823            .unwrap_or(false)
4824        {
4825            return;
4826        }
4827
4828        if matches!(self.mode, EditorMode::SingleLine) {
4829            cx.propagate_action();
4830            return;
4831        }
4832
4833        let row_count = if let Some(row_count) = self.visible_line_count() {
4834            row_count as u32 - 1
4835        } else {
4836            return;
4837        };
4838
4839        let autoscroll = if action.center_cursor {
4840            Autoscroll::center()
4841        } else {
4842            Autoscroll::fit()
4843        };
4844
4845        self.change_selections(Some(autoscroll), cx, |s| {
4846            let line_mode = s.line_mode;
4847            s.move_with(|map, selection| {
4848                if !selection.is_empty() && !line_mode {
4849                    selection.goal = SelectionGoal::None;
4850                }
4851                let (cursor, goal) =
4852                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4853                selection.collapse_to(cursor, goal);
4854            });
4855        });
4856    }
4857
4858    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4859        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4860            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4861        });
4862    }
4863
4864    pub fn move_to_previous_word_start(
4865        &mut self,
4866        _: &MoveToPreviousWordStart,
4867        cx: &mut ViewContext<Self>,
4868    ) {
4869        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4870            s.move_cursors_with(|map, head, _| {
4871                (
4872                    movement::previous_word_start(map, head),
4873                    SelectionGoal::None,
4874                )
4875            });
4876        })
4877    }
4878
4879    pub fn move_to_previous_subword_start(
4880        &mut self,
4881        _: &MoveToPreviousSubwordStart,
4882        cx: &mut ViewContext<Self>,
4883    ) {
4884        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4885            s.move_cursors_with(|map, head, _| {
4886                (
4887                    movement::previous_subword_start(map, head),
4888                    SelectionGoal::None,
4889                )
4890            });
4891        })
4892    }
4893
4894    pub fn select_to_previous_word_start(
4895        &mut self,
4896        _: &SelectToPreviousWordStart,
4897        cx: &mut ViewContext<Self>,
4898    ) {
4899        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4900            s.move_heads_with(|map, head, _| {
4901                (
4902                    movement::previous_word_start(map, head),
4903                    SelectionGoal::None,
4904                )
4905            });
4906        })
4907    }
4908
4909    pub fn select_to_previous_subword_start(
4910        &mut self,
4911        _: &SelectToPreviousSubwordStart,
4912        cx: &mut ViewContext<Self>,
4913    ) {
4914        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4915            s.move_heads_with(|map, head, _| {
4916                (
4917                    movement::previous_subword_start(map, head),
4918                    SelectionGoal::None,
4919                )
4920            });
4921        })
4922    }
4923
4924    pub fn delete_to_previous_word_start(
4925        &mut self,
4926        _: &DeleteToPreviousWordStart,
4927        cx: &mut ViewContext<Self>,
4928    ) {
4929        self.transact(cx, |this, cx| {
4930            this.select_autoclose_pair(cx);
4931            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4932                let line_mode = s.line_mode;
4933                s.move_with(|map, selection| {
4934                    if selection.is_empty() && !line_mode {
4935                        let cursor = movement::previous_word_start(map, selection.head());
4936                        selection.set_head(cursor, SelectionGoal::None);
4937                    }
4938                });
4939            });
4940            this.insert("", cx);
4941        });
4942    }
4943
4944    pub fn delete_to_previous_subword_start(
4945        &mut self,
4946        _: &DeleteToPreviousSubwordStart,
4947        cx: &mut ViewContext<Self>,
4948    ) {
4949        self.transact(cx, |this, cx| {
4950            this.select_autoclose_pair(cx);
4951            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4952                let line_mode = s.line_mode;
4953                s.move_with(|map, selection| {
4954                    if selection.is_empty() && !line_mode {
4955                        let cursor = movement::previous_subword_start(map, selection.head());
4956                        selection.set_head(cursor, SelectionGoal::None);
4957                    }
4958                });
4959            });
4960            this.insert("", cx);
4961        });
4962    }
4963
4964    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4965        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4966            s.move_cursors_with(|map, head, _| {
4967                (movement::next_word_end(map, head), SelectionGoal::None)
4968            });
4969        })
4970    }
4971
4972    pub fn move_to_next_subword_end(
4973        &mut self,
4974        _: &MoveToNextSubwordEnd,
4975        cx: &mut ViewContext<Self>,
4976    ) {
4977        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4978            s.move_cursors_with(|map, head, _| {
4979                (movement::next_subword_end(map, head), SelectionGoal::None)
4980            });
4981        })
4982    }
4983
4984    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4985        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4986            s.move_heads_with(|map, head, _| {
4987                (movement::next_word_end(map, head), SelectionGoal::None)
4988            });
4989        })
4990    }
4991
4992    pub fn select_to_next_subword_end(
4993        &mut self,
4994        _: &SelectToNextSubwordEnd,
4995        cx: &mut ViewContext<Self>,
4996    ) {
4997        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4998            s.move_heads_with(|map, head, _| {
4999                (movement::next_subword_end(map, head), SelectionGoal::None)
5000            });
5001        })
5002    }
5003
5004    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5005        self.transact(cx, |this, cx| {
5006            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5007                let line_mode = s.line_mode;
5008                s.move_with(|map, selection| {
5009                    if selection.is_empty() && !line_mode {
5010                        let cursor = movement::next_word_end(map, selection.head());
5011                        selection.set_head(cursor, SelectionGoal::None);
5012                    }
5013                });
5014            });
5015            this.insert("", cx);
5016        });
5017    }
5018
5019    pub fn delete_to_next_subword_end(
5020        &mut self,
5021        _: &DeleteToNextSubwordEnd,
5022        cx: &mut ViewContext<Self>,
5023    ) {
5024        self.transact(cx, |this, cx| {
5025            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5026                s.move_with(|map, selection| {
5027                    if selection.is_empty() {
5028                        let cursor = movement::next_subword_end(map, selection.head());
5029                        selection.set_head(cursor, SelectionGoal::None);
5030                    }
5031                });
5032            });
5033            this.insert("", cx);
5034        });
5035    }
5036
5037    pub fn move_to_beginning_of_line(
5038        &mut self,
5039        _: &MoveToBeginningOfLine,
5040        cx: &mut ViewContext<Self>,
5041    ) {
5042        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5043            s.move_cursors_with(|map, head, _| {
5044                (
5045                    movement::indented_line_beginning(map, head, true),
5046                    SelectionGoal::None,
5047                )
5048            });
5049        })
5050    }
5051
5052    pub fn select_to_beginning_of_line(
5053        &mut self,
5054        action: &SelectToBeginningOfLine,
5055        cx: &mut ViewContext<Self>,
5056    ) {
5057        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5058            s.move_heads_with(|map, head, _| {
5059                (
5060                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5061                    SelectionGoal::None,
5062                )
5063            });
5064        });
5065    }
5066
5067    pub fn delete_to_beginning_of_line(
5068        &mut self,
5069        _: &DeleteToBeginningOfLine,
5070        cx: &mut ViewContext<Self>,
5071    ) {
5072        self.transact(cx, |this, cx| {
5073            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5074                s.move_with(|_, selection| {
5075                    selection.reversed = true;
5076                });
5077            });
5078
5079            this.select_to_beginning_of_line(
5080                &SelectToBeginningOfLine {
5081                    stop_at_soft_wraps: false,
5082                },
5083                cx,
5084            );
5085            this.backspace(&Backspace, cx);
5086        });
5087    }
5088
5089    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5090        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5091            s.move_cursors_with(|map, head, _| {
5092                (movement::line_end(map, head, true), SelectionGoal::None)
5093            });
5094        })
5095    }
5096
5097    pub fn select_to_end_of_line(
5098        &mut self,
5099        action: &SelectToEndOfLine,
5100        cx: &mut ViewContext<Self>,
5101    ) {
5102        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5103            s.move_heads_with(|map, head, _| {
5104                (
5105                    movement::line_end(map, head, action.stop_at_soft_wraps),
5106                    SelectionGoal::None,
5107                )
5108            });
5109        })
5110    }
5111
5112    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5113        self.transact(cx, |this, cx| {
5114            this.select_to_end_of_line(
5115                &SelectToEndOfLine {
5116                    stop_at_soft_wraps: false,
5117                },
5118                cx,
5119            );
5120            this.delete(&Delete, cx);
5121        });
5122    }
5123
5124    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5125        self.transact(cx, |this, cx| {
5126            this.select_to_end_of_line(
5127                &SelectToEndOfLine {
5128                    stop_at_soft_wraps: false,
5129                },
5130                cx,
5131            );
5132            this.cut(&Cut, cx);
5133        });
5134    }
5135
5136    pub fn move_to_start_of_paragraph(
5137        &mut self,
5138        _: &MoveToStartOfParagraph,
5139        cx: &mut ViewContext<Self>,
5140    ) {
5141        if matches!(self.mode, EditorMode::SingleLine) {
5142            cx.propagate_action();
5143            return;
5144        }
5145
5146        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5147            s.move_with(|map, selection| {
5148                selection.collapse_to(
5149                    movement::start_of_paragraph(map, selection.head(), 1),
5150                    SelectionGoal::None,
5151                )
5152            });
5153        })
5154    }
5155
5156    pub fn move_to_end_of_paragraph(
5157        &mut self,
5158        _: &MoveToEndOfParagraph,
5159        cx: &mut ViewContext<Self>,
5160    ) {
5161        if matches!(self.mode, EditorMode::SingleLine) {
5162            cx.propagate_action();
5163            return;
5164        }
5165
5166        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5167            s.move_with(|map, selection| {
5168                selection.collapse_to(
5169                    movement::end_of_paragraph(map, selection.head(), 1),
5170                    SelectionGoal::None,
5171                )
5172            });
5173        })
5174    }
5175
5176    pub fn select_to_start_of_paragraph(
5177        &mut self,
5178        _: &SelectToStartOfParagraph,
5179        cx: &mut ViewContext<Self>,
5180    ) {
5181        if matches!(self.mode, EditorMode::SingleLine) {
5182            cx.propagate_action();
5183            return;
5184        }
5185
5186        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5187            s.move_heads_with(|map, head, _| {
5188                (
5189                    movement::start_of_paragraph(map, head, 1),
5190                    SelectionGoal::None,
5191                )
5192            });
5193        })
5194    }
5195
5196    pub fn select_to_end_of_paragraph(
5197        &mut self,
5198        _: &SelectToEndOfParagraph,
5199        cx: &mut ViewContext<Self>,
5200    ) {
5201        if matches!(self.mode, EditorMode::SingleLine) {
5202            cx.propagate_action();
5203            return;
5204        }
5205
5206        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5207            s.move_heads_with(|map, head, _| {
5208                (
5209                    movement::end_of_paragraph(map, head, 1),
5210                    SelectionGoal::None,
5211                )
5212            });
5213        })
5214    }
5215
5216    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5217        if matches!(self.mode, EditorMode::SingleLine) {
5218            cx.propagate_action();
5219            return;
5220        }
5221
5222        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5223            s.select_ranges(vec![0..0]);
5224        });
5225    }
5226
5227    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5228        let mut selection = self.selections.last::<Point>(cx);
5229        selection.set_head(Point::zero(), SelectionGoal::None);
5230
5231        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5232            s.select(vec![selection]);
5233        });
5234    }
5235
5236    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5237        if matches!(self.mode, EditorMode::SingleLine) {
5238            cx.propagate_action();
5239            return;
5240        }
5241
5242        let cursor = self.buffer.read(cx).read(cx).len();
5243        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5244            s.select_ranges(vec![cursor..cursor])
5245        });
5246    }
5247
5248    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5249        self.nav_history = nav_history;
5250    }
5251
5252    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5253        self.nav_history.as_ref()
5254    }
5255
5256    fn push_to_nav_history(
5257        &mut self,
5258        cursor_anchor: Anchor,
5259        new_position: Option<Point>,
5260        cx: &mut ViewContext<Self>,
5261    ) {
5262        if let Some(nav_history) = self.nav_history.as_mut() {
5263            let buffer = self.buffer.read(cx).read(cx);
5264            let cursor_position = cursor_anchor.to_point(&buffer);
5265            let scroll_state = self.scroll_manager.anchor();
5266            let scroll_top_row = scroll_state.top_row(&buffer);
5267            drop(buffer);
5268
5269            if let Some(new_position) = new_position {
5270                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5271                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5272                    return;
5273                }
5274            }
5275
5276            nav_history.push(
5277                Some(NavigationData {
5278                    cursor_anchor,
5279                    cursor_position,
5280                    scroll_anchor: scroll_state,
5281                    scroll_top_row,
5282                }),
5283                cx,
5284            );
5285        }
5286    }
5287
5288    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5289        let buffer = self.buffer.read(cx).snapshot(cx);
5290        let mut selection = self.selections.first::<usize>(cx);
5291        selection.set_head(buffer.len(), SelectionGoal::None);
5292        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5293            s.select(vec![selection]);
5294        });
5295    }
5296
5297    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5298        let end = self.buffer.read(cx).read(cx).len();
5299        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5300            s.select_ranges(vec![0..end]);
5301        });
5302    }
5303
5304    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5305        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5306        let mut selections = self.selections.all::<Point>(cx);
5307        let max_point = display_map.buffer_snapshot.max_point();
5308        for selection in &mut selections {
5309            let rows = selection.spanned_rows(true, &display_map);
5310            selection.start = Point::new(rows.start, 0);
5311            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5312            selection.reversed = false;
5313        }
5314        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5315            s.select(selections);
5316        });
5317    }
5318
5319    pub fn split_selection_into_lines(
5320        &mut self,
5321        _: &SplitSelectionIntoLines,
5322        cx: &mut ViewContext<Self>,
5323    ) {
5324        let mut to_unfold = Vec::new();
5325        let mut new_selection_ranges = Vec::new();
5326        {
5327            let selections = self.selections.all::<Point>(cx);
5328            let buffer = self.buffer.read(cx).read(cx);
5329            for selection in selections {
5330                for row in selection.start.row..selection.end.row {
5331                    let cursor = Point::new(row, buffer.line_len(row));
5332                    new_selection_ranges.push(cursor..cursor);
5333                }
5334                new_selection_ranges.push(selection.end..selection.end);
5335                to_unfold.push(selection.start..selection.end);
5336            }
5337        }
5338        self.unfold_ranges(to_unfold, true, true, cx);
5339        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5340            s.select_ranges(new_selection_ranges);
5341        });
5342    }
5343
5344    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5345        self.add_selection(true, cx);
5346    }
5347
5348    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5349        self.add_selection(false, cx);
5350    }
5351
5352    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5353        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5354        let mut selections = self.selections.all::<Point>(cx);
5355        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5356            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5357            let range = oldest_selection.display_range(&display_map).sorted();
5358            let columns = cmp::min(range.start.column(), range.end.column())
5359                ..cmp::max(range.start.column(), range.end.column());
5360
5361            selections.clear();
5362            let mut stack = Vec::new();
5363            for row in range.start.row()..=range.end.row() {
5364                if let Some(selection) = self.selections.build_columnar_selection(
5365                    &display_map,
5366                    row,
5367                    &columns,
5368                    oldest_selection.reversed,
5369                ) {
5370                    stack.push(selection.id);
5371                    selections.push(selection);
5372                }
5373            }
5374
5375            if above {
5376                stack.reverse();
5377            }
5378
5379            AddSelectionsState { above, stack }
5380        });
5381
5382        let last_added_selection = *state.stack.last().unwrap();
5383        let mut new_selections = Vec::new();
5384        if above == state.above {
5385            let end_row = if above {
5386                0
5387            } else {
5388                display_map.max_point().row()
5389            };
5390
5391            'outer: for selection in selections {
5392                if selection.id == last_added_selection {
5393                    let range = selection.display_range(&display_map).sorted();
5394                    debug_assert_eq!(range.start.row(), range.end.row());
5395                    let mut row = range.start.row();
5396                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5397                    {
5398                        start..end
5399                    } else {
5400                        cmp::min(range.start.column(), range.end.column())
5401                            ..cmp::max(range.start.column(), range.end.column())
5402                    };
5403
5404                    while row != end_row {
5405                        if above {
5406                            row -= 1;
5407                        } else {
5408                            row += 1;
5409                        }
5410
5411                        if let Some(new_selection) = self.selections.build_columnar_selection(
5412                            &display_map,
5413                            row,
5414                            &columns,
5415                            selection.reversed,
5416                        ) {
5417                            state.stack.push(new_selection.id);
5418                            if above {
5419                                new_selections.push(new_selection);
5420                                new_selections.push(selection);
5421                            } else {
5422                                new_selections.push(selection);
5423                                new_selections.push(new_selection);
5424                            }
5425
5426                            continue 'outer;
5427                        }
5428                    }
5429                }
5430
5431                new_selections.push(selection);
5432            }
5433        } else {
5434            new_selections = selections;
5435            new_selections.retain(|s| s.id != last_added_selection);
5436            state.stack.pop();
5437        }
5438
5439        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5440            s.select(new_selections);
5441        });
5442        if state.stack.len() > 1 {
5443            self.add_selections_state = Some(state);
5444        }
5445    }
5446
5447    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5448        self.push_to_selection_history();
5449        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5450        let buffer = &display_map.buffer_snapshot;
5451        let mut selections = self.selections.all::<usize>(cx);
5452        if let Some(mut select_next_state) = self.select_next_state.take() {
5453            let query = &select_next_state.query;
5454            if !select_next_state.done {
5455                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5456                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5457                let mut next_selected_range = None;
5458
5459                let bytes_after_last_selection =
5460                    buffer.bytes_in_range(last_selection.end..buffer.len());
5461                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5462                let query_matches = query
5463                    .stream_find_iter(bytes_after_last_selection)
5464                    .map(|result| (last_selection.end, result))
5465                    .chain(
5466                        query
5467                            .stream_find_iter(bytes_before_first_selection)
5468                            .map(|result| (0, result)),
5469                    );
5470                for (start_offset, query_match) in query_matches {
5471                    let query_match = query_match.unwrap(); // can only fail due to I/O
5472                    let offset_range =
5473                        start_offset + query_match.start()..start_offset + query_match.end();
5474                    let display_range = offset_range.start.to_display_point(&display_map)
5475                        ..offset_range.end.to_display_point(&display_map);
5476
5477                    if !select_next_state.wordwise
5478                        || (!movement::is_inside_word(&display_map, display_range.start)
5479                            && !movement::is_inside_word(&display_map, display_range.end))
5480                    {
5481                        next_selected_range = Some(offset_range);
5482                        break;
5483                    }
5484                }
5485
5486                if let Some(next_selected_range) = next_selected_range {
5487                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5488                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5489                        if action.replace_newest {
5490                            s.delete(s.newest_anchor().id);
5491                        }
5492                        s.insert_range(next_selected_range);
5493                    });
5494                } else {
5495                    select_next_state.done = true;
5496                }
5497            }
5498
5499            self.select_next_state = Some(select_next_state);
5500        } else if selections.len() == 1 {
5501            let selection = selections.last_mut().unwrap();
5502            if selection.start == selection.end {
5503                let word_range = movement::surrounding_word(
5504                    &display_map,
5505                    selection.start.to_display_point(&display_map),
5506                );
5507                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5508                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5509                selection.goal = SelectionGoal::None;
5510                selection.reversed = false;
5511
5512                let query = buffer
5513                    .text_for_range(selection.start..selection.end)
5514                    .collect::<String>();
5515                let select_state = SelectNextState {
5516                    query: AhoCorasick::new_auto_configured(&[query]),
5517                    wordwise: true,
5518                    done: false,
5519                };
5520                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5521                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5522                    s.select(selections);
5523                });
5524                self.select_next_state = Some(select_state);
5525            } else {
5526                let query = buffer
5527                    .text_for_range(selection.start..selection.end)
5528                    .collect::<String>();
5529                self.select_next_state = Some(SelectNextState {
5530                    query: AhoCorasick::new_auto_configured(&[query]),
5531                    wordwise: false,
5532                    done: false,
5533                });
5534                self.select_next(action, cx);
5535            }
5536        }
5537    }
5538
5539    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5540        self.push_to_selection_history();
5541        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5542        let buffer = &display_map.buffer_snapshot;
5543        let mut selections = self.selections.all::<usize>(cx);
5544        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5545            let query = &select_prev_state.query;
5546            if !select_prev_state.done {
5547                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5548                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5549                let mut next_selected_range = None;
5550                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5551                let bytes_before_last_selection =
5552                    buffer.reversed_bytes_in_range(0..last_selection.start);
5553                let bytes_after_first_selection =
5554                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5555                let query_matches = query
5556                    .stream_find_iter(bytes_before_last_selection)
5557                    .map(|result| (last_selection.start, result))
5558                    .chain(
5559                        query
5560                            .stream_find_iter(bytes_after_first_selection)
5561                            .map(|result| (buffer.len(), result)),
5562                    );
5563                for (end_offset, query_match) in query_matches {
5564                    let query_match = query_match.unwrap(); // can only fail due to I/O
5565                    let offset_range =
5566                        end_offset - query_match.end()..end_offset - query_match.start();
5567                    let display_range = offset_range.start.to_display_point(&display_map)
5568                        ..offset_range.end.to_display_point(&display_map);
5569
5570                    if !select_prev_state.wordwise
5571                        || (!movement::is_inside_word(&display_map, display_range.start)
5572                            && !movement::is_inside_word(&display_map, display_range.end))
5573                    {
5574                        next_selected_range = Some(offset_range);
5575                        break;
5576                    }
5577                }
5578
5579                if let Some(next_selected_range) = next_selected_range {
5580                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5581                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5582                        if action.replace_newest {
5583                            s.delete(s.newest_anchor().id);
5584                        }
5585                        s.insert_range(next_selected_range);
5586                    });
5587                } else {
5588                    select_prev_state.done = true;
5589                }
5590            }
5591
5592            self.select_prev_state = Some(select_prev_state);
5593        } else if selections.len() == 1 {
5594            let selection = selections.last_mut().unwrap();
5595            if selection.start == selection.end {
5596                let word_range = movement::surrounding_word(
5597                    &display_map,
5598                    selection.start.to_display_point(&display_map),
5599                );
5600                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5601                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5602                selection.goal = SelectionGoal::None;
5603                selection.reversed = false;
5604
5605                let query = buffer
5606                    .text_for_range(selection.start..selection.end)
5607                    .collect::<String>();
5608                let query = query.chars().rev().collect::<String>();
5609                let select_state = SelectNextState {
5610                    query: AhoCorasick::new_auto_configured(&[query]),
5611                    wordwise: true,
5612                    done: false,
5613                };
5614                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5615                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5616                    s.select(selections);
5617                });
5618                self.select_prev_state = Some(select_state);
5619            } else {
5620                let query = buffer
5621                    .text_for_range(selection.start..selection.end)
5622                    .collect::<String>();
5623                let query = query.chars().rev().collect::<String>();
5624                self.select_prev_state = Some(SelectNextState {
5625                    query: AhoCorasick::new_auto_configured(&[query]),
5626                    wordwise: false,
5627                    done: false,
5628                });
5629                self.select_previous(action, cx);
5630            }
5631        }
5632    }
5633
5634    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5635        self.transact(cx, |this, cx| {
5636            let mut selections = this.selections.all::<Point>(cx);
5637            let mut edits = Vec::new();
5638            let mut selection_edit_ranges = Vec::new();
5639            let mut last_toggled_row = None;
5640            let snapshot = this.buffer.read(cx).read(cx);
5641            let empty_str: Arc<str> = "".into();
5642            let mut suffixes_inserted = Vec::new();
5643
5644            fn comment_prefix_range(
5645                snapshot: &MultiBufferSnapshot,
5646                row: u32,
5647                comment_prefix: &str,
5648                comment_prefix_whitespace: &str,
5649            ) -> Range<Point> {
5650                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5651
5652                let mut line_bytes = snapshot
5653                    .bytes_in_range(start..snapshot.max_point())
5654                    .flatten()
5655                    .copied();
5656
5657                // If this line currently begins with the line comment prefix, then record
5658                // the range containing the prefix.
5659                if line_bytes
5660                    .by_ref()
5661                    .take(comment_prefix.len())
5662                    .eq(comment_prefix.bytes())
5663                {
5664                    // Include any whitespace that matches the comment prefix.
5665                    let matching_whitespace_len = line_bytes
5666                        .zip(comment_prefix_whitespace.bytes())
5667                        .take_while(|(a, b)| a == b)
5668                        .count() as u32;
5669                    let end = Point::new(
5670                        start.row,
5671                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5672                    );
5673                    start..end
5674                } else {
5675                    start..start
5676                }
5677            }
5678
5679            fn comment_suffix_range(
5680                snapshot: &MultiBufferSnapshot,
5681                row: u32,
5682                comment_suffix: &str,
5683                comment_suffix_has_leading_space: bool,
5684            ) -> Range<Point> {
5685                let end = Point::new(row, snapshot.line_len(row));
5686                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5687
5688                let mut line_end_bytes = snapshot
5689                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5690                    .flatten()
5691                    .copied();
5692
5693                let leading_space_len = if suffix_start_column > 0
5694                    && line_end_bytes.next() == Some(b' ')
5695                    && comment_suffix_has_leading_space
5696                {
5697                    1
5698                } else {
5699                    0
5700                };
5701
5702                // If this line currently begins with the line comment prefix, then record
5703                // the range containing the prefix.
5704                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5705                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5706                    start..end
5707                } else {
5708                    end..end
5709                }
5710            }
5711
5712            // TODO: Handle selections that cross excerpts
5713            for selection in &mut selections {
5714                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5715                let language = if let Some(language) =
5716                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5717                {
5718                    language
5719                } else {
5720                    continue;
5721                };
5722
5723                selection_edit_ranges.clear();
5724
5725                // If multiple selections contain a given row, avoid processing that
5726                // row more than once.
5727                let mut start_row = selection.start.row;
5728                if last_toggled_row == Some(start_row) {
5729                    start_row += 1;
5730                }
5731                let end_row =
5732                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5733                        selection.end.row - 1
5734                    } else {
5735                        selection.end.row
5736                    };
5737                last_toggled_row = Some(end_row);
5738
5739                if start_row > end_row {
5740                    continue;
5741                }
5742
5743                // If the language has line comments, toggle those.
5744                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5745                    // Split the comment prefix's trailing whitespace into a separate string,
5746                    // as that portion won't be used for detecting if a line is a comment.
5747                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5748                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5749                    let mut all_selection_lines_are_comments = true;
5750
5751                    for row in start_row..=end_row {
5752                        if snapshot.is_line_blank(row) && start_row < end_row {
5753                            continue;
5754                        }
5755
5756                        let prefix_range = comment_prefix_range(
5757                            snapshot.deref(),
5758                            row,
5759                            comment_prefix,
5760                            comment_prefix_whitespace,
5761                        );
5762                        if prefix_range.is_empty() {
5763                            all_selection_lines_are_comments = false;
5764                        }
5765                        selection_edit_ranges.push(prefix_range);
5766                    }
5767
5768                    if all_selection_lines_are_comments {
5769                        edits.extend(
5770                            selection_edit_ranges
5771                                .iter()
5772                                .cloned()
5773                                .map(|range| (range, empty_str.clone())),
5774                        );
5775                    } else {
5776                        let min_column = selection_edit_ranges
5777                            .iter()
5778                            .map(|r| r.start.column)
5779                            .min()
5780                            .unwrap_or(0);
5781                        edits.extend(selection_edit_ranges.iter().map(|range| {
5782                            let position = Point::new(range.start.row, min_column);
5783                            (position..position, full_comment_prefix.clone())
5784                        }));
5785                    }
5786                } else if let Some((full_comment_prefix, comment_suffix)) =
5787                    language.block_comment_delimiters()
5788                {
5789                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5790                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5791                    let prefix_range = comment_prefix_range(
5792                        snapshot.deref(),
5793                        start_row,
5794                        comment_prefix,
5795                        comment_prefix_whitespace,
5796                    );
5797                    let suffix_range = comment_suffix_range(
5798                        snapshot.deref(),
5799                        end_row,
5800                        comment_suffix.trim_start_matches(' '),
5801                        comment_suffix.starts_with(' '),
5802                    );
5803
5804                    if prefix_range.is_empty() || suffix_range.is_empty() {
5805                        edits.push((
5806                            prefix_range.start..prefix_range.start,
5807                            full_comment_prefix.clone(),
5808                        ));
5809                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5810                        suffixes_inserted.push((end_row, comment_suffix.len()));
5811                    } else {
5812                        edits.push((prefix_range, empty_str.clone()));
5813                        edits.push((suffix_range, empty_str.clone()));
5814                    }
5815                } else {
5816                    continue;
5817                }
5818            }
5819
5820            drop(snapshot);
5821            this.buffer.update(cx, |buffer, cx| {
5822                buffer.edit(edits, None, cx);
5823            });
5824
5825            // Adjust selections so that they end before any comment suffixes that
5826            // were inserted.
5827            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5828            let mut selections = this.selections.all::<Point>(cx);
5829            let snapshot = this.buffer.read(cx).read(cx);
5830            for selection in &mut selections {
5831                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5832                    match row.cmp(&selection.end.row) {
5833                        Ordering::Less => {
5834                            suffixes_inserted.next();
5835                            continue;
5836                        }
5837                        Ordering::Greater => break,
5838                        Ordering::Equal => {
5839                            if selection.end.column == snapshot.line_len(row) {
5840                                if selection.is_empty() {
5841                                    selection.start.column -= suffix_len as u32;
5842                                }
5843                                selection.end.column -= suffix_len as u32;
5844                            }
5845                            break;
5846                        }
5847                    }
5848                }
5849            }
5850
5851            drop(snapshot);
5852            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5853
5854            let selections = this.selections.all::<Point>(cx);
5855            let selections_on_single_row = selections.windows(2).all(|selections| {
5856                selections[0].start.row == selections[1].start.row
5857                    && selections[0].end.row == selections[1].end.row
5858                    && selections[0].start.row == selections[0].end.row
5859            });
5860            let selections_selecting = selections
5861                .iter()
5862                .any(|selection| selection.start != selection.end);
5863            let advance_downwards = action.advance_downwards
5864                && selections_on_single_row
5865                && !selections_selecting
5866                && this.mode != EditorMode::SingleLine;
5867
5868            if advance_downwards {
5869                let snapshot = this.buffer.read(cx).snapshot(cx);
5870
5871                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5872                    s.move_cursors_with(|display_snapshot, display_point, _| {
5873                        let mut point = display_point.to_point(display_snapshot);
5874                        point.row += 1;
5875                        point = snapshot.clip_point(point, Bias::Left);
5876                        let display_point = point.to_display_point(display_snapshot);
5877                        (display_point, SelectionGoal::Column(display_point.column()))
5878                    })
5879                });
5880            }
5881        });
5882    }
5883
5884    pub fn select_larger_syntax_node(
5885        &mut self,
5886        _: &SelectLargerSyntaxNode,
5887        cx: &mut ViewContext<Self>,
5888    ) {
5889        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5890        let buffer = self.buffer.read(cx).snapshot(cx);
5891        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5892
5893        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5894        let mut selected_larger_node = false;
5895        let new_selections = old_selections
5896            .iter()
5897            .map(|selection| {
5898                let old_range = selection.start..selection.end;
5899                let mut new_range = old_range.clone();
5900                while let Some(containing_range) =
5901                    buffer.range_for_syntax_ancestor(new_range.clone())
5902                {
5903                    new_range = containing_range;
5904                    if !display_map.intersects_fold(new_range.start)
5905                        && !display_map.intersects_fold(new_range.end)
5906                    {
5907                        break;
5908                    }
5909                }
5910
5911                selected_larger_node |= new_range != old_range;
5912                Selection {
5913                    id: selection.id,
5914                    start: new_range.start,
5915                    end: new_range.end,
5916                    goal: SelectionGoal::None,
5917                    reversed: selection.reversed,
5918                }
5919            })
5920            .collect::<Vec<_>>();
5921
5922        if selected_larger_node {
5923            stack.push(old_selections);
5924            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5925                s.select(new_selections);
5926            });
5927        }
5928        self.select_larger_syntax_node_stack = stack;
5929    }
5930
5931    pub fn select_smaller_syntax_node(
5932        &mut self,
5933        _: &SelectSmallerSyntaxNode,
5934        cx: &mut ViewContext<Self>,
5935    ) {
5936        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5937        if let Some(selections) = stack.pop() {
5938            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5939                s.select(selections.to_vec());
5940            });
5941        }
5942        self.select_larger_syntax_node_stack = stack;
5943    }
5944
5945    pub fn move_to_enclosing_bracket(
5946        &mut self,
5947        _: &MoveToEnclosingBracket,
5948        cx: &mut ViewContext<Self>,
5949    ) {
5950        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5951            s.move_offsets_with(|snapshot, selection| {
5952                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5953                    return;
5954                };
5955
5956                let mut best_length = usize::MAX;
5957                let mut best_inside = false;
5958                let mut best_in_bracket_range = false;
5959                let mut best_destination = None;
5960                for (open, close) in enclosing_bracket_ranges {
5961                    let close = close.to_inclusive();
5962                    let length = close.end() - open.start;
5963                    let inside = selection.start >= open.end && selection.end <= *close.start();
5964                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5965
5966                    // If best is next to a bracket and current isn't, skip
5967                    if !in_bracket_range && best_in_bracket_range {
5968                        continue;
5969                    }
5970
5971                    // Prefer smaller lengths unless best is inside and current isn't
5972                    if length > best_length && (best_inside || !inside) {
5973                        continue;
5974                    }
5975
5976                    best_length = length;
5977                    best_inside = inside;
5978                    best_in_bracket_range = in_bracket_range;
5979                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5980                        if inside {
5981                            open.end
5982                        } else {
5983                            open.start
5984                        }
5985                    } else {
5986                        if inside {
5987                            *close.start()
5988                        } else {
5989                            *close.end()
5990                        }
5991                    });
5992                }
5993
5994                if let Some(destination) = best_destination {
5995                    selection.collapse_to(destination, SelectionGoal::None);
5996                }
5997            })
5998        });
5999    }
6000
6001    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6002        self.end_selection(cx);
6003        self.selection_history.mode = SelectionHistoryMode::Undoing;
6004        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6005            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6006            self.select_next_state = entry.select_next_state;
6007            self.select_prev_state = entry.select_prev_state;
6008            self.add_selections_state = entry.add_selections_state;
6009            self.request_autoscroll(Autoscroll::newest(), cx);
6010        }
6011        self.selection_history.mode = SelectionHistoryMode::Normal;
6012    }
6013
6014    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6015        self.end_selection(cx);
6016        self.selection_history.mode = SelectionHistoryMode::Redoing;
6017        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6018            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6019            self.select_next_state = entry.select_next_state;
6020            self.select_prev_state = entry.select_prev_state;
6021            self.add_selections_state = entry.add_selections_state;
6022            self.request_autoscroll(Autoscroll::newest(), cx);
6023        }
6024        self.selection_history.mode = SelectionHistoryMode::Normal;
6025    }
6026
6027    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6028        self.go_to_diagnostic_impl(Direction::Next, cx)
6029    }
6030
6031    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6032        self.go_to_diagnostic_impl(Direction::Prev, cx)
6033    }
6034
6035    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6036        let buffer = self.buffer.read(cx).snapshot(cx);
6037        let selection = self.selections.newest::<usize>(cx);
6038
6039        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6040        if direction == Direction::Next {
6041            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6042                let (group_id, jump_to) = popover.activation_info();
6043                if self.activate_diagnostics(group_id, cx) {
6044                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6045                        let mut new_selection = s.newest_anchor().clone();
6046                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6047                        s.select_anchors(vec![new_selection.clone()]);
6048                    });
6049                }
6050                return;
6051            }
6052        }
6053
6054        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6055            active_diagnostics
6056                .primary_range
6057                .to_offset(&buffer)
6058                .to_inclusive()
6059        });
6060        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6061            if active_primary_range.contains(&selection.head()) {
6062                *active_primary_range.end()
6063            } else {
6064                selection.head()
6065            }
6066        } else {
6067            selection.head()
6068        };
6069
6070        loop {
6071            let mut diagnostics = if direction == Direction::Prev {
6072                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6073            } else {
6074                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6075            };
6076            let group = diagnostics.find_map(|entry| {
6077                if entry.diagnostic.is_primary
6078                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6079                    && !entry.range.is_empty()
6080                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6081                {
6082                    Some((entry.range, entry.diagnostic.group_id))
6083                } else {
6084                    None
6085                }
6086            });
6087
6088            if let Some((primary_range, group_id)) = group {
6089                if self.activate_diagnostics(group_id, cx) {
6090                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6091                        s.select(vec![Selection {
6092                            id: selection.id,
6093                            start: primary_range.start,
6094                            end: primary_range.start,
6095                            reversed: false,
6096                            goal: SelectionGoal::None,
6097                        }]);
6098                    });
6099                }
6100                break;
6101            } else {
6102                // Cycle around to the start of the buffer, potentially moving back to the start of
6103                // the currently active diagnostic.
6104                active_primary_range.take();
6105                if direction == Direction::Prev {
6106                    if search_start == buffer.len() {
6107                        break;
6108                    } else {
6109                        search_start = buffer.len();
6110                    }
6111                } else if search_start == 0 {
6112                    break;
6113                } else {
6114                    search_start = 0;
6115                }
6116            }
6117        }
6118    }
6119
6120    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6121        let snapshot = self
6122            .display_map
6123            .update(cx, |display_map, cx| display_map.snapshot(cx));
6124        let selection = self.selections.newest::<Point>(cx);
6125
6126        if !self.seek_in_direction(
6127            &snapshot,
6128            selection.head(),
6129            false,
6130            snapshot
6131                .buffer_snapshot
6132                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6133            cx,
6134        ) {
6135            let wrapped_point = Point::zero();
6136            self.seek_in_direction(
6137                &snapshot,
6138                wrapped_point,
6139                true,
6140                snapshot
6141                    .buffer_snapshot
6142                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6143                cx,
6144            );
6145        }
6146    }
6147
6148    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6149        let snapshot = self
6150            .display_map
6151            .update(cx, |display_map, cx| display_map.snapshot(cx));
6152        let selection = self.selections.newest::<Point>(cx);
6153
6154        if !self.seek_in_direction(
6155            &snapshot,
6156            selection.head(),
6157            false,
6158            snapshot
6159                .buffer_snapshot
6160                .git_diff_hunks_in_range_rev(0..selection.head().row),
6161            cx,
6162        ) {
6163            let wrapped_point = snapshot.buffer_snapshot.max_point();
6164            self.seek_in_direction(
6165                &snapshot,
6166                wrapped_point,
6167                true,
6168                snapshot
6169                    .buffer_snapshot
6170                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6171                cx,
6172            );
6173        }
6174    }
6175
6176    fn seek_in_direction(
6177        &mut self,
6178        snapshot: &DisplaySnapshot,
6179        initial_point: Point,
6180        is_wrapped: bool,
6181        hunks: impl Iterator<Item = DiffHunk<u32>>,
6182        cx: &mut ViewContext<Editor>,
6183    ) -> bool {
6184        let display_point = initial_point.to_display_point(snapshot);
6185        let mut hunks = hunks
6186            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6187            .skip_while(|hunk| {
6188                if is_wrapped {
6189                    false
6190                } else {
6191                    hunk.contains_display_row(display_point.row())
6192                }
6193            })
6194            .dedup();
6195
6196        if let Some(hunk) = hunks.next() {
6197            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6198                let row = hunk.start_display_row();
6199                let point = DisplayPoint::new(row, 0);
6200                s.select_display_ranges([point..point]);
6201            });
6202
6203            true
6204        } else {
6205            false
6206        }
6207    }
6208
6209    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6210        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6211    }
6212
6213    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6214        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6215    }
6216
6217    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6218        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6219    }
6220
6221    pub fn go_to_type_definition_split(
6222        &mut self,
6223        _: &GoToTypeDefinitionSplit,
6224        cx: &mut ViewContext<Self>,
6225    ) {
6226        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6227    }
6228
6229    fn go_to_definition_of_kind(
6230        &mut self,
6231        kind: GotoDefinitionKind,
6232        split: bool,
6233        cx: &mut ViewContext<Self>,
6234    ) {
6235        let Some(workspace) = self.workspace(cx) else { return };
6236        let buffer = self.buffer.read(cx);
6237        let head = self.selections.newest::<usize>(cx).head();
6238        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6239            text_anchor
6240        } else {
6241            return;
6242        };
6243
6244        let project = workspace.read(cx).project().clone();
6245        let definitions = project.update(cx, |project, cx| match kind {
6246            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6247            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6248        });
6249
6250        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6251            let definitions = definitions.await?;
6252            editor.update(&mut cx, |editor, cx| {
6253                editor.navigate_to_definitions(definitions, split, cx);
6254            })?;
6255            Ok::<(), anyhow::Error>(())
6256        })
6257        .detach_and_log_err(cx);
6258    }
6259
6260    pub fn navigate_to_definitions(
6261        &mut self,
6262        mut definitions: Vec<LocationLink>,
6263        split: bool,
6264        cx: &mut ViewContext<Editor>,
6265    ) {
6266        let Some(workspace) = self.workspace(cx) else { return };
6267        let pane = workspace.read(cx).active_pane().clone();
6268        // If there is one definition, just open it directly
6269        if definitions.len() == 1 {
6270            let definition = definitions.pop().unwrap();
6271            let range = definition
6272                .target
6273                .range
6274                .to_offset(definition.target.buffer.read(cx));
6275
6276            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6277                let range = self.range_for_match(&range);
6278                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6279                    s.select_ranges([range]);
6280                });
6281            } else {
6282                cx.window_context().defer(move |cx| {
6283                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6284                        if split {
6285                            workspace.split_project_item(definition.target.buffer.clone(), cx)
6286                        } else {
6287                            workspace.open_project_item(definition.target.buffer.clone(), cx)
6288                        }
6289                    });
6290                    target_editor.update(cx, |target_editor, cx| {
6291                        // When selecting a definition in a different buffer, disable the nav history
6292                        // to avoid creating a history entry at the previous cursor location.
6293                        pane.update(cx, |pane, _| pane.disable_history());
6294                        let range = target_editor.range_for_match(&range);
6295                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6296                            s.select_ranges([range]);
6297                        });
6298                        pane.update(cx, |pane, _| pane.enable_history());
6299                    });
6300                });
6301            }
6302        } else if !definitions.is_empty() {
6303            let replica_id = self.replica_id(cx);
6304            cx.window_context().defer(move |cx| {
6305                let title = definitions
6306                    .iter()
6307                    .find(|definition| definition.origin.is_some())
6308                    .and_then(|definition| {
6309                        definition.origin.as_ref().map(|origin| {
6310                            let buffer = origin.buffer.read(cx);
6311                            format!(
6312                                "Definitions for {}",
6313                                buffer
6314                                    .text_for_range(origin.range.clone())
6315                                    .collect::<String>()
6316                            )
6317                        })
6318                    })
6319                    .unwrap_or("Definitions".to_owned());
6320                let locations = definitions
6321                    .into_iter()
6322                    .map(|definition| definition.target)
6323                    .collect();
6324                workspace.update(cx, |workspace, cx| {
6325                    Self::open_locations_in_multibuffer(
6326                        workspace, locations, replica_id, title, split, cx,
6327                    )
6328                });
6329            });
6330        }
6331    }
6332
6333    pub fn find_all_references(
6334        workspace: &mut Workspace,
6335        _: &FindAllReferences,
6336        cx: &mut ViewContext<Workspace>,
6337    ) -> Option<Task<Result<()>>> {
6338        let active_item = workspace.active_item(cx)?;
6339        let editor_handle = active_item.act_as::<Self>(cx)?;
6340
6341        let editor = editor_handle.read(cx);
6342        let buffer = editor.buffer.read(cx);
6343        let head = editor.selections.newest::<usize>(cx).head();
6344        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6345        let replica_id = editor.replica_id(cx);
6346
6347        let project = workspace.project().clone();
6348        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6349        Some(cx.spawn_labeled(
6350            "Finding All References...",
6351            |workspace, mut cx| async move {
6352                let locations = references.await?;
6353                if locations.is_empty() {
6354                    return Ok(());
6355                }
6356
6357                workspace.update(&mut cx, |workspace, cx| {
6358                    let title = locations
6359                        .first()
6360                        .as_ref()
6361                        .map(|location| {
6362                            let buffer = location.buffer.read(cx);
6363                            format!(
6364                                "References to `{}`",
6365                                buffer
6366                                    .text_for_range(location.range.clone())
6367                                    .collect::<String>()
6368                            )
6369                        })
6370                        .unwrap();
6371                    Self::open_locations_in_multibuffer(
6372                        workspace, locations, replica_id, title, false, cx,
6373                    );
6374                })?;
6375
6376                Ok(())
6377            },
6378        ))
6379    }
6380
6381    /// Opens a multibuffer with the given project locations in it
6382    pub fn open_locations_in_multibuffer(
6383        workspace: &mut Workspace,
6384        mut locations: Vec<Location>,
6385        replica_id: ReplicaId,
6386        title: String,
6387        split: bool,
6388        cx: &mut ViewContext<Workspace>,
6389    ) {
6390        // If there are multiple definitions, open them in a multibuffer
6391        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6392        let mut locations = locations.into_iter().peekable();
6393        let mut ranges_to_highlight = Vec::new();
6394
6395        let excerpt_buffer = cx.add_model(|cx| {
6396            let mut multibuffer = MultiBuffer::new(replica_id);
6397            while let Some(location) = locations.next() {
6398                let buffer = location.buffer.read(cx);
6399                let mut ranges_for_buffer = Vec::new();
6400                let range = location.range.to_offset(buffer);
6401                ranges_for_buffer.push(range.clone());
6402
6403                while let Some(next_location) = locations.peek() {
6404                    if next_location.buffer == location.buffer {
6405                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6406                        locations.next();
6407                    } else {
6408                        break;
6409                    }
6410                }
6411
6412                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6413                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6414                    location.buffer.clone(),
6415                    ranges_for_buffer,
6416                    1,
6417                    cx,
6418                ))
6419            }
6420
6421            multibuffer.with_title(title)
6422        });
6423
6424        let editor = cx.add_view(|cx| {
6425            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6426        });
6427        editor.update(cx, |editor, cx| {
6428            editor.highlight_background::<Self>(
6429                ranges_to_highlight,
6430                |theme| theme.editor.highlighted_line_background,
6431                cx,
6432            );
6433        });
6434        if split {
6435            workspace.split_item(Box::new(editor), cx);
6436        } else {
6437            workspace.add_item(Box::new(editor), cx);
6438        }
6439    }
6440
6441    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6442        use language::ToOffset as _;
6443
6444        let project = self.project.clone()?;
6445        let selection = self.selections.newest_anchor().clone();
6446        let (cursor_buffer, cursor_buffer_position) = self
6447            .buffer
6448            .read(cx)
6449            .text_anchor_for_position(selection.head(), cx)?;
6450        let (tail_buffer, _) = self
6451            .buffer
6452            .read(cx)
6453            .text_anchor_for_position(selection.tail(), cx)?;
6454        if tail_buffer != cursor_buffer {
6455            return None;
6456        }
6457
6458        let snapshot = cursor_buffer.read(cx).snapshot();
6459        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6460        let prepare_rename = project.update(cx, |project, cx| {
6461            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6462        });
6463
6464        Some(cx.spawn(|this, mut cx| async move {
6465            let rename_range = if let Some(range) = prepare_rename.await? {
6466                Some(range)
6467            } else {
6468                this.read_with(&cx, |this, cx| {
6469                    let buffer = this.buffer.read(cx).snapshot(cx);
6470                    let mut buffer_highlights = this
6471                        .document_highlights_for_position(selection.head(), &buffer)
6472                        .filter(|highlight| {
6473                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6474                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6475                        });
6476                    buffer_highlights
6477                        .next()
6478                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6479                })?
6480            };
6481            if let Some(rename_range) = rename_range {
6482                let rename_buffer_range = rename_range.to_offset(&snapshot);
6483                let cursor_offset_in_rename_range =
6484                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6485
6486                this.update(&mut cx, |this, cx| {
6487                    this.take_rename(false, cx);
6488                    let style = this.style(cx);
6489                    let buffer = this.buffer.read(cx).read(cx);
6490                    let cursor_offset = selection.head().to_offset(&buffer);
6491                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6492                    let rename_end = rename_start + rename_buffer_range.len();
6493                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6494                    let mut old_highlight_id = None;
6495                    let old_name: Arc<str> = buffer
6496                        .chunks(rename_start..rename_end, true)
6497                        .map(|chunk| {
6498                            if old_highlight_id.is_none() {
6499                                old_highlight_id = chunk.syntax_highlight_id;
6500                            }
6501                            chunk.text
6502                        })
6503                        .collect::<String>()
6504                        .into();
6505
6506                    drop(buffer);
6507
6508                    // Position the selection in the rename editor so that it matches the current selection.
6509                    this.show_local_selections = false;
6510                    let rename_editor = cx.add_view(|cx| {
6511                        let mut editor = Editor::single_line(None, cx);
6512                        if let Some(old_highlight_id) = old_highlight_id {
6513                            editor.override_text_style =
6514                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6515                        }
6516                        editor.buffer.update(cx, |buffer, cx| {
6517                            buffer.edit([(0..0, old_name.clone())], None, cx)
6518                        });
6519                        editor.select_all(&SelectAll, cx);
6520                        editor
6521                    });
6522
6523                    let ranges = this
6524                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6525                        .into_iter()
6526                        .flat_map(|(_, ranges)| ranges)
6527                        .chain(
6528                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6529                                .into_iter()
6530                                .flat_map(|(_, ranges)| ranges),
6531                        )
6532                        .collect();
6533
6534                    this.highlight_text::<Rename>(
6535                        ranges,
6536                        HighlightStyle {
6537                            fade_out: Some(style.rename_fade),
6538                            ..Default::default()
6539                        },
6540                        cx,
6541                    );
6542                    cx.focus(&rename_editor);
6543                    let block_id = this.insert_blocks(
6544                        [BlockProperties {
6545                            style: BlockStyle::Flex,
6546                            position: range.start.clone(),
6547                            height: 1,
6548                            render: Arc::new({
6549                                let editor = rename_editor.clone();
6550                                move |cx: &mut BlockContext| {
6551                                    ChildView::new(&editor, cx)
6552                                        .contained()
6553                                        .with_padding_left(cx.anchor_x)
6554                                        .into_any()
6555                                }
6556                            }),
6557                            disposition: BlockDisposition::Below,
6558                        }],
6559                        Some(Autoscroll::fit()),
6560                        cx,
6561                    )[0];
6562                    this.pending_rename = Some(RenameState {
6563                        range,
6564                        old_name,
6565                        editor: rename_editor,
6566                        block_id,
6567                    });
6568                })?;
6569            }
6570
6571            Ok(())
6572        }))
6573    }
6574
6575    pub fn confirm_rename(
6576        workspace: &mut Workspace,
6577        _: &ConfirmRename,
6578        cx: &mut ViewContext<Workspace>,
6579    ) -> Option<Task<Result<()>>> {
6580        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6581
6582        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6583            let rename = editor.take_rename(false, cx)?;
6584            let buffer = editor.buffer.read(cx);
6585            let (start_buffer, start) =
6586                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6587            let (end_buffer, end) =
6588                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6589            if start_buffer == end_buffer {
6590                let new_name = rename.editor.read(cx).text(cx);
6591                Some((start_buffer, start..end, rename.old_name, new_name))
6592            } else {
6593                None
6594            }
6595        })?;
6596
6597        let rename = workspace.project().clone().update(cx, |project, cx| {
6598            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6599        });
6600
6601        let editor = editor.downgrade();
6602        Some(cx.spawn(|workspace, mut cx| async move {
6603            let project_transaction = rename.await?;
6604            Self::open_project_transaction(
6605                &editor,
6606                workspace,
6607                project_transaction,
6608                format!("Rename: {}{}", old_name, new_name),
6609                cx.clone(),
6610            )
6611            .await?;
6612
6613            editor.update(&mut cx, |editor, cx| {
6614                editor.refresh_document_highlights(cx);
6615            })?;
6616            Ok(())
6617        }))
6618    }
6619
6620    fn take_rename(
6621        &mut self,
6622        moving_cursor: bool,
6623        cx: &mut ViewContext<Self>,
6624    ) -> Option<RenameState> {
6625        let rename = self.pending_rename.take()?;
6626        self.remove_blocks(
6627            [rename.block_id].into_iter().collect(),
6628            Some(Autoscroll::fit()),
6629            cx,
6630        );
6631        self.clear_text_highlights::<Rename>(cx);
6632        self.show_local_selections = true;
6633
6634        if moving_cursor {
6635            let rename_editor = rename.editor.read(cx);
6636            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6637
6638            // Update the selection to match the position of the selection inside
6639            // the rename editor.
6640            let snapshot = self.buffer.read(cx).read(cx);
6641            let rename_range = rename.range.to_offset(&snapshot);
6642            let cursor_in_editor = snapshot
6643                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6644                .min(rename_range.end);
6645            drop(snapshot);
6646
6647            self.change_selections(None, cx, |s| {
6648                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6649            });
6650        } else {
6651            self.refresh_document_highlights(cx);
6652        }
6653
6654        Some(rename)
6655    }
6656
6657    #[cfg(any(test, feature = "test-support"))]
6658    pub fn pending_rename(&self) -> Option<&RenameState> {
6659        self.pending_rename.as_ref()
6660    }
6661
6662    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6663        let project = match &self.project {
6664            Some(project) => project.clone(),
6665            None => return None,
6666        };
6667
6668        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6669    }
6670
6671    fn perform_format(
6672        &mut self,
6673        project: ModelHandle<Project>,
6674        trigger: FormatTrigger,
6675        cx: &mut ViewContext<Self>,
6676    ) -> Task<Result<()>> {
6677        let buffer = self.buffer().clone();
6678        let buffers = buffer.read(cx).all_buffers();
6679
6680        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6681        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6682
6683        cx.spawn(|_, mut cx| async move {
6684            let transaction = futures::select_biased! {
6685                _ = timeout => {
6686                    log::warn!("timed out waiting for formatting");
6687                    None
6688                }
6689                transaction = format.log_err().fuse() => transaction,
6690            };
6691
6692            buffer.update(&mut cx, |buffer, cx| {
6693                if let Some(transaction) = transaction {
6694                    if !buffer.is_singleton() {
6695                        buffer.push_transaction(&transaction.0, cx);
6696                    }
6697                }
6698
6699                cx.notify();
6700            });
6701
6702            Ok(())
6703        })
6704    }
6705
6706    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6707        if let Some(project) = self.project.clone() {
6708            self.buffer.update(cx, |multi_buffer, cx| {
6709                project.update(cx, |project, cx| {
6710                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6711                });
6712            })
6713        }
6714    }
6715
6716    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6717        cx.show_character_palette();
6718    }
6719
6720    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6721        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6722            let buffer = self.buffer.read(cx).snapshot(cx);
6723            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6724            let is_valid = buffer
6725                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6726                .any(|entry| {
6727                    entry.diagnostic.is_primary
6728                        && !entry.range.is_empty()
6729                        && entry.range.start == primary_range_start
6730                        && entry.diagnostic.message == active_diagnostics.primary_message
6731                });
6732
6733            if is_valid != active_diagnostics.is_valid {
6734                active_diagnostics.is_valid = is_valid;
6735                let mut new_styles = HashMap::default();
6736                for (block_id, diagnostic) in &active_diagnostics.blocks {
6737                    new_styles.insert(
6738                        *block_id,
6739                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6740                    );
6741                }
6742                self.display_map
6743                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6744            }
6745        }
6746    }
6747
6748    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6749        self.dismiss_diagnostics(cx);
6750        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6751            let buffer = self.buffer.read(cx).snapshot(cx);
6752
6753            let mut primary_range = None;
6754            let mut primary_message = None;
6755            let mut group_end = Point::zero();
6756            let diagnostic_group = buffer
6757                .diagnostic_group::<Point>(group_id)
6758                .map(|entry| {
6759                    if entry.range.end > group_end {
6760                        group_end = entry.range.end;
6761                    }
6762                    if entry.diagnostic.is_primary {
6763                        primary_range = Some(entry.range.clone());
6764                        primary_message = Some(entry.diagnostic.message.clone());
6765                    }
6766                    entry
6767                })
6768                .collect::<Vec<_>>();
6769            let primary_range = primary_range?;
6770            let primary_message = primary_message?;
6771            let primary_range =
6772                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6773
6774            let blocks = display_map
6775                .insert_blocks(
6776                    diagnostic_group.iter().map(|entry| {
6777                        let diagnostic = entry.diagnostic.clone();
6778                        let message_height = diagnostic.message.lines().count() as u8;
6779                        BlockProperties {
6780                            style: BlockStyle::Fixed,
6781                            position: buffer.anchor_after(entry.range.start),
6782                            height: message_height,
6783                            render: diagnostic_block_renderer(diagnostic, true),
6784                            disposition: BlockDisposition::Below,
6785                        }
6786                    }),
6787                    cx,
6788                )
6789                .into_iter()
6790                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6791                .collect();
6792
6793            Some(ActiveDiagnosticGroup {
6794                primary_range,
6795                primary_message,
6796                blocks,
6797                is_valid: true,
6798            })
6799        });
6800        self.active_diagnostics.is_some()
6801    }
6802
6803    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6804        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6805            self.display_map.update(cx, |display_map, cx| {
6806                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6807            });
6808            cx.notify();
6809        }
6810    }
6811
6812    pub fn set_selections_from_remote(
6813        &mut self,
6814        selections: Vec<Selection<Anchor>>,
6815        pending_selection: Option<Selection<Anchor>>,
6816        cx: &mut ViewContext<Self>,
6817    ) {
6818        let old_cursor_position = self.selections.newest_anchor().head();
6819        self.selections.change_with(cx, |s| {
6820            s.select_anchors(selections);
6821            if let Some(pending_selection) = pending_selection {
6822                s.set_pending(pending_selection, SelectMode::Character);
6823            } else {
6824                s.clear_pending();
6825            }
6826        });
6827        self.selections_did_change(false, &old_cursor_position, cx);
6828    }
6829
6830    fn push_to_selection_history(&mut self) {
6831        self.selection_history.push(SelectionHistoryEntry {
6832            selections: self.selections.disjoint_anchors(),
6833            select_next_state: self.select_next_state.clone(),
6834            select_prev_state: self.select_prev_state.clone(),
6835            add_selections_state: self.add_selections_state.clone(),
6836        });
6837    }
6838
6839    pub fn transact(
6840        &mut self,
6841        cx: &mut ViewContext<Self>,
6842        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6843    ) -> Option<TransactionId> {
6844        self.start_transaction_at(Instant::now(), cx);
6845        update(self, cx);
6846        self.end_transaction_at(Instant::now(), cx)
6847    }
6848
6849    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6850        self.end_selection(cx);
6851        if let Some(tx_id) = self
6852            .buffer
6853            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6854        {
6855            self.selection_history
6856                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6857        }
6858    }
6859
6860    fn end_transaction_at(
6861        &mut self,
6862        now: Instant,
6863        cx: &mut ViewContext<Self>,
6864    ) -> Option<TransactionId> {
6865        if let Some(tx_id) = self
6866            .buffer
6867            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6868        {
6869            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6870                *end_selections = Some(self.selections.disjoint_anchors());
6871            } else {
6872                error!("unexpectedly ended a transaction that wasn't started by this editor");
6873            }
6874
6875            cx.emit(Event::Edited);
6876            Some(tx_id)
6877        } else {
6878            None
6879        }
6880    }
6881
6882    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6883        let mut fold_ranges = Vec::new();
6884
6885        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6886
6887        let selections = self.selections.all::<Point>(cx);
6888        for selection in selections {
6889            let range = selection.range().sorted();
6890            let buffer_start_row = range.start.row;
6891
6892            for row in (0..=range.end.row).rev() {
6893                let fold_range = display_map.foldable_range(row);
6894
6895                if let Some(fold_range) = fold_range {
6896                    if fold_range.end.row >= buffer_start_row {
6897                        fold_ranges.push(fold_range);
6898                        if row <= range.start.row {
6899                            break;
6900                        }
6901                    }
6902                }
6903            }
6904        }
6905
6906        self.fold_ranges(fold_ranges, true, cx);
6907    }
6908
6909    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6910        let buffer_row = fold_at.buffer_row;
6911        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6912
6913        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6914            let autoscroll = self
6915                .selections
6916                .all::<Point>(cx)
6917                .iter()
6918                .any(|selection| fold_range.overlaps(&selection.range()));
6919
6920            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6921        }
6922    }
6923
6924    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6925        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6926        let buffer = &display_map.buffer_snapshot;
6927        let selections = self.selections.all::<Point>(cx);
6928        let ranges = selections
6929            .iter()
6930            .map(|s| {
6931                let range = s.display_range(&display_map).sorted();
6932                let mut start = range.start.to_point(&display_map);
6933                let mut end = range.end.to_point(&display_map);
6934                start.column = 0;
6935                end.column = buffer.line_len(end.row);
6936                start..end
6937            })
6938            .collect::<Vec<_>>();
6939
6940        self.unfold_ranges(ranges, true, true, cx);
6941    }
6942
6943    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6944        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6945
6946        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6947            ..Point::new(
6948                unfold_at.buffer_row,
6949                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6950            );
6951
6952        let autoscroll = self
6953            .selections
6954            .all::<Point>(cx)
6955            .iter()
6956            .any(|selection| selection.range().overlaps(&intersection_range));
6957
6958        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6959    }
6960
6961    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6962        let selections = self.selections.all::<Point>(cx);
6963        let ranges = selections.into_iter().map(|s| s.start..s.end);
6964        self.fold_ranges(ranges, true, cx);
6965    }
6966
6967    pub fn fold_ranges<T: ToOffset + Clone>(
6968        &mut self,
6969        ranges: impl IntoIterator<Item = Range<T>>,
6970        auto_scroll: bool,
6971        cx: &mut ViewContext<Self>,
6972    ) {
6973        let mut ranges = ranges.into_iter().peekable();
6974        if ranges.peek().is_some() {
6975            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6976
6977            if auto_scroll {
6978                self.request_autoscroll(Autoscroll::fit(), cx);
6979            }
6980
6981            cx.notify();
6982        }
6983    }
6984
6985    pub fn unfold_ranges<T: ToOffset + Clone>(
6986        &mut self,
6987        ranges: impl IntoIterator<Item = Range<T>>,
6988        inclusive: bool,
6989        auto_scroll: bool,
6990        cx: &mut ViewContext<Self>,
6991    ) {
6992        let mut ranges = ranges.into_iter().peekable();
6993        if ranges.peek().is_some() {
6994            self.display_map
6995                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6996            if auto_scroll {
6997                self.request_autoscroll(Autoscroll::fit(), cx);
6998            }
6999
7000            cx.notify();
7001        }
7002    }
7003
7004    pub fn gutter_hover(
7005        &mut self,
7006        GutterHover { hovered }: &GutterHover,
7007        cx: &mut ViewContext<Self>,
7008    ) {
7009        self.gutter_hovered = *hovered;
7010        cx.notify();
7011    }
7012
7013    pub fn insert_blocks(
7014        &mut self,
7015        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7016        autoscroll: Option<Autoscroll>,
7017        cx: &mut ViewContext<Self>,
7018    ) -> Vec<BlockId> {
7019        let blocks = self
7020            .display_map
7021            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7022        if let Some(autoscroll) = autoscroll {
7023            self.request_autoscroll(autoscroll, cx);
7024        }
7025        blocks
7026    }
7027
7028    pub fn replace_blocks(
7029        &mut self,
7030        blocks: HashMap<BlockId, RenderBlock>,
7031        autoscroll: Option<Autoscroll>,
7032        cx: &mut ViewContext<Self>,
7033    ) {
7034        self.display_map
7035            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7036        if let Some(autoscroll) = autoscroll {
7037            self.request_autoscroll(autoscroll, cx);
7038        }
7039    }
7040
7041    pub fn remove_blocks(
7042        &mut self,
7043        block_ids: HashSet<BlockId>,
7044        autoscroll: Option<Autoscroll>,
7045        cx: &mut ViewContext<Self>,
7046    ) {
7047        self.display_map.update(cx, |display_map, cx| {
7048            display_map.remove_blocks(block_ids, cx)
7049        });
7050        if let Some(autoscroll) = autoscroll {
7051            self.request_autoscroll(autoscroll, cx);
7052        }
7053    }
7054
7055    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7056        self.display_map
7057            .update(cx, |map, cx| map.snapshot(cx))
7058            .longest_row()
7059    }
7060
7061    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7062        self.display_map
7063            .update(cx, |map, cx| map.snapshot(cx))
7064            .max_point()
7065    }
7066
7067    pub fn text(&self, cx: &AppContext) -> String {
7068        self.buffer.read(cx).read(cx).text()
7069    }
7070
7071    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7072        self.transact(cx, |this, cx| {
7073            this.buffer
7074                .read(cx)
7075                .as_singleton()
7076                .expect("you can only call set_text on editors for singleton buffers")
7077                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7078        });
7079    }
7080
7081    pub fn display_text(&self, cx: &mut AppContext) -> String {
7082        self.display_map
7083            .update(cx, |map, cx| map.snapshot(cx))
7084            .text()
7085    }
7086
7087    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7088        let settings = self.buffer.read(cx).settings_at(0, cx);
7089        let mode = self
7090            .soft_wrap_mode_override
7091            .unwrap_or_else(|| settings.soft_wrap);
7092        match mode {
7093            language_settings::SoftWrap::None => SoftWrap::None,
7094            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7095            language_settings::SoftWrap::PreferredLineLength => {
7096                SoftWrap::Column(settings.preferred_line_length)
7097            }
7098        }
7099    }
7100
7101    pub fn set_soft_wrap_mode(
7102        &mut self,
7103        mode: language_settings::SoftWrap,
7104        cx: &mut ViewContext<Self>,
7105    ) {
7106        self.soft_wrap_mode_override = Some(mode);
7107        cx.notify();
7108    }
7109
7110    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7111        self.display_map
7112            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7113    }
7114
7115    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7116        if self.soft_wrap_mode_override.is_some() {
7117            self.soft_wrap_mode_override.take();
7118        } else {
7119            let soft_wrap = match self.soft_wrap_mode(cx) {
7120                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7121                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7122            };
7123            self.soft_wrap_mode_override = Some(soft_wrap);
7124        }
7125        cx.notify();
7126    }
7127
7128    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7129        self.show_gutter = show_gutter;
7130        cx.notify();
7131    }
7132
7133    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7134        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7135            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7136                cx.reveal_path(&file.abs_path(cx));
7137            }
7138        }
7139    }
7140
7141    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7142        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7143            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7144                if let Some(path) = file.abs_path(cx).to_str() {
7145                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7146                }
7147            }
7148        }
7149    }
7150
7151    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7152        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7153            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7154                if let Some(path) = file.path().to_str() {
7155                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7156                }
7157            }
7158        }
7159    }
7160
7161    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7162        self.highlighted_rows = rows;
7163    }
7164
7165    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7166        self.highlighted_rows.clone()
7167    }
7168
7169    pub fn highlight_background<T: 'static>(
7170        &mut self,
7171        ranges: Vec<Range<Anchor>>,
7172        color_fetcher: fn(&Theme) -> Color,
7173        cx: &mut ViewContext<Self>,
7174    ) {
7175        self.background_highlights
7176            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7177        cx.notify();
7178    }
7179
7180    #[allow(clippy::type_complexity)]
7181    pub fn clear_background_highlights<T: 'static>(
7182        &mut self,
7183        cx: &mut ViewContext<Self>,
7184    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7185        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7186        if highlights.is_some() {
7187            cx.notify();
7188        }
7189        highlights
7190    }
7191
7192    #[cfg(feature = "test-support")]
7193    pub fn all_background_highlights(
7194        &mut self,
7195        cx: &mut ViewContext<Self>,
7196    ) -> Vec<(Range<DisplayPoint>, Color)> {
7197        let snapshot = self.snapshot(cx);
7198        let buffer = &snapshot.buffer_snapshot;
7199        let start = buffer.anchor_before(0);
7200        let end = buffer.anchor_after(buffer.len());
7201        let theme = theme::current(cx);
7202        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7203    }
7204
7205    fn document_highlights_for_position<'a>(
7206        &'a self,
7207        position: Anchor,
7208        buffer: &'a MultiBufferSnapshot,
7209    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7210        let read_highlights = self
7211            .background_highlights
7212            .get(&TypeId::of::<DocumentHighlightRead>())
7213            .map(|h| &h.1);
7214        let write_highlights = self
7215            .background_highlights
7216            .get(&TypeId::of::<DocumentHighlightWrite>())
7217            .map(|h| &h.1);
7218        let left_position = position.bias_left(buffer);
7219        let right_position = position.bias_right(buffer);
7220        read_highlights
7221            .into_iter()
7222            .chain(write_highlights)
7223            .flat_map(move |ranges| {
7224                let start_ix = match ranges.binary_search_by(|probe| {
7225                    let cmp = probe.end.cmp(&left_position, buffer);
7226                    if cmp.is_ge() {
7227                        Ordering::Greater
7228                    } else {
7229                        Ordering::Less
7230                    }
7231                }) {
7232                    Ok(i) | Err(i) => i,
7233                };
7234
7235                let right_position = right_position.clone();
7236                ranges[start_ix..]
7237                    .iter()
7238                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7239            })
7240    }
7241
7242    pub fn background_highlights_in_range(
7243        &self,
7244        search_range: Range<Anchor>,
7245        display_snapshot: &DisplaySnapshot,
7246        theme: &Theme,
7247    ) -> Vec<(Range<DisplayPoint>, Color)> {
7248        let mut results = Vec::new();
7249        let buffer = &display_snapshot.buffer_snapshot;
7250        for (color_fetcher, ranges) in self.background_highlights.values() {
7251            let color = color_fetcher(theme);
7252            let start_ix = match ranges.binary_search_by(|probe| {
7253                let cmp = probe.end.cmp(&search_range.start, buffer);
7254                if cmp.is_gt() {
7255                    Ordering::Greater
7256                } else {
7257                    Ordering::Less
7258                }
7259            }) {
7260                Ok(i) | Err(i) => i,
7261            };
7262            for range in &ranges[start_ix..] {
7263                if range.start.cmp(&search_range.end, buffer).is_ge() {
7264                    break;
7265                }
7266                let start = range
7267                    .start
7268                    .to_point(buffer)
7269                    .to_display_point(display_snapshot);
7270                let end = range
7271                    .end
7272                    .to_point(buffer)
7273                    .to_display_point(display_snapshot);
7274                results.push((start..end, color))
7275            }
7276        }
7277        results
7278    }
7279    pub fn background_highlights_in_range_for<T: 'static>(
7280        &self,
7281        search_range: Range<Anchor>,
7282        display_snapshot: &DisplaySnapshot,
7283        theme: &Theme,
7284    ) -> Vec<(Range<DisplayPoint>, Color)> {
7285        let mut results = Vec::new();
7286        let buffer = &display_snapshot.buffer_snapshot;
7287        let Some((color_fetcher, ranges)) = self.background_highlights
7288            .get(&TypeId::of::<T>()) else {
7289                return vec![];
7290            };
7291
7292        let color = color_fetcher(theme);
7293        let start_ix = match ranges.binary_search_by(|probe| {
7294            let cmp = probe.end.cmp(&search_range.start, buffer);
7295            if cmp.is_gt() {
7296                Ordering::Greater
7297            } else {
7298                Ordering::Less
7299            }
7300        }) {
7301            Ok(i) | Err(i) => i,
7302        };
7303        for range in &ranges[start_ix..] {
7304            if range.start.cmp(&search_range.end, buffer).is_ge() {
7305                break;
7306            }
7307            let start = range
7308                .start
7309                .to_point(buffer)
7310                .to_display_point(display_snapshot);
7311            let end = range
7312                .end
7313                .to_point(buffer)
7314                .to_display_point(display_snapshot);
7315            results.push((start..end, color))
7316        }
7317
7318        results
7319    }
7320
7321    pub fn highlight_text<T: 'static>(
7322        &mut self,
7323        ranges: Vec<Range<Anchor>>,
7324        style: HighlightStyle,
7325        cx: &mut ViewContext<Self>,
7326    ) {
7327        self.display_map.update(cx, |map, _| {
7328            map.highlight_text(TypeId::of::<T>(), ranges, style)
7329        });
7330        cx.notify();
7331    }
7332
7333    pub fn text_highlights<'a, T: 'static>(
7334        &'a self,
7335        cx: &'a AppContext,
7336    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7337        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7338    }
7339
7340    pub fn clear_text_highlights<T: 'static>(
7341        &mut self,
7342        cx: &mut ViewContext<Self>,
7343    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7344        let highlights = self
7345            .display_map
7346            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7347        if highlights.is_some() {
7348            cx.notify();
7349        }
7350        highlights
7351    }
7352
7353    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7354        self.blink_manager.read(cx).visible() && self.focused
7355    }
7356
7357    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7358        cx.notify();
7359    }
7360
7361    fn on_buffer_event(
7362        &mut self,
7363        multibuffer: ModelHandle<MultiBuffer>,
7364        event: &multi_buffer::Event,
7365        cx: &mut ViewContext<Self>,
7366    ) {
7367        match event {
7368            multi_buffer::Event::Edited => {
7369                self.refresh_active_diagnostics(cx);
7370                self.refresh_code_actions(cx);
7371                if self.has_active_copilot_suggestion(cx) {
7372                    self.update_visible_copilot_suggestion(cx);
7373                }
7374                cx.emit(Event::BufferEdited);
7375
7376                if let Some(project) = &self.project {
7377                    let project = project.read(cx);
7378                    let languages_affected = multibuffer
7379                        .read(cx)
7380                        .all_buffers()
7381                        .into_iter()
7382                        .filter_map(|buffer| {
7383                            let buffer = buffer.read(cx);
7384                            let language = buffer.language()?;
7385                            if project.is_local()
7386                                && project.language_servers_for_buffer(buffer, cx).count() == 0
7387                            {
7388                                None
7389                            } else {
7390                                Some(language)
7391                            }
7392                        })
7393                        .cloned()
7394                        .collect::<HashSet<_>>();
7395                    if !languages_affected.is_empty() {
7396                        self.refresh_inlays(
7397                            InlayRefreshReason::BufferEdited(languages_affected),
7398                            cx,
7399                        );
7400                    }
7401                }
7402            }
7403            multi_buffer::Event::ExcerptsAdded {
7404                buffer,
7405                predecessor,
7406                excerpts,
7407            } => cx.emit(Event::ExcerptsAdded {
7408                buffer: buffer.clone(),
7409                predecessor: *predecessor,
7410                excerpts: excerpts.clone(),
7411            }),
7412            multi_buffer::Event::ExcerptsRemoved { ids } => {
7413                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7414            }
7415            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7416            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7417            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7418            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7419            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7420            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7421            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7422            multi_buffer::Event::DiagnosticsUpdated => {
7423                self.refresh_active_diagnostics(cx);
7424            }
7425            _ => {}
7426        };
7427    }
7428
7429    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7430        cx.notify();
7431    }
7432
7433    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7434        self.refresh_copilot_suggestions(true, cx);
7435        self.refresh_inlays(
7436            InlayRefreshReason::SettingsChange(inlay_hint_settings(
7437                self.selections.newest_anchor().head(),
7438                &self.buffer.read(cx).snapshot(cx),
7439                cx,
7440            )),
7441            cx,
7442        );
7443    }
7444
7445    pub fn set_searchable(&mut self, searchable: bool) {
7446        self.searchable = searchable;
7447    }
7448
7449    pub fn searchable(&self) -> bool {
7450        self.searchable
7451    }
7452
7453    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7454        let active_item = workspace.active_item(cx);
7455        let editor_handle = if let Some(editor) = active_item
7456            .as_ref()
7457            .and_then(|item| item.act_as::<Self>(cx))
7458        {
7459            editor
7460        } else {
7461            cx.propagate_action();
7462            return;
7463        };
7464
7465        let editor = editor_handle.read(cx);
7466        let buffer = editor.buffer.read(cx);
7467        if buffer.is_singleton() {
7468            cx.propagate_action();
7469            return;
7470        }
7471
7472        let mut new_selections_by_buffer = HashMap::default();
7473        for selection in editor.selections.all::<usize>(cx) {
7474            for (buffer, mut range, _) in
7475                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7476            {
7477                if selection.reversed {
7478                    mem::swap(&mut range.start, &mut range.end);
7479                }
7480                new_selections_by_buffer
7481                    .entry(buffer)
7482                    .or_insert(Vec::new())
7483                    .push(range)
7484            }
7485        }
7486
7487        editor_handle.update(cx, |editor, cx| {
7488            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7489        });
7490        let pane = workspace.active_pane().clone();
7491        pane.update(cx, |pane, _| pane.disable_history());
7492
7493        // We defer the pane interaction because we ourselves are a workspace item
7494        // and activating a new item causes the pane to call a method on us reentrantly,
7495        // which panics if we're on the stack.
7496        cx.defer(move |workspace, cx| {
7497            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7498                let editor = workspace.open_project_item::<Self>(buffer, cx);
7499                editor.update(cx, |editor, cx| {
7500                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7501                        s.select_ranges(ranges);
7502                    });
7503                });
7504            }
7505
7506            pane.update(cx, |pane, _| pane.enable_history());
7507        });
7508    }
7509
7510    fn jump(
7511        workspace: &mut Workspace,
7512        path: ProjectPath,
7513        position: Point,
7514        anchor: language::Anchor,
7515        cx: &mut ViewContext<Workspace>,
7516    ) {
7517        let editor = workspace.open_path(path, None, true, cx);
7518        cx.spawn(|_, mut cx| async move {
7519            let editor = editor
7520                .await?
7521                .downcast::<Editor>()
7522                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7523                .downgrade();
7524            editor.update(&mut cx, |editor, cx| {
7525                let buffer = editor
7526                    .buffer()
7527                    .read(cx)
7528                    .as_singleton()
7529                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7530                let buffer = buffer.read(cx);
7531                let cursor = if buffer.can_resolve(&anchor) {
7532                    language::ToPoint::to_point(&anchor, buffer)
7533                } else {
7534                    buffer.clip_point(position, Bias::Left)
7535                };
7536
7537                let nav_history = editor.nav_history.take();
7538                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7539                    s.select_ranges([cursor..cursor]);
7540                });
7541                editor.nav_history = nav_history;
7542
7543                anyhow::Ok(())
7544            })??;
7545
7546            anyhow::Ok(())
7547        })
7548        .detach_and_log_err(cx);
7549    }
7550
7551    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7552        let snapshot = self.buffer.read(cx).read(cx);
7553        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7554        Some(
7555            ranges
7556                .iter()
7557                .map(move |range| {
7558                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7559                })
7560                .collect(),
7561        )
7562    }
7563
7564    fn selection_replacement_ranges(
7565        &self,
7566        range: Range<OffsetUtf16>,
7567        cx: &AppContext,
7568    ) -> Vec<Range<OffsetUtf16>> {
7569        let selections = self.selections.all::<OffsetUtf16>(cx);
7570        let newest_selection = selections
7571            .iter()
7572            .max_by_key(|selection| selection.id)
7573            .unwrap();
7574        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7575        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7576        let snapshot = self.buffer.read(cx).read(cx);
7577        selections
7578            .into_iter()
7579            .map(|mut selection| {
7580                selection.start.0 =
7581                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7582                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7583                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7584                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7585            })
7586            .collect()
7587    }
7588
7589    fn report_copilot_event(
7590        &self,
7591        suggestion_id: Option<String>,
7592        suggestion_accepted: bool,
7593        cx: &AppContext,
7594    ) {
7595        let Some(project) = &self.project else {
7596            return
7597        };
7598
7599        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7600        let file_extension = self
7601            .buffer
7602            .read(cx)
7603            .as_singleton()
7604            .and_then(|b| b.read(cx).file())
7605            .and_then(|file| Path::new(file.file_name(cx)).extension())
7606            .and_then(|e| e.to_str())
7607            .map(|a| a.to_string());
7608
7609        let telemetry = project.read(cx).client().telemetry().clone();
7610        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7611
7612        let event = ClickhouseEvent::Copilot {
7613            suggestion_id,
7614            suggestion_accepted,
7615            file_extension,
7616        };
7617        telemetry.report_clickhouse_event(event, telemetry_settings);
7618    }
7619
7620    fn report_editor_event(
7621        &self,
7622        operation: &'static str,
7623        file_extension: Option<String>,
7624        cx: &AppContext,
7625    ) {
7626        let Some(project) = &self.project else {
7627            return
7628        };
7629
7630        // If None, we are in a file without an extension
7631        let file = self
7632            .buffer
7633            .read(cx)
7634            .as_singleton()
7635            .and_then(|b| b.read(cx).file());
7636        let file_extension = file_extension.or(file
7637            .as_ref()
7638            .and_then(|file| Path::new(file.file_name(cx)).extension())
7639            .and_then(|e| e.to_str())
7640            .map(|a| a.to_string()));
7641
7642        let vim_mode = cx
7643            .global::<SettingsStore>()
7644            .raw_user_settings()
7645            .get("vim_mode")
7646            == Some(&serde_json::Value::Bool(true));
7647        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7648        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7649        let copilot_enabled_for_language = self
7650            .buffer
7651            .read(cx)
7652            .settings_at(0, cx)
7653            .show_copilot_suggestions;
7654
7655        let telemetry = project.read(cx).client().telemetry().clone();
7656        let event = ClickhouseEvent::Editor {
7657            file_extension,
7658            vim_mode,
7659            operation,
7660            copilot_enabled,
7661            copilot_enabled_for_language,
7662        };
7663        telemetry.report_clickhouse_event(event, telemetry_settings)
7664    }
7665
7666    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7667    /// with each line being an array of {text, highlight} objects.
7668    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7669        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7670            return;
7671        };
7672
7673        #[derive(Serialize)]
7674        struct Chunk<'a> {
7675            text: String,
7676            highlight: Option<&'a str>,
7677        }
7678
7679        let snapshot = buffer.read(cx).snapshot();
7680        let range = self
7681            .selected_text_range(cx)
7682            .and_then(|selected_range| {
7683                if selected_range.is_empty() {
7684                    None
7685                } else {
7686                    Some(selected_range)
7687                }
7688            })
7689            .unwrap_or_else(|| 0..snapshot.len());
7690
7691        let chunks = snapshot.chunks(range, true);
7692        let mut lines = Vec::new();
7693        let mut line: VecDeque<Chunk> = VecDeque::new();
7694
7695        let theme = &theme::current(cx).editor.syntax;
7696
7697        for chunk in chunks {
7698            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7699            let mut chunk_lines = chunk.text.split("\n").peekable();
7700            while let Some(text) = chunk_lines.next() {
7701                let mut merged_with_last_token = false;
7702                if let Some(last_token) = line.back_mut() {
7703                    if last_token.highlight == highlight {
7704                        last_token.text.push_str(text);
7705                        merged_with_last_token = true;
7706                    }
7707                }
7708
7709                if !merged_with_last_token {
7710                    line.push_back(Chunk {
7711                        text: text.into(),
7712                        highlight,
7713                    });
7714                }
7715
7716                if chunk_lines.peek().is_some() {
7717                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7718                        line.pop_front();
7719                    }
7720                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7721                        line.pop_back();
7722                    }
7723
7724                    lines.push(mem::take(&mut line));
7725                }
7726            }
7727        }
7728
7729        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7730        cx.write_to_clipboard(ClipboardItem::new(lines));
7731    }
7732
7733    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
7734        &self.inlay_hint_cache
7735    }
7736}
7737
7738fn inlay_hint_settings(
7739    location: Anchor,
7740    snapshot: &MultiBufferSnapshot,
7741    cx: &mut ViewContext<'_, '_, Editor>,
7742) -> InlayHintSettings {
7743    let file = snapshot.file_at(location);
7744    let language = snapshot.language_at(location);
7745    let settings = all_language_settings(file, cx);
7746    settings
7747        .language(language.map(|l| l.name()).as_deref())
7748        .inlay_hints
7749}
7750
7751fn consume_contiguous_rows(
7752    contiguous_row_selections: &mut Vec<Selection<Point>>,
7753    selection: &Selection<Point>,
7754    display_map: &DisplaySnapshot,
7755    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7756) -> (u32, u32) {
7757    contiguous_row_selections.push(selection.clone());
7758    let start_row = selection.start.row;
7759    let mut end_row = ending_row(selection, display_map);
7760
7761    while let Some(next_selection) = selections.peek() {
7762        if next_selection.start.row <= end_row {
7763            end_row = ending_row(next_selection, display_map);
7764            contiguous_row_selections.push(selections.next().unwrap().clone());
7765        } else {
7766            break;
7767        }
7768    }
7769    (start_row, end_row)
7770}
7771
7772fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7773    if next_selection.end.column > 0 || next_selection.is_empty() {
7774        display_map.next_line_boundary(next_selection.end).0.row + 1
7775    } else {
7776        next_selection.end.row
7777    }
7778}
7779
7780impl EditorSnapshot {
7781    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7782        self.display_snapshot.buffer_snapshot.language_at(position)
7783    }
7784
7785    pub fn is_focused(&self) -> bool {
7786        self.is_focused
7787    }
7788
7789    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7790        self.placeholder_text.as_ref()
7791    }
7792
7793    pub fn scroll_position(&self) -> Vector2F {
7794        self.scroll_anchor.scroll_position(&self.display_snapshot)
7795    }
7796}
7797
7798impl Deref for EditorSnapshot {
7799    type Target = DisplaySnapshot;
7800
7801    fn deref(&self) -> &Self::Target {
7802        &self.display_snapshot
7803    }
7804}
7805
7806#[derive(Clone, Debug, PartialEq, Eq)]
7807pub enum Event {
7808    InputIgnored {
7809        text: Arc<str>,
7810    },
7811    ExcerptsAdded {
7812        buffer: ModelHandle<Buffer>,
7813        predecessor: ExcerptId,
7814        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7815    },
7816    ExcerptsRemoved {
7817        ids: Vec<ExcerptId>,
7818    },
7819    BufferEdited,
7820    Edited,
7821    Reparsed,
7822    Focused,
7823    Blurred,
7824    DirtyChanged,
7825    Saved,
7826    TitleChanged,
7827    DiffBaseChanged,
7828    SelectionsChanged {
7829        local: bool,
7830    },
7831    ScrollPositionChanged {
7832        local: bool,
7833        autoscroll: bool,
7834    },
7835    Closed,
7836}
7837
7838pub struct EditorFocused(pub ViewHandle<Editor>);
7839pub struct EditorBlurred(pub ViewHandle<Editor>);
7840pub struct EditorReleased(pub WeakViewHandle<Editor>);
7841
7842impl Entity for Editor {
7843    type Event = Event;
7844
7845    fn release(&mut self, cx: &mut AppContext) {
7846        cx.emit_global(EditorReleased(self.handle.clone()));
7847    }
7848}
7849
7850impl View for Editor {
7851    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7852        let style = self.style(cx);
7853        let font_changed = self.display_map.update(cx, |map, cx| {
7854            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7855            map.set_font(style.text.font_id, style.text.font_size, cx)
7856        });
7857
7858        if font_changed {
7859            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7860                hide_hover(editor, cx);
7861                hide_link_definition(editor, cx);
7862            });
7863        }
7864
7865        Stack::new()
7866            .with_child(EditorElement::new(style.clone()))
7867            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7868            .into_any()
7869    }
7870
7871    fn ui_name() -> &'static str {
7872        "Editor"
7873    }
7874
7875    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7876        if cx.is_self_focused() {
7877            let focused_event = EditorFocused(cx.handle());
7878            cx.emit(Event::Focused);
7879            cx.emit_global(focused_event);
7880        }
7881        if let Some(rename) = self.pending_rename.as_ref() {
7882            cx.focus(&rename.editor);
7883        } else {
7884            if !self.focused {
7885                self.blink_manager.update(cx, BlinkManager::enable);
7886            }
7887            self.focused = true;
7888            self.buffer.update(cx, |buffer, cx| {
7889                buffer.finalize_last_transaction(cx);
7890                if self.leader_replica_id.is_none() {
7891                    buffer.set_active_selections(
7892                        &self.selections.disjoint_anchors(),
7893                        self.selections.line_mode,
7894                        self.cursor_shape,
7895                        cx,
7896                    );
7897                }
7898            });
7899        }
7900    }
7901
7902    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7903        let blurred_event = EditorBlurred(cx.handle());
7904        cx.emit_global(blurred_event);
7905        self.focused = false;
7906        self.blink_manager.update(cx, BlinkManager::disable);
7907        self.buffer
7908            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7909        self.hide_context_menu(cx);
7910        hide_hover(self, cx);
7911        cx.emit(Event::Blurred);
7912        cx.notify();
7913    }
7914
7915    fn modifiers_changed(
7916        &mut self,
7917        event: &gpui::platform::ModifiersChangedEvent,
7918        cx: &mut ViewContext<Self>,
7919    ) -> bool {
7920        let pending_selection = self.has_pending_selection();
7921
7922        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7923            if event.cmd && !pending_selection {
7924                let snapshot = self.snapshot(cx);
7925                let kind = if event.shift {
7926                    LinkDefinitionKind::Type
7927                } else {
7928                    LinkDefinitionKind::Symbol
7929                };
7930
7931                show_link_definition(kind, self, point, snapshot, cx);
7932                return false;
7933            }
7934        }
7935
7936        {
7937            if self.link_go_to_definition_state.symbol_range.is_some()
7938                || !self.link_go_to_definition_state.definitions.is_empty()
7939            {
7940                self.link_go_to_definition_state.symbol_range.take();
7941                self.link_go_to_definition_state.definitions.clear();
7942                cx.notify();
7943            }
7944
7945            self.link_go_to_definition_state.task = None;
7946
7947            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7948        }
7949
7950        false
7951    }
7952
7953    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7954        Self::reset_to_default_keymap_context(keymap);
7955        let mode = match self.mode {
7956            EditorMode::SingleLine => "single_line",
7957            EditorMode::AutoHeight { .. } => "auto_height",
7958            EditorMode::Full => "full",
7959        };
7960        keymap.add_key("mode", mode);
7961        if self.pending_rename.is_some() {
7962            keymap.add_identifier("renaming");
7963        }
7964        match self.context_menu.as_ref() {
7965            Some(ContextMenu::Completions(_)) => {
7966                keymap.add_identifier("menu");
7967                keymap.add_identifier("showing_completions")
7968            }
7969            Some(ContextMenu::CodeActions(_)) => {
7970                keymap.add_identifier("menu");
7971                keymap.add_identifier("showing_code_actions")
7972            }
7973            None => {}
7974        }
7975        for layer in self.keymap_context_layers.values() {
7976            keymap.extend(layer);
7977        }
7978
7979        if let Some(extension) = self
7980            .buffer
7981            .read(cx)
7982            .as_singleton()
7983            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7984        {
7985            keymap.add_key("extension", extension.to_string());
7986        }
7987    }
7988
7989    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7990        Some(
7991            self.buffer
7992                .read(cx)
7993                .read(cx)
7994                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7995                .collect(),
7996        )
7997    }
7998
7999    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8000        // Prevent the IME menu from appearing when holding down an alphabetic key
8001        // while input is disabled.
8002        if !self.input_enabled {
8003            return None;
8004        }
8005
8006        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8007        Some(range.start.0..range.end.0)
8008    }
8009
8010    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8011        let snapshot = self.buffer.read(cx).read(cx);
8012        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8013        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8014    }
8015
8016    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8017        self.clear_text_highlights::<InputComposition>(cx);
8018        self.ime_transaction.take();
8019    }
8020
8021    fn replace_text_in_range(
8022        &mut self,
8023        range_utf16: Option<Range<usize>>,
8024        text: &str,
8025        cx: &mut ViewContext<Self>,
8026    ) {
8027        self.transact(cx, |this, cx| {
8028            if this.input_enabled {
8029                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8030                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8031                    Some(this.selection_replacement_ranges(range_utf16, cx))
8032                } else {
8033                    this.marked_text_ranges(cx)
8034                };
8035
8036                if let Some(new_selected_ranges) = new_selected_ranges {
8037                    this.change_selections(None, cx, |selections| {
8038                        selections.select_ranges(new_selected_ranges)
8039                    });
8040                }
8041            }
8042
8043            this.handle_input(text, cx);
8044        });
8045
8046        if !self.input_enabled {
8047            return;
8048        }
8049
8050        if let Some(transaction) = self.ime_transaction {
8051            self.buffer.update(cx, |buffer, cx| {
8052                buffer.group_until_transaction(transaction, cx);
8053            });
8054        }
8055
8056        self.unmark_text(cx);
8057    }
8058
8059    fn replace_and_mark_text_in_range(
8060        &mut self,
8061        range_utf16: Option<Range<usize>>,
8062        text: &str,
8063        new_selected_range_utf16: Option<Range<usize>>,
8064        cx: &mut ViewContext<Self>,
8065    ) {
8066        if !self.input_enabled {
8067            return;
8068        }
8069
8070        let transaction = self.transact(cx, |this, cx| {
8071            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8072                let snapshot = this.buffer.read(cx).read(cx);
8073                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8074                    for marked_range in &mut marked_ranges {
8075                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8076                        marked_range.start.0 += relative_range_utf16.start;
8077                        marked_range.start =
8078                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8079                        marked_range.end =
8080                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8081                    }
8082                }
8083                Some(marked_ranges)
8084            } else if let Some(range_utf16) = range_utf16 {
8085                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8086                Some(this.selection_replacement_ranges(range_utf16, cx))
8087            } else {
8088                None
8089            };
8090
8091            if let Some(ranges) = ranges_to_replace {
8092                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8093            }
8094
8095            let marked_ranges = {
8096                let snapshot = this.buffer.read(cx).read(cx);
8097                this.selections
8098                    .disjoint_anchors()
8099                    .iter()
8100                    .map(|selection| {
8101                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8102                    })
8103                    .collect::<Vec<_>>()
8104            };
8105
8106            if text.is_empty() {
8107                this.unmark_text(cx);
8108            } else {
8109                this.highlight_text::<InputComposition>(
8110                    marked_ranges.clone(),
8111                    this.style(cx).composition_mark,
8112                    cx,
8113                );
8114            }
8115
8116            this.handle_input(text, cx);
8117
8118            if let Some(new_selected_range) = new_selected_range_utf16 {
8119                let snapshot = this.buffer.read(cx).read(cx);
8120                let new_selected_ranges = marked_ranges
8121                    .into_iter()
8122                    .map(|marked_range| {
8123                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8124                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8125                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8126                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8127                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8128                    })
8129                    .collect::<Vec<_>>();
8130
8131                drop(snapshot);
8132                this.change_selections(None, cx, |selections| {
8133                    selections.select_ranges(new_selected_ranges)
8134                });
8135            }
8136        });
8137
8138        self.ime_transaction = self.ime_transaction.or(transaction);
8139        if let Some(transaction) = self.ime_transaction {
8140            self.buffer.update(cx, |buffer, cx| {
8141                buffer.group_until_transaction(transaction, cx);
8142            });
8143        }
8144
8145        if self.text_highlights::<InputComposition>(cx).is_none() {
8146            self.ime_transaction.take();
8147        }
8148    }
8149}
8150
8151fn build_style(
8152    settings: &ThemeSettings,
8153    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8154    override_text_style: Option<&OverrideTextStyle>,
8155    cx: &AppContext,
8156) -> EditorStyle {
8157    let font_cache = cx.font_cache();
8158    let line_height_scalar = settings.line_height();
8159    let theme_id = settings.theme.meta.id;
8160    let mut theme = settings.theme.editor.clone();
8161    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8162        let field_editor_theme = get_field_editor_theme(&settings.theme);
8163        theme.text_color = field_editor_theme.text.color;
8164        theme.selection = field_editor_theme.selection;
8165        theme.background = field_editor_theme
8166            .container
8167            .background_color
8168            .unwrap_or_default();
8169        EditorStyle {
8170            text: field_editor_theme.text,
8171            placeholder_text: field_editor_theme.placeholder_text,
8172            line_height_scalar,
8173            theme,
8174            theme_id,
8175        }
8176    } else {
8177        let font_family_id = settings.buffer_font_family;
8178        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8179        let font_properties = Default::default();
8180        let font_id = font_cache
8181            .select_font(font_family_id, &font_properties)
8182            .unwrap();
8183        let font_size = settings.buffer_font_size(cx);
8184        EditorStyle {
8185            text: TextStyle {
8186                color: settings.theme.editor.text_color,
8187                font_family_name,
8188                font_family_id,
8189                font_id,
8190                font_size,
8191                font_properties,
8192                underline: Default::default(),
8193            },
8194            placeholder_text: None,
8195            line_height_scalar,
8196            theme,
8197            theme_id,
8198        }
8199    };
8200
8201    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8202        if let Some(highlighted) = style
8203            .text
8204            .clone()
8205            .highlight(highlight_style, font_cache)
8206            .log_err()
8207        {
8208            style.text = highlighted;
8209        }
8210    }
8211
8212    style
8213}
8214
8215trait SelectionExt {
8216    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8217    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8218    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8219    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8220        -> Range<u32>;
8221}
8222
8223impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8224    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8225        let start = self.start.to_point(buffer);
8226        let end = self.end.to_point(buffer);
8227        if self.reversed {
8228            end..start
8229        } else {
8230            start..end
8231        }
8232    }
8233
8234    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8235        let start = self.start.to_offset(buffer);
8236        let end = self.end.to_offset(buffer);
8237        if self.reversed {
8238            end..start
8239        } else {
8240            start..end
8241        }
8242    }
8243
8244    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8245        let start = self
8246            .start
8247            .to_point(&map.buffer_snapshot)
8248            .to_display_point(map);
8249        let end = self
8250            .end
8251            .to_point(&map.buffer_snapshot)
8252            .to_display_point(map);
8253        if self.reversed {
8254            end..start
8255        } else {
8256            start..end
8257        }
8258    }
8259
8260    fn spanned_rows(
8261        &self,
8262        include_end_if_at_line_start: bool,
8263        map: &DisplaySnapshot,
8264    ) -> Range<u32> {
8265        let start = self.start.to_point(&map.buffer_snapshot);
8266        let mut end = self.end.to_point(&map.buffer_snapshot);
8267        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8268            end.row -= 1;
8269        }
8270
8271        let buffer_start = map.prev_line_boundary(start).0;
8272        let buffer_end = map.next_line_boundary(end).0;
8273        buffer_start.row..buffer_end.row + 1
8274    }
8275}
8276
8277impl<T: InvalidationRegion> InvalidationStack<T> {
8278    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8279    where
8280        S: Clone + ToOffset,
8281    {
8282        while let Some(region) = self.last() {
8283            let all_selections_inside_invalidation_ranges =
8284                if selections.len() == region.ranges().len() {
8285                    selections
8286                        .iter()
8287                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8288                        .all(|(selection, invalidation_range)| {
8289                            let head = selection.head().to_offset(buffer);
8290                            invalidation_range.start <= head && invalidation_range.end >= head
8291                        })
8292                } else {
8293                    false
8294                };
8295
8296            if all_selections_inside_invalidation_ranges {
8297                break;
8298            } else {
8299                self.pop();
8300            }
8301        }
8302    }
8303}
8304
8305impl<T> Default for InvalidationStack<T> {
8306    fn default() -> Self {
8307        Self(Default::default())
8308    }
8309}
8310
8311impl<T> Deref for InvalidationStack<T> {
8312    type Target = Vec<T>;
8313
8314    fn deref(&self) -> &Self::Target {
8315        &self.0
8316    }
8317}
8318
8319impl<T> DerefMut for InvalidationStack<T> {
8320    fn deref_mut(&mut self) -> &mut Self::Target {
8321        &mut self.0
8322    }
8323}
8324
8325impl InvalidationRegion for SnippetState {
8326    fn ranges(&self) -> &[Range<Anchor>] {
8327        &self.ranges[self.active_index]
8328    }
8329}
8330
8331impl Deref for EditorStyle {
8332    type Target = theme::Editor;
8333
8334    fn deref(&self) -> &Self::Target {
8335        &self.theme
8336    }
8337}
8338
8339pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8340    let mut highlighted_lines = Vec::new();
8341
8342    for (index, line) in diagnostic.message.lines().enumerate() {
8343        let line = match &diagnostic.source {
8344            Some(source) if index == 0 => {
8345                let source_highlight = Vec::from_iter(0..source.len());
8346                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8347            }
8348
8349            _ => highlight_diagnostic_message(Vec::new(), line),
8350        };
8351        highlighted_lines.push(line);
8352    }
8353    let message = diagnostic.message;
8354    Arc::new(move |cx: &mut BlockContext| {
8355        let message = message.clone();
8356        let settings = settings::get::<ThemeSettings>(cx);
8357        let tooltip_style = settings.theme.tooltip.clone();
8358        let theme = &settings.theme.editor;
8359        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8360        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8361        let anchor_x = cx.anchor_x;
8362        enum BlockContextToolip {}
8363        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
8364            Flex::column()
8365                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8366                    Label::new(
8367                        line.clone(),
8368                        style.message.clone().with_font_size(font_size),
8369                    )
8370                    .with_highlights(highlights.clone())
8371                    .contained()
8372                    .with_margin_left(anchor_x)
8373                }))
8374                .aligned()
8375                .left()
8376                .into_any()
8377        })
8378        .with_cursor_style(CursorStyle::PointingHand)
8379        .on_click(MouseButton::Left, move |_, _, cx| {
8380            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8381        })
8382        // We really need to rethink this ID system...
8383        .with_tooltip::<BlockContextToolip>(
8384            cx.block_id,
8385            "Copy diagnostic message".to_string(),
8386            None,
8387            tooltip_style,
8388            cx,
8389        )
8390        .into_any()
8391    })
8392}
8393
8394pub fn highlight_diagnostic_message(
8395    initial_highlights: Vec<usize>,
8396    message: &str,
8397) -> (String, Vec<usize>) {
8398    let mut message_without_backticks = String::new();
8399    let mut prev_offset = 0;
8400    let mut inside_block = false;
8401    let mut highlights = initial_highlights;
8402    for (match_ix, (offset, _)) in message
8403        .match_indices('`')
8404        .chain([(message.len(), "")])
8405        .enumerate()
8406    {
8407        message_without_backticks.push_str(&message[prev_offset..offset]);
8408        if inside_block {
8409            highlights.extend(prev_offset - match_ix..offset - match_ix);
8410        }
8411
8412        inside_block = !inside_block;
8413        prev_offset = offset + 1;
8414    }
8415
8416    (message_without_backticks, highlights)
8417}
8418
8419pub fn diagnostic_style(
8420    severity: DiagnosticSeverity,
8421    valid: bool,
8422    theme: &theme::Editor,
8423) -> DiagnosticStyle {
8424    match (severity, valid) {
8425        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8426        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8427        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8428        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8429        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8430        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8431        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8432        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8433        _ => theme.invalid_hint_diagnostic.clone(),
8434    }
8435}
8436
8437pub fn combine_syntax_and_fuzzy_match_highlights(
8438    text: &str,
8439    default_style: HighlightStyle,
8440    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8441    match_indices: &[usize],
8442) -> Vec<(Range<usize>, HighlightStyle)> {
8443    let mut result = Vec::new();
8444    let mut match_indices = match_indices.iter().copied().peekable();
8445
8446    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8447    {
8448        syntax_highlight.weight = None;
8449
8450        // Add highlights for any fuzzy match characters before the next
8451        // syntax highlight range.
8452        while let Some(&match_index) = match_indices.peek() {
8453            if match_index >= range.start {
8454                break;
8455            }
8456            match_indices.next();
8457            let end_index = char_ix_after(match_index, text);
8458            let mut match_style = default_style;
8459            match_style.weight = Some(fonts::Weight::BOLD);
8460            result.push((match_index..end_index, match_style));
8461        }
8462
8463        if range.start == usize::MAX {
8464            break;
8465        }
8466
8467        // Add highlights for any fuzzy match characters within the
8468        // syntax highlight range.
8469        let mut offset = range.start;
8470        while let Some(&match_index) = match_indices.peek() {
8471            if match_index >= range.end {
8472                break;
8473            }
8474
8475            match_indices.next();
8476            if match_index > offset {
8477                result.push((offset..match_index, syntax_highlight));
8478            }
8479
8480            let mut end_index = char_ix_after(match_index, text);
8481            while let Some(&next_match_index) = match_indices.peek() {
8482                if next_match_index == end_index && next_match_index < range.end {
8483                    end_index = char_ix_after(next_match_index, text);
8484                    match_indices.next();
8485                } else {
8486                    break;
8487                }
8488            }
8489
8490            let mut match_style = syntax_highlight;
8491            match_style.weight = Some(fonts::Weight::BOLD);
8492            result.push((match_index..end_index, match_style));
8493            offset = end_index;
8494        }
8495
8496        if offset < range.end {
8497            result.push((offset..range.end, syntax_highlight));
8498        }
8499    }
8500
8501    fn char_ix_after(ix: usize, text: &str) -> usize {
8502        ix + text[ix..].chars().next().unwrap().len_utf8()
8503    }
8504
8505    result
8506}
8507
8508pub fn styled_runs_for_code_label<'a>(
8509    label: &'a CodeLabel,
8510    syntax_theme: &'a theme::SyntaxTheme,
8511) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8512    let fade_out = HighlightStyle {
8513        fade_out: Some(0.35),
8514        ..Default::default()
8515    };
8516
8517    let mut prev_end = label.filter_range.end;
8518    label
8519        .runs
8520        .iter()
8521        .enumerate()
8522        .flat_map(move |(ix, (range, highlight_id))| {
8523            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8524                style
8525            } else {
8526                return Default::default();
8527            };
8528            let mut muted_style = style;
8529            muted_style.highlight(fade_out);
8530
8531            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8532            if range.start >= label.filter_range.end {
8533                if range.start > prev_end {
8534                    runs.push((prev_end..range.start, fade_out));
8535                }
8536                runs.push((range.clone(), muted_style));
8537            } else if range.end <= label.filter_range.end {
8538                runs.push((range.clone(), style));
8539            } else {
8540                runs.push((range.start..label.filter_range.end, style));
8541                runs.push((label.filter_range.end..range.end, muted_style));
8542            }
8543            prev_end = cmp::max(prev_end, range.end);
8544
8545            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8546                runs.push((prev_end..label.text.len(), fade_out));
8547            }
8548
8549            runs
8550        })
8551}
8552
8553pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8554    let mut index = 0;
8555    let mut codepoints = text.char_indices().peekable();
8556
8557    std::iter::from_fn(move || {
8558        let start_index = index;
8559        while let Some((new_index, codepoint)) = codepoints.next() {
8560            index = new_index + codepoint.len_utf8();
8561            let current_upper = codepoint.is_uppercase();
8562            let next_upper = codepoints
8563                .peek()
8564                .map(|(_, c)| c.is_uppercase())
8565                .unwrap_or(false);
8566
8567            if !current_upper && next_upper {
8568                return Some(&text[start_index..index]);
8569            }
8570        }
8571
8572        index = text.len();
8573        if start_index < text.len() {
8574            return Some(&text[start_index..]);
8575        }
8576        None
8577    })
8578    .flat_map(|word| word.split_inclusive('_'))
8579}
8580
8581trait RangeToAnchorExt {
8582    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8583}
8584
8585impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8586    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8587        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8588    }
8589}