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