editor.rs

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