editor.rs

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