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