editor.rs

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