editor.rs

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