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