editor.rs

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