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