editor.rs

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