editor.rs

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