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()),
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()),
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                (movement::start_of_paragraph(map, head), SelectionGoal::None)
5163            });
5164        })
5165    }
5166
5167    pub fn select_to_end_of_paragraph(
5168        &mut self,
5169        _: &SelectToEndOfParagraph,
5170        cx: &mut ViewContext<Self>,
5171    ) {
5172        if matches!(self.mode, EditorMode::SingleLine) {
5173            cx.propagate_action();
5174            return;
5175        }
5176
5177        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5178            s.move_heads_with(|map, head, _| {
5179                (movement::end_of_paragraph(map, head), SelectionGoal::None)
5180            });
5181        })
5182    }
5183
5184    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5185        if matches!(self.mode, EditorMode::SingleLine) {
5186            cx.propagate_action();
5187            return;
5188        }
5189
5190        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5191            s.select_ranges(vec![0..0]);
5192        });
5193    }
5194
5195    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5196        let mut selection = self.selections.last::<Point>(cx);
5197        selection.set_head(Point::zero(), SelectionGoal::None);
5198
5199        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5200            s.select(vec![selection]);
5201        });
5202    }
5203
5204    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5205        if matches!(self.mode, EditorMode::SingleLine) {
5206            cx.propagate_action();
5207            return;
5208        }
5209
5210        let cursor = self.buffer.read(cx).read(cx).len();
5211        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5212            s.select_ranges(vec![cursor..cursor])
5213        });
5214    }
5215
5216    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5217        self.nav_history = nav_history;
5218    }
5219
5220    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5221        self.nav_history.as_ref()
5222    }
5223
5224    fn push_to_nav_history(
5225        &mut self,
5226        cursor_anchor: Anchor,
5227        new_position: Option<Point>,
5228        cx: &mut ViewContext<Self>,
5229    ) {
5230        if let Some(nav_history) = self.nav_history.as_mut() {
5231            let buffer = self.buffer.read(cx).read(cx);
5232            let cursor_position = cursor_anchor.to_point(&buffer);
5233            let scroll_state = self.scroll_manager.anchor();
5234            let scroll_top_row = scroll_state.top_row(&buffer);
5235            drop(buffer);
5236
5237            if let Some(new_position) = new_position {
5238                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5239                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5240                    return;
5241                }
5242            }
5243
5244            nav_history.push(
5245                Some(NavigationData {
5246                    cursor_anchor,
5247                    cursor_position,
5248                    scroll_anchor: scroll_state,
5249                    scroll_top_row,
5250                }),
5251                cx,
5252            );
5253        }
5254    }
5255
5256    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5257        let buffer = self.buffer.read(cx).snapshot(cx);
5258        let mut selection = self.selections.first::<usize>(cx);
5259        selection.set_head(buffer.len(), SelectionGoal::None);
5260        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5261            s.select(vec![selection]);
5262        });
5263    }
5264
5265    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5266        let end = self.buffer.read(cx).read(cx).len();
5267        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5268            s.select_ranges(vec![0..end]);
5269        });
5270    }
5271
5272    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5273        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5274        let mut selections = self.selections.all::<Point>(cx);
5275        let max_point = display_map.buffer_snapshot.max_point();
5276        for selection in &mut selections {
5277            let rows = selection.spanned_rows(true, &display_map);
5278            selection.start = Point::new(rows.start, 0);
5279            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5280            selection.reversed = false;
5281        }
5282        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5283            s.select(selections);
5284        });
5285    }
5286
5287    pub fn split_selection_into_lines(
5288        &mut self,
5289        _: &SplitSelectionIntoLines,
5290        cx: &mut ViewContext<Self>,
5291    ) {
5292        let mut to_unfold = Vec::new();
5293        let mut new_selection_ranges = Vec::new();
5294        {
5295            let selections = self.selections.all::<Point>(cx);
5296            let buffer = self.buffer.read(cx).read(cx);
5297            for selection in selections {
5298                for row in selection.start.row..selection.end.row {
5299                    let cursor = Point::new(row, buffer.line_len(row));
5300                    new_selection_ranges.push(cursor..cursor);
5301                }
5302                new_selection_ranges.push(selection.end..selection.end);
5303                to_unfold.push(selection.start..selection.end);
5304            }
5305        }
5306        self.unfold_ranges(to_unfold, true, true, cx);
5307        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5308            s.select_ranges(new_selection_ranges);
5309        });
5310    }
5311
5312    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5313        self.add_selection(true, cx);
5314    }
5315
5316    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5317        self.add_selection(false, cx);
5318    }
5319
5320    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5321        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5322        let mut selections = self.selections.all::<Point>(cx);
5323        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5324            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5325            let range = oldest_selection.display_range(&display_map).sorted();
5326            let columns = cmp::min(range.start.column(), range.end.column())
5327                ..cmp::max(range.start.column(), range.end.column());
5328
5329            selections.clear();
5330            let mut stack = Vec::new();
5331            for row in range.start.row()..=range.end.row() {
5332                if let Some(selection) = self.selections.build_columnar_selection(
5333                    &display_map,
5334                    row,
5335                    &columns,
5336                    oldest_selection.reversed,
5337                ) {
5338                    stack.push(selection.id);
5339                    selections.push(selection);
5340                }
5341            }
5342
5343            if above {
5344                stack.reverse();
5345            }
5346
5347            AddSelectionsState { above, stack }
5348        });
5349
5350        let last_added_selection = *state.stack.last().unwrap();
5351        let mut new_selections = Vec::new();
5352        if above == state.above {
5353            let end_row = if above {
5354                0
5355            } else {
5356                display_map.max_point().row()
5357            };
5358
5359            'outer: for selection in selections {
5360                if selection.id == last_added_selection {
5361                    let range = selection.display_range(&display_map).sorted();
5362                    debug_assert_eq!(range.start.row(), range.end.row());
5363                    let mut row = range.start.row();
5364                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5365                    {
5366                        start..end
5367                    } else {
5368                        cmp::min(range.start.column(), range.end.column())
5369                            ..cmp::max(range.start.column(), range.end.column())
5370                    };
5371
5372                    while row != end_row {
5373                        if above {
5374                            row -= 1;
5375                        } else {
5376                            row += 1;
5377                        }
5378
5379                        if let Some(new_selection) = self.selections.build_columnar_selection(
5380                            &display_map,
5381                            row,
5382                            &columns,
5383                            selection.reversed,
5384                        ) {
5385                            state.stack.push(new_selection.id);
5386                            if above {
5387                                new_selections.push(new_selection);
5388                                new_selections.push(selection);
5389                            } else {
5390                                new_selections.push(selection);
5391                                new_selections.push(new_selection);
5392                            }
5393
5394                            continue 'outer;
5395                        }
5396                    }
5397                }
5398
5399                new_selections.push(selection);
5400            }
5401        } else {
5402            new_selections = selections;
5403            new_selections.retain(|s| s.id != last_added_selection);
5404            state.stack.pop();
5405        }
5406
5407        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5408            s.select(new_selections);
5409        });
5410        if state.stack.len() > 1 {
5411            self.add_selections_state = Some(state);
5412        }
5413    }
5414
5415    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5416        self.push_to_selection_history();
5417        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5418        let buffer = &display_map.buffer_snapshot;
5419        let mut selections = self.selections.all::<usize>(cx);
5420        if let Some(mut select_next_state) = self.select_next_state.take() {
5421            let query = &select_next_state.query;
5422            if !select_next_state.done {
5423                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5424                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5425                let mut next_selected_range = None;
5426
5427                let bytes_after_last_selection =
5428                    buffer.bytes_in_range(last_selection.end..buffer.len());
5429                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5430                let query_matches = query
5431                    .stream_find_iter(bytes_after_last_selection)
5432                    .map(|result| (last_selection.end, result))
5433                    .chain(
5434                        query
5435                            .stream_find_iter(bytes_before_first_selection)
5436                            .map(|result| (0, result)),
5437                    );
5438                for (start_offset, query_match) in query_matches {
5439                    let query_match = query_match.unwrap(); // can only fail due to I/O
5440                    let offset_range =
5441                        start_offset + query_match.start()..start_offset + query_match.end();
5442                    let display_range = offset_range.start.to_display_point(&display_map)
5443                        ..offset_range.end.to_display_point(&display_map);
5444
5445                    if !select_next_state.wordwise
5446                        || (!movement::is_inside_word(&display_map, display_range.start)
5447                            && !movement::is_inside_word(&display_map, display_range.end))
5448                    {
5449                        next_selected_range = Some(offset_range);
5450                        break;
5451                    }
5452                }
5453
5454                if let Some(next_selected_range) = next_selected_range {
5455                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5456                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5457                        if action.replace_newest {
5458                            s.delete(s.newest_anchor().id);
5459                        }
5460                        s.insert_range(next_selected_range);
5461                    });
5462                } else {
5463                    select_next_state.done = true;
5464                }
5465            }
5466
5467            self.select_next_state = Some(select_next_state);
5468        } else if selections.len() == 1 {
5469            let selection = selections.last_mut().unwrap();
5470            if selection.start == selection.end {
5471                let word_range = movement::surrounding_word(
5472                    &display_map,
5473                    selection.start.to_display_point(&display_map),
5474                );
5475                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5476                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5477                selection.goal = SelectionGoal::None;
5478                selection.reversed = false;
5479
5480                let query = buffer
5481                    .text_for_range(selection.start..selection.end)
5482                    .collect::<String>();
5483                let select_state = SelectNextState {
5484                    query: AhoCorasick::new_auto_configured(&[query]),
5485                    wordwise: true,
5486                    done: false,
5487                };
5488                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5489                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5490                    s.select(selections);
5491                });
5492                self.select_next_state = Some(select_state);
5493            } else {
5494                let query = buffer
5495                    .text_for_range(selection.start..selection.end)
5496                    .collect::<String>();
5497                self.select_next_state = Some(SelectNextState {
5498                    query: AhoCorasick::new_auto_configured(&[query]),
5499                    wordwise: false,
5500                    done: false,
5501                });
5502                self.select_next(action, cx);
5503            }
5504        }
5505    }
5506
5507    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5508        self.push_to_selection_history();
5509        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5510        let buffer = &display_map.buffer_snapshot;
5511        let mut selections = self.selections.all::<usize>(cx);
5512        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5513            let query = &select_prev_state.query;
5514            if !select_prev_state.done {
5515                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5516                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5517                let mut next_selected_range = None;
5518                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5519                let bytes_before_last_selection =
5520                    buffer.reversed_bytes_in_range(0..last_selection.start);
5521                let bytes_after_first_selection =
5522                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5523                let query_matches = query
5524                    .stream_find_iter(bytes_before_last_selection)
5525                    .map(|result| (last_selection.start, result))
5526                    .chain(
5527                        query
5528                            .stream_find_iter(bytes_after_first_selection)
5529                            .map(|result| (buffer.len(), result)),
5530                    );
5531                for (end_offset, query_match) in query_matches {
5532                    let query_match = query_match.unwrap(); // can only fail due to I/O
5533                    let offset_range =
5534                        end_offset - query_match.end()..end_offset - query_match.start();
5535                    let display_range = offset_range.start.to_display_point(&display_map)
5536                        ..offset_range.end.to_display_point(&display_map);
5537
5538                    if !select_prev_state.wordwise
5539                        || (!movement::is_inside_word(&display_map, display_range.start)
5540                            && !movement::is_inside_word(&display_map, display_range.end))
5541                    {
5542                        next_selected_range = Some(offset_range);
5543                        break;
5544                    }
5545                }
5546
5547                if let Some(next_selected_range) = next_selected_range {
5548                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5549                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5550                        if action.replace_newest {
5551                            s.delete(s.newest_anchor().id);
5552                        }
5553                        s.insert_range(next_selected_range);
5554                    });
5555                } else {
5556                    select_prev_state.done = true;
5557                }
5558            }
5559
5560            self.select_prev_state = Some(select_prev_state);
5561        } else if selections.len() == 1 {
5562            let selection = selections.last_mut().unwrap();
5563            if selection.start == selection.end {
5564                let word_range = movement::surrounding_word(
5565                    &display_map,
5566                    selection.start.to_display_point(&display_map),
5567                );
5568                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5569                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5570                selection.goal = SelectionGoal::None;
5571                selection.reversed = false;
5572
5573                let query = buffer
5574                    .text_for_range(selection.start..selection.end)
5575                    .collect::<String>();
5576                let query = query.chars().rev().collect::<String>();
5577                let select_state = SelectNextState {
5578                    query: AhoCorasick::new_auto_configured(&[query]),
5579                    wordwise: true,
5580                    done: false,
5581                };
5582                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5583                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5584                    s.select(selections);
5585                });
5586                self.select_prev_state = Some(select_state);
5587            } else {
5588                let query = buffer
5589                    .text_for_range(selection.start..selection.end)
5590                    .collect::<String>();
5591                let query = query.chars().rev().collect::<String>();
5592                self.select_prev_state = Some(SelectNextState {
5593                    query: AhoCorasick::new_auto_configured(&[query]),
5594                    wordwise: false,
5595                    done: false,
5596                });
5597                self.select_previous(action, cx);
5598            }
5599        }
5600    }
5601
5602    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5603        self.transact(cx, |this, cx| {
5604            let mut selections = this.selections.all::<Point>(cx);
5605            let mut edits = Vec::new();
5606            let mut selection_edit_ranges = Vec::new();
5607            let mut last_toggled_row = None;
5608            let snapshot = this.buffer.read(cx).read(cx);
5609            let empty_str: Arc<str> = "".into();
5610            let mut suffixes_inserted = Vec::new();
5611
5612            fn comment_prefix_range(
5613                snapshot: &MultiBufferSnapshot,
5614                row: u32,
5615                comment_prefix: &str,
5616                comment_prefix_whitespace: &str,
5617            ) -> Range<Point> {
5618                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5619
5620                let mut line_bytes = snapshot
5621                    .bytes_in_range(start..snapshot.max_point())
5622                    .flatten()
5623                    .copied();
5624
5625                // If this line currently begins with the line comment prefix, then record
5626                // the range containing the prefix.
5627                if line_bytes
5628                    .by_ref()
5629                    .take(comment_prefix.len())
5630                    .eq(comment_prefix.bytes())
5631                {
5632                    // Include any whitespace that matches the comment prefix.
5633                    let matching_whitespace_len = line_bytes
5634                        .zip(comment_prefix_whitespace.bytes())
5635                        .take_while(|(a, b)| a == b)
5636                        .count() as u32;
5637                    let end = Point::new(
5638                        start.row,
5639                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5640                    );
5641                    start..end
5642                } else {
5643                    start..start
5644                }
5645            }
5646
5647            fn comment_suffix_range(
5648                snapshot: &MultiBufferSnapshot,
5649                row: u32,
5650                comment_suffix: &str,
5651                comment_suffix_has_leading_space: bool,
5652            ) -> Range<Point> {
5653                let end = Point::new(row, snapshot.line_len(row));
5654                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5655
5656                let mut line_end_bytes = snapshot
5657                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5658                    .flatten()
5659                    .copied();
5660
5661                let leading_space_len = if suffix_start_column > 0
5662                    && line_end_bytes.next() == Some(b' ')
5663                    && comment_suffix_has_leading_space
5664                {
5665                    1
5666                } else {
5667                    0
5668                };
5669
5670                // If this line currently begins with the line comment prefix, then record
5671                // the range containing the prefix.
5672                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5673                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5674                    start..end
5675                } else {
5676                    end..end
5677                }
5678            }
5679
5680            // TODO: Handle selections that cross excerpts
5681            for selection in &mut selections {
5682                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5683                let language = if let Some(language) =
5684                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5685                {
5686                    language
5687                } else {
5688                    continue;
5689                };
5690
5691                selection_edit_ranges.clear();
5692
5693                // If multiple selections contain a given row, avoid processing that
5694                // row more than once.
5695                let mut start_row = selection.start.row;
5696                if last_toggled_row == Some(start_row) {
5697                    start_row += 1;
5698                }
5699                let end_row =
5700                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5701                        selection.end.row - 1
5702                    } else {
5703                        selection.end.row
5704                    };
5705                last_toggled_row = Some(end_row);
5706
5707                if start_row > end_row {
5708                    continue;
5709                }
5710
5711                // If the language has line comments, toggle those.
5712                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5713                    // Split the comment prefix's trailing whitespace into a separate string,
5714                    // as that portion won't be used for detecting if a line is a comment.
5715                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5716                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5717                    let mut all_selection_lines_are_comments = true;
5718
5719                    for row in start_row..=end_row {
5720                        if snapshot.is_line_blank(row) && start_row < end_row {
5721                            continue;
5722                        }
5723
5724                        let prefix_range = comment_prefix_range(
5725                            snapshot.deref(),
5726                            row,
5727                            comment_prefix,
5728                            comment_prefix_whitespace,
5729                        );
5730                        if prefix_range.is_empty() {
5731                            all_selection_lines_are_comments = false;
5732                        }
5733                        selection_edit_ranges.push(prefix_range);
5734                    }
5735
5736                    if all_selection_lines_are_comments {
5737                        edits.extend(
5738                            selection_edit_ranges
5739                                .iter()
5740                                .cloned()
5741                                .map(|range| (range, empty_str.clone())),
5742                        );
5743                    } else {
5744                        let min_column = selection_edit_ranges
5745                            .iter()
5746                            .map(|r| r.start.column)
5747                            .min()
5748                            .unwrap_or(0);
5749                        edits.extend(selection_edit_ranges.iter().map(|range| {
5750                            let position = Point::new(range.start.row, min_column);
5751                            (position..position, full_comment_prefix.clone())
5752                        }));
5753                    }
5754                } else if let Some((full_comment_prefix, comment_suffix)) =
5755                    language.block_comment_delimiters()
5756                {
5757                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5758                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5759                    let prefix_range = comment_prefix_range(
5760                        snapshot.deref(),
5761                        start_row,
5762                        comment_prefix,
5763                        comment_prefix_whitespace,
5764                    );
5765                    let suffix_range = comment_suffix_range(
5766                        snapshot.deref(),
5767                        end_row,
5768                        comment_suffix.trim_start_matches(' '),
5769                        comment_suffix.starts_with(' '),
5770                    );
5771
5772                    if prefix_range.is_empty() || suffix_range.is_empty() {
5773                        edits.push((
5774                            prefix_range.start..prefix_range.start,
5775                            full_comment_prefix.clone(),
5776                        ));
5777                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5778                        suffixes_inserted.push((end_row, comment_suffix.len()));
5779                    } else {
5780                        edits.push((prefix_range, empty_str.clone()));
5781                        edits.push((suffix_range, empty_str.clone()));
5782                    }
5783                } else {
5784                    continue;
5785                }
5786            }
5787
5788            drop(snapshot);
5789            this.buffer.update(cx, |buffer, cx| {
5790                buffer.edit(edits, None, cx);
5791            });
5792
5793            // Adjust selections so that they end before any comment suffixes that
5794            // were inserted.
5795            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5796            let mut selections = this.selections.all::<Point>(cx);
5797            let snapshot = this.buffer.read(cx).read(cx);
5798            for selection in &mut selections {
5799                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5800                    match row.cmp(&selection.end.row) {
5801                        Ordering::Less => {
5802                            suffixes_inserted.next();
5803                            continue;
5804                        }
5805                        Ordering::Greater => break,
5806                        Ordering::Equal => {
5807                            if selection.end.column == snapshot.line_len(row) {
5808                                if selection.is_empty() {
5809                                    selection.start.column -= suffix_len as u32;
5810                                }
5811                                selection.end.column -= suffix_len as u32;
5812                            }
5813                            break;
5814                        }
5815                    }
5816                }
5817            }
5818
5819            drop(snapshot);
5820            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5821
5822            let selections = this.selections.all::<Point>(cx);
5823            let selections_on_single_row = selections.windows(2).all(|selections| {
5824                selections[0].start.row == selections[1].start.row
5825                    && selections[0].end.row == selections[1].end.row
5826                    && selections[0].start.row == selections[0].end.row
5827            });
5828            let selections_selecting = selections
5829                .iter()
5830                .any(|selection| selection.start != selection.end);
5831            let advance_downwards = action.advance_downwards
5832                && selections_on_single_row
5833                && !selections_selecting
5834                && this.mode != EditorMode::SingleLine;
5835
5836            if advance_downwards {
5837                let snapshot = this.buffer.read(cx).snapshot(cx);
5838
5839                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5840                    s.move_cursors_with(|display_snapshot, display_point, _| {
5841                        let mut point = display_point.to_point(display_snapshot);
5842                        point.row += 1;
5843                        point = snapshot.clip_point(point, Bias::Left);
5844                        let display_point = point.to_display_point(display_snapshot);
5845                        (display_point, SelectionGoal::Column(display_point.column()))
5846                    })
5847                });
5848            }
5849        });
5850    }
5851
5852    pub fn select_larger_syntax_node(
5853        &mut self,
5854        _: &SelectLargerSyntaxNode,
5855        cx: &mut ViewContext<Self>,
5856    ) {
5857        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5858        let buffer = self.buffer.read(cx).snapshot(cx);
5859        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5860
5861        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5862        let mut selected_larger_node = false;
5863        let new_selections = old_selections
5864            .iter()
5865            .map(|selection| {
5866                let old_range = selection.start..selection.end;
5867                let mut new_range = old_range.clone();
5868                while let Some(containing_range) =
5869                    buffer.range_for_syntax_ancestor(new_range.clone())
5870                {
5871                    new_range = containing_range;
5872                    if !display_map.intersects_fold(new_range.start)
5873                        && !display_map.intersects_fold(new_range.end)
5874                    {
5875                        break;
5876                    }
5877                }
5878
5879                selected_larger_node |= new_range != old_range;
5880                Selection {
5881                    id: selection.id,
5882                    start: new_range.start,
5883                    end: new_range.end,
5884                    goal: SelectionGoal::None,
5885                    reversed: selection.reversed,
5886                }
5887            })
5888            .collect::<Vec<_>>();
5889
5890        if selected_larger_node {
5891            stack.push(old_selections);
5892            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5893                s.select(new_selections);
5894            });
5895        }
5896        self.select_larger_syntax_node_stack = stack;
5897    }
5898
5899    pub fn select_smaller_syntax_node(
5900        &mut self,
5901        _: &SelectSmallerSyntaxNode,
5902        cx: &mut ViewContext<Self>,
5903    ) {
5904        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5905        if let Some(selections) = stack.pop() {
5906            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5907                s.select(selections.to_vec());
5908            });
5909        }
5910        self.select_larger_syntax_node_stack = stack;
5911    }
5912
5913    pub fn move_to_enclosing_bracket(
5914        &mut self,
5915        _: &MoveToEnclosingBracket,
5916        cx: &mut ViewContext<Self>,
5917    ) {
5918        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5919            s.move_offsets_with(|snapshot, selection| {
5920                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5921                    return;
5922                };
5923
5924                let mut best_length = usize::MAX;
5925                let mut best_inside = false;
5926                let mut best_in_bracket_range = false;
5927                let mut best_destination = None;
5928                for (open, close) in enclosing_bracket_ranges {
5929                    let close = close.to_inclusive();
5930                    let length = close.end() - open.start;
5931                    let inside = selection.start >= open.end && selection.end <= *close.start();
5932                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5933
5934                    // If best is next to a bracket and current isn't, skip
5935                    if !in_bracket_range && best_in_bracket_range {
5936                        continue;
5937                    }
5938
5939                    // Prefer smaller lengths unless best is inside and current isn't
5940                    if length > best_length && (best_inside || !inside) {
5941                        continue;
5942                    }
5943
5944                    best_length = length;
5945                    best_inside = inside;
5946                    best_in_bracket_range = in_bracket_range;
5947                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5948                        if inside {
5949                            open.end
5950                        } else {
5951                            open.start
5952                        }
5953                    } else {
5954                        if inside {
5955                            *close.start()
5956                        } else {
5957                            *close.end()
5958                        }
5959                    });
5960                }
5961
5962                if let Some(destination) = best_destination {
5963                    selection.collapse_to(destination, SelectionGoal::None);
5964                }
5965            })
5966        });
5967    }
5968
5969    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5970        self.end_selection(cx);
5971        self.selection_history.mode = SelectionHistoryMode::Undoing;
5972        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5973            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5974            self.select_next_state = entry.select_next_state;
5975            self.select_prev_state = entry.select_prev_state;
5976            self.add_selections_state = entry.add_selections_state;
5977            self.request_autoscroll(Autoscroll::newest(), cx);
5978        }
5979        self.selection_history.mode = SelectionHistoryMode::Normal;
5980    }
5981
5982    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5983        self.end_selection(cx);
5984        self.selection_history.mode = SelectionHistoryMode::Redoing;
5985        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5986            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5987            self.select_next_state = entry.select_next_state;
5988            self.select_prev_state = entry.select_prev_state;
5989            self.add_selections_state = entry.add_selections_state;
5990            self.request_autoscroll(Autoscroll::newest(), cx);
5991        }
5992        self.selection_history.mode = SelectionHistoryMode::Normal;
5993    }
5994
5995    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5996        self.go_to_diagnostic_impl(Direction::Next, cx)
5997    }
5998
5999    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6000        self.go_to_diagnostic_impl(Direction::Prev, cx)
6001    }
6002
6003    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6004        let buffer = self.buffer.read(cx).snapshot(cx);
6005        let selection = self.selections.newest::<usize>(cx);
6006
6007        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6008        if direction == Direction::Next {
6009            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6010                let (group_id, jump_to) = popover.activation_info();
6011                if self.activate_diagnostics(group_id, cx) {
6012                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6013                        let mut new_selection = s.newest_anchor().clone();
6014                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6015                        s.select_anchors(vec![new_selection.clone()]);
6016                    });
6017                }
6018                return;
6019            }
6020        }
6021
6022        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6023            active_diagnostics
6024                .primary_range
6025                .to_offset(&buffer)
6026                .to_inclusive()
6027        });
6028        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6029            if active_primary_range.contains(&selection.head()) {
6030                *active_primary_range.end()
6031            } else {
6032                selection.head()
6033            }
6034        } else {
6035            selection.head()
6036        };
6037
6038        loop {
6039            let mut diagnostics = if direction == Direction::Prev {
6040                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6041            } else {
6042                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6043            };
6044            let group = diagnostics.find_map(|entry| {
6045                if entry.diagnostic.is_primary
6046                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6047                    && !entry.range.is_empty()
6048                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6049                {
6050                    Some((entry.range, entry.diagnostic.group_id))
6051                } else {
6052                    None
6053                }
6054            });
6055
6056            if let Some((primary_range, group_id)) = group {
6057                if self.activate_diagnostics(group_id, cx) {
6058                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6059                        s.select(vec![Selection {
6060                            id: selection.id,
6061                            start: primary_range.start,
6062                            end: primary_range.start,
6063                            reversed: false,
6064                            goal: SelectionGoal::None,
6065                        }]);
6066                    });
6067                }
6068                break;
6069            } else {
6070                // Cycle around to the start of the buffer, potentially moving back to the start of
6071                // the currently active diagnostic.
6072                active_primary_range.take();
6073                if direction == Direction::Prev {
6074                    if search_start == buffer.len() {
6075                        break;
6076                    } else {
6077                        search_start = buffer.len();
6078                    }
6079                } else if search_start == 0 {
6080                    break;
6081                } else {
6082                    search_start = 0;
6083                }
6084            }
6085        }
6086    }
6087
6088    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6089        let snapshot = self
6090            .display_map
6091            .update(cx, |display_map, cx| display_map.snapshot(cx));
6092        let selection = self.selections.newest::<Point>(cx);
6093
6094        if !self.seek_in_direction(
6095            &snapshot,
6096            selection.head(),
6097            false,
6098            snapshot
6099                .buffer_snapshot
6100                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6101            cx,
6102        ) {
6103            let wrapped_point = Point::zero();
6104            self.seek_in_direction(
6105                &snapshot,
6106                wrapped_point,
6107                true,
6108                snapshot
6109                    .buffer_snapshot
6110                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6111                cx,
6112            );
6113        }
6114    }
6115
6116    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6117        let snapshot = self
6118            .display_map
6119            .update(cx, |display_map, cx| display_map.snapshot(cx));
6120        let selection = self.selections.newest::<Point>(cx);
6121
6122        if !self.seek_in_direction(
6123            &snapshot,
6124            selection.head(),
6125            false,
6126            snapshot
6127                .buffer_snapshot
6128                .git_diff_hunks_in_range_rev(0..selection.head().row),
6129            cx,
6130        ) {
6131            let wrapped_point = snapshot.buffer_snapshot.max_point();
6132            self.seek_in_direction(
6133                &snapshot,
6134                wrapped_point,
6135                true,
6136                snapshot
6137                    .buffer_snapshot
6138                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6139                cx,
6140            );
6141        }
6142    }
6143
6144    fn seek_in_direction(
6145        &mut self,
6146        snapshot: &DisplaySnapshot,
6147        initial_point: Point,
6148        is_wrapped: bool,
6149        hunks: impl Iterator<Item = DiffHunk<u32>>,
6150        cx: &mut ViewContext<Editor>,
6151    ) -> bool {
6152        let display_point = initial_point.to_display_point(snapshot);
6153        let mut hunks = hunks
6154            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6155            .skip_while(|hunk| {
6156                if is_wrapped {
6157                    false
6158                } else {
6159                    hunk.contains_display_row(display_point.row())
6160                }
6161            })
6162            .dedup();
6163
6164        if let Some(hunk) = hunks.next() {
6165            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6166                let row = hunk.start_display_row();
6167                let point = DisplayPoint::new(row, 0);
6168                s.select_display_ranges([point..point]);
6169            });
6170
6171            true
6172        } else {
6173            false
6174        }
6175    }
6176
6177    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6178        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
6179    }
6180
6181    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6182        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
6183    }
6184
6185    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
6186        let Some(workspace) = self.workspace(cx) else { return };
6187        let buffer = self.buffer.read(cx);
6188        let head = self.selections.newest::<usize>(cx).head();
6189        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6190            text_anchor
6191        } else {
6192            return;
6193        };
6194
6195        let project = workspace.read(cx).project().clone();
6196        let definitions = project.update(cx, |project, cx| match kind {
6197            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6198            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6199        });
6200
6201        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6202            let definitions = definitions.await?;
6203            editor.update(&mut cx, |editor, cx| {
6204                editor.navigate_to_definitions(definitions, cx);
6205            })?;
6206            Ok::<(), anyhow::Error>(())
6207        })
6208        .detach_and_log_err(cx);
6209    }
6210
6211    pub fn navigate_to_definitions(
6212        &mut self,
6213        mut definitions: Vec<LocationLink>,
6214        cx: &mut ViewContext<Editor>,
6215    ) {
6216        let Some(workspace) = self.workspace(cx) else { return };
6217        let pane = workspace.read(cx).active_pane().clone();
6218        // If there is one definition, just open it directly
6219        if definitions.len() == 1 {
6220            let definition = definitions.pop().unwrap();
6221            let range = definition
6222                .target
6223                .range
6224                .to_offset(definition.target.buffer.read(cx));
6225
6226            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6227                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6228                    s.select_ranges([range]);
6229                });
6230            } else {
6231                cx.window_context().defer(move |cx| {
6232                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6233                        workspace.open_project_item(definition.target.buffer.clone(), cx)
6234                    });
6235                    target_editor.update(cx, |target_editor, cx| {
6236                        // When selecting a definition in a different buffer, disable the nav history
6237                        // to avoid creating a history entry at the previous cursor location.
6238                        pane.update(cx, |pane, _| pane.disable_history());
6239                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6240                            s.select_ranges([range]);
6241                        });
6242                        pane.update(cx, |pane, _| pane.enable_history());
6243                    });
6244                });
6245            }
6246        } else if !definitions.is_empty() {
6247            let replica_id = self.replica_id(cx);
6248            cx.window_context().defer(move |cx| {
6249                let title = definitions
6250                    .iter()
6251                    .find(|definition| definition.origin.is_some())
6252                    .and_then(|definition| {
6253                        definition.origin.as_ref().map(|origin| {
6254                            let buffer = origin.buffer.read(cx);
6255                            format!(
6256                                "Definitions for {}",
6257                                buffer
6258                                    .text_for_range(origin.range.clone())
6259                                    .collect::<String>()
6260                            )
6261                        })
6262                    })
6263                    .unwrap_or("Definitions".to_owned());
6264                let locations = definitions
6265                    .into_iter()
6266                    .map(|definition| definition.target)
6267                    .collect();
6268                workspace.update(cx, |workspace, cx| {
6269                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
6270                });
6271            });
6272        }
6273    }
6274
6275    pub fn find_all_references(
6276        workspace: &mut Workspace,
6277        _: &FindAllReferences,
6278        cx: &mut ViewContext<Workspace>,
6279    ) -> Option<Task<Result<()>>> {
6280        let active_item = workspace.active_item(cx)?;
6281        let editor_handle = active_item.act_as::<Self>(cx)?;
6282
6283        let editor = editor_handle.read(cx);
6284        let buffer = editor.buffer.read(cx);
6285        let head = editor.selections.newest::<usize>(cx).head();
6286        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6287        let replica_id = editor.replica_id(cx);
6288
6289        let project = workspace.project().clone();
6290        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6291        Some(cx.spawn_labeled(
6292            "Finding All References...",
6293            |workspace, mut cx| async move {
6294                let locations = references.await?;
6295                if locations.is_empty() {
6296                    return Ok(());
6297                }
6298
6299                workspace.update(&mut cx, |workspace, cx| {
6300                    let title = locations
6301                        .first()
6302                        .as_ref()
6303                        .map(|location| {
6304                            let buffer = location.buffer.read(cx);
6305                            format!(
6306                                "References to `{}`",
6307                                buffer
6308                                    .text_for_range(location.range.clone())
6309                                    .collect::<String>()
6310                            )
6311                        })
6312                        .unwrap();
6313                    Self::open_locations_in_multibuffer(
6314                        workspace, locations, replica_id, title, cx,
6315                    );
6316                })?;
6317
6318                Ok(())
6319            },
6320        ))
6321    }
6322
6323    /// Opens a multibuffer with the given project locations in it
6324    pub fn open_locations_in_multibuffer(
6325        workspace: &mut Workspace,
6326        mut locations: Vec<Location>,
6327        replica_id: ReplicaId,
6328        title: String,
6329        cx: &mut ViewContext<Workspace>,
6330    ) {
6331        // If there are multiple definitions, open them in a multibuffer
6332        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6333        let mut locations = locations.into_iter().peekable();
6334        let mut ranges_to_highlight = Vec::new();
6335
6336        let excerpt_buffer = cx.add_model(|cx| {
6337            let mut multibuffer = MultiBuffer::new(replica_id);
6338            while let Some(location) = locations.next() {
6339                let buffer = location.buffer.read(cx);
6340                let mut ranges_for_buffer = Vec::new();
6341                let range = location.range.to_offset(buffer);
6342                ranges_for_buffer.push(range.clone());
6343
6344                while let Some(next_location) = locations.peek() {
6345                    if next_location.buffer == location.buffer {
6346                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6347                        locations.next();
6348                    } else {
6349                        break;
6350                    }
6351                }
6352
6353                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6354                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6355                    location.buffer.clone(),
6356                    ranges_for_buffer,
6357                    1,
6358                    cx,
6359                ))
6360            }
6361
6362            multibuffer.with_title(title)
6363        });
6364
6365        let editor = cx.add_view(|cx| {
6366            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6367        });
6368        editor.update(cx, |editor, cx| {
6369            editor.highlight_background::<Self>(
6370                ranges_to_highlight,
6371                |theme| theme.editor.highlighted_line_background,
6372                cx,
6373            );
6374        });
6375        workspace.add_item(Box::new(editor), cx);
6376    }
6377
6378    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6379        use language::ToOffset as _;
6380
6381        let project = self.project.clone()?;
6382        let selection = self.selections.newest_anchor().clone();
6383        let (cursor_buffer, cursor_buffer_position) = self
6384            .buffer
6385            .read(cx)
6386            .text_anchor_for_position(selection.head(), cx)?;
6387        let (tail_buffer, _) = self
6388            .buffer
6389            .read(cx)
6390            .text_anchor_for_position(selection.tail(), cx)?;
6391        if tail_buffer != cursor_buffer {
6392            return None;
6393        }
6394
6395        let snapshot = cursor_buffer.read(cx).snapshot();
6396        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6397        let prepare_rename = project.update(cx, |project, cx| {
6398            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6399        });
6400
6401        Some(cx.spawn(|this, mut cx| async move {
6402            let rename_range = if let Some(range) = prepare_rename.await? {
6403                Some(range)
6404            } else {
6405                this.read_with(&cx, |this, cx| {
6406                    let buffer = this.buffer.read(cx).snapshot(cx);
6407                    let mut buffer_highlights = this
6408                        .document_highlights_for_position(selection.head(), &buffer)
6409                        .filter(|highlight| {
6410                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6411                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6412                        });
6413                    buffer_highlights
6414                        .next()
6415                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6416                })?
6417            };
6418            if let Some(rename_range) = rename_range {
6419                let rename_buffer_range = rename_range.to_offset(&snapshot);
6420                let cursor_offset_in_rename_range =
6421                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6422
6423                this.update(&mut cx, |this, cx| {
6424                    this.take_rename(false, cx);
6425                    let style = this.style(cx);
6426                    let buffer = this.buffer.read(cx).read(cx);
6427                    let cursor_offset = selection.head().to_offset(&buffer);
6428                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6429                    let rename_end = rename_start + rename_buffer_range.len();
6430                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6431                    let mut old_highlight_id = None;
6432                    let old_name: Arc<str> = buffer
6433                        .chunks(rename_start..rename_end, true)
6434                        .map(|chunk| {
6435                            if old_highlight_id.is_none() {
6436                                old_highlight_id = chunk.syntax_highlight_id;
6437                            }
6438                            chunk.text
6439                        })
6440                        .collect::<String>()
6441                        .into();
6442
6443                    drop(buffer);
6444
6445                    // Position the selection in the rename editor so that it matches the current selection.
6446                    this.show_local_selections = false;
6447                    let rename_editor = cx.add_view(|cx| {
6448                        let mut editor = Editor::single_line(None, cx);
6449                        if let Some(old_highlight_id) = old_highlight_id {
6450                            editor.override_text_style =
6451                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6452                        }
6453                        editor.buffer.update(cx, |buffer, cx| {
6454                            buffer.edit([(0..0, old_name.clone())], None, cx)
6455                        });
6456                        editor.select_all(&SelectAll, cx);
6457                        editor
6458                    });
6459
6460                    let ranges = this
6461                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6462                        .into_iter()
6463                        .flat_map(|(_, ranges)| ranges)
6464                        .chain(
6465                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6466                                .into_iter()
6467                                .flat_map(|(_, ranges)| ranges),
6468                        )
6469                        .collect();
6470
6471                    this.highlight_text::<Rename>(
6472                        ranges,
6473                        HighlightStyle {
6474                            fade_out: Some(style.rename_fade),
6475                            ..Default::default()
6476                        },
6477                        cx,
6478                    );
6479                    cx.focus(&rename_editor);
6480                    let block_id = this.insert_blocks(
6481                        [BlockProperties {
6482                            style: BlockStyle::Flex,
6483                            position: range.start.clone(),
6484                            height: 1,
6485                            render: Arc::new({
6486                                let editor = rename_editor.clone();
6487                                move |cx: &mut BlockContext| {
6488                                    ChildView::new(&editor, cx)
6489                                        .contained()
6490                                        .with_padding_left(cx.anchor_x)
6491                                        .into_any()
6492                                }
6493                            }),
6494                            disposition: BlockDisposition::Below,
6495                        }],
6496                        Some(Autoscroll::fit()),
6497                        cx,
6498                    )[0];
6499                    this.pending_rename = Some(RenameState {
6500                        range,
6501                        old_name,
6502                        editor: rename_editor,
6503                        block_id,
6504                    });
6505                })?;
6506            }
6507
6508            Ok(())
6509        }))
6510    }
6511
6512    pub fn confirm_rename(
6513        workspace: &mut Workspace,
6514        _: &ConfirmRename,
6515        cx: &mut ViewContext<Workspace>,
6516    ) -> Option<Task<Result<()>>> {
6517        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6518
6519        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6520            let rename = editor.take_rename(false, cx)?;
6521            let buffer = editor.buffer.read(cx);
6522            let (start_buffer, start) =
6523                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6524            let (end_buffer, end) =
6525                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6526            if start_buffer == end_buffer {
6527                let new_name = rename.editor.read(cx).text(cx);
6528                Some((start_buffer, start..end, rename.old_name, new_name))
6529            } else {
6530                None
6531            }
6532        })?;
6533
6534        let rename = workspace.project().clone().update(cx, |project, cx| {
6535            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6536        });
6537
6538        let editor = editor.downgrade();
6539        Some(cx.spawn(|workspace, mut cx| async move {
6540            let project_transaction = rename.await?;
6541            Self::open_project_transaction(
6542                &editor,
6543                workspace,
6544                project_transaction,
6545                format!("Rename: {}{}", old_name, new_name),
6546                cx.clone(),
6547            )
6548            .await?;
6549
6550            editor.update(&mut cx, |editor, cx| {
6551                editor.refresh_document_highlights(cx);
6552            })?;
6553            Ok(())
6554        }))
6555    }
6556
6557    fn take_rename(
6558        &mut self,
6559        moving_cursor: bool,
6560        cx: &mut ViewContext<Self>,
6561    ) -> Option<RenameState> {
6562        let rename = self.pending_rename.take()?;
6563        self.remove_blocks(
6564            [rename.block_id].into_iter().collect(),
6565            Some(Autoscroll::fit()),
6566            cx,
6567        );
6568        self.clear_text_highlights::<Rename>(cx);
6569        self.show_local_selections = true;
6570
6571        if moving_cursor {
6572            let rename_editor = rename.editor.read(cx);
6573            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6574
6575            // Update the selection to match the position of the selection inside
6576            // the rename editor.
6577            let snapshot = self.buffer.read(cx).read(cx);
6578            let rename_range = rename.range.to_offset(&snapshot);
6579            let cursor_in_editor = snapshot
6580                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6581                .min(rename_range.end);
6582            drop(snapshot);
6583
6584            self.change_selections(None, cx, |s| {
6585                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6586            });
6587        } else {
6588            self.refresh_document_highlights(cx);
6589        }
6590
6591        Some(rename)
6592    }
6593
6594    #[cfg(any(test, feature = "test-support"))]
6595    pub fn pending_rename(&self) -> Option<&RenameState> {
6596        self.pending_rename.as_ref()
6597    }
6598
6599    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6600        let project = match &self.project {
6601            Some(project) => project.clone(),
6602            None => return None,
6603        };
6604
6605        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6606    }
6607
6608    fn perform_format(
6609        &mut self,
6610        project: ModelHandle<Project>,
6611        trigger: FormatTrigger,
6612        cx: &mut ViewContext<Self>,
6613    ) -> Task<Result<()>> {
6614        let buffer = self.buffer().clone();
6615        let buffers = buffer.read(cx).all_buffers();
6616
6617        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6618        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6619
6620        cx.spawn(|_, mut cx| async move {
6621            let transaction = futures::select_biased! {
6622                _ = timeout => {
6623                    log::warn!("timed out waiting for formatting");
6624                    None
6625                }
6626                transaction = format.log_err().fuse() => transaction,
6627            };
6628
6629            buffer.update(&mut cx, |buffer, cx| {
6630                if let Some(transaction) = transaction {
6631                    if !buffer.is_singleton() {
6632                        buffer.push_transaction(&transaction.0, cx);
6633                    }
6634                }
6635
6636                cx.notify();
6637            });
6638
6639            Ok(())
6640        })
6641    }
6642
6643    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6644        if let Some(project) = self.project.clone() {
6645            self.buffer.update(cx, |multi_buffer, cx| {
6646                project.update(cx, |project, cx| {
6647                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6648                });
6649            })
6650        }
6651    }
6652
6653    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6654        cx.show_character_palette();
6655    }
6656
6657    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6658        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6659            let buffer = self.buffer.read(cx).snapshot(cx);
6660            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6661            let is_valid = buffer
6662                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6663                .any(|entry| {
6664                    entry.diagnostic.is_primary
6665                        && !entry.range.is_empty()
6666                        && entry.range.start == primary_range_start
6667                        && entry.diagnostic.message == active_diagnostics.primary_message
6668                });
6669
6670            if is_valid != active_diagnostics.is_valid {
6671                active_diagnostics.is_valid = is_valid;
6672                let mut new_styles = HashMap::default();
6673                for (block_id, diagnostic) in &active_diagnostics.blocks {
6674                    new_styles.insert(
6675                        *block_id,
6676                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6677                    );
6678                }
6679                self.display_map
6680                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6681            }
6682        }
6683    }
6684
6685    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6686        self.dismiss_diagnostics(cx);
6687        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6688            let buffer = self.buffer.read(cx).snapshot(cx);
6689
6690            let mut primary_range = None;
6691            let mut primary_message = None;
6692            let mut group_end = Point::zero();
6693            let diagnostic_group = buffer
6694                .diagnostic_group::<Point>(group_id)
6695                .map(|entry| {
6696                    if entry.range.end > group_end {
6697                        group_end = entry.range.end;
6698                    }
6699                    if entry.diagnostic.is_primary {
6700                        primary_range = Some(entry.range.clone());
6701                        primary_message = Some(entry.diagnostic.message.clone());
6702                    }
6703                    entry
6704                })
6705                .collect::<Vec<_>>();
6706            let primary_range = primary_range?;
6707            let primary_message = primary_message?;
6708            let primary_range =
6709                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6710
6711            let blocks = display_map
6712                .insert_blocks(
6713                    diagnostic_group.iter().map(|entry| {
6714                        let diagnostic = entry.diagnostic.clone();
6715                        let message_height = diagnostic.message.lines().count() as u8;
6716                        BlockProperties {
6717                            style: BlockStyle::Fixed,
6718                            position: buffer.anchor_after(entry.range.start),
6719                            height: message_height,
6720                            render: diagnostic_block_renderer(diagnostic, true),
6721                            disposition: BlockDisposition::Below,
6722                        }
6723                    }),
6724                    cx,
6725                )
6726                .into_iter()
6727                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6728                .collect();
6729
6730            Some(ActiveDiagnosticGroup {
6731                primary_range,
6732                primary_message,
6733                blocks,
6734                is_valid: true,
6735            })
6736        });
6737        self.active_diagnostics.is_some()
6738    }
6739
6740    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6741        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6742            self.display_map.update(cx, |display_map, cx| {
6743                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6744            });
6745            cx.notify();
6746        }
6747    }
6748
6749    pub fn set_selections_from_remote(
6750        &mut self,
6751        selections: Vec<Selection<Anchor>>,
6752        pending_selection: Option<Selection<Anchor>>,
6753        cx: &mut ViewContext<Self>,
6754    ) {
6755        let old_cursor_position = self.selections.newest_anchor().head();
6756        self.selections.change_with(cx, |s| {
6757            s.select_anchors(selections);
6758            if let Some(pending_selection) = pending_selection {
6759                s.set_pending(pending_selection, SelectMode::Character);
6760            } else {
6761                s.clear_pending();
6762            }
6763        });
6764        self.selections_did_change(false, &old_cursor_position, cx);
6765    }
6766
6767    fn push_to_selection_history(&mut self) {
6768        self.selection_history.push(SelectionHistoryEntry {
6769            selections: self.selections.disjoint_anchors(),
6770            select_next_state: self.select_next_state.clone(),
6771            select_prev_state: self.select_prev_state.clone(),
6772            add_selections_state: self.add_selections_state.clone(),
6773        });
6774    }
6775
6776    pub fn transact(
6777        &mut self,
6778        cx: &mut ViewContext<Self>,
6779        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6780    ) -> Option<TransactionId> {
6781        self.start_transaction_at(Instant::now(), cx);
6782        update(self, cx);
6783        self.end_transaction_at(Instant::now(), cx)
6784    }
6785
6786    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6787        self.end_selection(cx);
6788        if let Some(tx_id) = self
6789            .buffer
6790            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6791        {
6792            self.selection_history
6793                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6794        }
6795    }
6796
6797    fn end_transaction_at(
6798        &mut self,
6799        now: Instant,
6800        cx: &mut ViewContext<Self>,
6801    ) -> Option<TransactionId> {
6802        if let Some(tx_id) = self
6803            .buffer
6804            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6805        {
6806            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6807                *end_selections = Some(self.selections.disjoint_anchors());
6808            } else {
6809                error!("unexpectedly ended a transaction that wasn't started by this editor");
6810            }
6811
6812            cx.emit(Event::Edited);
6813            Some(tx_id)
6814        } else {
6815            None
6816        }
6817    }
6818
6819    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6820        let mut fold_ranges = Vec::new();
6821
6822        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6823
6824        let selections = self.selections.all::<Point>(cx);
6825        for selection in selections {
6826            let range = selection.range().sorted();
6827            let buffer_start_row = range.start.row;
6828
6829            for row in (0..=range.end.row).rev() {
6830                let fold_range = display_map.foldable_range(row);
6831
6832                if let Some(fold_range) = fold_range {
6833                    if fold_range.end.row >= buffer_start_row {
6834                        fold_ranges.push(fold_range);
6835                        if row <= range.start.row {
6836                            break;
6837                        }
6838                    }
6839                }
6840            }
6841        }
6842
6843        self.fold_ranges(fold_ranges, true, cx);
6844    }
6845
6846    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6847        let buffer_row = fold_at.buffer_row;
6848        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6849
6850        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6851            let autoscroll = self
6852                .selections
6853                .all::<Point>(cx)
6854                .iter()
6855                .any(|selection| fold_range.overlaps(&selection.range()));
6856
6857            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6858        }
6859    }
6860
6861    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6862        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6863        let buffer = &display_map.buffer_snapshot;
6864        let selections = self.selections.all::<Point>(cx);
6865        let ranges = selections
6866            .iter()
6867            .map(|s| {
6868                let range = s.display_range(&display_map).sorted();
6869                let mut start = range.start.to_point(&display_map);
6870                let mut end = range.end.to_point(&display_map);
6871                start.column = 0;
6872                end.column = buffer.line_len(end.row);
6873                start..end
6874            })
6875            .collect::<Vec<_>>();
6876
6877        self.unfold_ranges(ranges, true, true, cx);
6878    }
6879
6880    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6881        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6882
6883        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6884            ..Point::new(
6885                unfold_at.buffer_row,
6886                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6887            );
6888
6889        let autoscroll = self
6890            .selections
6891            .all::<Point>(cx)
6892            .iter()
6893            .any(|selection| selection.range().overlaps(&intersection_range));
6894
6895        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6896    }
6897
6898    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6899        let selections = self.selections.all::<Point>(cx);
6900        let ranges = selections.into_iter().map(|s| s.start..s.end);
6901        self.fold_ranges(ranges, true, cx);
6902    }
6903
6904    pub fn fold_ranges<T: ToOffset + Clone>(
6905        &mut self,
6906        ranges: impl IntoIterator<Item = Range<T>>,
6907        auto_scroll: bool,
6908        cx: &mut ViewContext<Self>,
6909    ) {
6910        let mut ranges = ranges.into_iter().peekable();
6911        if ranges.peek().is_some() {
6912            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6913
6914            if auto_scroll {
6915                self.request_autoscroll(Autoscroll::fit(), cx);
6916            }
6917
6918            cx.notify();
6919        }
6920    }
6921
6922    pub fn unfold_ranges<T: ToOffset + Clone>(
6923        &mut self,
6924        ranges: impl IntoIterator<Item = Range<T>>,
6925        inclusive: bool,
6926        auto_scroll: bool,
6927        cx: &mut ViewContext<Self>,
6928    ) {
6929        let mut ranges = ranges.into_iter().peekable();
6930        if ranges.peek().is_some() {
6931            self.display_map
6932                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6933            if auto_scroll {
6934                self.request_autoscroll(Autoscroll::fit(), cx);
6935            }
6936
6937            cx.notify();
6938        }
6939    }
6940
6941    pub fn gutter_hover(
6942        &mut self,
6943        GutterHover { hovered }: &GutterHover,
6944        cx: &mut ViewContext<Self>,
6945    ) {
6946        self.gutter_hovered = *hovered;
6947        cx.notify();
6948    }
6949
6950    pub fn insert_blocks(
6951        &mut self,
6952        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6953        autoscroll: Option<Autoscroll>,
6954        cx: &mut ViewContext<Self>,
6955    ) -> Vec<BlockId> {
6956        let blocks = self
6957            .display_map
6958            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6959        if let Some(autoscroll) = autoscroll {
6960            self.request_autoscroll(autoscroll, cx);
6961        }
6962        blocks
6963    }
6964
6965    pub fn replace_blocks(
6966        &mut self,
6967        blocks: HashMap<BlockId, RenderBlock>,
6968        autoscroll: Option<Autoscroll>,
6969        cx: &mut ViewContext<Self>,
6970    ) {
6971        self.display_map
6972            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6973        if let Some(autoscroll) = autoscroll {
6974            self.request_autoscroll(autoscroll, cx);
6975        }
6976    }
6977
6978    pub fn remove_blocks(
6979        &mut self,
6980        block_ids: HashSet<BlockId>,
6981        autoscroll: Option<Autoscroll>,
6982        cx: &mut ViewContext<Self>,
6983    ) {
6984        self.display_map.update(cx, |display_map, cx| {
6985            display_map.remove_blocks(block_ids, cx)
6986        });
6987        if let Some(autoscroll) = autoscroll {
6988            self.request_autoscroll(autoscroll, cx);
6989        }
6990    }
6991
6992    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6993        self.display_map
6994            .update(cx, |map, cx| map.snapshot(cx))
6995            .longest_row()
6996    }
6997
6998    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6999        self.display_map
7000            .update(cx, |map, cx| map.snapshot(cx))
7001            .max_point()
7002    }
7003
7004    pub fn text(&self, cx: &AppContext) -> String {
7005        self.buffer.read(cx).read(cx).text()
7006    }
7007
7008    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7009        self.transact(cx, |this, cx| {
7010            this.buffer
7011                .read(cx)
7012                .as_singleton()
7013                .expect("you can only call set_text on editors for singleton buffers")
7014                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7015        });
7016    }
7017
7018    pub fn display_text(&self, cx: &mut AppContext) -> String {
7019        self.display_map
7020            .update(cx, |map, cx| map.snapshot(cx))
7021            .text()
7022    }
7023
7024    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7025        let settings = self.buffer.read(cx).settings_at(0, cx);
7026        let mode = self
7027            .soft_wrap_mode_override
7028            .unwrap_or_else(|| settings.soft_wrap);
7029        match mode {
7030            language_settings::SoftWrap::None => SoftWrap::None,
7031            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7032            language_settings::SoftWrap::PreferredLineLength => {
7033                SoftWrap::Column(settings.preferred_line_length)
7034            }
7035        }
7036    }
7037
7038    pub fn set_soft_wrap_mode(
7039        &mut self,
7040        mode: language_settings::SoftWrap,
7041        cx: &mut ViewContext<Self>,
7042    ) {
7043        self.soft_wrap_mode_override = Some(mode);
7044        cx.notify();
7045    }
7046
7047    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7048        self.display_map
7049            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7050    }
7051
7052    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7053        if self.soft_wrap_mode_override.is_some() {
7054            self.soft_wrap_mode_override.take();
7055        } else {
7056            let soft_wrap = match self.soft_wrap_mode(cx) {
7057                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7058                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7059            };
7060            self.soft_wrap_mode_override = Some(soft_wrap);
7061        }
7062        cx.notify();
7063    }
7064
7065    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7066        self.show_gutter = show_gutter;
7067        cx.notify();
7068    }
7069
7070    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7071        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7072            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7073                cx.reveal_path(&file.abs_path(cx));
7074            }
7075        }
7076    }
7077
7078    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7079        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7080            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7081                if let Some(path) = file.abs_path(cx).to_str() {
7082                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7083                }
7084            }
7085        }
7086    }
7087
7088    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7089        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7090            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7091                if let Some(path) = file.path().to_str() {
7092                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7093                }
7094            }
7095        }
7096    }
7097
7098    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7099        self.highlighted_rows = rows;
7100    }
7101
7102    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7103        self.highlighted_rows.clone()
7104    }
7105
7106    pub fn highlight_background<T: 'static>(
7107        &mut self,
7108        ranges: Vec<Range<Anchor>>,
7109        color_fetcher: fn(&Theme) -> Color,
7110        cx: &mut ViewContext<Self>,
7111    ) {
7112        self.background_highlights
7113            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7114        cx.notify();
7115    }
7116
7117    #[allow(clippy::type_complexity)]
7118    pub fn clear_background_highlights<T: 'static>(
7119        &mut self,
7120        cx: &mut ViewContext<Self>,
7121    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7122        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7123        if highlights.is_some() {
7124            cx.notify();
7125        }
7126        highlights
7127    }
7128
7129    #[cfg(feature = "test-support")]
7130    pub fn all_background_highlights(
7131        &mut self,
7132        cx: &mut ViewContext<Self>,
7133    ) -> Vec<(Range<DisplayPoint>, Color)> {
7134        let snapshot = self.snapshot(cx);
7135        let buffer = &snapshot.buffer_snapshot;
7136        let start = buffer.anchor_before(0);
7137        let end = buffer.anchor_after(buffer.len());
7138        let theme = theme::current(cx);
7139        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7140    }
7141
7142    fn document_highlights_for_position<'a>(
7143        &'a self,
7144        position: Anchor,
7145        buffer: &'a MultiBufferSnapshot,
7146    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7147        let read_highlights = self
7148            .background_highlights
7149            .get(&TypeId::of::<DocumentHighlightRead>())
7150            .map(|h| &h.1);
7151        let write_highlights = self
7152            .background_highlights
7153            .get(&TypeId::of::<DocumentHighlightWrite>())
7154            .map(|h| &h.1);
7155        let left_position = position.bias_left(buffer);
7156        let right_position = position.bias_right(buffer);
7157        read_highlights
7158            .into_iter()
7159            .chain(write_highlights)
7160            .flat_map(move |ranges| {
7161                let start_ix = match ranges.binary_search_by(|probe| {
7162                    let cmp = probe.end.cmp(&left_position, buffer);
7163                    if cmp.is_ge() {
7164                        Ordering::Greater
7165                    } else {
7166                        Ordering::Less
7167                    }
7168                }) {
7169                    Ok(i) | Err(i) => i,
7170                };
7171
7172                let right_position = right_position.clone();
7173                ranges[start_ix..]
7174                    .iter()
7175                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7176            })
7177    }
7178
7179    pub fn background_highlights_in_range(
7180        &self,
7181        search_range: Range<Anchor>,
7182        display_snapshot: &DisplaySnapshot,
7183        theme: &Theme,
7184    ) -> Vec<(Range<DisplayPoint>, Color)> {
7185        let mut results = Vec::new();
7186        let buffer = &display_snapshot.buffer_snapshot;
7187        for (color_fetcher, ranges) in self.background_highlights.values() {
7188            let color = color_fetcher(theme);
7189            let start_ix = match ranges.binary_search_by(|probe| {
7190                let cmp = probe.end.cmp(&search_range.start, buffer);
7191                if cmp.is_gt() {
7192                    Ordering::Greater
7193                } else {
7194                    Ordering::Less
7195                }
7196            }) {
7197                Ok(i) | Err(i) => i,
7198            };
7199            for range in &ranges[start_ix..] {
7200                if range.start.cmp(&search_range.end, buffer).is_ge() {
7201                    break;
7202                }
7203                let start = range
7204                    .start
7205                    .to_point(buffer)
7206                    .to_display_point(display_snapshot);
7207                let end = range
7208                    .end
7209                    .to_point(buffer)
7210                    .to_display_point(display_snapshot);
7211                results.push((start..end, color))
7212            }
7213        }
7214        results
7215    }
7216
7217    pub fn highlight_text<T: 'static>(
7218        &mut self,
7219        ranges: Vec<Range<Anchor>>,
7220        style: HighlightStyle,
7221        cx: &mut ViewContext<Self>,
7222    ) {
7223        self.display_map.update(cx, |map, _| {
7224            map.highlight_text(TypeId::of::<T>(), ranges, style)
7225        });
7226        cx.notify();
7227    }
7228
7229    pub fn text_highlights<'a, T: 'static>(
7230        &'a self,
7231        cx: &'a AppContext,
7232    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7233        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7234    }
7235
7236    pub fn clear_text_highlights<T: 'static>(
7237        &mut self,
7238        cx: &mut ViewContext<Self>,
7239    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7240        let highlights = self
7241            .display_map
7242            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7243        if highlights.is_some() {
7244            cx.notify();
7245        }
7246        highlights
7247    }
7248
7249    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7250        self.blink_manager.read(cx).visible() && self.focused
7251    }
7252
7253    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7254        cx.notify();
7255    }
7256
7257    fn on_buffer_event(
7258        &mut self,
7259        _: ModelHandle<MultiBuffer>,
7260        event: &multi_buffer::Event,
7261        cx: &mut ViewContext<Self>,
7262    ) {
7263        match event {
7264            multi_buffer::Event::Edited => {
7265                self.refresh_active_diagnostics(cx);
7266                self.refresh_code_actions(cx);
7267                if self.has_active_copilot_suggestion(cx) {
7268                    self.update_visible_copilot_suggestion(cx);
7269                }
7270                cx.emit(Event::BufferEdited);
7271                self.refresh_inlays(InlayRefreshReason::ExcerptEdited, cx);
7272            }
7273            multi_buffer::Event::ExcerptsAdded {
7274                buffer,
7275                predecessor,
7276                excerpts,
7277            } => cx.emit(Event::ExcerptsAdded {
7278                buffer: buffer.clone(),
7279                predecessor: *predecessor,
7280                excerpts: excerpts.clone(),
7281            }),
7282            multi_buffer::Event::ExcerptsRemoved { ids } => {
7283                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7284            }
7285            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7286            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7287            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7288            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7289            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7290            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7291            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7292            multi_buffer::Event::DiagnosticsUpdated => {
7293                self.refresh_active_diagnostics(cx);
7294            }
7295            _ => {}
7296        };
7297    }
7298
7299    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7300        cx.notify();
7301    }
7302
7303    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7304        self.refresh_copilot_suggestions(true, cx);
7305        self.refresh_inlays(
7306            InlayRefreshReason::SettingsChange(inlay_hint_settings(
7307                self.selections.newest_anchor().head(),
7308                &self.buffer.read(cx).snapshot(cx),
7309                cx,
7310            )),
7311            cx,
7312        );
7313    }
7314
7315    pub fn set_searchable(&mut self, searchable: bool) {
7316        self.searchable = searchable;
7317    }
7318
7319    pub fn searchable(&self) -> bool {
7320        self.searchable
7321    }
7322
7323    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7324        let active_item = workspace.active_item(cx);
7325        let editor_handle = if let Some(editor) = active_item
7326            .as_ref()
7327            .and_then(|item| item.act_as::<Self>(cx))
7328        {
7329            editor
7330        } else {
7331            cx.propagate_action();
7332            return;
7333        };
7334
7335        let editor = editor_handle.read(cx);
7336        let buffer = editor.buffer.read(cx);
7337        if buffer.is_singleton() {
7338            cx.propagate_action();
7339            return;
7340        }
7341
7342        let mut new_selections_by_buffer = HashMap::default();
7343        for selection in editor.selections.all::<usize>(cx) {
7344            for (buffer, mut range, _) in
7345                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7346            {
7347                if selection.reversed {
7348                    mem::swap(&mut range.start, &mut range.end);
7349                }
7350                new_selections_by_buffer
7351                    .entry(buffer)
7352                    .or_insert(Vec::new())
7353                    .push(range)
7354            }
7355        }
7356
7357        editor_handle.update(cx, |editor, cx| {
7358            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7359        });
7360        let pane = workspace.active_pane().clone();
7361        pane.update(cx, |pane, _| pane.disable_history());
7362
7363        // We defer the pane interaction because we ourselves are a workspace item
7364        // and activating a new item causes the pane to call a method on us reentrantly,
7365        // which panics if we're on the stack.
7366        cx.defer(move |workspace, cx| {
7367            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7368                let editor = workspace.open_project_item::<Self>(buffer, cx);
7369                editor.update(cx, |editor, cx| {
7370                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7371                        s.select_ranges(ranges);
7372                    });
7373                });
7374            }
7375
7376            pane.update(cx, |pane, _| pane.enable_history());
7377        });
7378    }
7379
7380    fn jump(
7381        workspace: &mut Workspace,
7382        path: ProjectPath,
7383        position: Point,
7384        anchor: language::Anchor,
7385        cx: &mut ViewContext<Workspace>,
7386    ) {
7387        let editor = workspace.open_path(path, None, true, cx);
7388        cx.spawn(|_, mut cx| async move {
7389            let editor = editor
7390                .await?
7391                .downcast::<Editor>()
7392                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7393                .downgrade();
7394            editor.update(&mut cx, |editor, cx| {
7395                let buffer = editor
7396                    .buffer()
7397                    .read(cx)
7398                    .as_singleton()
7399                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7400                let buffer = buffer.read(cx);
7401                let cursor = if buffer.can_resolve(&anchor) {
7402                    language::ToPoint::to_point(&anchor, buffer)
7403                } else {
7404                    buffer.clip_point(position, Bias::Left)
7405                };
7406
7407                let nav_history = editor.nav_history.take();
7408                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7409                    s.select_ranges([cursor..cursor]);
7410                });
7411                editor.nav_history = nav_history;
7412
7413                anyhow::Ok(())
7414            })??;
7415
7416            anyhow::Ok(())
7417        })
7418        .detach_and_log_err(cx);
7419    }
7420
7421    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7422        let snapshot = self.buffer.read(cx).read(cx);
7423        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7424        Some(
7425            ranges
7426                .iter()
7427                .map(move |range| {
7428                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7429                })
7430                .collect(),
7431        )
7432    }
7433
7434    fn selection_replacement_ranges(
7435        &self,
7436        range: Range<OffsetUtf16>,
7437        cx: &AppContext,
7438    ) -> Vec<Range<OffsetUtf16>> {
7439        let selections = self.selections.all::<OffsetUtf16>(cx);
7440        let newest_selection = selections
7441            .iter()
7442            .max_by_key(|selection| selection.id)
7443            .unwrap();
7444        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7445        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7446        let snapshot = self.buffer.read(cx).read(cx);
7447        selections
7448            .into_iter()
7449            .map(|mut selection| {
7450                selection.start.0 =
7451                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7452                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7453                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7454                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7455            })
7456            .collect()
7457    }
7458
7459    fn report_copilot_event(
7460        &self,
7461        suggestion_id: Option<String>,
7462        suggestion_accepted: bool,
7463        cx: &AppContext,
7464    ) {
7465        let Some(project) = &self.project else {
7466            return
7467        };
7468
7469        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7470        let file_extension = self
7471            .buffer
7472            .read(cx)
7473            .as_singleton()
7474            .and_then(|b| b.read(cx).file())
7475            .and_then(|file| Path::new(file.file_name(cx)).extension())
7476            .and_then(|e| e.to_str())
7477            .map(|a| a.to_string());
7478
7479        let telemetry = project.read(cx).client().telemetry().clone();
7480        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7481
7482        let event = ClickhouseEvent::Copilot {
7483            suggestion_id,
7484            suggestion_accepted,
7485            file_extension,
7486        };
7487        telemetry.report_clickhouse_event(event, telemetry_settings);
7488    }
7489
7490    fn report_editor_event(
7491        &self,
7492        name: &'static str,
7493        file_extension: Option<String>,
7494        cx: &AppContext,
7495    ) {
7496        let Some(project) = &self.project else {
7497            return
7498        };
7499
7500        // If None, we are in a file without an extension
7501        let file = self
7502            .buffer
7503            .read(cx)
7504            .as_singleton()
7505            .and_then(|b| b.read(cx).file());
7506        let file_extension = file_extension.or(file
7507            .as_ref()
7508            .and_then(|file| Path::new(file.file_name(cx)).extension())
7509            .and_then(|e| e.to_str())
7510            .map(|a| a.to_string()));
7511
7512        let vim_mode = cx
7513            .global::<SettingsStore>()
7514            .raw_user_settings()
7515            .get("vim_mode")
7516            == Some(&serde_json::Value::Bool(true));
7517        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7518        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7519        let copilot_enabled_for_language = self
7520            .buffer
7521            .read(cx)
7522            .settings_at(0, cx)
7523            .show_copilot_suggestions;
7524
7525        let telemetry = project.read(cx).client().telemetry().clone();
7526        let event = ClickhouseEvent::Editor {
7527            file_extension,
7528            vim_mode,
7529            operation: name,
7530            copilot_enabled,
7531            copilot_enabled_for_language,
7532        };
7533        telemetry.report_clickhouse_event(event, telemetry_settings)
7534    }
7535
7536    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7537    /// with each line being an array of {text, highlight} objects.
7538    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7539        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7540            return;
7541        };
7542
7543        #[derive(Serialize)]
7544        struct Chunk<'a> {
7545            text: String,
7546            highlight: Option<&'a str>,
7547        }
7548
7549        let snapshot = buffer.read(cx).snapshot();
7550        let range = self
7551            .selected_text_range(cx)
7552            .and_then(|selected_range| {
7553                if selected_range.is_empty() {
7554                    None
7555                } else {
7556                    Some(selected_range)
7557                }
7558            })
7559            .unwrap_or_else(|| 0..snapshot.len());
7560
7561        let chunks = snapshot.chunks(range, true);
7562        let mut lines = Vec::new();
7563        let mut line: VecDeque<Chunk> = VecDeque::new();
7564
7565        let theme = &theme::current(cx).editor.syntax;
7566
7567        for chunk in chunks {
7568            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7569            let mut chunk_lines = chunk.text.split("\n").peekable();
7570            while let Some(text) = chunk_lines.next() {
7571                let mut merged_with_last_token = false;
7572                if let Some(last_token) = line.back_mut() {
7573                    if last_token.highlight == highlight {
7574                        last_token.text.push_str(text);
7575                        merged_with_last_token = true;
7576                    }
7577                }
7578
7579                if !merged_with_last_token {
7580                    line.push_back(Chunk {
7581                        text: text.into(),
7582                        highlight,
7583                    });
7584                }
7585
7586                if chunk_lines.peek().is_some() {
7587                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7588                        line.pop_front();
7589                    }
7590                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7591                        line.pop_back();
7592                    }
7593
7594                    lines.push(mem::take(&mut line));
7595                }
7596            }
7597        }
7598
7599        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7600        cx.write_to_clipboard(ClipboardItem::new(lines));
7601    }
7602
7603    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
7604        &self.inlay_hint_cache
7605    }
7606}
7607
7608fn inlay_hint_settings(
7609    location: Anchor,
7610    snapshot: &MultiBufferSnapshot,
7611    cx: &mut ViewContext<'_, '_, Editor>,
7612) -> InlayHintSettings {
7613    let file = snapshot.file_at(location);
7614    let language = snapshot.language_at(location);
7615    let settings = all_language_settings(file, cx);
7616    settings
7617        .language(language.map(|l| l.name()).as_deref())
7618        .inlay_hints
7619}
7620
7621fn consume_contiguous_rows(
7622    contiguous_row_selections: &mut Vec<Selection<Point>>,
7623    selection: &Selection<Point>,
7624    display_map: &DisplaySnapshot,
7625    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7626) -> (u32, u32) {
7627    contiguous_row_selections.push(selection.clone());
7628    let start_row = selection.start.row;
7629    let mut end_row = ending_row(selection, display_map);
7630
7631    while let Some(next_selection) = selections.peek() {
7632        if next_selection.start.row <= end_row {
7633            end_row = ending_row(next_selection, display_map);
7634            contiguous_row_selections.push(selections.next().unwrap().clone());
7635        } else {
7636            break;
7637        }
7638    }
7639    (start_row, end_row)
7640}
7641
7642fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7643    if next_selection.end.column > 0 || next_selection.is_empty() {
7644        display_map.next_line_boundary(next_selection.end).0.row + 1
7645    } else {
7646        next_selection.end.row
7647    }
7648}
7649
7650impl EditorSnapshot {
7651    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7652        self.display_snapshot.buffer_snapshot.language_at(position)
7653    }
7654
7655    pub fn is_focused(&self) -> bool {
7656        self.is_focused
7657    }
7658
7659    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7660        self.placeholder_text.as_ref()
7661    }
7662
7663    pub fn scroll_position(&self) -> Vector2F {
7664        self.scroll_anchor.scroll_position(&self.display_snapshot)
7665    }
7666}
7667
7668impl Deref for EditorSnapshot {
7669    type Target = DisplaySnapshot;
7670
7671    fn deref(&self) -> &Self::Target {
7672        &self.display_snapshot
7673    }
7674}
7675
7676#[derive(Clone, Debug, PartialEq, Eq)]
7677pub enum Event {
7678    InputIgnored {
7679        text: Arc<str>,
7680    },
7681    ExcerptsAdded {
7682        buffer: ModelHandle<Buffer>,
7683        predecessor: ExcerptId,
7684        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7685    },
7686    ExcerptsRemoved {
7687        ids: Vec<ExcerptId>,
7688    },
7689    BufferEdited,
7690    Edited,
7691    Reparsed,
7692    Focused,
7693    Blurred,
7694    DirtyChanged,
7695    Saved,
7696    TitleChanged,
7697    DiffBaseChanged,
7698    SelectionsChanged {
7699        local: bool,
7700    },
7701    ScrollPositionChanged {
7702        local: bool,
7703        autoscroll: bool,
7704    },
7705    Closed,
7706}
7707
7708pub struct EditorFocused(pub ViewHandle<Editor>);
7709pub struct EditorBlurred(pub ViewHandle<Editor>);
7710pub struct EditorReleased(pub WeakViewHandle<Editor>);
7711
7712impl Entity for Editor {
7713    type Event = Event;
7714
7715    fn release(&mut self, cx: &mut AppContext) {
7716        cx.emit_global(EditorReleased(self.handle.clone()));
7717    }
7718}
7719
7720impl View for Editor {
7721    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7722        let style = self.style(cx);
7723        let font_changed = self.display_map.update(cx, |map, cx| {
7724            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7725            map.set_font(style.text.font_id, style.text.font_size, cx)
7726        });
7727
7728        if font_changed {
7729            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7730                hide_hover(editor, cx);
7731                hide_link_definition(editor, cx);
7732            });
7733        }
7734
7735        Stack::new()
7736            .with_child(EditorElement::new(style.clone()))
7737            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7738            .into_any()
7739    }
7740
7741    fn ui_name() -> &'static str {
7742        "Editor"
7743    }
7744
7745    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7746        if cx.is_self_focused() {
7747            let focused_event = EditorFocused(cx.handle());
7748            cx.emit(Event::Focused);
7749            cx.emit_global(focused_event);
7750        }
7751        if let Some(rename) = self.pending_rename.as_ref() {
7752            cx.focus(&rename.editor);
7753        } else {
7754            if !self.focused {
7755                self.blink_manager.update(cx, BlinkManager::enable);
7756            }
7757            self.focused = true;
7758            self.buffer.update(cx, |buffer, cx| {
7759                buffer.finalize_last_transaction(cx);
7760                if self.leader_replica_id.is_none() {
7761                    buffer.set_active_selections(
7762                        &self.selections.disjoint_anchors(),
7763                        self.selections.line_mode,
7764                        self.cursor_shape,
7765                        cx,
7766                    );
7767                }
7768            });
7769        }
7770    }
7771
7772    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7773        let blurred_event = EditorBlurred(cx.handle());
7774        cx.emit_global(blurred_event);
7775        self.focused = false;
7776        self.blink_manager.update(cx, BlinkManager::disable);
7777        self.buffer
7778            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7779        self.hide_context_menu(cx);
7780        hide_hover(self, cx);
7781        cx.emit(Event::Blurred);
7782        cx.notify();
7783    }
7784
7785    fn modifiers_changed(
7786        &mut self,
7787        event: &gpui::platform::ModifiersChangedEvent,
7788        cx: &mut ViewContext<Self>,
7789    ) -> bool {
7790        let pending_selection = self.has_pending_selection();
7791
7792        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7793            if event.cmd && !pending_selection {
7794                let snapshot = self.snapshot(cx);
7795                let kind = if event.shift {
7796                    LinkDefinitionKind::Type
7797                } else {
7798                    LinkDefinitionKind::Symbol
7799                };
7800
7801                show_link_definition(kind, self, point, snapshot, cx);
7802                return false;
7803            }
7804        }
7805
7806        {
7807            if self.link_go_to_definition_state.symbol_range.is_some()
7808                || !self.link_go_to_definition_state.definitions.is_empty()
7809            {
7810                self.link_go_to_definition_state.symbol_range.take();
7811                self.link_go_to_definition_state.definitions.clear();
7812                cx.notify();
7813            }
7814
7815            self.link_go_to_definition_state.task = None;
7816
7817            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7818        }
7819
7820        false
7821    }
7822
7823    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7824        Self::reset_to_default_keymap_context(keymap);
7825        let mode = match self.mode {
7826            EditorMode::SingleLine => "single_line",
7827            EditorMode::AutoHeight { .. } => "auto_height",
7828            EditorMode::Full => "full",
7829        };
7830        keymap.add_key("mode", mode);
7831        if self.pending_rename.is_some() {
7832            keymap.add_identifier("renaming");
7833        }
7834        match self.context_menu.as_ref() {
7835            Some(ContextMenu::Completions(_)) => {
7836                keymap.add_identifier("menu");
7837                keymap.add_identifier("showing_completions")
7838            }
7839            Some(ContextMenu::CodeActions(_)) => {
7840                keymap.add_identifier("menu");
7841                keymap.add_identifier("showing_code_actions")
7842            }
7843            None => {}
7844        }
7845        for layer in self.keymap_context_layers.values() {
7846            keymap.extend(layer);
7847        }
7848
7849        if let Some(extension) = self
7850            .buffer
7851            .read(cx)
7852            .as_singleton()
7853            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7854        {
7855            keymap.add_key("extension", extension.to_string());
7856        }
7857    }
7858
7859    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7860        Some(
7861            self.buffer
7862                .read(cx)
7863                .read(cx)
7864                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7865                .collect(),
7866        )
7867    }
7868
7869    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7870        // Prevent the IME menu from appearing when holding down an alphabetic key
7871        // while input is disabled.
7872        if !self.input_enabled {
7873            return None;
7874        }
7875
7876        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7877        Some(range.start.0..range.end.0)
7878    }
7879
7880    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7881        let snapshot = self.buffer.read(cx).read(cx);
7882        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7883        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7884    }
7885
7886    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7887        self.clear_text_highlights::<InputComposition>(cx);
7888        self.ime_transaction.take();
7889    }
7890
7891    fn replace_text_in_range(
7892        &mut self,
7893        range_utf16: Option<Range<usize>>,
7894        text: &str,
7895        cx: &mut ViewContext<Self>,
7896    ) {
7897        self.transact(cx, |this, cx| {
7898            if this.input_enabled {
7899                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7900                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7901                    Some(this.selection_replacement_ranges(range_utf16, cx))
7902                } else {
7903                    this.marked_text_ranges(cx)
7904                };
7905
7906                if let Some(new_selected_ranges) = new_selected_ranges {
7907                    this.change_selections(None, cx, |selections| {
7908                        selections.select_ranges(new_selected_ranges)
7909                    });
7910                }
7911            }
7912
7913            this.handle_input(text, cx);
7914        });
7915
7916        if !self.input_enabled {
7917            return;
7918        }
7919
7920        if let Some(transaction) = self.ime_transaction {
7921            self.buffer.update(cx, |buffer, cx| {
7922                buffer.group_until_transaction(transaction, cx);
7923            });
7924        }
7925
7926        self.unmark_text(cx);
7927    }
7928
7929    fn replace_and_mark_text_in_range(
7930        &mut self,
7931        range_utf16: Option<Range<usize>>,
7932        text: &str,
7933        new_selected_range_utf16: Option<Range<usize>>,
7934        cx: &mut ViewContext<Self>,
7935    ) {
7936        if !self.input_enabled {
7937            return;
7938        }
7939
7940        let transaction = self.transact(cx, |this, cx| {
7941            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7942                let snapshot = this.buffer.read(cx).read(cx);
7943                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7944                    for marked_range in &mut marked_ranges {
7945                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7946                        marked_range.start.0 += relative_range_utf16.start;
7947                        marked_range.start =
7948                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7949                        marked_range.end =
7950                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7951                    }
7952                }
7953                Some(marked_ranges)
7954            } else if let Some(range_utf16) = range_utf16 {
7955                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7956                Some(this.selection_replacement_ranges(range_utf16, cx))
7957            } else {
7958                None
7959            };
7960
7961            if let Some(ranges) = ranges_to_replace {
7962                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7963            }
7964
7965            let marked_ranges = {
7966                let snapshot = this.buffer.read(cx).read(cx);
7967                this.selections
7968                    .disjoint_anchors()
7969                    .iter()
7970                    .map(|selection| {
7971                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7972                    })
7973                    .collect::<Vec<_>>()
7974            };
7975
7976            if text.is_empty() {
7977                this.unmark_text(cx);
7978            } else {
7979                this.highlight_text::<InputComposition>(
7980                    marked_ranges.clone(),
7981                    this.style(cx).composition_mark,
7982                    cx,
7983                );
7984            }
7985
7986            this.handle_input(text, cx);
7987
7988            if let Some(new_selected_range) = new_selected_range_utf16 {
7989                let snapshot = this.buffer.read(cx).read(cx);
7990                let new_selected_ranges = marked_ranges
7991                    .into_iter()
7992                    .map(|marked_range| {
7993                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7994                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7995                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7996                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7997                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7998                    })
7999                    .collect::<Vec<_>>();
8000
8001                drop(snapshot);
8002                this.change_selections(None, cx, |selections| {
8003                    selections.select_ranges(new_selected_ranges)
8004                });
8005            }
8006        });
8007
8008        self.ime_transaction = self.ime_transaction.or(transaction);
8009        if let Some(transaction) = self.ime_transaction {
8010            self.buffer.update(cx, |buffer, cx| {
8011                buffer.group_until_transaction(transaction, cx);
8012            });
8013        }
8014
8015        if self.text_highlights::<InputComposition>(cx).is_none() {
8016            self.ime_transaction.take();
8017        }
8018    }
8019}
8020
8021fn build_style(
8022    settings: &ThemeSettings,
8023    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8024    override_text_style: Option<&OverrideTextStyle>,
8025    cx: &AppContext,
8026) -> EditorStyle {
8027    let font_cache = cx.font_cache();
8028
8029    let theme_id = settings.theme.meta.id;
8030    let mut theme = settings.theme.editor.clone();
8031    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8032        let field_editor_theme = get_field_editor_theme(&settings.theme);
8033        theme.text_color = field_editor_theme.text.color;
8034        theme.selection = field_editor_theme.selection;
8035        theme.background = field_editor_theme
8036            .container
8037            .background_color
8038            .unwrap_or_default();
8039        EditorStyle {
8040            text: field_editor_theme.text,
8041            placeholder_text: field_editor_theme.placeholder_text,
8042            theme,
8043            theme_id,
8044        }
8045    } else {
8046        let font_family_id = settings.buffer_font_family;
8047        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8048        let font_properties = Default::default();
8049        let font_id = font_cache
8050            .select_font(font_family_id, &font_properties)
8051            .unwrap();
8052        let font_size = settings.buffer_font_size(cx);
8053        EditorStyle {
8054            text: TextStyle {
8055                color: settings.theme.editor.text_color,
8056                font_family_name,
8057                font_family_id,
8058                font_id,
8059                font_size,
8060                font_properties,
8061                underline: Default::default(),
8062            },
8063            placeholder_text: None,
8064            theme,
8065            theme_id,
8066        }
8067    };
8068
8069    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8070        if let Some(highlighted) = style
8071            .text
8072            .clone()
8073            .highlight(highlight_style, font_cache)
8074            .log_err()
8075        {
8076            style.text = highlighted;
8077        }
8078    }
8079
8080    style
8081}
8082
8083trait SelectionExt {
8084    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8085    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8086    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8087    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8088        -> Range<u32>;
8089}
8090
8091impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8092    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8093        let start = self.start.to_point(buffer);
8094        let end = self.end.to_point(buffer);
8095        if self.reversed {
8096            end..start
8097        } else {
8098            start..end
8099        }
8100    }
8101
8102    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8103        let start = self.start.to_offset(buffer);
8104        let end = self.end.to_offset(buffer);
8105        if self.reversed {
8106            end..start
8107        } else {
8108            start..end
8109        }
8110    }
8111
8112    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8113        let start = self
8114            .start
8115            .to_point(&map.buffer_snapshot)
8116            .to_display_point(map);
8117        let end = self
8118            .end
8119            .to_point(&map.buffer_snapshot)
8120            .to_display_point(map);
8121        if self.reversed {
8122            end..start
8123        } else {
8124            start..end
8125        }
8126    }
8127
8128    fn spanned_rows(
8129        &self,
8130        include_end_if_at_line_start: bool,
8131        map: &DisplaySnapshot,
8132    ) -> Range<u32> {
8133        let start = self.start.to_point(&map.buffer_snapshot);
8134        let mut end = self.end.to_point(&map.buffer_snapshot);
8135        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8136            end.row -= 1;
8137        }
8138
8139        let buffer_start = map.prev_line_boundary(start).0;
8140        let buffer_end = map.next_line_boundary(end).0;
8141        buffer_start.row..buffer_end.row + 1
8142    }
8143}
8144
8145impl<T: InvalidationRegion> InvalidationStack<T> {
8146    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8147    where
8148        S: Clone + ToOffset,
8149    {
8150        while let Some(region) = self.last() {
8151            let all_selections_inside_invalidation_ranges =
8152                if selections.len() == region.ranges().len() {
8153                    selections
8154                        .iter()
8155                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8156                        .all(|(selection, invalidation_range)| {
8157                            let head = selection.head().to_offset(buffer);
8158                            invalidation_range.start <= head && invalidation_range.end >= head
8159                        })
8160                } else {
8161                    false
8162                };
8163
8164            if all_selections_inside_invalidation_ranges {
8165                break;
8166            } else {
8167                self.pop();
8168            }
8169        }
8170    }
8171}
8172
8173impl<T> Default for InvalidationStack<T> {
8174    fn default() -> Self {
8175        Self(Default::default())
8176    }
8177}
8178
8179impl<T> Deref for InvalidationStack<T> {
8180    type Target = Vec<T>;
8181
8182    fn deref(&self) -> &Self::Target {
8183        &self.0
8184    }
8185}
8186
8187impl<T> DerefMut for InvalidationStack<T> {
8188    fn deref_mut(&mut self) -> &mut Self::Target {
8189        &mut self.0
8190    }
8191}
8192
8193impl InvalidationRegion for SnippetState {
8194    fn ranges(&self) -> &[Range<Anchor>] {
8195        &self.ranges[self.active_index]
8196    }
8197}
8198
8199impl Deref for EditorStyle {
8200    type Target = theme::Editor;
8201
8202    fn deref(&self) -> &Self::Target {
8203        &self.theme
8204    }
8205}
8206
8207pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8208    let mut highlighted_lines = Vec::new();
8209
8210    for (index, line) in diagnostic.message.lines().enumerate() {
8211        let line = match &diagnostic.source {
8212            Some(source) if index == 0 => {
8213                let source_highlight = Vec::from_iter(0..source.len());
8214                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8215            }
8216
8217            _ => highlight_diagnostic_message(Vec::new(), line),
8218        };
8219        highlighted_lines.push(line);
8220    }
8221    let message = diagnostic.message;
8222    Arc::new(move |cx: &mut BlockContext| {
8223        let message = message.clone();
8224        let settings = settings::get::<ThemeSettings>(cx);
8225        let tooltip_style = settings.theme.tooltip.clone();
8226        let theme = &settings.theme.editor;
8227        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8228        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8229        let anchor_x = cx.anchor_x;
8230        enum BlockContextToolip {}
8231        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
8232            Flex::column()
8233                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8234                    Label::new(
8235                        line.clone(),
8236                        style.message.clone().with_font_size(font_size),
8237                    )
8238                    .with_highlights(highlights.clone())
8239                    .contained()
8240                    .with_margin_left(anchor_x)
8241                }))
8242                .aligned()
8243                .left()
8244                .into_any()
8245        })
8246        .with_cursor_style(CursorStyle::PointingHand)
8247        .on_click(MouseButton::Left, move |_, _, cx| {
8248            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8249        })
8250        // We really need to rethink this ID system...
8251        .with_tooltip::<BlockContextToolip>(
8252            cx.block_id,
8253            "Copy diagnostic message".to_string(),
8254            None,
8255            tooltip_style,
8256            cx,
8257        )
8258        .into_any()
8259    })
8260}
8261
8262pub fn highlight_diagnostic_message(
8263    initial_highlights: Vec<usize>,
8264    message: &str,
8265) -> (String, Vec<usize>) {
8266    let mut message_without_backticks = String::new();
8267    let mut prev_offset = 0;
8268    let mut inside_block = false;
8269    let mut highlights = initial_highlights;
8270    for (match_ix, (offset, _)) in message
8271        .match_indices('`')
8272        .chain([(message.len(), "")])
8273        .enumerate()
8274    {
8275        message_without_backticks.push_str(&message[prev_offset..offset]);
8276        if inside_block {
8277            highlights.extend(prev_offset - match_ix..offset - match_ix);
8278        }
8279
8280        inside_block = !inside_block;
8281        prev_offset = offset + 1;
8282    }
8283
8284    (message_without_backticks, highlights)
8285}
8286
8287pub fn diagnostic_style(
8288    severity: DiagnosticSeverity,
8289    valid: bool,
8290    theme: &theme::Editor,
8291) -> DiagnosticStyle {
8292    match (severity, valid) {
8293        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8294        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8295        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8296        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8297        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8298        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8299        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8300        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8301        _ => theme.invalid_hint_diagnostic.clone(),
8302    }
8303}
8304
8305pub fn combine_syntax_and_fuzzy_match_highlights(
8306    text: &str,
8307    default_style: HighlightStyle,
8308    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8309    match_indices: &[usize],
8310) -> Vec<(Range<usize>, HighlightStyle)> {
8311    let mut result = Vec::new();
8312    let mut match_indices = match_indices.iter().copied().peekable();
8313
8314    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8315    {
8316        syntax_highlight.weight = None;
8317
8318        // Add highlights for any fuzzy match characters before the next
8319        // syntax highlight range.
8320        while let Some(&match_index) = match_indices.peek() {
8321            if match_index >= range.start {
8322                break;
8323            }
8324            match_indices.next();
8325            let end_index = char_ix_after(match_index, text);
8326            let mut match_style = default_style;
8327            match_style.weight = Some(fonts::Weight::BOLD);
8328            result.push((match_index..end_index, match_style));
8329        }
8330
8331        if range.start == usize::MAX {
8332            break;
8333        }
8334
8335        // Add highlights for any fuzzy match characters within the
8336        // syntax highlight range.
8337        let mut offset = range.start;
8338        while let Some(&match_index) = match_indices.peek() {
8339            if match_index >= range.end {
8340                break;
8341            }
8342
8343            match_indices.next();
8344            if match_index > offset {
8345                result.push((offset..match_index, syntax_highlight));
8346            }
8347
8348            let mut end_index = char_ix_after(match_index, text);
8349            while let Some(&next_match_index) = match_indices.peek() {
8350                if next_match_index == end_index && next_match_index < range.end {
8351                    end_index = char_ix_after(next_match_index, text);
8352                    match_indices.next();
8353                } else {
8354                    break;
8355                }
8356            }
8357
8358            let mut match_style = syntax_highlight;
8359            match_style.weight = Some(fonts::Weight::BOLD);
8360            result.push((match_index..end_index, match_style));
8361            offset = end_index;
8362        }
8363
8364        if offset < range.end {
8365            result.push((offset..range.end, syntax_highlight));
8366        }
8367    }
8368
8369    fn char_ix_after(ix: usize, text: &str) -> usize {
8370        ix + text[ix..].chars().next().unwrap().len_utf8()
8371    }
8372
8373    result
8374}
8375
8376pub fn styled_runs_for_code_label<'a>(
8377    label: &'a CodeLabel,
8378    syntax_theme: &'a theme::SyntaxTheme,
8379) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8380    let fade_out = HighlightStyle {
8381        fade_out: Some(0.35),
8382        ..Default::default()
8383    };
8384
8385    let mut prev_end = label.filter_range.end;
8386    label
8387        .runs
8388        .iter()
8389        .enumerate()
8390        .flat_map(move |(ix, (range, highlight_id))| {
8391            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8392                style
8393            } else {
8394                return Default::default();
8395            };
8396            let mut muted_style = style;
8397            muted_style.highlight(fade_out);
8398
8399            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8400            if range.start >= label.filter_range.end {
8401                if range.start > prev_end {
8402                    runs.push((prev_end..range.start, fade_out));
8403                }
8404                runs.push((range.clone(), muted_style));
8405            } else if range.end <= label.filter_range.end {
8406                runs.push((range.clone(), style));
8407            } else {
8408                runs.push((range.start..label.filter_range.end, style));
8409                runs.push((label.filter_range.end..range.end, muted_style));
8410            }
8411            prev_end = cmp::max(prev_end, range.end);
8412
8413            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8414                runs.push((prev_end..label.text.len(), fade_out));
8415            }
8416
8417            runs
8418        })
8419}
8420
8421pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8422    let mut index = 0;
8423    let mut codepoints = text.char_indices().peekable();
8424
8425    std::iter::from_fn(move || {
8426        let start_index = index;
8427        while let Some((new_index, codepoint)) = codepoints.next() {
8428            index = new_index + codepoint.len_utf8();
8429            let current_upper = codepoint.is_uppercase();
8430            let next_upper = codepoints
8431                .peek()
8432                .map(|(_, c)| c.is_uppercase())
8433                .unwrap_or(false);
8434
8435            if !current_upper && next_upper {
8436                return Some(&text[start_index..index]);
8437            }
8438        }
8439
8440        index = text.len();
8441        if start_index < text.len() {
8442            return Some(&text[start_index..]);
8443        }
8444        None
8445    })
8446    .flat_map(|word| word.split_inclusive('_'))
8447}
8448
8449trait RangeToAnchorExt {
8450    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8451}
8452
8453impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8454    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8455        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8456    }
8457}