editor.rs

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