editor.rs

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