editor.rs

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