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