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