editor.rs

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