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