editor.rs

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