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