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