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 cursor_position = self.selections.newest::<Point>(cx).head();
3959        let snapshot = self.buffer.read(cx).snapshot(cx);
3960        let end_of_line = Point::new(cursor_position.row, snapshot.line_len(cursor_position.row));
3961        let start_of_next_line = end_of_line + Point::new(1, 0);
3962
3963        self.buffer.update(cx, |buffer, cx| {
3964            buffer.edit([(end_of_line..start_of_next_line, " ")], None, cx)
3965        });
3966    }
3967
3968    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3969        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3970        let buffer = &display_map.buffer_snapshot;
3971        let selections = self.selections.all::<Point>(cx);
3972
3973        let mut edits = Vec::new();
3974        let mut selections_iter = selections.iter().peekable();
3975        while let Some(selection) = selections_iter.next() {
3976            // Avoid duplicating the same lines twice.
3977            let mut rows = selection.spanned_rows(false, &display_map);
3978
3979            while let Some(next_selection) = selections_iter.peek() {
3980                let next_rows = next_selection.spanned_rows(false, &display_map);
3981                if next_rows.start < rows.end {
3982                    rows.end = next_rows.end;
3983                    selections_iter.next().unwrap();
3984                } else {
3985                    break;
3986                }
3987            }
3988
3989            // Copy the text from the selected row region and splice it at the start of the region.
3990            let start = Point::new(rows.start, 0);
3991            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3992            let text = buffer
3993                .text_for_range(start..end)
3994                .chain(Some("\n"))
3995                .collect::<String>();
3996            edits.push((start..start, text));
3997        }
3998
3999        self.transact(cx, |this, cx| {
4000            this.buffer.update(cx, |buffer, cx| {
4001                buffer.edit(edits, None, cx);
4002            });
4003
4004            this.request_autoscroll(Autoscroll::fit(), cx);
4005        });
4006    }
4007
4008    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4009        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4010        let buffer = self.buffer.read(cx).snapshot(cx);
4011
4012        let mut edits = Vec::new();
4013        let mut unfold_ranges = Vec::new();
4014        let mut refold_ranges = Vec::new();
4015
4016        let selections = self.selections.all::<Point>(cx);
4017        let mut selections = selections.iter().peekable();
4018        let mut contiguous_row_selections = Vec::new();
4019        let mut new_selections = Vec::new();
4020
4021        while let Some(selection) = selections.next() {
4022            // Find all the selections that span a contiguous row range
4023            let (start_row, end_row) = consume_contiguous_rows(
4024                &mut contiguous_row_selections,
4025                selection,
4026                &display_map,
4027                &mut selections,
4028            );
4029
4030            // Move the text spanned by the row range to be before the line preceding the row range
4031            if start_row > 0 {
4032                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4033                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4034                let insertion_point = display_map
4035                    .prev_line_boundary(Point::new(start_row - 1, 0))
4036                    .0;
4037
4038                // Don't move lines across excerpts
4039                if buffer
4040                    .excerpt_boundaries_in_range((
4041                        Bound::Excluded(insertion_point),
4042                        Bound::Included(range_to_move.end),
4043                    ))
4044                    .next()
4045                    .is_none()
4046                {
4047                    let text = buffer
4048                        .text_for_range(range_to_move.clone())
4049                        .flat_map(|s| s.chars())
4050                        .skip(1)
4051                        .chain(['\n'])
4052                        .collect::<String>();
4053
4054                    edits.push((
4055                        buffer.anchor_after(range_to_move.start)
4056                            ..buffer.anchor_before(range_to_move.end),
4057                        String::new(),
4058                    ));
4059                    let insertion_anchor = buffer.anchor_after(insertion_point);
4060                    edits.push((insertion_anchor..insertion_anchor, text));
4061
4062                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4063
4064                    // Move selections up
4065                    new_selections.extend(contiguous_row_selections.drain(..).map(
4066                        |mut selection| {
4067                            selection.start.row -= row_delta;
4068                            selection.end.row -= row_delta;
4069                            selection
4070                        },
4071                    ));
4072
4073                    // Move folds up
4074                    unfold_ranges.push(range_to_move.clone());
4075                    for fold in display_map.folds_in_range(
4076                        buffer.anchor_before(range_to_move.start)
4077                            ..buffer.anchor_after(range_to_move.end),
4078                    ) {
4079                        let mut start = fold.start.to_point(&buffer);
4080                        let mut end = fold.end.to_point(&buffer);
4081                        start.row -= row_delta;
4082                        end.row -= row_delta;
4083                        refold_ranges.push(start..end);
4084                    }
4085                }
4086            }
4087
4088            // If we didn't move line(s), preserve the existing selections
4089            new_selections.append(&mut contiguous_row_selections);
4090        }
4091
4092        self.transact(cx, |this, cx| {
4093            this.unfold_ranges(unfold_ranges, true, true, cx);
4094            this.buffer.update(cx, |buffer, cx| {
4095                for (range, text) in edits {
4096                    buffer.edit([(range, text)], None, cx);
4097                }
4098            });
4099            this.fold_ranges(refold_ranges, true, cx);
4100            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4101                s.select(new_selections);
4102            })
4103        });
4104    }
4105
4106    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4107        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4108        let buffer = self.buffer.read(cx).snapshot(cx);
4109
4110        let mut edits = Vec::new();
4111        let mut unfold_ranges = Vec::new();
4112        let mut refold_ranges = Vec::new();
4113
4114        let selections = self.selections.all::<Point>(cx);
4115        let mut selections = selections.iter().peekable();
4116        let mut contiguous_row_selections = Vec::new();
4117        let mut new_selections = Vec::new();
4118
4119        while let Some(selection) = selections.next() {
4120            // Find all the selections that span a contiguous row range
4121            let (start_row, end_row) = consume_contiguous_rows(
4122                &mut contiguous_row_selections,
4123                selection,
4124                &display_map,
4125                &mut selections,
4126            );
4127
4128            // Move the text spanned by the row range to be after the last line of the row range
4129            if end_row <= buffer.max_point().row {
4130                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4131                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4132
4133                // Don't move lines across excerpt boundaries
4134                if buffer
4135                    .excerpt_boundaries_in_range((
4136                        Bound::Excluded(range_to_move.start),
4137                        Bound::Included(insertion_point),
4138                    ))
4139                    .next()
4140                    .is_none()
4141                {
4142                    let mut text = String::from("\n");
4143                    text.extend(buffer.text_for_range(range_to_move.clone()));
4144                    text.pop(); // Drop trailing newline
4145                    edits.push((
4146                        buffer.anchor_after(range_to_move.start)
4147                            ..buffer.anchor_before(range_to_move.end),
4148                        String::new(),
4149                    ));
4150                    let insertion_anchor = buffer.anchor_after(insertion_point);
4151                    edits.push((insertion_anchor..insertion_anchor, text));
4152
4153                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4154
4155                    // Move selections down
4156                    new_selections.extend(contiguous_row_selections.drain(..).map(
4157                        |mut selection| {
4158                            selection.start.row += row_delta;
4159                            selection.end.row += row_delta;
4160                            selection
4161                        },
4162                    ));
4163
4164                    // Move folds down
4165                    unfold_ranges.push(range_to_move.clone());
4166                    for fold in display_map.folds_in_range(
4167                        buffer.anchor_before(range_to_move.start)
4168                            ..buffer.anchor_after(range_to_move.end),
4169                    ) {
4170                        let mut start = fold.start.to_point(&buffer);
4171                        let mut end = fold.end.to_point(&buffer);
4172                        start.row += row_delta;
4173                        end.row += row_delta;
4174                        refold_ranges.push(start..end);
4175                    }
4176                }
4177            }
4178
4179            // If we didn't move line(s), preserve the existing selections
4180            new_selections.append(&mut contiguous_row_selections);
4181        }
4182
4183        self.transact(cx, |this, cx| {
4184            this.unfold_ranges(unfold_ranges, true, true, cx);
4185            this.buffer.update(cx, |buffer, cx| {
4186                for (range, text) in edits {
4187                    buffer.edit([(range, text)], None, cx);
4188                }
4189            });
4190            this.fold_ranges(refold_ranges, true, cx);
4191            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4192        });
4193    }
4194
4195    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4196        self.transact(cx, |this, cx| {
4197            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4198                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4199                let line_mode = s.line_mode;
4200                s.move_with(|display_map, selection| {
4201                    if !selection.is_empty() || line_mode {
4202                        return;
4203                    }
4204
4205                    let mut head = selection.head();
4206                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4207                    if head.column() == display_map.line_len(head.row()) {
4208                        transpose_offset = display_map
4209                            .buffer_snapshot
4210                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4211                    }
4212
4213                    if transpose_offset == 0 {
4214                        return;
4215                    }
4216
4217                    *head.column_mut() += 1;
4218                    head = display_map.clip_point(head, Bias::Right);
4219                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4220
4221                    let transpose_start = display_map
4222                        .buffer_snapshot
4223                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4224                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4225                        let transpose_end = display_map
4226                            .buffer_snapshot
4227                            .clip_offset(transpose_offset + 1, Bias::Right);
4228                        if let Some(ch) =
4229                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4230                        {
4231                            edits.push((transpose_start..transpose_offset, String::new()));
4232                            edits.push((transpose_end..transpose_end, ch.to_string()));
4233                        }
4234                    }
4235                });
4236                edits
4237            });
4238            this.buffer
4239                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4240            let selections = this.selections.all::<usize>(cx);
4241            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4242                s.select(selections);
4243            });
4244        });
4245    }
4246
4247    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4248        let mut text = String::new();
4249        let buffer = self.buffer.read(cx).snapshot(cx);
4250        let mut selections = self.selections.all::<Point>(cx);
4251        let mut clipboard_selections = Vec::with_capacity(selections.len());
4252        {
4253            let max_point = buffer.max_point();
4254            for selection in &mut selections {
4255                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4256                if is_entire_line {
4257                    selection.start = Point::new(selection.start.row, 0);
4258                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4259                    selection.goal = SelectionGoal::None;
4260                }
4261                let mut len = 0;
4262                for chunk in buffer.text_for_range(selection.start..selection.end) {
4263                    text.push_str(chunk);
4264                    len += chunk.len();
4265                }
4266                clipboard_selections.push(ClipboardSelection {
4267                    len,
4268                    is_entire_line,
4269                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4270                });
4271            }
4272        }
4273
4274        self.transact(cx, |this, cx| {
4275            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4276                s.select(selections);
4277            });
4278            this.insert("", cx);
4279            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4280        });
4281    }
4282
4283    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4284        let selections = self.selections.all::<Point>(cx);
4285        let buffer = self.buffer.read(cx).read(cx);
4286        let mut text = String::new();
4287
4288        let mut clipboard_selections = Vec::with_capacity(selections.len());
4289        {
4290            let max_point = buffer.max_point();
4291            for selection in selections.iter() {
4292                let mut start = selection.start;
4293                let mut end = selection.end;
4294                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4295                if is_entire_line {
4296                    start = Point::new(start.row, 0);
4297                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4298                }
4299                let mut len = 0;
4300                for chunk in buffer.text_for_range(start..end) {
4301                    text.push_str(chunk);
4302                    len += chunk.len();
4303                }
4304                clipboard_selections.push(ClipboardSelection {
4305                    len,
4306                    is_entire_line,
4307                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4308                });
4309            }
4310        }
4311
4312        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4313    }
4314
4315    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4316        self.transact(cx, |this, cx| {
4317            if let Some(item) = cx.read_from_clipboard() {
4318                let mut clipboard_text = Cow::Borrowed(item.text());
4319                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4320                    let old_selections = this.selections.all::<usize>(cx);
4321                    let all_selections_were_entire_line =
4322                        clipboard_selections.iter().all(|s| s.is_entire_line);
4323                    let first_selection_indent_column =
4324                        clipboard_selections.first().map(|s| s.first_line_indent);
4325                    if clipboard_selections.len() != old_selections.len() {
4326                        let mut newline_separated_text = String::new();
4327                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4328                        let mut ix = 0;
4329                        while let Some(clipboard_selection) = clipboard_selections.next() {
4330                            newline_separated_text
4331                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4332                            ix += clipboard_selection.len;
4333                            if clipboard_selections.peek().is_some() {
4334                                newline_separated_text.push('\n');
4335                            }
4336                        }
4337                        clipboard_text = Cow::Owned(newline_separated_text);
4338                    }
4339
4340                    this.buffer.update(cx, |buffer, cx| {
4341                        let snapshot = buffer.read(cx);
4342                        let mut start_offset = 0;
4343                        let mut edits = Vec::new();
4344                        let mut original_indent_columns = Vec::new();
4345                        let line_mode = this.selections.line_mode;
4346                        for (ix, selection) in old_selections.iter().enumerate() {
4347                            let to_insert;
4348                            let entire_line;
4349                            let original_indent_column;
4350                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4351                                let end_offset = start_offset + clipboard_selection.len;
4352                                to_insert = &clipboard_text[start_offset..end_offset];
4353                                entire_line = clipboard_selection.is_entire_line;
4354                                start_offset = end_offset;
4355                                original_indent_column =
4356                                    Some(clipboard_selection.first_line_indent);
4357                            } else {
4358                                to_insert = clipboard_text.as_str();
4359                                entire_line = all_selections_were_entire_line;
4360                                original_indent_column = first_selection_indent_column
4361                            }
4362
4363                            // If the corresponding selection was empty when this slice of the
4364                            // clipboard text was written, then the entire line containing the
4365                            // selection was copied. If this selection is also currently empty,
4366                            // then paste the line before the current line of the buffer.
4367                            let range = if selection.is_empty() && !line_mode && entire_line {
4368                                let column = selection.start.to_point(&snapshot).column as usize;
4369                                let line_start = selection.start - column;
4370                                line_start..line_start
4371                            } else {
4372                                selection.range()
4373                            };
4374
4375                            edits.push((range, to_insert));
4376                            original_indent_columns.extend(original_indent_column);
4377                        }
4378                        drop(snapshot);
4379
4380                        buffer.edit(
4381                            edits,
4382                            Some(AutoindentMode::Block {
4383                                original_indent_columns,
4384                            }),
4385                            cx,
4386                        );
4387                    });
4388
4389                    let selections = this.selections.all::<usize>(cx);
4390                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4391                } else {
4392                    this.insert(&clipboard_text, cx);
4393                }
4394            }
4395        });
4396    }
4397
4398    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4399        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4400            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4401                self.change_selections(None, cx, |s| {
4402                    s.select_anchors(selections.to_vec());
4403                });
4404            }
4405            self.request_autoscroll(Autoscroll::fit(), cx);
4406            self.unmark_text(cx);
4407            self.refresh_copilot_suggestions(true, cx);
4408            cx.emit(Event::Edited);
4409        }
4410    }
4411
4412    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4413        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4414            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4415            {
4416                self.change_selections(None, cx, |s| {
4417                    s.select_anchors(selections.to_vec());
4418                });
4419            }
4420            self.request_autoscroll(Autoscroll::fit(), cx);
4421            self.unmark_text(cx);
4422            self.refresh_copilot_suggestions(true, cx);
4423            cx.emit(Event::Edited);
4424        }
4425    }
4426
4427    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4428        self.buffer
4429            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4430    }
4431
4432    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4433        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4434            let line_mode = s.line_mode;
4435            s.move_with(|map, selection| {
4436                let cursor = if selection.is_empty() && !line_mode {
4437                    movement::left(map, selection.start)
4438                } else {
4439                    selection.start
4440                };
4441                selection.collapse_to(cursor, SelectionGoal::None);
4442            });
4443        })
4444    }
4445
4446    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4447        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4448            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4449        })
4450    }
4451
4452    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4453        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4454            let line_mode = s.line_mode;
4455            s.move_with(|map, selection| {
4456                let cursor = if selection.is_empty() && !line_mode {
4457                    movement::right(map, selection.end)
4458                } else {
4459                    selection.end
4460                };
4461                selection.collapse_to(cursor, SelectionGoal::None)
4462            });
4463        })
4464    }
4465
4466    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4467        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4468            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4469        })
4470    }
4471
4472    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4473        if self.take_rename(true, cx).is_some() {
4474            return;
4475        }
4476
4477        if let Some(context_menu) = self.context_menu.as_mut() {
4478            if context_menu.select_prev(cx) {
4479                return;
4480            }
4481        }
4482
4483        if matches!(self.mode, EditorMode::SingleLine) {
4484            cx.propagate_action();
4485            return;
4486        }
4487
4488        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4489            let line_mode = s.line_mode;
4490            s.move_with(|map, selection| {
4491                if !selection.is_empty() && !line_mode {
4492                    selection.goal = SelectionGoal::None;
4493                }
4494                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4495                selection.collapse_to(cursor, goal);
4496            });
4497        })
4498    }
4499
4500    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4501        if self.take_rename(true, cx).is_some() {
4502            return;
4503        }
4504
4505        if self
4506            .context_menu
4507            .as_mut()
4508            .map(|menu| menu.select_first(cx))
4509            .unwrap_or(false)
4510        {
4511            return;
4512        }
4513
4514        if matches!(self.mode, EditorMode::SingleLine) {
4515            cx.propagate_action();
4516            return;
4517        }
4518
4519        let row_count = if let Some(row_count) = self.visible_line_count() {
4520            row_count as u32 - 1
4521        } else {
4522            return;
4523        };
4524
4525        let autoscroll = if action.center_cursor {
4526            Autoscroll::center()
4527        } else {
4528            Autoscroll::fit()
4529        };
4530
4531        self.change_selections(Some(autoscroll), cx, |s| {
4532            let line_mode = s.line_mode;
4533            s.move_with(|map, selection| {
4534                if !selection.is_empty() && !line_mode {
4535                    selection.goal = SelectionGoal::None;
4536                }
4537                let (cursor, goal) =
4538                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4539                selection.collapse_to(cursor, goal);
4540            });
4541        });
4542    }
4543
4544    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4545        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4546            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4547        })
4548    }
4549
4550    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4551        self.take_rename(true, cx);
4552
4553        if let Some(context_menu) = self.context_menu.as_mut() {
4554            if context_menu.select_next(cx) {
4555                return;
4556            }
4557        }
4558
4559        if self.mode == EditorMode::SingleLine {
4560            cx.propagate_action();
4561            return;
4562        }
4563
4564        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4565            let line_mode = s.line_mode;
4566            s.move_with(|map, selection| {
4567                if !selection.is_empty() && !line_mode {
4568                    selection.goal = SelectionGoal::None;
4569                }
4570                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4571                selection.collapse_to(cursor, goal);
4572            });
4573        });
4574    }
4575
4576    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4577        if self.take_rename(true, cx).is_some() {
4578            return;
4579        }
4580
4581        if self
4582            .context_menu
4583            .as_mut()
4584            .map(|menu| menu.select_last(cx))
4585            .unwrap_or(false)
4586        {
4587            return;
4588        }
4589
4590        if matches!(self.mode, EditorMode::SingleLine) {
4591            cx.propagate_action();
4592            return;
4593        }
4594
4595        let row_count = if let Some(row_count) = self.visible_line_count() {
4596            row_count as u32 - 1
4597        } else {
4598            return;
4599        };
4600
4601        let autoscroll = if action.center_cursor {
4602            Autoscroll::center()
4603        } else {
4604            Autoscroll::fit()
4605        };
4606
4607        self.change_selections(Some(autoscroll), cx, |s| {
4608            let line_mode = s.line_mode;
4609            s.move_with(|map, selection| {
4610                if !selection.is_empty() && !line_mode {
4611                    selection.goal = SelectionGoal::None;
4612                }
4613                let (cursor, goal) =
4614                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4615                selection.collapse_to(cursor, goal);
4616            });
4617        });
4618    }
4619
4620    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4621        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4622            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4623        });
4624    }
4625
4626    pub fn move_to_previous_word_start(
4627        &mut self,
4628        _: &MoveToPreviousWordStart,
4629        cx: &mut ViewContext<Self>,
4630    ) {
4631        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4632            s.move_cursors_with(|map, head, _| {
4633                (
4634                    movement::previous_word_start(map, head),
4635                    SelectionGoal::None,
4636                )
4637            });
4638        })
4639    }
4640
4641    pub fn move_to_previous_subword_start(
4642        &mut self,
4643        _: &MoveToPreviousSubwordStart,
4644        cx: &mut ViewContext<Self>,
4645    ) {
4646        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4647            s.move_cursors_with(|map, head, _| {
4648                (
4649                    movement::previous_subword_start(map, head),
4650                    SelectionGoal::None,
4651                )
4652            });
4653        })
4654    }
4655
4656    pub fn select_to_previous_word_start(
4657        &mut self,
4658        _: &SelectToPreviousWordStart,
4659        cx: &mut ViewContext<Self>,
4660    ) {
4661        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4662            s.move_heads_with(|map, head, _| {
4663                (
4664                    movement::previous_word_start(map, head),
4665                    SelectionGoal::None,
4666                )
4667            });
4668        })
4669    }
4670
4671    pub fn select_to_previous_subword_start(
4672        &mut self,
4673        _: &SelectToPreviousSubwordStart,
4674        cx: &mut ViewContext<Self>,
4675    ) {
4676        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4677            s.move_heads_with(|map, head, _| {
4678                (
4679                    movement::previous_subword_start(map, head),
4680                    SelectionGoal::None,
4681                )
4682            });
4683        })
4684    }
4685
4686    pub fn delete_to_previous_word_start(
4687        &mut self,
4688        _: &DeleteToPreviousWordStart,
4689        cx: &mut ViewContext<Self>,
4690    ) {
4691        self.transact(cx, |this, cx| {
4692            this.select_autoclose_pair(cx);
4693            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4694                let line_mode = s.line_mode;
4695                s.move_with(|map, selection| {
4696                    if selection.is_empty() && !line_mode {
4697                        let cursor = movement::previous_word_start(map, selection.head());
4698                        selection.set_head(cursor, SelectionGoal::None);
4699                    }
4700                });
4701            });
4702            this.insert("", cx);
4703        });
4704    }
4705
4706    pub fn delete_to_previous_subword_start(
4707        &mut self,
4708        _: &DeleteToPreviousSubwordStart,
4709        cx: &mut ViewContext<Self>,
4710    ) {
4711        self.transact(cx, |this, cx| {
4712            this.select_autoclose_pair(cx);
4713            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4714                let line_mode = s.line_mode;
4715                s.move_with(|map, selection| {
4716                    if selection.is_empty() && !line_mode {
4717                        let cursor = movement::previous_subword_start(map, selection.head());
4718                        selection.set_head(cursor, SelectionGoal::None);
4719                    }
4720                });
4721            });
4722            this.insert("", cx);
4723        });
4724    }
4725
4726    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4727        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4728            s.move_cursors_with(|map, head, _| {
4729                (movement::next_word_end(map, head), SelectionGoal::None)
4730            });
4731        })
4732    }
4733
4734    pub fn move_to_next_subword_end(
4735        &mut self,
4736        _: &MoveToNextSubwordEnd,
4737        cx: &mut ViewContext<Self>,
4738    ) {
4739        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4740            s.move_cursors_with(|map, head, _| {
4741                (movement::next_subword_end(map, head), SelectionGoal::None)
4742            });
4743        })
4744    }
4745
4746    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4747        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4748            s.move_heads_with(|map, head, _| {
4749                (movement::next_word_end(map, head), SelectionGoal::None)
4750            });
4751        })
4752    }
4753
4754    pub fn select_to_next_subword_end(
4755        &mut self,
4756        _: &SelectToNextSubwordEnd,
4757        cx: &mut ViewContext<Self>,
4758    ) {
4759        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4760            s.move_heads_with(|map, head, _| {
4761                (movement::next_subword_end(map, head), SelectionGoal::None)
4762            });
4763        })
4764    }
4765
4766    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4767        self.transact(cx, |this, cx| {
4768            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4769                let line_mode = s.line_mode;
4770                s.move_with(|map, selection| {
4771                    if selection.is_empty() && !line_mode {
4772                        let cursor = movement::next_word_end(map, selection.head());
4773                        selection.set_head(cursor, SelectionGoal::None);
4774                    }
4775                });
4776            });
4777            this.insert("", cx);
4778        });
4779    }
4780
4781    pub fn delete_to_next_subword_end(
4782        &mut self,
4783        _: &DeleteToNextSubwordEnd,
4784        cx: &mut ViewContext<Self>,
4785    ) {
4786        self.transact(cx, |this, cx| {
4787            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4788                s.move_with(|map, selection| {
4789                    if selection.is_empty() {
4790                        let cursor = movement::next_subword_end(map, selection.head());
4791                        selection.set_head(cursor, SelectionGoal::None);
4792                    }
4793                });
4794            });
4795            this.insert("", cx);
4796        });
4797    }
4798
4799    pub fn move_to_beginning_of_line(
4800        &mut self,
4801        _: &MoveToBeginningOfLine,
4802        cx: &mut ViewContext<Self>,
4803    ) {
4804        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4805            s.move_cursors_with(|map, head, _| {
4806                (
4807                    movement::indented_line_beginning(map, head, true),
4808                    SelectionGoal::None,
4809                )
4810            });
4811        })
4812    }
4813
4814    pub fn select_to_beginning_of_line(
4815        &mut self,
4816        action: &SelectToBeginningOfLine,
4817        cx: &mut ViewContext<Self>,
4818    ) {
4819        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4820            s.move_heads_with(|map, head, _| {
4821                (
4822                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4823                    SelectionGoal::None,
4824                )
4825            });
4826        });
4827    }
4828
4829    pub fn delete_to_beginning_of_line(
4830        &mut self,
4831        _: &DeleteToBeginningOfLine,
4832        cx: &mut ViewContext<Self>,
4833    ) {
4834        self.transact(cx, |this, cx| {
4835            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4836                s.move_with(|_, selection| {
4837                    selection.reversed = true;
4838                });
4839            });
4840
4841            this.select_to_beginning_of_line(
4842                &SelectToBeginningOfLine {
4843                    stop_at_soft_wraps: false,
4844                },
4845                cx,
4846            );
4847            this.backspace(&Backspace, cx);
4848        });
4849    }
4850
4851    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4852        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4853            s.move_cursors_with(|map, head, _| {
4854                (movement::line_end(map, head, true), SelectionGoal::None)
4855            });
4856        })
4857    }
4858
4859    pub fn select_to_end_of_line(
4860        &mut self,
4861        action: &SelectToEndOfLine,
4862        cx: &mut ViewContext<Self>,
4863    ) {
4864        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4865            s.move_heads_with(|map, head, _| {
4866                (
4867                    movement::line_end(map, head, action.stop_at_soft_wraps),
4868                    SelectionGoal::None,
4869                )
4870            });
4871        })
4872    }
4873
4874    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4875        self.transact(cx, |this, cx| {
4876            this.select_to_end_of_line(
4877                &SelectToEndOfLine {
4878                    stop_at_soft_wraps: false,
4879                },
4880                cx,
4881            );
4882            this.delete(&Delete, cx);
4883        });
4884    }
4885
4886    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4887        self.transact(cx, |this, cx| {
4888            this.select_to_end_of_line(
4889                &SelectToEndOfLine {
4890                    stop_at_soft_wraps: false,
4891                },
4892                cx,
4893            );
4894            this.cut(&Cut, cx);
4895        });
4896    }
4897
4898    pub fn move_to_start_of_paragraph(
4899        &mut self,
4900        _: &MoveToStartOfParagraph,
4901        cx: &mut ViewContext<Self>,
4902    ) {
4903        if matches!(self.mode, EditorMode::SingleLine) {
4904            cx.propagate_action();
4905            return;
4906        }
4907
4908        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4909            s.move_with(|map, selection| {
4910                selection.collapse_to(
4911                    movement::start_of_paragraph(map, selection.head()),
4912                    SelectionGoal::None,
4913                )
4914            });
4915        })
4916    }
4917
4918    pub fn move_to_end_of_paragraph(
4919        &mut self,
4920        _: &MoveToEndOfParagraph,
4921        cx: &mut ViewContext<Self>,
4922    ) {
4923        if matches!(self.mode, EditorMode::SingleLine) {
4924            cx.propagate_action();
4925            return;
4926        }
4927
4928        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4929            s.move_with(|map, selection| {
4930                selection.collapse_to(
4931                    movement::end_of_paragraph(map, selection.head()),
4932                    SelectionGoal::None,
4933                )
4934            });
4935        })
4936    }
4937
4938    pub fn select_to_start_of_paragraph(
4939        &mut self,
4940        _: &SelectToStartOfParagraph,
4941        cx: &mut ViewContext<Self>,
4942    ) {
4943        if matches!(self.mode, EditorMode::SingleLine) {
4944            cx.propagate_action();
4945            return;
4946        }
4947
4948        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4949            s.move_heads_with(|map, head, _| {
4950                (movement::start_of_paragraph(map, head), SelectionGoal::None)
4951            });
4952        })
4953    }
4954
4955    pub fn select_to_end_of_paragraph(
4956        &mut self,
4957        _: &SelectToEndOfParagraph,
4958        cx: &mut ViewContext<Self>,
4959    ) {
4960        if matches!(self.mode, EditorMode::SingleLine) {
4961            cx.propagate_action();
4962            return;
4963        }
4964
4965        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4966            s.move_heads_with(|map, head, _| {
4967                (movement::end_of_paragraph(map, head), SelectionGoal::None)
4968            });
4969        })
4970    }
4971
4972    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4973        if matches!(self.mode, EditorMode::SingleLine) {
4974            cx.propagate_action();
4975            return;
4976        }
4977
4978        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4979            s.select_ranges(vec![0..0]);
4980        });
4981    }
4982
4983    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4984        let mut selection = self.selections.last::<Point>(cx);
4985        selection.set_head(Point::zero(), SelectionGoal::None);
4986
4987        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4988            s.select(vec![selection]);
4989        });
4990    }
4991
4992    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4993        if matches!(self.mode, EditorMode::SingleLine) {
4994            cx.propagate_action();
4995            return;
4996        }
4997
4998        let cursor = self.buffer.read(cx).read(cx).len();
4999        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5000            s.select_ranges(vec![cursor..cursor])
5001        });
5002    }
5003
5004    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5005        self.nav_history = nav_history;
5006    }
5007
5008    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5009        self.nav_history.as_ref()
5010    }
5011
5012    fn push_to_nav_history(
5013        &mut self,
5014        cursor_anchor: Anchor,
5015        new_position: Option<Point>,
5016        cx: &mut ViewContext<Self>,
5017    ) {
5018        if let Some(nav_history) = self.nav_history.as_mut() {
5019            let buffer = self.buffer.read(cx).read(cx);
5020            let cursor_position = cursor_anchor.to_point(&buffer);
5021            let scroll_state = self.scroll_manager.anchor();
5022            let scroll_top_row = scroll_state.top_row(&buffer);
5023            drop(buffer);
5024
5025            if let Some(new_position) = new_position {
5026                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5027                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5028                    return;
5029                }
5030            }
5031
5032            nav_history.push(
5033                Some(NavigationData {
5034                    cursor_anchor,
5035                    cursor_position,
5036                    scroll_anchor: scroll_state,
5037                    scroll_top_row,
5038                }),
5039                cx,
5040            );
5041        }
5042    }
5043
5044    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5045        let buffer = self.buffer.read(cx).snapshot(cx);
5046        let mut selection = self.selections.first::<usize>(cx);
5047        selection.set_head(buffer.len(), SelectionGoal::None);
5048        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5049            s.select(vec![selection]);
5050        });
5051    }
5052
5053    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5054        let end = self.buffer.read(cx).read(cx).len();
5055        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5056            s.select_ranges(vec![0..end]);
5057        });
5058    }
5059
5060    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5061        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5062        let mut selections = self.selections.all::<Point>(cx);
5063        let max_point = display_map.buffer_snapshot.max_point();
5064        for selection in &mut selections {
5065            let rows = selection.spanned_rows(true, &display_map);
5066            selection.start = Point::new(rows.start, 0);
5067            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5068            selection.reversed = false;
5069        }
5070        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5071            s.select(selections);
5072        });
5073    }
5074
5075    pub fn split_selection_into_lines(
5076        &mut self,
5077        _: &SplitSelectionIntoLines,
5078        cx: &mut ViewContext<Self>,
5079    ) {
5080        let mut to_unfold = Vec::new();
5081        let mut new_selection_ranges = Vec::new();
5082        {
5083            let selections = self.selections.all::<Point>(cx);
5084            let buffer = self.buffer.read(cx).read(cx);
5085            for selection in selections {
5086                for row in selection.start.row..selection.end.row {
5087                    let cursor = Point::new(row, buffer.line_len(row));
5088                    new_selection_ranges.push(cursor..cursor);
5089                }
5090                new_selection_ranges.push(selection.end..selection.end);
5091                to_unfold.push(selection.start..selection.end);
5092            }
5093        }
5094        self.unfold_ranges(to_unfold, true, true, cx);
5095        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5096            s.select_ranges(new_selection_ranges);
5097        });
5098    }
5099
5100    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5101        self.add_selection(true, cx);
5102    }
5103
5104    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5105        self.add_selection(false, cx);
5106    }
5107
5108    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5109        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5110        let mut selections = self.selections.all::<Point>(cx);
5111        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5112            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5113            let range = oldest_selection.display_range(&display_map).sorted();
5114            let columns = cmp::min(range.start.column(), range.end.column())
5115                ..cmp::max(range.start.column(), range.end.column());
5116
5117            selections.clear();
5118            let mut stack = Vec::new();
5119            for row in range.start.row()..=range.end.row() {
5120                if let Some(selection) = self.selections.build_columnar_selection(
5121                    &display_map,
5122                    row,
5123                    &columns,
5124                    oldest_selection.reversed,
5125                ) {
5126                    stack.push(selection.id);
5127                    selections.push(selection);
5128                }
5129            }
5130
5131            if above {
5132                stack.reverse();
5133            }
5134
5135            AddSelectionsState { above, stack }
5136        });
5137
5138        let last_added_selection = *state.stack.last().unwrap();
5139        let mut new_selections = Vec::new();
5140        if above == state.above {
5141            let end_row = if above {
5142                0
5143            } else {
5144                display_map.max_point().row()
5145            };
5146
5147            'outer: for selection in selections {
5148                if selection.id == last_added_selection {
5149                    let range = selection.display_range(&display_map).sorted();
5150                    debug_assert_eq!(range.start.row(), range.end.row());
5151                    let mut row = range.start.row();
5152                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5153                    {
5154                        start..end
5155                    } else {
5156                        cmp::min(range.start.column(), range.end.column())
5157                            ..cmp::max(range.start.column(), range.end.column())
5158                    };
5159
5160                    while row != end_row {
5161                        if above {
5162                            row -= 1;
5163                        } else {
5164                            row += 1;
5165                        }
5166
5167                        if let Some(new_selection) = self.selections.build_columnar_selection(
5168                            &display_map,
5169                            row,
5170                            &columns,
5171                            selection.reversed,
5172                        ) {
5173                            state.stack.push(new_selection.id);
5174                            if above {
5175                                new_selections.push(new_selection);
5176                                new_selections.push(selection);
5177                            } else {
5178                                new_selections.push(selection);
5179                                new_selections.push(new_selection);
5180                            }
5181
5182                            continue 'outer;
5183                        }
5184                    }
5185                }
5186
5187                new_selections.push(selection);
5188            }
5189        } else {
5190            new_selections = selections;
5191            new_selections.retain(|s| s.id != last_added_selection);
5192            state.stack.pop();
5193        }
5194
5195        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5196            s.select(new_selections);
5197        });
5198        if state.stack.len() > 1 {
5199            self.add_selections_state = Some(state);
5200        }
5201    }
5202
5203    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5204        self.push_to_selection_history();
5205        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5206        let buffer = &display_map.buffer_snapshot;
5207        let mut selections = self.selections.all::<usize>(cx);
5208        if let Some(mut select_next_state) = self.select_next_state.take() {
5209            let query = &select_next_state.query;
5210            if !select_next_state.done {
5211                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5212                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5213                let mut next_selected_range = None;
5214
5215                let bytes_after_last_selection =
5216                    buffer.bytes_in_range(last_selection.end..buffer.len());
5217                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5218                let query_matches = query
5219                    .stream_find_iter(bytes_after_last_selection)
5220                    .map(|result| (last_selection.end, result))
5221                    .chain(
5222                        query
5223                            .stream_find_iter(bytes_before_first_selection)
5224                            .map(|result| (0, result)),
5225                    );
5226                for (start_offset, query_match) in query_matches {
5227                    let query_match = query_match.unwrap(); // can only fail due to I/O
5228                    let offset_range =
5229                        start_offset + query_match.start()..start_offset + query_match.end();
5230                    let display_range = offset_range.start.to_display_point(&display_map)
5231                        ..offset_range.end.to_display_point(&display_map);
5232
5233                    if !select_next_state.wordwise
5234                        || (!movement::is_inside_word(&display_map, display_range.start)
5235                            && !movement::is_inside_word(&display_map, display_range.end))
5236                    {
5237                        next_selected_range = Some(offset_range);
5238                        break;
5239                    }
5240                }
5241
5242                if let Some(next_selected_range) = next_selected_range {
5243                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5244                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5245                        if action.replace_newest {
5246                            s.delete(s.newest_anchor().id);
5247                        }
5248                        s.insert_range(next_selected_range);
5249                    });
5250                } else {
5251                    select_next_state.done = true;
5252                }
5253            }
5254
5255            self.select_next_state = Some(select_next_state);
5256        } else if selections.len() == 1 {
5257            let selection = selections.last_mut().unwrap();
5258            if selection.start == selection.end {
5259                let word_range = movement::surrounding_word(
5260                    &display_map,
5261                    selection.start.to_display_point(&display_map),
5262                );
5263                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5264                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5265                selection.goal = SelectionGoal::None;
5266                selection.reversed = false;
5267
5268                let query = buffer
5269                    .text_for_range(selection.start..selection.end)
5270                    .collect::<String>();
5271                let select_state = SelectNextState {
5272                    query: AhoCorasick::new_auto_configured(&[query]),
5273                    wordwise: true,
5274                    done: false,
5275                };
5276                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5277                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5278                    s.select(selections);
5279                });
5280                self.select_next_state = Some(select_state);
5281            } else {
5282                let query = buffer
5283                    .text_for_range(selection.start..selection.end)
5284                    .collect::<String>();
5285                self.select_next_state = Some(SelectNextState {
5286                    query: AhoCorasick::new_auto_configured(&[query]),
5287                    wordwise: false,
5288                    done: false,
5289                });
5290                self.select_next(action, cx);
5291            }
5292        }
5293    }
5294
5295    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5296        self.push_to_selection_history();
5297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5298        let buffer = &display_map.buffer_snapshot;
5299        let mut selections = self.selections.all::<usize>(cx);
5300        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5301            let query = &select_prev_state.query;
5302            if !select_prev_state.done {
5303                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5304                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5305                let mut next_selected_range = None;
5306                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5307                let bytes_before_last_selection =
5308                    buffer.reversed_bytes_in_range(0..last_selection.start);
5309                let bytes_after_first_selection =
5310                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5311                let query_matches = query
5312                    .stream_find_iter(bytes_before_last_selection)
5313                    .map(|result| (last_selection.start, result))
5314                    .chain(
5315                        query
5316                            .stream_find_iter(bytes_after_first_selection)
5317                            .map(|result| (buffer.len(), result)),
5318                    );
5319                for (end_offset, query_match) in query_matches {
5320                    let query_match = query_match.unwrap(); // can only fail due to I/O
5321                    let offset_range =
5322                        end_offset - query_match.end()..end_offset - query_match.start();
5323                    let display_range = offset_range.start.to_display_point(&display_map)
5324                        ..offset_range.end.to_display_point(&display_map);
5325
5326                    if !select_prev_state.wordwise
5327                        || (!movement::is_inside_word(&display_map, display_range.start)
5328                            && !movement::is_inside_word(&display_map, display_range.end))
5329                    {
5330                        next_selected_range = Some(offset_range);
5331                        break;
5332                    }
5333                }
5334
5335                if let Some(next_selected_range) = next_selected_range {
5336                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5337                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5338                        if action.replace_newest {
5339                            s.delete(s.newest_anchor().id);
5340                        }
5341                        s.insert_range(next_selected_range);
5342                    });
5343                } else {
5344                    select_prev_state.done = true;
5345                }
5346            }
5347
5348            self.select_prev_state = Some(select_prev_state);
5349        } else if selections.len() == 1 {
5350            let selection = selections.last_mut().unwrap();
5351            if selection.start == selection.end {
5352                let word_range = movement::surrounding_word(
5353                    &display_map,
5354                    selection.start.to_display_point(&display_map),
5355                );
5356                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5357                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5358                selection.goal = SelectionGoal::None;
5359                selection.reversed = false;
5360
5361                let query = buffer
5362                    .text_for_range(selection.start..selection.end)
5363                    .collect::<String>();
5364                let query = query.chars().rev().collect::<String>();
5365                let select_state = SelectNextState {
5366                    query: AhoCorasick::new_auto_configured(&[query]),
5367                    wordwise: true,
5368                    done: false,
5369                };
5370                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5371                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5372                    s.select(selections);
5373                });
5374                self.select_prev_state = Some(select_state);
5375            } else {
5376                let query = buffer
5377                    .text_for_range(selection.start..selection.end)
5378                    .collect::<String>();
5379                let query = query.chars().rev().collect::<String>();
5380                self.select_prev_state = Some(SelectNextState {
5381                    query: AhoCorasick::new_auto_configured(&[query]),
5382                    wordwise: false,
5383                    done: false,
5384                });
5385                self.select_previous(action, cx);
5386            }
5387        }
5388    }
5389
5390    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5391        self.transact(cx, |this, cx| {
5392            let mut selections = this.selections.all::<Point>(cx);
5393            let mut edits = Vec::new();
5394            let mut selection_edit_ranges = Vec::new();
5395            let mut last_toggled_row = None;
5396            let snapshot = this.buffer.read(cx).read(cx);
5397            let empty_str: Arc<str> = "".into();
5398            let mut suffixes_inserted = Vec::new();
5399
5400            fn comment_prefix_range(
5401                snapshot: &MultiBufferSnapshot,
5402                row: u32,
5403                comment_prefix: &str,
5404                comment_prefix_whitespace: &str,
5405            ) -> Range<Point> {
5406                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5407
5408                let mut line_bytes = snapshot
5409                    .bytes_in_range(start..snapshot.max_point())
5410                    .flatten()
5411                    .copied();
5412
5413                // If this line currently begins with the line comment prefix, then record
5414                // the range containing the prefix.
5415                if line_bytes
5416                    .by_ref()
5417                    .take(comment_prefix.len())
5418                    .eq(comment_prefix.bytes())
5419                {
5420                    // Include any whitespace that matches the comment prefix.
5421                    let matching_whitespace_len = line_bytes
5422                        .zip(comment_prefix_whitespace.bytes())
5423                        .take_while(|(a, b)| a == b)
5424                        .count() as u32;
5425                    let end = Point::new(
5426                        start.row,
5427                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5428                    );
5429                    start..end
5430                } else {
5431                    start..start
5432                }
5433            }
5434
5435            fn comment_suffix_range(
5436                snapshot: &MultiBufferSnapshot,
5437                row: u32,
5438                comment_suffix: &str,
5439                comment_suffix_has_leading_space: bool,
5440            ) -> Range<Point> {
5441                let end = Point::new(row, snapshot.line_len(row));
5442                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5443
5444                let mut line_end_bytes = snapshot
5445                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5446                    .flatten()
5447                    .copied();
5448
5449                let leading_space_len = if suffix_start_column > 0
5450                    && line_end_bytes.next() == Some(b' ')
5451                    && comment_suffix_has_leading_space
5452                {
5453                    1
5454                } else {
5455                    0
5456                };
5457
5458                // If this line currently begins with the line comment prefix, then record
5459                // the range containing the prefix.
5460                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5461                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5462                    start..end
5463                } else {
5464                    end..end
5465                }
5466            }
5467
5468            // TODO: Handle selections that cross excerpts
5469            for selection in &mut selections {
5470                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5471                let language = if let Some(language) =
5472                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5473                {
5474                    language
5475                } else {
5476                    continue;
5477                };
5478
5479                selection_edit_ranges.clear();
5480
5481                // If multiple selections contain a given row, avoid processing that
5482                // row more than once.
5483                let mut start_row = selection.start.row;
5484                if last_toggled_row == Some(start_row) {
5485                    start_row += 1;
5486                }
5487                let end_row =
5488                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5489                        selection.end.row - 1
5490                    } else {
5491                        selection.end.row
5492                    };
5493                last_toggled_row = Some(end_row);
5494
5495                if start_row > end_row {
5496                    continue;
5497                }
5498
5499                // If the language has line comments, toggle those.
5500                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5501                    // Split the comment prefix's trailing whitespace into a separate string,
5502                    // as that portion won't be used for detecting if a line is a comment.
5503                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5504                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5505                    let mut all_selection_lines_are_comments = true;
5506
5507                    for row in start_row..=end_row {
5508                        if snapshot.is_line_blank(row) && start_row < end_row {
5509                            continue;
5510                        }
5511
5512                        let prefix_range = comment_prefix_range(
5513                            snapshot.deref(),
5514                            row,
5515                            comment_prefix,
5516                            comment_prefix_whitespace,
5517                        );
5518                        if prefix_range.is_empty() {
5519                            all_selection_lines_are_comments = false;
5520                        }
5521                        selection_edit_ranges.push(prefix_range);
5522                    }
5523
5524                    if all_selection_lines_are_comments {
5525                        edits.extend(
5526                            selection_edit_ranges
5527                                .iter()
5528                                .cloned()
5529                                .map(|range| (range, empty_str.clone())),
5530                        );
5531                    } else {
5532                        let min_column = selection_edit_ranges
5533                            .iter()
5534                            .map(|r| r.start.column)
5535                            .min()
5536                            .unwrap_or(0);
5537                        edits.extend(selection_edit_ranges.iter().map(|range| {
5538                            let position = Point::new(range.start.row, min_column);
5539                            (position..position, full_comment_prefix.clone())
5540                        }));
5541                    }
5542                } else if let Some((full_comment_prefix, comment_suffix)) =
5543                    language.block_comment_delimiters()
5544                {
5545                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5546                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5547                    let prefix_range = comment_prefix_range(
5548                        snapshot.deref(),
5549                        start_row,
5550                        comment_prefix,
5551                        comment_prefix_whitespace,
5552                    );
5553                    let suffix_range = comment_suffix_range(
5554                        snapshot.deref(),
5555                        end_row,
5556                        comment_suffix.trim_start_matches(' '),
5557                        comment_suffix.starts_with(' '),
5558                    );
5559
5560                    if prefix_range.is_empty() || suffix_range.is_empty() {
5561                        edits.push((
5562                            prefix_range.start..prefix_range.start,
5563                            full_comment_prefix.clone(),
5564                        ));
5565                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5566                        suffixes_inserted.push((end_row, comment_suffix.len()));
5567                    } else {
5568                        edits.push((prefix_range, empty_str.clone()));
5569                        edits.push((suffix_range, empty_str.clone()));
5570                    }
5571                } else {
5572                    continue;
5573                }
5574            }
5575
5576            drop(snapshot);
5577            this.buffer.update(cx, |buffer, cx| {
5578                buffer.edit(edits, None, cx);
5579            });
5580
5581            // Adjust selections so that they end before any comment suffixes that
5582            // were inserted.
5583            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5584            let mut selections = this.selections.all::<Point>(cx);
5585            let snapshot = this.buffer.read(cx).read(cx);
5586            for selection in &mut selections {
5587                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5588                    match row.cmp(&selection.end.row) {
5589                        Ordering::Less => {
5590                            suffixes_inserted.next();
5591                            continue;
5592                        }
5593                        Ordering::Greater => break,
5594                        Ordering::Equal => {
5595                            if selection.end.column == snapshot.line_len(row) {
5596                                if selection.is_empty() {
5597                                    selection.start.column -= suffix_len as u32;
5598                                }
5599                                selection.end.column -= suffix_len as u32;
5600                            }
5601                            break;
5602                        }
5603                    }
5604                }
5605            }
5606
5607            drop(snapshot);
5608            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5609
5610            let selections = this.selections.all::<Point>(cx);
5611            let selections_on_single_row = selections.windows(2).all(|selections| {
5612                selections[0].start.row == selections[1].start.row
5613                    && selections[0].end.row == selections[1].end.row
5614                    && selections[0].start.row == selections[0].end.row
5615            });
5616            let selections_selecting = selections
5617                .iter()
5618                .any(|selection| selection.start != selection.end);
5619            let advance_downwards = action.advance_downwards
5620                && selections_on_single_row
5621                && !selections_selecting
5622                && this.mode != EditorMode::SingleLine;
5623
5624            if advance_downwards {
5625                let snapshot = this.buffer.read(cx).snapshot(cx);
5626
5627                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5628                    s.move_cursors_with(|display_snapshot, display_point, _| {
5629                        let mut point = display_point.to_point(display_snapshot);
5630                        point.row += 1;
5631                        point = snapshot.clip_point(point, Bias::Left);
5632                        let display_point = point.to_display_point(display_snapshot);
5633                        (display_point, SelectionGoal::Column(display_point.column()))
5634                    })
5635                });
5636            }
5637        });
5638    }
5639
5640    pub fn select_larger_syntax_node(
5641        &mut self,
5642        _: &SelectLargerSyntaxNode,
5643        cx: &mut ViewContext<Self>,
5644    ) {
5645        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5646        let buffer = self.buffer.read(cx).snapshot(cx);
5647        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5648
5649        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5650        let mut selected_larger_node = false;
5651        let new_selections = old_selections
5652            .iter()
5653            .map(|selection| {
5654                let old_range = selection.start..selection.end;
5655                let mut new_range = old_range.clone();
5656                while let Some(containing_range) =
5657                    buffer.range_for_syntax_ancestor(new_range.clone())
5658                {
5659                    new_range = containing_range;
5660                    if !display_map.intersects_fold(new_range.start)
5661                        && !display_map.intersects_fold(new_range.end)
5662                    {
5663                        break;
5664                    }
5665                }
5666
5667                selected_larger_node |= new_range != old_range;
5668                Selection {
5669                    id: selection.id,
5670                    start: new_range.start,
5671                    end: new_range.end,
5672                    goal: SelectionGoal::None,
5673                    reversed: selection.reversed,
5674                }
5675            })
5676            .collect::<Vec<_>>();
5677
5678        if selected_larger_node {
5679            stack.push(old_selections);
5680            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5681                s.select(new_selections);
5682            });
5683        }
5684        self.select_larger_syntax_node_stack = stack;
5685    }
5686
5687    pub fn select_smaller_syntax_node(
5688        &mut self,
5689        _: &SelectSmallerSyntaxNode,
5690        cx: &mut ViewContext<Self>,
5691    ) {
5692        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5693        if let Some(selections) = stack.pop() {
5694            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5695                s.select(selections.to_vec());
5696            });
5697        }
5698        self.select_larger_syntax_node_stack = stack;
5699    }
5700
5701    pub fn move_to_enclosing_bracket(
5702        &mut self,
5703        _: &MoveToEnclosingBracket,
5704        cx: &mut ViewContext<Self>,
5705    ) {
5706        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5707            s.move_offsets_with(|snapshot, selection| {
5708                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5709                    return;
5710                };
5711
5712                let mut best_length = usize::MAX;
5713                let mut best_inside = false;
5714                let mut best_in_bracket_range = false;
5715                let mut best_destination = None;
5716                for (open, close) in enclosing_bracket_ranges {
5717                    let close = close.to_inclusive();
5718                    let length = close.end() - open.start;
5719                    let inside = selection.start >= open.end && selection.end <= *close.start();
5720                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5721
5722                    // If best is next to a bracket and current isn't, skip
5723                    if !in_bracket_range && best_in_bracket_range {
5724                        continue;
5725                    }
5726
5727                    // Prefer smaller lengths unless best is inside and current isn't
5728                    if length > best_length && (best_inside || !inside) {
5729                        continue;
5730                    }
5731
5732                    best_length = length;
5733                    best_inside = inside;
5734                    best_in_bracket_range = in_bracket_range;
5735                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5736                        if inside {
5737                            open.end
5738                        } else {
5739                            open.start
5740                        }
5741                    } else {
5742                        if inside {
5743                            *close.start()
5744                        } else {
5745                            *close.end()
5746                        }
5747                    });
5748                }
5749
5750                if let Some(destination) = best_destination {
5751                    selection.collapse_to(destination, SelectionGoal::None);
5752                }
5753            })
5754        });
5755    }
5756
5757    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5758        self.end_selection(cx);
5759        self.selection_history.mode = SelectionHistoryMode::Undoing;
5760        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5761            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5762            self.select_next_state = entry.select_next_state;
5763            self.select_prev_state = entry.select_prev_state;
5764            self.add_selections_state = entry.add_selections_state;
5765            self.request_autoscroll(Autoscroll::newest(), cx);
5766        }
5767        self.selection_history.mode = SelectionHistoryMode::Normal;
5768    }
5769
5770    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5771        self.end_selection(cx);
5772        self.selection_history.mode = SelectionHistoryMode::Redoing;
5773        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5774            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5775            self.select_next_state = entry.select_next_state;
5776            self.select_prev_state = entry.select_prev_state;
5777            self.add_selections_state = entry.add_selections_state;
5778            self.request_autoscroll(Autoscroll::newest(), cx);
5779        }
5780        self.selection_history.mode = SelectionHistoryMode::Normal;
5781    }
5782
5783    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5784        self.go_to_diagnostic_impl(Direction::Next, cx)
5785    }
5786
5787    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5788        self.go_to_diagnostic_impl(Direction::Prev, cx)
5789    }
5790
5791    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5792        let buffer = self.buffer.read(cx).snapshot(cx);
5793        let selection = self.selections.newest::<usize>(cx);
5794
5795        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5796        if direction == Direction::Next {
5797            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5798                let (group_id, jump_to) = popover.activation_info();
5799                if self.activate_diagnostics(group_id, cx) {
5800                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5801                        let mut new_selection = s.newest_anchor().clone();
5802                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5803                        s.select_anchors(vec![new_selection.clone()]);
5804                    });
5805                }
5806                return;
5807            }
5808        }
5809
5810        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5811            active_diagnostics
5812                .primary_range
5813                .to_offset(&buffer)
5814                .to_inclusive()
5815        });
5816        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5817            if active_primary_range.contains(&selection.head()) {
5818                *active_primary_range.end()
5819            } else {
5820                selection.head()
5821            }
5822        } else {
5823            selection.head()
5824        };
5825
5826        loop {
5827            let mut diagnostics = if direction == Direction::Prev {
5828                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5829            } else {
5830                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5831            };
5832            let group = diagnostics.find_map(|entry| {
5833                if entry.diagnostic.is_primary
5834                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5835                    && !entry.range.is_empty()
5836                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5837                {
5838                    Some((entry.range, entry.diagnostic.group_id))
5839                } else {
5840                    None
5841                }
5842            });
5843
5844            if let Some((primary_range, group_id)) = group {
5845                if self.activate_diagnostics(group_id, cx) {
5846                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5847                        s.select(vec![Selection {
5848                            id: selection.id,
5849                            start: primary_range.start,
5850                            end: primary_range.start,
5851                            reversed: false,
5852                            goal: SelectionGoal::None,
5853                        }]);
5854                    });
5855                }
5856                break;
5857            } else {
5858                // Cycle around to the start of the buffer, potentially moving back to the start of
5859                // the currently active diagnostic.
5860                active_primary_range.take();
5861                if direction == Direction::Prev {
5862                    if search_start == buffer.len() {
5863                        break;
5864                    } else {
5865                        search_start = buffer.len();
5866                    }
5867                } else if search_start == 0 {
5868                    break;
5869                } else {
5870                    search_start = 0;
5871                }
5872            }
5873        }
5874    }
5875
5876    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5877        let snapshot = self
5878            .display_map
5879            .update(cx, |display_map, cx| display_map.snapshot(cx));
5880        let selection = self.selections.newest::<Point>(cx);
5881
5882        if !self.seek_in_direction(
5883            &snapshot,
5884            selection.head(),
5885            false,
5886            snapshot
5887                .buffer_snapshot
5888                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5889            cx,
5890        ) {
5891            let wrapped_point = Point::zero();
5892            self.seek_in_direction(
5893                &snapshot,
5894                wrapped_point,
5895                true,
5896                snapshot
5897                    .buffer_snapshot
5898                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5899                cx,
5900            );
5901        }
5902    }
5903
5904    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5905        let snapshot = self
5906            .display_map
5907            .update(cx, |display_map, cx| display_map.snapshot(cx));
5908        let selection = self.selections.newest::<Point>(cx);
5909
5910        if !self.seek_in_direction(
5911            &snapshot,
5912            selection.head(),
5913            false,
5914            snapshot
5915                .buffer_snapshot
5916                .git_diff_hunks_in_range_rev(0..selection.head().row),
5917            cx,
5918        ) {
5919            let wrapped_point = snapshot.buffer_snapshot.max_point();
5920            self.seek_in_direction(
5921                &snapshot,
5922                wrapped_point,
5923                true,
5924                snapshot
5925                    .buffer_snapshot
5926                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5927                cx,
5928            );
5929        }
5930    }
5931
5932    fn seek_in_direction(
5933        &mut self,
5934        snapshot: &DisplaySnapshot,
5935        initial_point: Point,
5936        is_wrapped: bool,
5937        hunks: impl Iterator<Item = DiffHunk<u32>>,
5938        cx: &mut ViewContext<Editor>,
5939    ) -> bool {
5940        let display_point = initial_point.to_display_point(snapshot);
5941        let mut hunks = hunks
5942            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5943            .skip_while(|hunk| {
5944                if is_wrapped {
5945                    false
5946                } else {
5947                    hunk.contains_display_row(display_point.row())
5948                }
5949            })
5950            .dedup();
5951
5952        if let Some(hunk) = hunks.next() {
5953            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5954                let row = hunk.start_display_row();
5955                let point = DisplayPoint::new(row, 0);
5956                s.select_display_ranges([point..point]);
5957            });
5958
5959            true
5960        } else {
5961            false
5962        }
5963    }
5964
5965    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5966        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5967    }
5968
5969    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5970        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5971    }
5972
5973    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5974        let Some(workspace) = self.workspace(cx) else { return };
5975        let buffer = self.buffer.read(cx);
5976        let head = self.selections.newest::<usize>(cx).head();
5977        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5978            text_anchor
5979        } else {
5980            return;
5981        };
5982
5983        let project = workspace.read(cx).project().clone();
5984        let definitions = project.update(cx, |project, cx| match kind {
5985            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5986            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5987        });
5988
5989        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5990            let definitions = definitions.await?;
5991            editor.update(&mut cx, |editor, cx| {
5992                editor.navigate_to_definitions(definitions, cx);
5993            })?;
5994            Ok::<(), anyhow::Error>(())
5995        })
5996        .detach_and_log_err(cx);
5997    }
5998
5999    pub fn navigate_to_definitions(
6000        &mut self,
6001        mut definitions: Vec<LocationLink>,
6002        cx: &mut ViewContext<Editor>,
6003    ) {
6004        let Some(workspace) = self.workspace(cx) else { return };
6005        let pane = workspace.read(cx).active_pane().clone();
6006        // If there is one definition, just open it directly
6007        if definitions.len() == 1 {
6008            let definition = definitions.pop().unwrap();
6009            let range = definition
6010                .target
6011                .range
6012                .to_offset(definition.target.buffer.read(cx));
6013
6014            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6015                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6016                    s.select_ranges([range]);
6017                });
6018            } else {
6019                cx.window_context().defer(move |cx| {
6020                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6021                        workspace.open_project_item(definition.target.buffer.clone(), cx)
6022                    });
6023                    target_editor.update(cx, |target_editor, cx| {
6024                        // When selecting a definition in a different buffer, disable the nav history
6025                        // to avoid creating a history entry at the previous cursor location.
6026                        pane.update(cx, |pane, _| pane.disable_history());
6027                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6028                            s.select_ranges([range]);
6029                        });
6030                        pane.update(cx, |pane, _| pane.enable_history());
6031                    });
6032                });
6033            }
6034        } else if !definitions.is_empty() {
6035            let replica_id = self.replica_id(cx);
6036            cx.window_context().defer(move |cx| {
6037                let title = definitions
6038                    .iter()
6039                    .find(|definition| definition.origin.is_some())
6040                    .and_then(|definition| {
6041                        definition.origin.as_ref().map(|origin| {
6042                            let buffer = origin.buffer.read(cx);
6043                            format!(
6044                                "Definitions for {}",
6045                                buffer
6046                                    .text_for_range(origin.range.clone())
6047                                    .collect::<String>()
6048                            )
6049                        })
6050                    })
6051                    .unwrap_or("Definitions".to_owned());
6052                let locations = definitions
6053                    .into_iter()
6054                    .map(|definition| definition.target)
6055                    .collect();
6056                workspace.update(cx, |workspace, cx| {
6057                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
6058                });
6059            });
6060        }
6061    }
6062
6063    pub fn find_all_references(
6064        workspace: &mut Workspace,
6065        _: &FindAllReferences,
6066        cx: &mut ViewContext<Workspace>,
6067    ) -> Option<Task<Result<()>>> {
6068        let active_item = workspace.active_item(cx)?;
6069        let editor_handle = active_item.act_as::<Self>(cx)?;
6070
6071        let editor = editor_handle.read(cx);
6072        let buffer = editor.buffer.read(cx);
6073        let head = editor.selections.newest::<usize>(cx).head();
6074        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6075        let replica_id = editor.replica_id(cx);
6076
6077        let project = workspace.project().clone();
6078        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6079        Some(cx.spawn_labeled(
6080            "Finding All References...",
6081            |workspace, mut cx| async move {
6082                let locations = references.await?;
6083                if locations.is_empty() {
6084                    return Ok(());
6085                }
6086
6087                workspace.update(&mut cx, |workspace, cx| {
6088                    let title = locations
6089                        .first()
6090                        .as_ref()
6091                        .map(|location| {
6092                            let buffer = location.buffer.read(cx);
6093                            format!(
6094                                "References to `{}`",
6095                                buffer
6096                                    .text_for_range(location.range.clone())
6097                                    .collect::<String>()
6098                            )
6099                        })
6100                        .unwrap();
6101                    Self::open_locations_in_multibuffer(
6102                        workspace, locations, replica_id, title, cx,
6103                    );
6104                })?;
6105
6106                Ok(())
6107            },
6108        ))
6109    }
6110
6111    /// Opens a multibuffer with the given project locations in it
6112    pub fn open_locations_in_multibuffer(
6113        workspace: &mut Workspace,
6114        mut locations: Vec<Location>,
6115        replica_id: ReplicaId,
6116        title: String,
6117        cx: &mut ViewContext<Workspace>,
6118    ) {
6119        // If there are multiple definitions, open them in a multibuffer
6120        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6121        let mut locations = locations.into_iter().peekable();
6122        let mut ranges_to_highlight = Vec::new();
6123
6124        let excerpt_buffer = cx.add_model(|cx| {
6125            let mut multibuffer = MultiBuffer::new(replica_id);
6126            while let Some(location) = locations.next() {
6127                let buffer = location.buffer.read(cx);
6128                let mut ranges_for_buffer = Vec::new();
6129                let range = location.range.to_offset(buffer);
6130                ranges_for_buffer.push(range.clone());
6131
6132                while let Some(next_location) = locations.peek() {
6133                    if next_location.buffer == location.buffer {
6134                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6135                        locations.next();
6136                    } else {
6137                        break;
6138                    }
6139                }
6140
6141                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6142                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6143                    location.buffer.clone(),
6144                    ranges_for_buffer,
6145                    1,
6146                    cx,
6147                ))
6148            }
6149
6150            multibuffer.with_title(title)
6151        });
6152
6153        let editor = cx.add_view(|cx| {
6154            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6155        });
6156        editor.update(cx, |editor, cx| {
6157            editor.highlight_background::<Self>(
6158                ranges_to_highlight,
6159                |theme| theme.editor.highlighted_line_background,
6160                cx,
6161            );
6162        });
6163        workspace.add_item(Box::new(editor), cx);
6164    }
6165
6166    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6167        use language::ToOffset as _;
6168
6169        let project = self.project.clone()?;
6170        let selection = self.selections.newest_anchor().clone();
6171        let (cursor_buffer, cursor_buffer_position) = self
6172            .buffer
6173            .read(cx)
6174            .text_anchor_for_position(selection.head(), cx)?;
6175        let (tail_buffer, _) = self
6176            .buffer
6177            .read(cx)
6178            .text_anchor_for_position(selection.tail(), cx)?;
6179        if tail_buffer != cursor_buffer {
6180            return None;
6181        }
6182
6183        let snapshot = cursor_buffer.read(cx).snapshot();
6184        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6185        let prepare_rename = project.update(cx, |project, cx| {
6186            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6187        });
6188
6189        Some(cx.spawn(|this, mut cx| async move {
6190            let rename_range = if let Some(range) = prepare_rename.await? {
6191                Some(range)
6192            } else {
6193                this.read_with(&cx, |this, cx| {
6194                    let buffer = this.buffer.read(cx).snapshot(cx);
6195                    let mut buffer_highlights = this
6196                        .document_highlights_for_position(selection.head(), &buffer)
6197                        .filter(|highlight| {
6198                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6199                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6200                        });
6201                    buffer_highlights
6202                        .next()
6203                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6204                })?
6205            };
6206            if let Some(rename_range) = rename_range {
6207                let rename_buffer_range = rename_range.to_offset(&snapshot);
6208                let cursor_offset_in_rename_range =
6209                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6210
6211                this.update(&mut cx, |this, cx| {
6212                    this.take_rename(false, cx);
6213                    let style = this.style(cx);
6214                    let buffer = this.buffer.read(cx).read(cx);
6215                    let cursor_offset = selection.head().to_offset(&buffer);
6216                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6217                    let rename_end = rename_start + rename_buffer_range.len();
6218                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6219                    let mut old_highlight_id = None;
6220                    let old_name: Arc<str> = buffer
6221                        .chunks(rename_start..rename_end, true)
6222                        .map(|chunk| {
6223                            if old_highlight_id.is_none() {
6224                                old_highlight_id = chunk.syntax_highlight_id;
6225                            }
6226                            chunk.text
6227                        })
6228                        .collect::<String>()
6229                        .into();
6230
6231                    drop(buffer);
6232
6233                    // Position the selection in the rename editor so that it matches the current selection.
6234                    this.show_local_selections = false;
6235                    let rename_editor = cx.add_view(|cx| {
6236                        let mut editor = Editor::single_line(None, cx);
6237                        if let Some(old_highlight_id) = old_highlight_id {
6238                            editor.override_text_style =
6239                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6240                        }
6241                        editor.buffer.update(cx, |buffer, cx| {
6242                            buffer.edit([(0..0, old_name.clone())], None, cx)
6243                        });
6244                        editor.select_all(&SelectAll, cx);
6245                        editor
6246                    });
6247
6248                    let ranges = this
6249                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6250                        .into_iter()
6251                        .flat_map(|(_, ranges)| ranges)
6252                        .chain(
6253                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6254                                .into_iter()
6255                                .flat_map(|(_, ranges)| ranges),
6256                        )
6257                        .collect();
6258
6259                    this.highlight_text::<Rename>(
6260                        ranges,
6261                        HighlightStyle {
6262                            fade_out: Some(style.rename_fade),
6263                            ..Default::default()
6264                        },
6265                        cx,
6266                    );
6267                    cx.focus(&rename_editor);
6268                    let block_id = this.insert_blocks(
6269                        [BlockProperties {
6270                            style: BlockStyle::Flex,
6271                            position: range.start.clone(),
6272                            height: 1,
6273                            render: Arc::new({
6274                                let editor = rename_editor.clone();
6275                                move |cx: &mut BlockContext| {
6276                                    ChildView::new(&editor, cx)
6277                                        .contained()
6278                                        .with_padding_left(cx.anchor_x)
6279                                        .into_any()
6280                                }
6281                            }),
6282                            disposition: BlockDisposition::Below,
6283                        }],
6284                        Some(Autoscroll::fit()),
6285                        cx,
6286                    )[0];
6287                    this.pending_rename = Some(RenameState {
6288                        range,
6289                        old_name,
6290                        editor: rename_editor,
6291                        block_id,
6292                    });
6293                })?;
6294            }
6295
6296            Ok(())
6297        }))
6298    }
6299
6300    pub fn confirm_rename(
6301        workspace: &mut Workspace,
6302        _: &ConfirmRename,
6303        cx: &mut ViewContext<Workspace>,
6304    ) -> Option<Task<Result<()>>> {
6305        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6306
6307        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6308            let rename = editor.take_rename(false, cx)?;
6309            let buffer = editor.buffer.read(cx);
6310            let (start_buffer, start) =
6311                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6312            let (end_buffer, end) =
6313                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6314            if start_buffer == end_buffer {
6315                let new_name = rename.editor.read(cx).text(cx);
6316                Some((start_buffer, start..end, rename.old_name, new_name))
6317            } else {
6318                None
6319            }
6320        })?;
6321
6322        let rename = workspace.project().clone().update(cx, |project, cx| {
6323            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6324        });
6325
6326        let editor = editor.downgrade();
6327        Some(cx.spawn(|workspace, mut cx| async move {
6328            let project_transaction = rename.await?;
6329            Self::open_project_transaction(
6330                &editor,
6331                workspace,
6332                project_transaction,
6333                format!("Rename: {}{}", old_name, new_name),
6334                cx.clone(),
6335            )
6336            .await?;
6337
6338            editor.update(&mut cx, |editor, cx| {
6339                editor.refresh_document_highlights(cx);
6340            })?;
6341            Ok(())
6342        }))
6343    }
6344
6345    fn take_rename(
6346        &mut self,
6347        moving_cursor: bool,
6348        cx: &mut ViewContext<Self>,
6349    ) -> Option<RenameState> {
6350        let rename = self.pending_rename.take()?;
6351        self.remove_blocks(
6352            [rename.block_id].into_iter().collect(),
6353            Some(Autoscroll::fit()),
6354            cx,
6355        );
6356        self.clear_text_highlights::<Rename>(cx);
6357        self.show_local_selections = true;
6358
6359        if moving_cursor {
6360            let rename_editor = rename.editor.read(cx);
6361            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6362
6363            // Update the selection to match the position of the selection inside
6364            // the rename editor.
6365            let snapshot = self.buffer.read(cx).read(cx);
6366            let rename_range = rename.range.to_offset(&snapshot);
6367            let cursor_in_editor = snapshot
6368                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6369                .min(rename_range.end);
6370            drop(snapshot);
6371
6372            self.change_selections(None, cx, |s| {
6373                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6374            });
6375        } else {
6376            self.refresh_document_highlights(cx);
6377        }
6378
6379        Some(rename)
6380    }
6381
6382    #[cfg(any(test, feature = "test-support"))]
6383    pub fn pending_rename(&self) -> Option<&RenameState> {
6384        self.pending_rename.as_ref()
6385    }
6386
6387    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6388        let project = match &self.project {
6389            Some(project) => project.clone(),
6390            None => return None,
6391        };
6392
6393        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6394    }
6395
6396    fn perform_format(
6397        &mut self,
6398        project: ModelHandle<Project>,
6399        trigger: FormatTrigger,
6400        cx: &mut ViewContext<Self>,
6401    ) -> Task<Result<()>> {
6402        let buffer = self.buffer().clone();
6403        let buffers = buffer.read(cx).all_buffers();
6404
6405        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6406        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6407
6408        cx.spawn(|_, mut cx| async move {
6409            let transaction = futures::select_biased! {
6410                _ = timeout => {
6411                    log::warn!("timed out waiting for formatting");
6412                    None
6413                }
6414                transaction = format.log_err().fuse() => transaction,
6415            };
6416
6417            buffer.update(&mut cx, |buffer, cx| {
6418                if let Some(transaction) = transaction {
6419                    if !buffer.is_singleton() {
6420                        buffer.push_transaction(&transaction.0, cx);
6421                    }
6422                }
6423
6424                cx.notify();
6425            });
6426
6427            Ok(())
6428        })
6429    }
6430
6431    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6432        if let Some(project) = self.project.clone() {
6433            self.buffer.update(cx, |multi_buffer, cx| {
6434                project.update(cx, |project, cx| {
6435                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6436                });
6437            })
6438        }
6439    }
6440
6441    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6442        cx.show_character_palette();
6443    }
6444
6445    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6446        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6447            let buffer = self.buffer.read(cx).snapshot(cx);
6448            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6449            let is_valid = buffer
6450                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6451                .any(|entry| {
6452                    entry.diagnostic.is_primary
6453                        && !entry.range.is_empty()
6454                        && entry.range.start == primary_range_start
6455                        && entry.diagnostic.message == active_diagnostics.primary_message
6456                });
6457
6458            if is_valid != active_diagnostics.is_valid {
6459                active_diagnostics.is_valid = is_valid;
6460                let mut new_styles = HashMap::default();
6461                for (block_id, diagnostic) in &active_diagnostics.blocks {
6462                    new_styles.insert(
6463                        *block_id,
6464                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6465                    );
6466                }
6467                self.display_map
6468                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6469            }
6470        }
6471    }
6472
6473    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6474        self.dismiss_diagnostics(cx);
6475        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6476            let buffer = self.buffer.read(cx).snapshot(cx);
6477
6478            let mut primary_range = None;
6479            let mut primary_message = None;
6480            let mut group_end = Point::zero();
6481            let diagnostic_group = buffer
6482                .diagnostic_group::<Point>(group_id)
6483                .map(|entry| {
6484                    if entry.range.end > group_end {
6485                        group_end = entry.range.end;
6486                    }
6487                    if entry.diagnostic.is_primary {
6488                        primary_range = Some(entry.range.clone());
6489                        primary_message = Some(entry.diagnostic.message.clone());
6490                    }
6491                    entry
6492                })
6493                .collect::<Vec<_>>();
6494            let primary_range = primary_range?;
6495            let primary_message = primary_message?;
6496            let primary_range =
6497                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6498
6499            let blocks = display_map
6500                .insert_blocks(
6501                    diagnostic_group.iter().map(|entry| {
6502                        let diagnostic = entry.diagnostic.clone();
6503                        let message_height = diagnostic.message.lines().count() as u8;
6504                        BlockProperties {
6505                            style: BlockStyle::Fixed,
6506                            position: buffer.anchor_after(entry.range.start),
6507                            height: message_height,
6508                            render: diagnostic_block_renderer(diagnostic, true),
6509                            disposition: BlockDisposition::Below,
6510                        }
6511                    }),
6512                    cx,
6513                )
6514                .into_iter()
6515                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6516                .collect();
6517
6518            Some(ActiveDiagnosticGroup {
6519                primary_range,
6520                primary_message,
6521                blocks,
6522                is_valid: true,
6523            })
6524        });
6525        self.active_diagnostics.is_some()
6526    }
6527
6528    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6529        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6530            self.display_map.update(cx, |display_map, cx| {
6531                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6532            });
6533            cx.notify();
6534        }
6535    }
6536
6537    pub fn set_selections_from_remote(
6538        &mut self,
6539        selections: Vec<Selection<Anchor>>,
6540        pending_selection: Option<Selection<Anchor>>,
6541        cx: &mut ViewContext<Self>,
6542    ) {
6543        let old_cursor_position = self.selections.newest_anchor().head();
6544        self.selections.change_with(cx, |s| {
6545            s.select_anchors(selections);
6546            if let Some(pending_selection) = pending_selection {
6547                s.set_pending(pending_selection, SelectMode::Character);
6548            } else {
6549                s.clear_pending();
6550            }
6551        });
6552        self.selections_did_change(false, &old_cursor_position, cx);
6553    }
6554
6555    fn push_to_selection_history(&mut self) {
6556        self.selection_history.push(SelectionHistoryEntry {
6557            selections: self.selections.disjoint_anchors(),
6558            select_next_state: self.select_next_state.clone(),
6559            select_prev_state: self.select_prev_state.clone(),
6560            add_selections_state: self.add_selections_state.clone(),
6561        });
6562    }
6563
6564    pub fn transact(
6565        &mut self,
6566        cx: &mut ViewContext<Self>,
6567        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6568    ) -> Option<TransactionId> {
6569        self.start_transaction_at(Instant::now(), cx);
6570        update(self, cx);
6571        self.end_transaction_at(Instant::now(), cx)
6572    }
6573
6574    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6575        self.end_selection(cx);
6576        if let Some(tx_id) = self
6577            .buffer
6578            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6579        {
6580            self.selection_history
6581                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6582        }
6583    }
6584
6585    fn end_transaction_at(
6586        &mut self,
6587        now: Instant,
6588        cx: &mut ViewContext<Self>,
6589    ) -> Option<TransactionId> {
6590        if let Some(tx_id) = self
6591            .buffer
6592            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6593        {
6594            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6595                *end_selections = Some(self.selections.disjoint_anchors());
6596            } else {
6597                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6598            }
6599
6600            cx.emit(Event::Edited);
6601            Some(tx_id)
6602        } else {
6603            None
6604        }
6605    }
6606
6607    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6608        let mut fold_ranges = Vec::new();
6609
6610        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6611
6612        let selections = self.selections.all::<Point>(cx);
6613        for selection in selections {
6614            let range = selection.range().sorted();
6615            let buffer_start_row = range.start.row;
6616
6617            for row in (0..=range.end.row).rev() {
6618                let fold_range = display_map.foldable_range(row);
6619
6620                if let Some(fold_range) = fold_range {
6621                    if fold_range.end.row >= buffer_start_row {
6622                        fold_ranges.push(fold_range);
6623                        if row <= range.start.row {
6624                            break;
6625                        }
6626                    }
6627                }
6628            }
6629        }
6630
6631        self.fold_ranges(fold_ranges, true, cx);
6632    }
6633
6634    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6635        let buffer_row = fold_at.buffer_row;
6636        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6637
6638        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6639            let autoscroll = self
6640                .selections
6641                .all::<Point>(cx)
6642                .iter()
6643                .any(|selection| fold_range.overlaps(&selection.range()));
6644
6645            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6646        }
6647    }
6648
6649    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6650        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6651        let buffer = &display_map.buffer_snapshot;
6652        let selections = self.selections.all::<Point>(cx);
6653        let ranges = selections
6654            .iter()
6655            .map(|s| {
6656                let range = s.display_range(&display_map).sorted();
6657                let mut start = range.start.to_point(&display_map);
6658                let mut end = range.end.to_point(&display_map);
6659                start.column = 0;
6660                end.column = buffer.line_len(end.row);
6661                start..end
6662            })
6663            .collect::<Vec<_>>();
6664
6665        self.unfold_ranges(ranges, true, true, cx);
6666    }
6667
6668    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6669        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6670
6671        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6672            ..Point::new(
6673                unfold_at.buffer_row,
6674                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6675            );
6676
6677        let autoscroll = self
6678            .selections
6679            .all::<Point>(cx)
6680            .iter()
6681            .any(|selection| selection.range().overlaps(&intersection_range));
6682
6683        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6684    }
6685
6686    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6687        let selections = self.selections.all::<Point>(cx);
6688        let ranges = selections.into_iter().map(|s| s.start..s.end);
6689        self.fold_ranges(ranges, true, cx);
6690    }
6691
6692    pub fn fold_ranges<T: ToOffset + Clone>(
6693        &mut self,
6694        ranges: impl IntoIterator<Item = Range<T>>,
6695        auto_scroll: bool,
6696        cx: &mut ViewContext<Self>,
6697    ) {
6698        let mut ranges = ranges.into_iter().peekable();
6699        if ranges.peek().is_some() {
6700            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6701
6702            if auto_scroll {
6703                self.request_autoscroll(Autoscroll::fit(), cx);
6704            }
6705
6706            cx.notify();
6707        }
6708    }
6709
6710    pub fn unfold_ranges<T: ToOffset + Clone>(
6711        &mut self,
6712        ranges: impl IntoIterator<Item = Range<T>>,
6713        inclusive: bool,
6714        auto_scroll: bool,
6715        cx: &mut ViewContext<Self>,
6716    ) {
6717        let mut ranges = ranges.into_iter().peekable();
6718        if ranges.peek().is_some() {
6719            self.display_map
6720                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6721            if auto_scroll {
6722                self.request_autoscroll(Autoscroll::fit(), cx);
6723            }
6724
6725            cx.notify();
6726        }
6727    }
6728
6729    pub fn gutter_hover(
6730        &mut self,
6731        GutterHover { hovered }: &GutterHover,
6732        cx: &mut ViewContext<Self>,
6733    ) {
6734        self.gutter_hovered = *hovered;
6735        cx.notify();
6736    }
6737
6738    pub fn insert_blocks(
6739        &mut self,
6740        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6741        autoscroll: Option<Autoscroll>,
6742        cx: &mut ViewContext<Self>,
6743    ) -> Vec<BlockId> {
6744        let blocks = self
6745            .display_map
6746            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6747        if let Some(autoscroll) = autoscroll {
6748            self.request_autoscroll(autoscroll, cx);
6749        }
6750        blocks
6751    }
6752
6753    pub fn replace_blocks(
6754        &mut self,
6755        blocks: HashMap<BlockId, RenderBlock>,
6756        autoscroll: Option<Autoscroll>,
6757        cx: &mut ViewContext<Self>,
6758    ) {
6759        self.display_map
6760            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6761        if let Some(autoscroll) = autoscroll {
6762            self.request_autoscroll(autoscroll, cx);
6763        }
6764    }
6765
6766    pub fn remove_blocks(
6767        &mut self,
6768        block_ids: HashSet<BlockId>,
6769        autoscroll: Option<Autoscroll>,
6770        cx: &mut ViewContext<Self>,
6771    ) {
6772        self.display_map.update(cx, |display_map, cx| {
6773            display_map.remove_blocks(block_ids, cx)
6774        });
6775        if let Some(autoscroll) = autoscroll {
6776            self.request_autoscroll(autoscroll, cx);
6777        }
6778    }
6779
6780    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6781        self.display_map
6782            .update(cx, |map, cx| map.snapshot(cx))
6783            .longest_row()
6784    }
6785
6786    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6787        self.display_map
6788            .update(cx, |map, cx| map.snapshot(cx))
6789            .max_point()
6790    }
6791
6792    pub fn text(&self, cx: &AppContext) -> String {
6793        self.buffer.read(cx).read(cx).text()
6794    }
6795
6796    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6797        self.transact(cx, |this, cx| {
6798            this.buffer
6799                .read(cx)
6800                .as_singleton()
6801                .expect("you can only call set_text on editors for singleton buffers")
6802                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6803        });
6804    }
6805
6806    pub fn display_text(&self, cx: &mut AppContext) -> String {
6807        self.display_map
6808            .update(cx, |map, cx| map.snapshot(cx))
6809            .text()
6810    }
6811
6812    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6813        let settings = self.buffer.read(cx).settings_at(0, cx);
6814        let mode = self
6815            .soft_wrap_mode_override
6816            .unwrap_or_else(|| settings.soft_wrap);
6817        match mode {
6818            language_settings::SoftWrap::None => SoftWrap::None,
6819            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6820            language_settings::SoftWrap::PreferredLineLength => {
6821                SoftWrap::Column(settings.preferred_line_length)
6822            }
6823        }
6824    }
6825
6826    pub fn set_soft_wrap_mode(
6827        &mut self,
6828        mode: language_settings::SoftWrap,
6829        cx: &mut ViewContext<Self>,
6830    ) {
6831        self.soft_wrap_mode_override = Some(mode);
6832        cx.notify();
6833    }
6834
6835    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6836        self.display_map
6837            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6838    }
6839
6840    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6841        if self.soft_wrap_mode_override.is_some() {
6842            self.soft_wrap_mode_override.take();
6843        } else {
6844            let soft_wrap = match self.soft_wrap_mode(cx) {
6845                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
6846                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
6847            };
6848            self.soft_wrap_mode_override = Some(soft_wrap);
6849        }
6850        cx.notify();
6851    }
6852
6853    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
6854        self.show_gutter = show_gutter;
6855        cx.notify();
6856    }
6857
6858    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6859        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6860            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6861                cx.reveal_path(&file.abs_path(cx));
6862            }
6863        }
6864    }
6865
6866    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6867        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6868            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6869                if let Some(path) = file.abs_path(cx).to_str() {
6870                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6871                }
6872            }
6873        }
6874    }
6875
6876    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6877        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6878            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6879                if let Some(path) = file.path().to_str() {
6880                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6881                }
6882            }
6883        }
6884    }
6885
6886    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6887        self.highlighted_rows = rows;
6888    }
6889
6890    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6891        self.highlighted_rows.clone()
6892    }
6893
6894    pub fn highlight_background<T: 'static>(
6895        &mut self,
6896        ranges: Vec<Range<Anchor>>,
6897        color_fetcher: fn(&Theme) -> Color,
6898        cx: &mut ViewContext<Self>,
6899    ) {
6900        self.background_highlights
6901            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6902        cx.notify();
6903    }
6904
6905    #[allow(clippy::type_complexity)]
6906    pub fn clear_background_highlights<T: 'static>(
6907        &mut self,
6908        cx: &mut ViewContext<Self>,
6909    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6910        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6911        if highlights.is_some() {
6912            cx.notify();
6913        }
6914        highlights
6915    }
6916
6917    #[cfg(feature = "test-support")]
6918    pub fn all_background_highlights(
6919        &mut self,
6920        cx: &mut ViewContext<Self>,
6921    ) -> Vec<(Range<DisplayPoint>, Color)> {
6922        let snapshot = self.snapshot(cx);
6923        let buffer = &snapshot.buffer_snapshot;
6924        let start = buffer.anchor_before(0);
6925        let end = buffer.anchor_after(buffer.len());
6926        let theme = theme::current(cx);
6927        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
6928    }
6929
6930    fn document_highlights_for_position<'a>(
6931        &'a self,
6932        position: Anchor,
6933        buffer: &'a MultiBufferSnapshot,
6934    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6935        let read_highlights = self
6936            .background_highlights
6937            .get(&TypeId::of::<DocumentHighlightRead>())
6938            .map(|h| &h.1);
6939        let write_highlights = self
6940            .background_highlights
6941            .get(&TypeId::of::<DocumentHighlightWrite>())
6942            .map(|h| &h.1);
6943        let left_position = position.bias_left(buffer);
6944        let right_position = position.bias_right(buffer);
6945        read_highlights
6946            .into_iter()
6947            .chain(write_highlights)
6948            .flat_map(move |ranges| {
6949                let start_ix = match ranges.binary_search_by(|probe| {
6950                    let cmp = probe.end.cmp(&left_position, buffer);
6951                    if cmp.is_ge() {
6952                        Ordering::Greater
6953                    } else {
6954                        Ordering::Less
6955                    }
6956                }) {
6957                    Ok(i) | Err(i) => i,
6958                };
6959
6960                let right_position = right_position.clone();
6961                ranges[start_ix..]
6962                    .iter()
6963                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6964            })
6965    }
6966
6967    pub fn background_highlights_in_range(
6968        &self,
6969        search_range: Range<Anchor>,
6970        display_snapshot: &DisplaySnapshot,
6971        theme: &Theme,
6972    ) -> Vec<(Range<DisplayPoint>, Color)> {
6973        let mut results = Vec::new();
6974        let buffer = &display_snapshot.buffer_snapshot;
6975        for (color_fetcher, ranges) in self.background_highlights.values() {
6976            let color = color_fetcher(theme);
6977            let start_ix = match ranges.binary_search_by(|probe| {
6978                let cmp = probe.end.cmp(&search_range.start, buffer);
6979                if cmp.is_gt() {
6980                    Ordering::Greater
6981                } else {
6982                    Ordering::Less
6983                }
6984            }) {
6985                Ok(i) | Err(i) => i,
6986            };
6987            for range in &ranges[start_ix..] {
6988                if range.start.cmp(&search_range.end, buffer).is_ge() {
6989                    break;
6990                }
6991                let start = range
6992                    .start
6993                    .to_point(buffer)
6994                    .to_display_point(display_snapshot);
6995                let end = range
6996                    .end
6997                    .to_point(buffer)
6998                    .to_display_point(display_snapshot);
6999                results.push((start..end, color))
7000            }
7001        }
7002        results
7003    }
7004
7005    pub fn highlight_text<T: 'static>(
7006        &mut self,
7007        ranges: Vec<Range<Anchor>>,
7008        style: HighlightStyle,
7009        cx: &mut ViewContext<Self>,
7010    ) {
7011        self.display_map.update(cx, |map, _| {
7012            map.highlight_text(TypeId::of::<T>(), ranges, style)
7013        });
7014        cx.notify();
7015    }
7016
7017    pub fn text_highlights<'a, T: 'static>(
7018        &'a self,
7019        cx: &'a AppContext,
7020    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7021        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7022    }
7023
7024    pub fn clear_text_highlights<T: 'static>(
7025        &mut self,
7026        cx: &mut ViewContext<Self>,
7027    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7028        let highlights = self
7029            .display_map
7030            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7031        if highlights.is_some() {
7032            cx.notify();
7033        }
7034        highlights
7035    }
7036
7037    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7038        self.blink_manager.read(cx).visible() && self.focused
7039    }
7040
7041    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7042        cx.notify();
7043    }
7044
7045    fn on_buffer_event(
7046        &mut self,
7047        _: ModelHandle<MultiBuffer>,
7048        event: &multi_buffer::Event,
7049        cx: &mut ViewContext<Self>,
7050    ) {
7051        match event {
7052            multi_buffer::Event::Edited => {
7053                self.refresh_active_diagnostics(cx);
7054                self.refresh_code_actions(cx);
7055                if self.has_active_copilot_suggestion(cx) {
7056                    self.update_visible_copilot_suggestion(cx);
7057                }
7058                cx.emit(Event::BufferEdited);
7059            }
7060            multi_buffer::Event::ExcerptsAdded {
7061                buffer,
7062                predecessor,
7063                excerpts,
7064            } => cx.emit(Event::ExcerptsAdded {
7065                buffer: buffer.clone(),
7066                predecessor: *predecessor,
7067                excerpts: excerpts.clone(),
7068            }),
7069            multi_buffer::Event::ExcerptsRemoved { ids } => {
7070                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7071            }
7072            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7073            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7074            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7075            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7076            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7077            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7078            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7079            multi_buffer::Event::DiagnosticsUpdated => {
7080                self.refresh_active_diagnostics(cx);
7081            }
7082            _ => {}
7083        }
7084    }
7085
7086    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7087        cx.notify();
7088    }
7089
7090    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7091        self.refresh_copilot_suggestions(true, cx);
7092    }
7093
7094    pub fn set_searchable(&mut self, searchable: bool) {
7095        self.searchable = searchable;
7096    }
7097
7098    pub fn searchable(&self) -> bool {
7099        self.searchable
7100    }
7101
7102    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7103        let active_item = workspace.active_item(cx);
7104        let editor_handle = if let Some(editor) = active_item
7105            .as_ref()
7106            .and_then(|item| item.act_as::<Self>(cx))
7107        {
7108            editor
7109        } else {
7110            cx.propagate_action();
7111            return;
7112        };
7113
7114        let editor = editor_handle.read(cx);
7115        let buffer = editor.buffer.read(cx);
7116        if buffer.is_singleton() {
7117            cx.propagate_action();
7118            return;
7119        }
7120
7121        let mut new_selections_by_buffer = HashMap::default();
7122        for selection in editor.selections.all::<usize>(cx) {
7123            for (buffer, mut range, _) in
7124                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7125            {
7126                if selection.reversed {
7127                    mem::swap(&mut range.start, &mut range.end);
7128                }
7129                new_selections_by_buffer
7130                    .entry(buffer)
7131                    .or_insert(Vec::new())
7132                    .push(range)
7133            }
7134        }
7135
7136        editor_handle.update(cx, |editor, cx| {
7137            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7138        });
7139        let pane = workspace.active_pane().clone();
7140        pane.update(cx, |pane, _| pane.disable_history());
7141
7142        // We defer the pane interaction because we ourselves are a workspace item
7143        // and activating a new item causes the pane to call a method on us reentrantly,
7144        // which panics if we're on the stack.
7145        cx.defer(move |workspace, cx| {
7146            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7147                let editor = workspace.open_project_item::<Self>(buffer, cx);
7148                editor.update(cx, |editor, cx| {
7149                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7150                        s.select_ranges(ranges);
7151                    });
7152                });
7153            }
7154
7155            pane.update(cx, |pane, _| pane.enable_history());
7156        });
7157    }
7158
7159    fn jump(
7160        workspace: &mut Workspace,
7161        path: ProjectPath,
7162        position: Point,
7163        anchor: language::Anchor,
7164        cx: &mut ViewContext<Workspace>,
7165    ) {
7166        let editor = workspace.open_path(path, None, true, cx);
7167        cx.spawn(|_, mut cx| async move {
7168            let editor = editor
7169                .await?
7170                .downcast::<Editor>()
7171                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7172                .downgrade();
7173            editor.update(&mut cx, |editor, cx| {
7174                let buffer = editor
7175                    .buffer()
7176                    .read(cx)
7177                    .as_singleton()
7178                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7179                let buffer = buffer.read(cx);
7180                let cursor = if buffer.can_resolve(&anchor) {
7181                    language::ToPoint::to_point(&anchor, buffer)
7182                } else {
7183                    buffer.clip_point(position, Bias::Left)
7184                };
7185
7186                let nav_history = editor.nav_history.take();
7187                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7188                    s.select_ranges([cursor..cursor]);
7189                });
7190                editor.nav_history = nav_history;
7191
7192                anyhow::Ok(())
7193            })??;
7194
7195            anyhow::Ok(())
7196        })
7197        .detach_and_log_err(cx);
7198    }
7199
7200    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7201        let snapshot = self.buffer.read(cx).read(cx);
7202        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7203        Some(
7204            ranges
7205                .iter()
7206                .map(move |range| {
7207                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7208                })
7209                .collect(),
7210        )
7211    }
7212
7213    fn selection_replacement_ranges(
7214        &self,
7215        range: Range<OffsetUtf16>,
7216        cx: &AppContext,
7217    ) -> Vec<Range<OffsetUtf16>> {
7218        let selections = self.selections.all::<OffsetUtf16>(cx);
7219        let newest_selection = selections
7220            .iter()
7221            .max_by_key(|selection| selection.id)
7222            .unwrap();
7223        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7224        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7225        let snapshot = self.buffer.read(cx).read(cx);
7226        selections
7227            .into_iter()
7228            .map(|mut selection| {
7229                selection.start.0 =
7230                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7231                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7232                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7233                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7234            })
7235            .collect()
7236    }
7237
7238    fn report_copilot_event(
7239        &self,
7240        suggestion_id: Option<String>,
7241        suggestion_accepted: bool,
7242        cx: &AppContext,
7243    ) {
7244        let Some(project) = &self.project else {
7245            return
7246        };
7247
7248        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7249        let file_extension = self
7250            .buffer
7251            .read(cx)
7252            .as_singleton()
7253            .and_then(|b| b.read(cx).file())
7254            .and_then(|file| Path::new(file.file_name(cx)).extension())
7255            .and_then(|e| e.to_str())
7256            .map(|a| a.to_string());
7257
7258        let telemetry = project.read(cx).client().telemetry().clone();
7259        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7260
7261        let event = ClickhouseEvent::Copilot {
7262            suggestion_id,
7263            suggestion_accepted,
7264            file_extension,
7265        };
7266        telemetry.report_clickhouse_event(event, telemetry_settings);
7267    }
7268
7269    fn report_editor_event(
7270        &self,
7271        name: &'static str,
7272        file_extension: Option<String>,
7273        cx: &AppContext,
7274    ) {
7275        let Some(project) = &self.project else {
7276            return
7277        };
7278
7279        // If None, we are in a file without an extension
7280        let file = self
7281            .buffer
7282            .read(cx)
7283            .as_singleton()
7284            .and_then(|b| b.read(cx).file());
7285        let file_extension = file_extension.or(file
7286            .as_ref()
7287            .and_then(|file| Path::new(file.file_name(cx)).extension())
7288            .and_then(|e| e.to_str())
7289            .map(|a| a.to_string()));
7290
7291        let vim_mode = cx
7292            .global::<SettingsStore>()
7293            .raw_user_settings()
7294            .get("vim_mode")
7295            == Some(&serde_json::Value::Bool(true));
7296        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7297        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7298        let copilot_enabled_for_language = self
7299            .buffer
7300            .read(cx)
7301            .settings_at(0, cx)
7302            .show_copilot_suggestions;
7303
7304        let telemetry = project.read(cx).client().telemetry().clone();
7305        let event = ClickhouseEvent::Editor {
7306            file_extension,
7307            vim_mode,
7308            operation: name,
7309            copilot_enabled,
7310            copilot_enabled_for_language,
7311        };
7312        telemetry.report_clickhouse_event(event, telemetry_settings)
7313    }
7314
7315    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7316    /// with each line being an array of {text, highlight} objects.
7317    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7318        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7319            return;
7320        };
7321
7322        #[derive(Serialize)]
7323        struct Chunk<'a> {
7324            text: String,
7325            highlight: Option<&'a str>,
7326        }
7327
7328        let snapshot = buffer.read(cx).snapshot();
7329        let range = self
7330            .selected_text_range(cx)
7331            .and_then(|selected_range| {
7332                if selected_range.is_empty() {
7333                    None
7334                } else {
7335                    Some(selected_range)
7336                }
7337            })
7338            .unwrap_or_else(|| 0..snapshot.len());
7339
7340        let chunks = snapshot.chunks(range, true);
7341        let mut lines = Vec::new();
7342        let mut line: VecDeque<Chunk> = VecDeque::new();
7343
7344        let theme = &theme::current(cx).editor.syntax;
7345
7346        for chunk in chunks {
7347            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7348            let mut chunk_lines = chunk.text.split("\n").peekable();
7349            while let Some(text) = chunk_lines.next() {
7350                let mut merged_with_last_token = false;
7351                if let Some(last_token) = line.back_mut() {
7352                    if last_token.highlight == highlight {
7353                        last_token.text.push_str(text);
7354                        merged_with_last_token = true;
7355                    }
7356                }
7357
7358                if !merged_with_last_token {
7359                    line.push_back(Chunk {
7360                        text: text.into(),
7361                        highlight,
7362                    });
7363                }
7364
7365                if chunk_lines.peek().is_some() {
7366                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7367                        line.pop_front();
7368                    }
7369                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7370                        line.pop_back();
7371                    }
7372
7373                    lines.push(mem::take(&mut line));
7374                }
7375            }
7376        }
7377
7378        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7379        cx.write_to_clipboard(ClipboardItem::new(lines));
7380    }
7381}
7382
7383fn consume_contiguous_rows(
7384    contiguous_row_selections: &mut Vec<Selection<Point>>,
7385    selection: &Selection<Point>,
7386    display_map: &DisplaySnapshot,
7387    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7388) -> (u32, u32) {
7389    contiguous_row_selections.push(selection.clone());
7390    let start_row = selection.start.row;
7391    let mut end_row = ending_row(selection, display_map);
7392
7393    while let Some(next_selection) = selections.peek() {
7394        if next_selection.start.row <= end_row {
7395            end_row = ending_row(next_selection, display_map);
7396            contiguous_row_selections.push(selections.next().unwrap().clone());
7397        } else {
7398            break;
7399        }
7400    }
7401    (start_row, end_row)
7402}
7403
7404fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7405    if next_selection.end.column > 0 || next_selection.is_empty() {
7406        display_map.next_line_boundary(next_selection.end).0.row + 1
7407    } else {
7408        next_selection.end.row
7409    }
7410}
7411
7412impl EditorSnapshot {
7413    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7414        self.display_snapshot.buffer_snapshot.language_at(position)
7415    }
7416
7417    pub fn is_focused(&self) -> bool {
7418        self.is_focused
7419    }
7420
7421    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7422        self.placeholder_text.as_ref()
7423    }
7424
7425    pub fn scroll_position(&self) -> Vector2F {
7426        self.scroll_anchor.scroll_position(&self.display_snapshot)
7427    }
7428}
7429
7430impl Deref for EditorSnapshot {
7431    type Target = DisplaySnapshot;
7432
7433    fn deref(&self) -> &Self::Target {
7434        &self.display_snapshot
7435    }
7436}
7437
7438#[derive(Clone, Debug, PartialEq, Eq)]
7439pub enum Event {
7440    InputIgnored {
7441        text: Arc<str>,
7442    },
7443    ExcerptsAdded {
7444        buffer: ModelHandle<Buffer>,
7445        predecessor: ExcerptId,
7446        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7447    },
7448    ExcerptsRemoved {
7449        ids: Vec<ExcerptId>,
7450    },
7451    BufferEdited,
7452    Edited,
7453    Reparsed,
7454    Focused,
7455    Blurred,
7456    DirtyChanged,
7457    Saved,
7458    TitleChanged,
7459    DiffBaseChanged,
7460    SelectionsChanged {
7461        local: bool,
7462    },
7463    ScrollPositionChanged {
7464        local: bool,
7465        autoscroll: bool,
7466    },
7467    Closed,
7468}
7469
7470pub struct EditorFocused(pub ViewHandle<Editor>);
7471pub struct EditorBlurred(pub ViewHandle<Editor>);
7472pub struct EditorReleased(pub WeakViewHandle<Editor>);
7473
7474impl Entity for Editor {
7475    type Event = Event;
7476
7477    fn release(&mut self, cx: &mut AppContext) {
7478        cx.emit_global(EditorReleased(self.handle.clone()));
7479    }
7480}
7481
7482impl View for Editor {
7483    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7484        let style = self.style(cx);
7485        let font_changed = self.display_map.update(cx, |map, cx| {
7486            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7487            map.set_font(style.text.font_id, style.text.font_size, cx)
7488        });
7489
7490        if font_changed {
7491            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7492                hide_hover(editor, cx);
7493                hide_link_definition(editor, cx);
7494            });
7495        }
7496
7497        Stack::new()
7498            .with_child(EditorElement::new(style.clone()))
7499            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7500            .into_any()
7501    }
7502
7503    fn ui_name() -> &'static str {
7504        "Editor"
7505    }
7506
7507    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7508        if cx.is_self_focused() {
7509            let focused_event = EditorFocused(cx.handle());
7510            cx.emit(Event::Focused);
7511            cx.emit_global(focused_event);
7512        }
7513        if let Some(rename) = self.pending_rename.as_ref() {
7514            cx.focus(&rename.editor);
7515        } else {
7516            if !self.focused {
7517                self.blink_manager.update(cx, BlinkManager::enable);
7518            }
7519            self.focused = true;
7520            self.buffer.update(cx, |buffer, cx| {
7521                buffer.finalize_last_transaction(cx);
7522                if self.leader_replica_id.is_none() {
7523                    buffer.set_active_selections(
7524                        &self.selections.disjoint_anchors(),
7525                        self.selections.line_mode,
7526                        self.cursor_shape,
7527                        cx,
7528                    );
7529                }
7530            });
7531        }
7532    }
7533
7534    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7535        let blurred_event = EditorBlurred(cx.handle());
7536        cx.emit_global(blurred_event);
7537        self.focused = false;
7538        self.blink_manager.update(cx, BlinkManager::disable);
7539        self.buffer
7540            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7541        self.hide_context_menu(cx);
7542        hide_hover(self, cx);
7543        cx.emit(Event::Blurred);
7544        cx.notify();
7545    }
7546
7547    fn modifiers_changed(
7548        &mut self,
7549        event: &gpui::platform::ModifiersChangedEvent,
7550        cx: &mut ViewContext<Self>,
7551    ) -> bool {
7552        let pending_selection = self.has_pending_selection();
7553
7554        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7555            if event.cmd && !pending_selection {
7556                let snapshot = self.snapshot(cx);
7557                let kind = if event.shift {
7558                    LinkDefinitionKind::Type
7559                } else {
7560                    LinkDefinitionKind::Symbol
7561                };
7562
7563                show_link_definition(kind, self, point, snapshot, cx);
7564                return false;
7565            }
7566        }
7567
7568        {
7569            if self.link_go_to_definition_state.symbol_range.is_some()
7570                || !self.link_go_to_definition_state.definitions.is_empty()
7571            {
7572                self.link_go_to_definition_state.symbol_range.take();
7573                self.link_go_to_definition_state.definitions.clear();
7574                cx.notify();
7575            }
7576
7577            self.link_go_to_definition_state.task = None;
7578
7579            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7580        }
7581
7582        false
7583    }
7584
7585    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7586        Self::reset_to_default_keymap_context(keymap);
7587        let mode = match self.mode {
7588            EditorMode::SingleLine => "single_line",
7589            EditorMode::AutoHeight { .. } => "auto_height",
7590            EditorMode::Full => "full",
7591        };
7592        keymap.add_key("mode", mode);
7593        if self.pending_rename.is_some() {
7594            keymap.add_identifier("renaming");
7595        }
7596        match self.context_menu.as_ref() {
7597            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7598            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7599            None => {}
7600        }
7601        for layer in self.keymap_context_layers.values() {
7602            keymap.extend(layer);
7603        }
7604
7605        if let Some(extension) = self
7606            .buffer
7607            .read(cx)
7608            .as_singleton()
7609            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7610        {
7611            keymap.add_key("extension", extension.to_string());
7612        }
7613    }
7614
7615    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7616        Some(
7617            self.buffer
7618                .read(cx)
7619                .read(cx)
7620                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7621                .collect(),
7622        )
7623    }
7624
7625    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7626        // Prevent the IME menu from appearing when holding down an alphabetic key
7627        // while input is disabled.
7628        if !self.input_enabled {
7629            return None;
7630        }
7631
7632        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7633        Some(range.start.0..range.end.0)
7634    }
7635
7636    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7637        let snapshot = self.buffer.read(cx).read(cx);
7638        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7639        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7640    }
7641
7642    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7643        self.clear_text_highlights::<InputComposition>(cx);
7644        self.ime_transaction.take();
7645    }
7646
7647    fn replace_text_in_range(
7648        &mut self,
7649        range_utf16: Option<Range<usize>>,
7650        text: &str,
7651        cx: &mut ViewContext<Self>,
7652    ) {
7653        self.transact(cx, |this, cx| {
7654            if this.input_enabled {
7655                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7656                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7657                    Some(this.selection_replacement_ranges(range_utf16, cx))
7658                } else {
7659                    this.marked_text_ranges(cx)
7660                };
7661
7662                if let Some(new_selected_ranges) = new_selected_ranges {
7663                    this.change_selections(None, cx, |selections| {
7664                        selections.select_ranges(new_selected_ranges)
7665                    });
7666                }
7667            }
7668
7669            this.handle_input(text, cx);
7670        });
7671
7672        if !self.input_enabled {
7673            return;
7674        }
7675
7676        if let Some(transaction) = self.ime_transaction {
7677            self.buffer.update(cx, |buffer, cx| {
7678                buffer.group_until_transaction(transaction, cx);
7679            });
7680        }
7681
7682        self.unmark_text(cx);
7683    }
7684
7685    fn replace_and_mark_text_in_range(
7686        &mut self,
7687        range_utf16: Option<Range<usize>>,
7688        text: &str,
7689        new_selected_range_utf16: Option<Range<usize>>,
7690        cx: &mut ViewContext<Self>,
7691    ) {
7692        if !self.input_enabled {
7693            return;
7694        }
7695
7696        let transaction = self.transact(cx, |this, cx| {
7697            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7698                let snapshot = this.buffer.read(cx).read(cx);
7699                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7700                    for marked_range in &mut marked_ranges {
7701                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7702                        marked_range.start.0 += relative_range_utf16.start;
7703                        marked_range.start =
7704                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7705                        marked_range.end =
7706                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7707                    }
7708                }
7709                Some(marked_ranges)
7710            } else if let Some(range_utf16) = range_utf16 {
7711                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7712                Some(this.selection_replacement_ranges(range_utf16, cx))
7713            } else {
7714                None
7715            };
7716
7717            if let Some(ranges) = ranges_to_replace {
7718                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7719            }
7720
7721            let marked_ranges = {
7722                let snapshot = this.buffer.read(cx).read(cx);
7723                this.selections
7724                    .disjoint_anchors()
7725                    .iter()
7726                    .map(|selection| {
7727                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7728                    })
7729                    .collect::<Vec<_>>()
7730            };
7731
7732            if text.is_empty() {
7733                this.unmark_text(cx);
7734            } else {
7735                this.highlight_text::<InputComposition>(
7736                    marked_ranges.clone(),
7737                    this.style(cx).composition_mark,
7738                    cx,
7739                );
7740            }
7741
7742            this.handle_input(text, cx);
7743
7744            if let Some(new_selected_range) = new_selected_range_utf16 {
7745                let snapshot = this.buffer.read(cx).read(cx);
7746                let new_selected_ranges = marked_ranges
7747                    .into_iter()
7748                    .map(|marked_range| {
7749                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7750                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7751                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7752                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7753                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7754                    })
7755                    .collect::<Vec<_>>();
7756
7757                drop(snapshot);
7758                this.change_selections(None, cx, |selections| {
7759                    selections.select_ranges(new_selected_ranges)
7760                });
7761            }
7762        });
7763
7764        self.ime_transaction = self.ime_transaction.or(transaction);
7765        if let Some(transaction) = self.ime_transaction {
7766            self.buffer.update(cx, |buffer, cx| {
7767                buffer.group_until_transaction(transaction, cx);
7768            });
7769        }
7770
7771        if self.text_highlights::<InputComposition>(cx).is_none() {
7772            self.ime_transaction.take();
7773        }
7774    }
7775}
7776
7777fn build_style(
7778    settings: &ThemeSettings,
7779    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7780    override_text_style: Option<&OverrideTextStyle>,
7781    cx: &AppContext,
7782) -> EditorStyle {
7783    let font_cache = cx.font_cache();
7784
7785    let theme_id = settings.theme.meta.id;
7786    let mut theme = settings.theme.editor.clone();
7787    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7788        let field_editor_theme = get_field_editor_theme(&settings.theme);
7789        theme.text_color = field_editor_theme.text.color;
7790        theme.selection = field_editor_theme.selection;
7791        theme.background = field_editor_theme
7792            .container
7793            .background_color
7794            .unwrap_or_default();
7795        EditorStyle {
7796            text: field_editor_theme.text,
7797            placeholder_text: field_editor_theme.placeholder_text,
7798            theme,
7799            theme_id,
7800        }
7801    } else {
7802        let font_family_id = settings.buffer_font_family;
7803        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7804        let font_properties = Default::default();
7805        let font_id = font_cache
7806            .select_font(font_family_id, &font_properties)
7807            .unwrap();
7808        let font_size = settings.buffer_font_size(cx);
7809        EditorStyle {
7810            text: TextStyle {
7811                color: settings.theme.editor.text_color,
7812                font_family_name,
7813                font_family_id,
7814                font_id,
7815                font_size,
7816                font_properties,
7817                underline: Default::default(),
7818            },
7819            placeholder_text: None,
7820            theme,
7821            theme_id,
7822        }
7823    };
7824
7825    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7826        if let Some(highlighted) = style
7827            .text
7828            .clone()
7829            .highlight(highlight_style, font_cache)
7830            .log_err()
7831        {
7832            style.text = highlighted;
7833        }
7834    }
7835
7836    style
7837}
7838
7839trait SelectionExt {
7840    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7841    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7842    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7843    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7844        -> Range<u32>;
7845}
7846
7847impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7848    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7849        let start = self.start.to_point(buffer);
7850        let end = self.end.to_point(buffer);
7851        if self.reversed {
7852            end..start
7853        } else {
7854            start..end
7855        }
7856    }
7857
7858    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7859        let start = self.start.to_offset(buffer);
7860        let end = self.end.to_offset(buffer);
7861        if self.reversed {
7862            end..start
7863        } else {
7864            start..end
7865        }
7866    }
7867
7868    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7869        let start = self
7870            .start
7871            .to_point(&map.buffer_snapshot)
7872            .to_display_point(map);
7873        let end = self
7874            .end
7875            .to_point(&map.buffer_snapshot)
7876            .to_display_point(map);
7877        if self.reversed {
7878            end..start
7879        } else {
7880            start..end
7881        }
7882    }
7883
7884    fn spanned_rows(
7885        &self,
7886        include_end_if_at_line_start: bool,
7887        map: &DisplaySnapshot,
7888    ) -> Range<u32> {
7889        let start = self.start.to_point(&map.buffer_snapshot);
7890        let mut end = self.end.to_point(&map.buffer_snapshot);
7891        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7892            end.row -= 1;
7893        }
7894
7895        let buffer_start = map.prev_line_boundary(start).0;
7896        let buffer_end = map.next_line_boundary(end).0;
7897        buffer_start.row..buffer_end.row + 1
7898    }
7899}
7900
7901impl<T: InvalidationRegion> InvalidationStack<T> {
7902    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7903    where
7904        S: Clone + ToOffset,
7905    {
7906        while let Some(region) = self.last() {
7907            let all_selections_inside_invalidation_ranges =
7908                if selections.len() == region.ranges().len() {
7909                    selections
7910                        .iter()
7911                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7912                        .all(|(selection, invalidation_range)| {
7913                            let head = selection.head().to_offset(buffer);
7914                            invalidation_range.start <= head && invalidation_range.end >= head
7915                        })
7916                } else {
7917                    false
7918                };
7919
7920            if all_selections_inside_invalidation_ranges {
7921                break;
7922            } else {
7923                self.pop();
7924            }
7925        }
7926    }
7927}
7928
7929impl<T> Default for InvalidationStack<T> {
7930    fn default() -> Self {
7931        Self(Default::default())
7932    }
7933}
7934
7935impl<T> Deref for InvalidationStack<T> {
7936    type Target = Vec<T>;
7937
7938    fn deref(&self) -> &Self::Target {
7939        &self.0
7940    }
7941}
7942
7943impl<T> DerefMut for InvalidationStack<T> {
7944    fn deref_mut(&mut self) -> &mut Self::Target {
7945        &mut self.0
7946    }
7947}
7948
7949impl InvalidationRegion for SnippetState {
7950    fn ranges(&self) -> &[Range<Anchor>] {
7951        &self.ranges[self.active_index]
7952    }
7953}
7954
7955impl Deref for EditorStyle {
7956    type Target = theme::Editor;
7957
7958    fn deref(&self) -> &Self::Target {
7959        &self.theme
7960    }
7961}
7962
7963pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7964    let mut highlighted_lines = Vec::new();
7965
7966    for (index, line) in diagnostic.message.lines().enumerate() {
7967        let line = match &diagnostic.source {
7968            Some(source) if index == 0 => {
7969                let source_highlight = Vec::from_iter(0..source.len());
7970                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7971            }
7972
7973            _ => highlight_diagnostic_message(Vec::new(), line),
7974        };
7975        highlighted_lines.push(line);
7976    }
7977    let message = diagnostic.message;
7978    Arc::new(move |cx: &mut BlockContext| {
7979        let message = message.clone();
7980        let settings = settings::get::<ThemeSettings>(cx);
7981        let tooltip_style = settings.theme.tooltip.clone();
7982        let theme = &settings.theme.editor;
7983        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7984        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7985        let anchor_x = cx.anchor_x;
7986        enum BlockContextToolip {}
7987        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
7988            Flex::column()
7989                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7990                    Label::new(
7991                        line.clone(),
7992                        style.message.clone().with_font_size(font_size),
7993                    )
7994                    .with_highlights(highlights.clone())
7995                    .contained()
7996                    .with_margin_left(anchor_x)
7997                }))
7998                .aligned()
7999                .left()
8000                .into_any()
8001        })
8002        .with_cursor_style(CursorStyle::PointingHand)
8003        .on_click(MouseButton::Left, move |_, _, cx| {
8004            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8005        })
8006        // We really need to rethink this ID system...
8007        .with_tooltip::<BlockContextToolip>(
8008            cx.block_id,
8009            "Copy diagnostic message".to_string(),
8010            None,
8011            tooltip_style,
8012            cx,
8013        )
8014        .into_any()
8015    })
8016}
8017
8018pub fn highlight_diagnostic_message(
8019    initial_highlights: Vec<usize>,
8020    message: &str,
8021) -> (String, Vec<usize>) {
8022    let mut message_without_backticks = String::new();
8023    let mut prev_offset = 0;
8024    let mut inside_block = false;
8025    let mut highlights = initial_highlights;
8026    for (match_ix, (offset, _)) in message
8027        .match_indices('`')
8028        .chain([(message.len(), "")])
8029        .enumerate()
8030    {
8031        message_without_backticks.push_str(&message[prev_offset..offset]);
8032        if inside_block {
8033            highlights.extend(prev_offset - match_ix..offset - match_ix);
8034        }
8035
8036        inside_block = !inside_block;
8037        prev_offset = offset + 1;
8038    }
8039
8040    (message_without_backticks, highlights)
8041}
8042
8043pub fn diagnostic_style(
8044    severity: DiagnosticSeverity,
8045    valid: bool,
8046    theme: &theme::Editor,
8047) -> DiagnosticStyle {
8048    match (severity, valid) {
8049        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8050        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8051        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8052        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8053        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8054        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8055        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8056        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8057        _ => theme.invalid_hint_diagnostic.clone(),
8058    }
8059}
8060
8061pub fn combine_syntax_and_fuzzy_match_highlights(
8062    text: &str,
8063    default_style: HighlightStyle,
8064    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8065    match_indices: &[usize],
8066) -> Vec<(Range<usize>, HighlightStyle)> {
8067    let mut result = Vec::new();
8068    let mut match_indices = match_indices.iter().copied().peekable();
8069
8070    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8071    {
8072        syntax_highlight.weight = None;
8073
8074        // Add highlights for any fuzzy match characters before the next
8075        // syntax highlight range.
8076        while let Some(&match_index) = match_indices.peek() {
8077            if match_index >= range.start {
8078                break;
8079            }
8080            match_indices.next();
8081            let end_index = char_ix_after(match_index, text);
8082            let mut match_style = default_style;
8083            match_style.weight = Some(fonts::Weight::BOLD);
8084            result.push((match_index..end_index, match_style));
8085        }
8086
8087        if range.start == usize::MAX {
8088            break;
8089        }
8090
8091        // Add highlights for any fuzzy match characters within the
8092        // syntax highlight range.
8093        let mut offset = range.start;
8094        while let Some(&match_index) = match_indices.peek() {
8095            if match_index >= range.end {
8096                break;
8097            }
8098
8099            match_indices.next();
8100            if match_index > offset {
8101                result.push((offset..match_index, syntax_highlight));
8102            }
8103
8104            let mut end_index = char_ix_after(match_index, text);
8105            while let Some(&next_match_index) = match_indices.peek() {
8106                if next_match_index == end_index && next_match_index < range.end {
8107                    end_index = char_ix_after(next_match_index, text);
8108                    match_indices.next();
8109                } else {
8110                    break;
8111                }
8112            }
8113
8114            let mut match_style = syntax_highlight;
8115            match_style.weight = Some(fonts::Weight::BOLD);
8116            result.push((match_index..end_index, match_style));
8117            offset = end_index;
8118        }
8119
8120        if offset < range.end {
8121            result.push((offset..range.end, syntax_highlight));
8122        }
8123    }
8124
8125    fn char_ix_after(ix: usize, text: &str) -> usize {
8126        ix + text[ix..].chars().next().unwrap().len_utf8()
8127    }
8128
8129    result
8130}
8131
8132pub fn styled_runs_for_code_label<'a>(
8133    label: &'a CodeLabel,
8134    syntax_theme: &'a theme::SyntaxTheme,
8135) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8136    let fade_out = HighlightStyle {
8137        fade_out: Some(0.35),
8138        ..Default::default()
8139    };
8140
8141    let mut prev_end = label.filter_range.end;
8142    label
8143        .runs
8144        .iter()
8145        .enumerate()
8146        .flat_map(move |(ix, (range, highlight_id))| {
8147            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8148                style
8149            } else {
8150                return Default::default();
8151            };
8152            let mut muted_style = style;
8153            muted_style.highlight(fade_out);
8154
8155            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8156            if range.start >= label.filter_range.end {
8157                if range.start > prev_end {
8158                    runs.push((prev_end..range.start, fade_out));
8159                }
8160                runs.push((range.clone(), muted_style));
8161            } else if range.end <= label.filter_range.end {
8162                runs.push((range.clone(), style));
8163            } else {
8164                runs.push((range.start..label.filter_range.end, style));
8165                runs.push((label.filter_range.end..range.end, muted_style));
8166            }
8167            prev_end = cmp::max(prev_end, range.end);
8168
8169            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8170                runs.push((prev_end..label.text.len(), fade_out));
8171            }
8172
8173            runs
8174        })
8175}
8176
8177pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8178    let mut index = 0;
8179    let mut codepoints = text.char_indices().peekable();
8180
8181    std::iter::from_fn(move || {
8182        let start_index = index;
8183        while let Some((new_index, codepoint)) = codepoints.next() {
8184            index = new_index + codepoint.len_utf8();
8185            let current_upper = codepoint.is_uppercase();
8186            let next_upper = codepoints
8187                .peek()
8188                .map(|(_, c)| c.is_uppercase())
8189                .unwrap_or(false);
8190
8191            if !current_upper && next_upper {
8192                return Some(&text[start_index..index]);
8193            }
8194        }
8195
8196        index = text.len();
8197        if start_index < text.len() {
8198            return Some(&text[start_index..]);
8199        }
8200        None
8201    })
8202    .flat_map(|word| word.split_inclusive('_'))
8203}
8204
8205trait RangeToAnchorExt {
8206    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8207}
8208
8209impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8210    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8211        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8212    }
8213}