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