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