editor.rs

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