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