editor.rs

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