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