editor.rs

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