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 ::git::diff::DiffHunk;
  23use aho_corasick::AhoCorasick;
  24use anyhow::{anyhow, Result};
  25use blink_manager::BlinkManager;
  26use client::ClickhouseEvent;
  27use clock::ReplicaId;
  28use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  29use copilot::Copilot;
  30pub use display_map::DisplayPoint;
  31use display_map::*;
  32pub use element::*;
  33use futures::FutureExt;
  34use fuzzy::{StringMatch, StringMatchCandidate};
  35use gpui::{
  36    actions,
  37    color::Color,
  38    elements::*,
  39    executor,
  40    fonts::{self, HighlightStyle, TextStyle},
  41    geometry::vector::Vector2F,
  42    impl_actions,
  43    keymap_matcher::KeymapContext,
  44    platform::{CursorStyle, MouseButton},
  45    serde_json::{self, json},
  46    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  47    ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
  48};
  49use highlight_matching_bracket::refresh_matching_bracket_highlights;
  50use hover_popover::{hide_hover, HoverState};
  51pub use items::MAX_TAB_TITLE_LEN;
  52use itertools::Itertools;
  53pub use language::{char_kind, CharKind};
  54use language::{
  55    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  56    Diagnostic, DiagnosticSeverity, File, IndentKind, IndentSize, Language, OffsetRangeExt,
  57    OffsetUtf16, Point, Selection, SelectionGoal, TransactionId,
  58};
  59use link_go_to_definition::{
  60    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  61};
  62pub use multi_buffer::{
  63    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  64    ToPoint,
  65};
  66use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  67use ordered_float::OrderedFloat;
  68use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  69use scroll::{
  70    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  71};
  72use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  73use serde::{Deserialize, Serialize};
  74use settings::Settings;
  75use smallvec::SmallVec;
  76use snippet::Snippet;
  77use std::{
  78    any::TypeId,
  79    borrow::Cow,
  80    cmp::{self, Ordering, Reverse},
  81    mem,
  82    num::NonZeroU32,
  83    ops::{Deref, DerefMut, Range},
  84    path::Path,
  85    sync::Arc,
  86    time::{Duration, Instant},
  87};
  88pub use sum_tree::Bias;
  89use theme::{DiagnosticStyle, Theme};
  90use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  91use workspace::{ItemNavHistory, ViewId, Workspace};
  92
  93use crate::git::diff_hunk_to_display;
  94
  95const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  96const MAX_LINE_LEN: usize = 1024;
  97const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  98const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  99const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 100
 101pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 102
 103#[derive(Clone, Deserialize, PartialEq, Default)]
 104pub struct SelectNext {
 105    #[serde(default)]
 106    pub replace_newest: bool,
 107}
 108
 109#[derive(Clone, Deserialize, PartialEq)]
 110pub struct SelectToBeginningOfLine {
 111    #[serde(default)]
 112    stop_at_soft_wraps: bool,
 113}
 114
 115#[derive(Clone, Default, Deserialize, PartialEq)]
 116pub struct MovePageUp {
 117    #[serde(default)]
 118    center_cursor: bool,
 119}
 120
 121#[derive(Clone, Default, Deserialize, PartialEq)]
 122pub struct MovePageDown {
 123    #[serde(default)]
 124    center_cursor: bool,
 125}
 126
 127#[derive(Clone, Deserialize, PartialEq)]
 128pub struct SelectToEndOfLine {
 129    #[serde(default)]
 130    stop_at_soft_wraps: bool,
 131}
 132
 133#[derive(Clone, Deserialize, PartialEq)]
 134pub struct ToggleCodeActions {
 135    #[serde(default)]
 136    pub deployed_from_indicator: bool,
 137}
 138
 139#[derive(Clone, Default, Deserialize, PartialEq)]
 140pub struct ConfirmCompletion {
 141    #[serde(default)]
 142    pub item_ix: Option<usize>,
 143}
 144
 145#[derive(Clone, Default, Deserialize, PartialEq)]
 146pub struct ConfirmCodeAction {
 147    #[serde(default)]
 148    pub item_ix: Option<usize>,
 149}
 150
 151#[derive(Clone, Default, Deserialize, PartialEq)]
 152pub struct ToggleComments {
 153    #[serde(default)]
 154    pub advance_downwards: bool,
 155}
 156
 157#[derive(Clone, Default, Deserialize, PartialEq)]
 158pub struct FoldAt {
 159    pub buffer_row: u32,
 160}
 161
 162#[derive(Clone, Default, Deserialize, PartialEq)]
 163pub struct UnfoldAt {
 164    pub buffer_row: u32,
 165}
 166
 167#[derive(Clone, Default, Deserialize, PartialEq)]
 168pub struct GutterHover {
 169    pub hovered: bool,
 170}
 171
 172actions!(
 173    editor,
 174    [
 175        Cancel,
 176        Backspace,
 177        Delete,
 178        Newline,
 179        NewlineAbove,
 180        NewlineBelow,
 181        GoToDiagnostic,
 182        GoToPrevDiagnostic,
 183        GoToHunk,
 184        GoToPrevHunk,
 185        Indent,
 186        Outdent,
 187        DeleteLine,
 188        DeleteToPreviousWordStart,
 189        DeleteToPreviousSubwordStart,
 190        DeleteToNextWordEnd,
 191        DeleteToNextSubwordEnd,
 192        DeleteToBeginningOfLine,
 193        DeleteToEndOfLine,
 194        CutToEndOfLine,
 195        DuplicateLine,
 196        MoveLineUp,
 197        MoveLineDown,
 198        Transpose,
 199        Cut,
 200        Copy,
 201        Paste,
 202        Undo,
 203        Redo,
 204        MoveUp,
 205        PageUp,
 206        MoveDown,
 207        PageDown,
 208        MoveLeft,
 209        MoveRight,
 210        MoveToPreviousWordStart,
 211        MoveToPreviousSubwordStart,
 212        MoveToNextWordEnd,
 213        MoveToNextSubwordEnd,
 214        MoveToBeginningOfLine,
 215        MoveToEndOfLine,
 216        MoveToBeginning,
 217        MoveToEnd,
 218        SelectUp,
 219        SelectDown,
 220        SelectLeft,
 221        SelectRight,
 222        SelectToPreviousWordStart,
 223        SelectToPreviousSubwordStart,
 224        SelectToNextWordEnd,
 225        SelectToNextSubwordEnd,
 226        SelectToBeginning,
 227        SelectToEnd,
 228        SelectAll,
 229        SelectLine,
 230        SplitSelectionIntoLines,
 231        AddSelectionAbove,
 232        AddSelectionBelow,
 233        Tab,
 234        TabPrev,
 235        ShowCharacterPalette,
 236        SelectLargerSyntaxNode,
 237        SelectSmallerSyntaxNode,
 238        GoToDefinition,
 239        GoToTypeDefinition,
 240        MoveToEnclosingBracket,
 241        UndoSelection,
 242        RedoSelection,
 243        FindAllReferences,
 244        Rename,
 245        ConfirmRename,
 246        Fold,
 247        UnfoldLines,
 248        FoldSelectedRanges,
 249        ShowCompletions,
 250        OpenExcerpts,
 251        RestartLanguageServer,
 252        Hover,
 253        Format,
 254        ToggleSoftWrap,
 255        RevealInFinder,
 256        CopyPath,
 257        CopyRelativePath,
 258        CopyHighlightJson
 259    ]
 260);
 261
 262impl_actions!(
 263    editor,
 264    [
 265        SelectNext,
 266        SelectToBeginningOfLine,
 267        SelectToEndOfLine,
 268        ToggleCodeActions,
 269        MovePageUp,
 270        MovePageDown,
 271        ConfirmCompletion,
 272        ConfirmCodeAction,
 273        ToggleComments,
 274        FoldAt,
 275        UnfoldAt,
 276        GutterHover
 277    ]
 278);
 279
 280enum DocumentHighlightRead {}
 281enum DocumentHighlightWrite {}
 282enum InputComposition {}
 283
 284#[derive(Copy, Clone, PartialEq, Eq)]
 285pub enum Direction {
 286    Prev,
 287    Next,
 288}
 289
 290pub fn init(cx: &mut AppContext) {
 291    cx.add_action(Editor::new_file);
 292    cx.add_action(Editor::cancel);
 293    cx.add_action(Editor::newline);
 294    cx.add_action(Editor::newline_above);
 295    cx.add_action(Editor::newline_below);
 296    cx.add_action(Editor::backspace);
 297    cx.add_action(Editor::delete);
 298    cx.add_action(Editor::tab);
 299    cx.add_action(Editor::tab_prev);
 300    cx.add_action(Editor::indent);
 301    cx.add_action(Editor::outdent);
 302    cx.add_action(Editor::delete_line);
 303    cx.add_action(Editor::delete_to_previous_word_start);
 304    cx.add_action(Editor::delete_to_previous_subword_start);
 305    cx.add_action(Editor::delete_to_next_word_end);
 306    cx.add_action(Editor::delete_to_next_subword_end);
 307    cx.add_action(Editor::delete_to_beginning_of_line);
 308    cx.add_action(Editor::delete_to_end_of_line);
 309    cx.add_action(Editor::cut_to_end_of_line);
 310    cx.add_action(Editor::duplicate_line);
 311    cx.add_action(Editor::move_line_up);
 312    cx.add_action(Editor::move_line_down);
 313    cx.add_action(Editor::transpose);
 314    cx.add_action(Editor::cut);
 315    cx.add_action(Editor::copy);
 316    cx.add_action(Editor::paste);
 317    cx.add_action(Editor::undo);
 318    cx.add_action(Editor::redo);
 319    cx.add_action(Editor::move_up);
 320    cx.add_action(Editor::move_page_up);
 321    cx.add_action(Editor::move_down);
 322    cx.add_action(Editor::move_page_down);
 323    cx.add_action(Editor::next_screen);
 324    cx.add_action(Editor::move_left);
 325    cx.add_action(Editor::move_right);
 326    cx.add_action(Editor::move_to_previous_word_start);
 327    cx.add_action(Editor::move_to_previous_subword_start);
 328    cx.add_action(Editor::move_to_next_word_end);
 329    cx.add_action(Editor::move_to_next_subword_end);
 330    cx.add_action(Editor::move_to_beginning_of_line);
 331    cx.add_action(Editor::move_to_end_of_line);
 332    cx.add_action(Editor::move_to_beginning);
 333    cx.add_action(Editor::move_to_end);
 334    cx.add_action(Editor::select_up);
 335    cx.add_action(Editor::select_down);
 336    cx.add_action(Editor::select_left);
 337    cx.add_action(Editor::select_right);
 338    cx.add_action(Editor::select_to_previous_word_start);
 339    cx.add_action(Editor::select_to_previous_subword_start);
 340    cx.add_action(Editor::select_to_next_word_end);
 341    cx.add_action(Editor::select_to_next_subword_end);
 342    cx.add_action(Editor::select_to_beginning_of_line);
 343    cx.add_action(Editor::select_to_end_of_line);
 344    cx.add_action(Editor::select_to_beginning);
 345    cx.add_action(Editor::select_to_end);
 346    cx.add_action(Editor::select_all);
 347    cx.add_action(Editor::select_line);
 348    cx.add_action(Editor::split_selection_into_lines);
 349    cx.add_action(Editor::add_selection_above);
 350    cx.add_action(Editor::add_selection_below);
 351    cx.add_action(Editor::select_next);
 352    cx.add_action(Editor::toggle_comments);
 353    cx.add_action(Editor::select_larger_syntax_node);
 354    cx.add_action(Editor::select_smaller_syntax_node);
 355    cx.add_action(Editor::move_to_enclosing_bracket);
 356    cx.add_action(Editor::undo_selection);
 357    cx.add_action(Editor::redo_selection);
 358    cx.add_action(Editor::go_to_diagnostic);
 359    cx.add_action(Editor::go_to_prev_diagnostic);
 360    cx.add_action(Editor::go_to_hunk);
 361    cx.add_action(Editor::go_to_prev_hunk);
 362    cx.add_action(Editor::go_to_definition);
 363    cx.add_action(Editor::go_to_type_definition);
 364    cx.add_action(Editor::fold);
 365    cx.add_action(Editor::fold_at);
 366    cx.add_action(Editor::unfold_lines);
 367    cx.add_action(Editor::unfold_at);
 368    cx.add_action(Editor::gutter_hover);
 369    cx.add_action(Editor::fold_selected_ranges);
 370    cx.add_action(Editor::show_completions);
 371    cx.add_action(Editor::toggle_code_actions);
 372    cx.add_action(Editor::open_excerpts);
 373    cx.add_action(Editor::toggle_soft_wrap);
 374    cx.add_action(Editor::reveal_in_finder);
 375    cx.add_action(Editor::copy_path);
 376    cx.add_action(Editor::copy_relative_path);
 377    cx.add_action(Editor::copy_highlight_json);
 378    cx.add_async_action(Editor::format);
 379    cx.add_action(Editor::restart_language_server);
 380    cx.add_action(Editor::show_character_palette);
 381    cx.add_async_action(Editor::confirm_completion);
 382    cx.add_async_action(Editor::confirm_code_action);
 383    cx.add_async_action(Editor::rename);
 384    cx.add_async_action(Editor::confirm_rename);
 385    cx.add_async_action(Editor::find_all_references);
 386    cx.add_action(Editor::next_copilot_suggestion);
 387    cx.add_action(Editor::previous_copilot_suggestion);
 388    cx.add_action(Editor::copilot_suggest);
 389
 390    hover_popover::init(cx);
 391    scroll::actions::init(cx);
 392
 393    workspace::register_project_item::<Editor>(cx);
 394    workspace::register_followable_item::<Editor>(cx);
 395    workspace::register_deserializable_item::<Editor>(cx);
 396}
 397
 398trait InvalidationRegion {
 399    fn ranges(&self) -> &[Range<Anchor>];
 400}
 401
 402#[derive(Clone, Debug, PartialEq)]
 403pub enum SelectPhase {
 404    Begin {
 405        position: DisplayPoint,
 406        add: bool,
 407        click_count: usize,
 408    },
 409    BeginColumnar {
 410        position: DisplayPoint,
 411        goal_column: u32,
 412    },
 413    Extend {
 414        position: DisplayPoint,
 415        click_count: usize,
 416    },
 417    Update {
 418        position: DisplayPoint,
 419        goal_column: u32,
 420        scroll_position: Vector2F,
 421    },
 422    End,
 423}
 424
 425#[derive(Clone, Debug)]
 426pub enum SelectMode {
 427    Character,
 428    Word(Range<Anchor>),
 429    Line(Range<Anchor>),
 430    All,
 431}
 432
 433#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 434pub enum EditorMode {
 435    SingleLine,
 436    AutoHeight { max_lines: usize },
 437    Full,
 438}
 439
 440#[derive(Clone)]
 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", None, 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.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3103            }
3104            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3105            cx.notify();
3106            true
3107        } else {
3108            false
3109        }
3110    }
3111
3112    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3113        if self.has_active_copilot_suggestion(cx) {
3114            if let Some(copilot) = Copilot::global(cx) {
3115                copilot
3116                    .update(cx, |copilot, cx| {
3117                        copilot.discard_completions(&self.copilot_state.completions, cx)
3118                    })
3119                    .detach_and_log_err(cx);
3120
3121                self.report_copilot_event(None, false, cx)
3122            }
3123
3124            self.display_map
3125                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
3126            cx.notify();
3127            true
3128        } else {
3129            false
3130        }
3131    }
3132
3133    fn is_copilot_enabled_at(
3134        &self,
3135        location: Anchor,
3136        snapshot: &MultiBufferSnapshot,
3137        cx: &mut ViewContext<Self>,
3138    ) -> bool {
3139        let settings = cx.global::<Settings>();
3140
3141        let path = snapshot.file_at(location).map(|file| file.path());
3142        let language_name = snapshot
3143            .language_at(location)
3144            .map(|language| language.name());
3145        if !settings.show_copilot_suggestions(language_name.as_deref(), path.map(|p| p.as_ref())) {
3146            return false;
3147        }
3148
3149        true
3150    }
3151
3152    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3153        self.display_map.read(cx).has_suggestion()
3154    }
3155
3156    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3157        let snapshot = self.buffer.read(cx).snapshot(cx);
3158        let selection = self.selections.newest_anchor();
3159        let cursor = selection.head();
3160
3161        if self.context_menu.is_some()
3162            || !self.completion_tasks.is_empty()
3163            || selection.start != selection.end
3164        {
3165            self.discard_copilot_suggestion(cx);
3166        } else if let Some(text) = self
3167            .copilot_state
3168            .text_for_active_completion(cursor, &snapshot)
3169        {
3170            self.display_map.update(cx, move |map, cx| {
3171                map.replace_suggestion(
3172                    Some(Suggestion {
3173                        position: cursor,
3174                        text: text.trim_end().into(),
3175                    }),
3176                    cx,
3177                )
3178            });
3179            cx.notify();
3180        } else {
3181            self.discard_copilot_suggestion(cx);
3182        }
3183    }
3184
3185    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3186        self.copilot_state = Default::default();
3187        self.discard_copilot_suggestion(cx);
3188    }
3189
3190    pub fn render_code_actions_indicator(
3191        &self,
3192        style: &EditorStyle,
3193        active: bool,
3194        cx: &mut ViewContext<Self>,
3195    ) -> Option<AnyElement<Self>> {
3196        if self.available_code_actions.is_some() {
3197            enum CodeActions {}
3198            Some(
3199                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3200                    Svg::new("icons/bolt_8.svg")
3201                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3202                })
3203                .with_cursor_style(CursorStyle::PointingHand)
3204                .with_padding(Padding::uniform(3.))
3205                .on_down(MouseButton::Left, |_, this, cx| {
3206                    this.toggle_code_actions(
3207                        &ToggleCodeActions {
3208                            deployed_from_indicator: true,
3209                        },
3210                        cx,
3211                    );
3212                })
3213                .into_any(),
3214            )
3215        } else {
3216            None
3217        }
3218    }
3219
3220    pub fn render_fold_indicators(
3221        &self,
3222        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3223        style: &EditorStyle,
3224        gutter_hovered: bool,
3225        line_height: f32,
3226        gutter_margin: f32,
3227        cx: &mut ViewContext<Self>,
3228    ) -> Vec<Option<AnyElement<Self>>> {
3229        enum FoldIndicators {}
3230
3231        let style = style.folds.clone();
3232
3233        fold_data
3234            .iter()
3235            .enumerate()
3236            .map(|(ix, fold_data)| {
3237                fold_data
3238                    .map(|(fold_status, buffer_row, active)| {
3239                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3240                            MouseEventHandler::<FoldIndicators, _>::new(
3241                                ix as usize,
3242                                cx,
3243                                |mouse_state, _| {
3244                                    Svg::new(match fold_status {
3245                                        FoldStatus::Folded => style.folded_icon.clone(),
3246                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3247                                    })
3248                                    .with_color(
3249                                        style
3250                                            .indicator
3251                                            .style_for(
3252                                                mouse_state,
3253                                                fold_status == FoldStatus::Folded,
3254                                            )
3255                                            .color,
3256                                    )
3257                                    .constrained()
3258                                    .with_width(gutter_margin * style.icon_margin_scale)
3259                                    .aligned()
3260                                    .constrained()
3261                                    .with_height(line_height)
3262                                    .with_width(gutter_margin)
3263                                    .aligned()
3264                                },
3265                            )
3266                            .with_cursor_style(CursorStyle::PointingHand)
3267                            .with_padding(Padding::uniform(3.))
3268                            .on_click(MouseButton::Left, {
3269                                move |_, editor, cx| match fold_status {
3270                                    FoldStatus::Folded => {
3271                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3272                                    }
3273                                    FoldStatus::Foldable => {
3274                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3275                                    }
3276                                }
3277                            })
3278                            .into_any()
3279                        })
3280                    })
3281                    .flatten()
3282            })
3283            .collect()
3284    }
3285
3286    pub fn context_menu_visible(&self) -> bool {
3287        self.context_menu
3288            .as_ref()
3289            .map_or(false, |menu| menu.visible())
3290    }
3291
3292    pub fn render_context_menu(
3293        &self,
3294        cursor_position: DisplayPoint,
3295        style: EditorStyle,
3296        cx: &mut ViewContext<Editor>,
3297    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3298        self.context_menu
3299            .as_ref()
3300            .map(|menu| menu.render(cursor_position, style, cx))
3301    }
3302
3303    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3304        if !matches!(menu, ContextMenu::Completions(_)) {
3305            self.completion_tasks.clear();
3306        }
3307        self.context_menu = Some(menu);
3308        self.discard_copilot_suggestion(cx);
3309        cx.notify();
3310    }
3311
3312    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3313        cx.notify();
3314        self.completion_tasks.clear();
3315        let context_menu = self.context_menu.take();
3316        if context_menu.is_some() {
3317            self.update_visible_copilot_suggestion(cx);
3318        }
3319        context_menu
3320    }
3321
3322    pub fn insert_snippet(
3323        &mut self,
3324        insertion_ranges: &[Range<usize>],
3325        snippet: Snippet,
3326        cx: &mut ViewContext<Self>,
3327    ) -> Result<()> {
3328        let tabstops = self.buffer.update(cx, |buffer, cx| {
3329            let snippet_text: Arc<str> = snippet.text.clone().into();
3330            buffer.edit(
3331                insertion_ranges
3332                    .iter()
3333                    .cloned()
3334                    .map(|range| (range, snippet_text.clone())),
3335                Some(AutoindentMode::EachLine),
3336                cx,
3337            );
3338
3339            let snapshot = &*buffer.read(cx);
3340            let snippet = &snippet;
3341            snippet
3342                .tabstops
3343                .iter()
3344                .map(|tabstop| {
3345                    let mut tabstop_ranges = tabstop
3346                        .iter()
3347                        .flat_map(|tabstop_range| {
3348                            let mut delta = 0_isize;
3349                            insertion_ranges.iter().map(move |insertion_range| {
3350                                let insertion_start = insertion_range.start as isize + delta;
3351                                delta +=
3352                                    snippet.text.len() as isize - insertion_range.len() as isize;
3353
3354                                let start = snapshot.anchor_before(
3355                                    (insertion_start + tabstop_range.start) as usize,
3356                                );
3357                                let end = snapshot
3358                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3359                                start..end
3360                            })
3361                        })
3362                        .collect::<Vec<_>>();
3363                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3364                    tabstop_ranges
3365                })
3366                .collect::<Vec<_>>()
3367        });
3368
3369        if let Some(tabstop) = tabstops.first() {
3370            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3371                s.select_ranges(tabstop.iter().cloned());
3372            });
3373            self.snippet_stack.push(SnippetState {
3374                active_index: 0,
3375                ranges: tabstops,
3376            });
3377        }
3378
3379        Ok(())
3380    }
3381
3382    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3383        self.move_to_snippet_tabstop(Bias::Right, cx)
3384    }
3385
3386    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3387        self.move_to_snippet_tabstop(Bias::Left, cx)
3388    }
3389
3390    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3391        if let Some(mut snippet) = self.snippet_stack.pop() {
3392            match bias {
3393                Bias::Left => {
3394                    if snippet.active_index > 0 {
3395                        snippet.active_index -= 1;
3396                    } else {
3397                        self.snippet_stack.push(snippet);
3398                        return false;
3399                    }
3400                }
3401                Bias::Right => {
3402                    if snippet.active_index + 1 < snippet.ranges.len() {
3403                        snippet.active_index += 1;
3404                    } else {
3405                        self.snippet_stack.push(snippet);
3406                        return false;
3407                    }
3408                }
3409            }
3410            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3411                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3412                    s.select_anchor_ranges(current_ranges.iter().cloned())
3413                });
3414                // If snippet state is not at the last tabstop, push it back on the stack
3415                if snippet.active_index + 1 < snippet.ranges.len() {
3416                    self.snippet_stack.push(snippet);
3417                }
3418                return true;
3419            }
3420        }
3421
3422        false
3423    }
3424
3425    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3426        self.transact(cx, |this, cx| {
3427            this.select_all(&SelectAll, cx);
3428            this.insert("", cx);
3429        });
3430    }
3431
3432    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3433        self.transact(cx, |this, cx| {
3434            this.select_autoclose_pair(cx);
3435            let mut selections = this.selections.all::<Point>(cx);
3436            if !this.selections.line_mode {
3437                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3438                for selection in &mut selections {
3439                    if selection.is_empty() {
3440                        let old_head = selection.head();
3441                        let mut new_head =
3442                            movement::left(&display_map, old_head.to_display_point(&display_map))
3443                                .to_point(&display_map);
3444                        if let Some((buffer, line_buffer_range)) = display_map
3445                            .buffer_snapshot
3446                            .buffer_line_for_row(old_head.row)
3447                        {
3448                            let indent_size =
3449                                buffer.indent_size_for_line(line_buffer_range.start.row);
3450                            let language_name = buffer
3451                                .language_at(line_buffer_range.start)
3452                                .map(|language| language.name());
3453                            let indent_len = match indent_size.kind {
3454                                IndentKind::Space => {
3455                                    cx.global::<Settings>().tab_size(language_name.as_deref())
3456                                }
3457                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3458                            };
3459                            if old_head.column <= indent_size.len && old_head.column > 0 {
3460                                let indent_len = indent_len.get();
3461                                new_head = cmp::min(
3462                                    new_head,
3463                                    Point::new(
3464                                        old_head.row,
3465                                        ((old_head.column - 1) / indent_len) * indent_len,
3466                                    ),
3467                                );
3468                            }
3469                        }
3470
3471                        selection.set_head(new_head, SelectionGoal::None);
3472                    }
3473                }
3474            }
3475
3476            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3477            this.insert("", cx);
3478            this.refresh_copilot_suggestions(true, cx);
3479        });
3480    }
3481
3482    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3483        self.transact(cx, |this, cx| {
3484            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3485                let line_mode = s.line_mode;
3486                s.move_with(|map, selection| {
3487                    if selection.is_empty() && !line_mode {
3488                        let cursor = movement::right(map, selection.head());
3489                        selection.set_head(cursor, SelectionGoal::None);
3490                    }
3491                })
3492            });
3493            this.insert("", cx);
3494            this.refresh_copilot_suggestions(true, cx);
3495        });
3496    }
3497
3498    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3499        if self.move_to_prev_snippet_tabstop(cx) {
3500            return;
3501        }
3502
3503        self.outdent(&Outdent, cx);
3504    }
3505
3506    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3507        if self.move_to_next_snippet_tabstop(cx) {
3508            return;
3509        }
3510
3511        let mut selections = self.selections.all_adjusted(cx);
3512        let buffer = self.buffer.read(cx);
3513        let snapshot = buffer.snapshot(cx);
3514        let rows_iter = selections.iter().map(|s| s.head().row);
3515        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3516
3517        let mut edits = Vec::new();
3518        let mut prev_edited_row = 0;
3519        let mut row_delta = 0;
3520        for selection in &mut selections {
3521            if selection.start.row != prev_edited_row {
3522                row_delta = 0;
3523            }
3524            prev_edited_row = selection.end.row;
3525
3526            // If the selection is non-empty, then increase the indentation of the selected lines.
3527            if !selection.is_empty() {
3528                row_delta =
3529                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3530                continue;
3531            }
3532
3533            // If the selection is empty and the cursor is in the leading whitespace before the
3534            // suggested indentation, then auto-indent the line.
3535            let cursor = selection.head();
3536            let current_indent = snapshot.indent_size_for_line(cursor.row);
3537            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3538                if cursor.column < suggested_indent.len
3539                    && cursor.column <= current_indent.len
3540                    && current_indent.len <= suggested_indent.len
3541                {
3542                    selection.start = Point::new(cursor.row, suggested_indent.len);
3543                    selection.end = selection.start;
3544                    if row_delta == 0 {
3545                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3546                            cursor.row,
3547                            current_indent,
3548                            suggested_indent,
3549                        ));
3550                        row_delta = suggested_indent.len - current_indent.len;
3551                    }
3552                    continue;
3553                }
3554            }
3555
3556            // Accept copilot suggestion if there is only one selection and the cursor is not
3557            // in the leading whitespace.
3558            if self.selections.count() == 1
3559                && cursor.column >= current_indent.len
3560                && self.has_active_copilot_suggestion(cx)
3561            {
3562                self.accept_copilot_suggestion(cx);
3563                return;
3564            }
3565
3566            // Otherwise, insert a hard or soft tab.
3567            let settings = cx.global::<Settings>();
3568            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3569            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3570                IndentSize::tab()
3571            } else {
3572                let tab_size = settings.tab_size(language_name.as_deref()).get();
3573                let char_column = snapshot
3574                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3575                    .flat_map(str::chars)
3576                    .count()
3577                    + row_delta as usize;
3578                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3579                IndentSize::spaces(chars_to_next_tab_stop)
3580            };
3581            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3582            selection.end = selection.start;
3583            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3584            row_delta += tab_size.len;
3585        }
3586
3587        self.transact(cx, |this, cx| {
3588            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3589            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3590            this.refresh_copilot_suggestions(true, cx);
3591        });
3592    }
3593
3594    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3595        let mut selections = self.selections.all::<Point>(cx);
3596        let mut prev_edited_row = 0;
3597        let mut row_delta = 0;
3598        let mut edits = Vec::new();
3599        let buffer = self.buffer.read(cx);
3600        let snapshot = buffer.snapshot(cx);
3601        for selection in &mut selections {
3602            if selection.start.row != prev_edited_row {
3603                row_delta = 0;
3604            }
3605            prev_edited_row = selection.end.row;
3606
3607            row_delta =
3608                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3609        }
3610
3611        self.transact(cx, |this, cx| {
3612            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3613            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3614        });
3615    }
3616
3617    fn indent_selection(
3618        buffer: &MultiBuffer,
3619        snapshot: &MultiBufferSnapshot,
3620        selection: &mut Selection<Point>,
3621        edits: &mut Vec<(Range<Point>, String)>,
3622        delta_for_start_row: u32,
3623        cx: &AppContext,
3624    ) -> u32 {
3625        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3626        let settings = cx.global::<Settings>();
3627        let tab_size = settings.tab_size(language_name.as_deref()).get();
3628        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3629            IndentKind::Tab
3630        } else {
3631            IndentKind::Space
3632        };
3633        let mut start_row = selection.start.row;
3634        let mut end_row = selection.end.row + 1;
3635
3636        // If a selection ends at the beginning of a line, don't indent
3637        // that last line.
3638        if selection.end.column == 0 {
3639            end_row -= 1;
3640        }
3641
3642        // Avoid re-indenting a row that has already been indented by a
3643        // previous selection, but still update this selection's column
3644        // to reflect that indentation.
3645        if delta_for_start_row > 0 {
3646            start_row += 1;
3647            selection.start.column += delta_for_start_row;
3648            if selection.end.row == selection.start.row {
3649                selection.end.column += delta_for_start_row;
3650            }
3651        }
3652
3653        let mut delta_for_end_row = 0;
3654        for row in start_row..end_row {
3655            let current_indent = snapshot.indent_size_for_line(row);
3656            let indent_delta = match (current_indent.kind, indent_kind) {
3657                (IndentKind::Space, IndentKind::Space) => {
3658                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3659                    IndentSize::spaces(columns_to_next_tab_stop)
3660                }
3661                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3662                (_, IndentKind::Tab) => IndentSize::tab(),
3663            };
3664
3665            let row_start = Point::new(row, 0);
3666            edits.push((
3667                row_start..row_start,
3668                indent_delta.chars().collect::<String>(),
3669            ));
3670
3671            // Update this selection's endpoints to reflect the indentation.
3672            if row == selection.start.row {
3673                selection.start.column += indent_delta.len;
3674            }
3675            if row == selection.end.row {
3676                selection.end.column += indent_delta.len;
3677                delta_for_end_row = indent_delta.len;
3678            }
3679        }
3680
3681        if selection.start.row == selection.end.row {
3682            delta_for_start_row + delta_for_end_row
3683        } else {
3684            delta_for_end_row
3685        }
3686    }
3687
3688    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3689        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3690        let selections = self.selections.all::<Point>(cx);
3691        let mut deletion_ranges = Vec::new();
3692        let mut last_outdent = None;
3693        {
3694            let buffer = self.buffer.read(cx);
3695            let snapshot = buffer.snapshot(cx);
3696            for selection in &selections {
3697                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3698                let tab_size = cx
3699                    .global::<Settings>()
3700                    .tab_size(language_name.as_deref())
3701                    .get();
3702                let mut rows = selection.spanned_rows(false, &display_map);
3703
3704                // Avoid re-outdenting a row that has already been outdented by a
3705                // previous selection.
3706                if let Some(last_row) = last_outdent {
3707                    if last_row == rows.start {
3708                        rows.start += 1;
3709                    }
3710                }
3711
3712                for row in rows {
3713                    let indent_size = snapshot.indent_size_for_line(row);
3714                    if indent_size.len > 0 {
3715                        let deletion_len = match indent_size.kind {
3716                            IndentKind::Space => {
3717                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3718                                if columns_to_prev_tab_stop == 0 {
3719                                    tab_size
3720                                } else {
3721                                    columns_to_prev_tab_stop
3722                                }
3723                            }
3724                            IndentKind::Tab => 1,
3725                        };
3726                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3727                        last_outdent = Some(row);
3728                    }
3729                }
3730            }
3731        }
3732
3733        self.transact(cx, |this, cx| {
3734            this.buffer.update(cx, |buffer, cx| {
3735                let empty_str: Arc<str> = "".into();
3736                buffer.edit(
3737                    deletion_ranges
3738                        .into_iter()
3739                        .map(|range| (range, empty_str.clone())),
3740                    None,
3741                    cx,
3742                );
3743            });
3744            let selections = this.selections.all::<usize>(cx);
3745            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3746        });
3747    }
3748
3749    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3750        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3751        let selections = self.selections.all::<Point>(cx);
3752
3753        let mut new_cursors = Vec::new();
3754        let mut edit_ranges = Vec::new();
3755        let mut selections = selections.iter().peekable();
3756        while let Some(selection) = selections.next() {
3757            let mut rows = selection.spanned_rows(false, &display_map);
3758            let goal_display_column = selection.head().to_display_point(&display_map).column();
3759
3760            // Accumulate contiguous regions of rows that we want to delete.
3761            while let Some(next_selection) = selections.peek() {
3762                let next_rows = next_selection.spanned_rows(false, &display_map);
3763                if next_rows.start <= rows.end {
3764                    rows.end = next_rows.end;
3765                    selections.next().unwrap();
3766                } else {
3767                    break;
3768                }
3769            }
3770
3771            let buffer = &display_map.buffer_snapshot;
3772            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3773            let edit_end;
3774            let cursor_buffer_row;
3775            if buffer.max_point().row >= rows.end {
3776                // If there's a line after the range, delete the \n from the end of the row range
3777                // and position the cursor on the next line.
3778                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3779                cursor_buffer_row = rows.end;
3780            } else {
3781                // If there isn't a line after the range, delete the \n from the line before the
3782                // start of the row range and position the cursor there.
3783                edit_start = edit_start.saturating_sub(1);
3784                edit_end = buffer.len();
3785                cursor_buffer_row = rows.start.saturating_sub(1);
3786            }
3787
3788            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3789            *cursor.column_mut() =
3790                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3791
3792            new_cursors.push((
3793                selection.id,
3794                buffer.anchor_after(cursor.to_point(&display_map)),
3795            ));
3796            edit_ranges.push(edit_start..edit_end);
3797        }
3798
3799        self.transact(cx, |this, cx| {
3800            let buffer = this.buffer.update(cx, |buffer, cx| {
3801                let empty_str: Arc<str> = "".into();
3802                buffer.edit(
3803                    edit_ranges
3804                        .into_iter()
3805                        .map(|range| (range, empty_str.clone())),
3806                    None,
3807                    cx,
3808                );
3809                buffer.snapshot(cx)
3810            });
3811            let new_selections = new_cursors
3812                .into_iter()
3813                .map(|(id, cursor)| {
3814                    let cursor = cursor.to_point(&buffer);
3815                    Selection {
3816                        id,
3817                        start: cursor,
3818                        end: cursor,
3819                        reversed: false,
3820                        goal: SelectionGoal::None,
3821                    }
3822                })
3823                .collect();
3824
3825            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3826                s.select(new_selections);
3827            });
3828        });
3829    }
3830
3831    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3832        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3833        let buffer = &display_map.buffer_snapshot;
3834        let selections = self.selections.all::<Point>(cx);
3835
3836        let mut edits = Vec::new();
3837        let mut selections_iter = selections.iter().peekable();
3838        while let Some(selection) = selections_iter.next() {
3839            // Avoid duplicating the same lines twice.
3840            let mut rows = selection.spanned_rows(false, &display_map);
3841
3842            while let Some(next_selection) = selections_iter.peek() {
3843                let next_rows = next_selection.spanned_rows(false, &display_map);
3844                if next_rows.start < rows.end {
3845                    rows.end = next_rows.end;
3846                    selections_iter.next().unwrap();
3847                } else {
3848                    break;
3849                }
3850            }
3851
3852            // Copy the text from the selected row region and splice it at the start of the region.
3853            let start = Point::new(rows.start, 0);
3854            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3855            let text = buffer
3856                .text_for_range(start..end)
3857                .chain(Some("\n"))
3858                .collect::<String>();
3859            edits.push((start..start, text));
3860        }
3861
3862        self.transact(cx, |this, cx| {
3863            this.buffer.update(cx, |buffer, cx| {
3864                buffer.edit(edits, None, cx);
3865            });
3866
3867            this.request_autoscroll(Autoscroll::fit(), cx);
3868        });
3869    }
3870
3871    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3872        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3873        let buffer = self.buffer.read(cx).snapshot(cx);
3874
3875        let mut edits = Vec::new();
3876        let mut unfold_ranges = Vec::new();
3877        let mut refold_ranges = Vec::new();
3878
3879        let selections = self.selections.all::<Point>(cx);
3880        let mut selections = selections.iter().peekable();
3881        let mut contiguous_row_selections = Vec::new();
3882        let mut new_selections = Vec::new();
3883
3884        while let Some(selection) = selections.next() {
3885            // Find all the selections that span a contiguous row range
3886            let (start_row, end_row) = consume_contiguous_rows(
3887                &mut contiguous_row_selections,
3888                selection,
3889                &display_map,
3890                &mut selections,
3891            );
3892
3893            // Move the text spanned by the row range to be before the line preceding the row range
3894            if start_row > 0 {
3895                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3896                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3897                let insertion_point = display_map
3898                    .prev_line_boundary(Point::new(start_row - 1, 0))
3899                    .0;
3900
3901                // Don't move lines across excerpts
3902                if buffer
3903                    .excerpt_boundaries_in_range((
3904                        Bound::Excluded(insertion_point),
3905                        Bound::Included(range_to_move.end),
3906                    ))
3907                    .next()
3908                    .is_none()
3909                {
3910                    let text = buffer
3911                        .text_for_range(range_to_move.clone())
3912                        .flat_map(|s| s.chars())
3913                        .skip(1)
3914                        .chain(['\n'])
3915                        .collect::<String>();
3916
3917                    edits.push((
3918                        buffer.anchor_after(range_to_move.start)
3919                            ..buffer.anchor_before(range_to_move.end),
3920                        String::new(),
3921                    ));
3922                    let insertion_anchor = buffer.anchor_after(insertion_point);
3923                    edits.push((insertion_anchor..insertion_anchor, text));
3924
3925                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3926
3927                    // Move selections up
3928                    new_selections.extend(contiguous_row_selections.drain(..).map(
3929                        |mut selection| {
3930                            selection.start.row -= row_delta;
3931                            selection.end.row -= row_delta;
3932                            selection
3933                        },
3934                    ));
3935
3936                    // Move folds up
3937                    unfold_ranges.push(range_to_move.clone());
3938                    for fold in display_map.folds_in_range(
3939                        buffer.anchor_before(range_to_move.start)
3940                            ..buffer.anchor_after(range_to_move.end),
3941                    ) {
3942                        let mut start = fold.start.to_point(&buffer);
3943                        let mut end = fold.end.to_point(&buffer);
3944                        start.row -= row_delta;
3945                        end.row -= row_delta;
3946                        refold_ranges.push(start..end);
3947                    }
3948                }
3949            }
3950
3951            // If we didn't move line(s), preserve the existing selections
3952            new_selections.append(&mut contiguous_row_selections);
3953        }
3954
3955        self.transact(cx, |this, cx| {
3956            this.unfold_ranges(unfold_ranges, true, true, cx);
3957            this.buffer.update(cx, |buffer, cx| {
3958                for (range, text) in edits {
3959                    buffer.edit([(range, text)], None, cx);
3960                }
3961            });
3962            this.fold_ranges(refold_ranges, true, cx);
3963            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3964                s.select(new_selections);
3965            })
3966        });
3967    }
3968
3969    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3970        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3971        let buffer = self.buffer.read(cx).snapshot(cx);
3972
3973        let mut edits = Vec::new();
3974        let mut unfold_ranges = Vec::new();
3975        let mut refold_ranges = Vec::new();
3976
3977        let selections = self.selections.all::<Point>(cx);
3978        let mut selections = selections.iter().peekable();
3979        let mut contiguous_row_selections = Vec::new();
3980        let mut new_selections = Vec::new();
3981
3982        while let Some(selection) = selections.next() {
3983            // Find all the selections that span a contiguous row range
3984            let (start_row, end_row) = consume_contiguous_rows(
3985                &mut contiguous_row_selections,
3986                selection,
3987                &display_map,
3988                &mut selections,
3989            );
3990
3991            // Move the text spanned by the row range to be after the last line of the row range
3992            if end_row <= buffer.max_point().row {
3993                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3994                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3995
3996                // Don't move lines across excerpt boundaries
3997                if buffer
3998                    .excerpt_boundaries_in_range((
3999                        Bound::Excluded(range_to_move.start),
4000                        Bound::Included(insertion_point),
4001                    ))
4002                    .next()
4003                    .is_none()
4004                {
4005                    let mut text = String::from("\n");
4006                    text.extend(buffer.text_for_range(range_to_move.clone()));
4007                    text.pop(); // Drop trailing newline
4008                    edits.push((
4009                        buffer.anchor_after(range_to_move.start)
4010                            ..buffer.anchor_before(range_to_move.end),
4011                        String::new(),
4012                    ));
4013                    let insertion_anchor = buffer.anchor_after(insertion_point);
4014                    edits.push((insertion_anchor..insertion_anchor, text));
4015
4016                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4017
4018                    // Move selections down
4019                    new_selections.extend(contiguous_row_selections.drain(..).map(
4020                        |mut selection| {
4021                            selection.start.row += row_delta;
4022                            selection.end.row += row_delta;
4023                            selection
4024                        },
4025                    ));
4026
4027                    // Move folds down
4028                    unfold_ranges.push(range_to_move.clone());
4029                    for fold in display_map.folds_in_range(
4030                        buffer.anchor_before(range_to_move.start)
4031                            ..buffer.anchor_after(range_to_move.end),
4032                    ) {
4033                        let mut start = fold.start.to_point(&buffer);
4034                        let mut end = fold.end.to_point(&buffer);
4035                        start.row += row_delta;
4036                        end.row += row_delta;
4037                        refold_ranges.push(start..end);
4038                    }
4039                }
4040            }
4041
4042            // If we didn't move line(s), preserve the existing selections
4043            new_selections.append(&mut contiguous_row_selections);
4044        }
4045
4046        self.transact(cx, |this, cx| {
4047            this.unfold_ranges(unfold_ranges, true, true, cx);
4048            this.buffer.update(cx, |buffer, cx| {
4049                for (range, text) in edits {
4050                    buffer.edit([(range, text)], None, cx);
4051                }
4052            });
4053            this.fold_ranges(refold_ranges, true, cx);
4054            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4055        });
4056    }
4057
4058    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4059        self.transact(cx, |this, cx| {
4060            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4061                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4062                let line_mode = s.line_mode;
4063                s.move_with(|display_map, selection| {
4064                    if !selection.is_empty() || line_mode {
4065                        return;
4066                    }
4067
4068                    let mut head = selection.head();
4069                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4070                    if head.column() == display_map.line_len(head.row()) {
4071                        transpose_offset = display_map
4072                            .buffer_snapshot
4073                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4074                    }
4075
4076                    if transpose_offset == 0 {
4077                        return;
4078                    }
4079
4080                    *head.column_mut() += 1;
4081                    head = display_map.clip_point(head, Bias::Right);
4082                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4083
4084                    let transpose_start = display_map
4085                        .buffer_snapshot
4086                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4087                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4088                        let transpose_end = display_map
4089                            .buffer_snapshot
4090                            .clip_offset(transpose_offset + 1, Bias::Right);
4091                        if let Some(ch) =
4092                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4093                        {
4094                            edits.push((transpose_start..transpose_offset, String::new()));
4095                            edits.push((transpose_end..transpose_end, ch.to_string()));
4096                        }
4097                    }
4098                });
4099                edits
4100            });
4101            this.buffer
4102                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4103            let selections = this.selections.all::<usize>(cx);
4104            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4105                s.select(selections);
4106            });
4107        });
4108    }
4109
4110    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4111        let mut text = String::new();
4112        let buffer = self.buffer.read(cx).snapshot(cx);
4113        let mut selections = self.selections.all::<Point>(cx);
4114        let mut clipboard_selections = Vec::with_capacity(selections.len());
4115        {
4116            let max_point = buffer.max_point();
4117            for selection in &mut selections {
4118                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4119                if is_entire_line {
4120                    selection.start = Point::new(selection.start.row, 0);
4121                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4122                    selection.goal = SelectionGoal::None;
4123                }
4124                let mut len = 0;
4125                for chunk in buffer.text_for_range(selection.start..selection.end) {
4126                    text.push_str(chunk);
4127                    len += chunk.len();
4128                }
4129                clipboard_selections.push(ClipboardSelection {
4130                    len,
4131                    is_entire_line,
4132                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4133                });
4134            }
4135        }
4136
4137        self.transact(cx, |this, cx| {
4138            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4139                s.select(selections);
4140            });
4141            this.insert("", cx);
4142            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4143        });
4144    }
4145
4146    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4147        let selections = self.selections.all::<Point>(cx);
4148        let buffer = self.buffer.read(cx).read(cx);
4149        let mut text = String::new();
4150
4151        let mut clipboard_selections = Vec::with_capacity(selections.len());
4152        {
4153            let max_point = buffer.max_point();
4154            for selection in selections.iter() {
4155                let mut start = selection.start;
4156                let mut end = selection.end;
4157                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4158                if is_entire_line {
4159                    start = Point::new(start.row, 0);
4160                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4161                }
4162                let mut len = 0;
4163                for chunk in buffer.text_for_range(start..end) {
4164                    text.push_str(chunk);
4165                    len += chunk.len();
4166                }
4167                clipboard_selections.push(ClipboardSelection {
4168                    len,
4169                    is_entire_line,
4170                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4171                });
4172            }
4173        }
4174
4175        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4176    }
4177
4178    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4179        self.transact(cx, |this, cx| {
4180            if let Some(item) = cx.read_from_clipboard() {
4181                let mut clipboard_text = Cow::Borrowed(item.text());
4182                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4183                    let old_selections = this.selections.all::<usize>(cx);
4184                    let all_selections_were_entire_line =
4185                        clipboard_selections.iter().all(|s| s.is_entire_line);
4186                    let first_selection_indent_column =
4187                        clipboard_selections.first().map(|s| s.first_line_indent);
4188                    if clipboard_selections.len() != old_selections.len() {
4189                        let mut newline_separated_text = String::new();
4190                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4191                        let mut ix = 0;
4192                        while let Some(clipboard_selection) = clipboard_selections.next() {
4193                            newline_separated_text
4194                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4195                            ix += clipboard_selection.len;
4196                            if clipboard_selections.peek().is_some() {
4197                                newline_separated_text.push('\n');
4198                            }
4199                        }
4200                        clipboard_text = Cow::Owned(newline_separated_text);
4201                    }
4202
4203                    this.buffer.update(cx, |buffer, cx| {
4204                        let snapshot = buffer.read(cx);
4205                        let mut start_offset = 0;
4206                        let mut edits = Vec::new();
4207                        let mut original_indent_columns = Vec::new();
4208                        let line_mode = this.selections.line_mode;
4209                        for (ix, selection) in old_selections.iter().enumerate() {
4210                            let to_insert;
4211                            let entire_line;
4212                            let original_indent_column;
4213                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4214                                let end_offset = start_offset + clipboard_selection.len;
4215                                to_insert = &clipboard_text[start_offset..end_offset];
4216                                entire_line = clipboard_selection.is_entire_line;
4217                                start_offset = end_offset;
4218                                original_indent_column =
4219                                    Some(clipboard_selection.first_line_indent);
4220                            } else {
4221                                to_insert = clipboard_text.as_str();
4222                                entire_line = all_selections_were_entire_line;
4223                                original_indent_column = first_selection_indent_column
4224                            }
4225
4226                            // If the corresponding selection was empty when this slice of the
4227                            // clipboard text was written, then the entire line containing the
4228                            // selection was copied. If this selection is also currently empty,
4229                            // then paste the line before the current line of the buffer.
4230                            let range = if selection.is_empty() && !line_mode && entire_line {
4231                                let column = selection.start.to_point(&snapshot).column as usize;
4232                                let line_start = selection.start - column;
4233                                line_start..line_start
4234                            } else {
4235                                selection.range()
4236                            };
4237
4238                            edits.push((range, to_insert));
4239                            original_indent_columns.extend(original_indent_column);
4240                        }
4241                        drop(snapshot);
4242
4243                        buffer.edit(
4244                            edits,
4245                            Some(AutoindentMode::Block {
4246                                original_indent_columns,
4247                            }),
4248                            cx,
4249                        );
4250                    });
4251
4252                    let selections = this.selections.all::<usize>(cx);
4253                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4254                } else {
4255                    this.insert(&clipboard_text, cx);
4256                }
4257            }
4258        });
4259    }
4260
4261    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4262        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4263            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4264                self.change_selections(None, cx, |s| {
4265                    s.select_anchors(selections.to_vec());
4266                });
4267            }
4268            self.request_autoscroll(Autoscroll::fit(), cx);
4269            self.unmark_text(cx);
4270            self.refresh_copilot_suggestions(true, cx);
4271            cx.emit(Event::Edited);
4272        }
4273    }
4274
4275    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4276        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4277            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4278            {
4279                self.change_selections(None, cx, |s| {
4280                    s.select_anchors(selections.to_vec());
4281                });
4282            }
4283            self.request_autoscroll(Autoscroll::fit(), cx);
4284            self.unmark_text(cx);
4285            self.refresh_copilot_suggestions(true, cx);
4286            cx.emit(Event::Edited);
4287        }
4288    }
4289
4290    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4291        self.buffer
4292            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4293    }
4294
4295    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4296        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4297            let line_mode = s.line_mode;
4298            s.move_with(|map, selection| {
4299                let cursor = if selection.is_empty() && !line_mode {
4300                    movement::left(map, selection.start)
4301                } else {
4302                    selection.start
4303                };
4304                selection.collapse_to(cursor, SelectionGoal::None);
4305            });
4306        })
4307    }
4308
4309    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4310        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4311            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4312        })
4313    }
4314
4315    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4316        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4317            let line_mode = s.line_mode;
4318            s.move_with(|map, selection| {
4319                let cursor = if selection.is_empty() && !line_mode {
4320                    movement::right(map, selection.end)
4321                } else {
4322                    selection.end
4323                };
4324                selection.collapse_to(cursor, SelectionGoal::None)
4325            });
4326        })
4327    }
4328
4329    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4330        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4331            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4332        })
4333    }
4334
4335    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4336        if self.take_rename(true, cx).is_some() {
4337            return;
4338        }
4339
4340        if let Some(context_menu) = self.context_menu.as_mut() {
4341            if context_menu.select_prev(cx) {
4342                return;
4343            }
4344        }
4345
4346        if matches!(self.mode, EditorMode::SingleLine) {
4347            cx.propagate_action();
4348            return;
4349        }
4350
4351        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4352            let line_mode = s.line_mode;
4353            s.move_with(|map, selection| {
4354                if !selection.is_empty() && !line_mode {
4355                    selection.goal = SelectionGoal::None;
4356                }
4357                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4358                selection.collapse_to(cursor, goal);
4359            });
4360        })
4361    }
4362
4363    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4364        if self.take_rename(true, cx).is_some() {
4365            return;
4366        }
4367
4368        if self
4369            .context_menu
4370            .as_mut()
4371            .map(|menu| menu.select_first(cx))
4372            .unwrap_or(false)
4373        {
4374            return;
4375        }
4376
4377        if matches!(self.mode, EditorMode::SingleLine) {
4378            cx.propagate_action();
4379            return;
4380        }
4381
4382        let row_count = if let Some(row_count) = self.visible_line_count() {
4383            row_count as u32 - 1
4384        } else {
4385            return;
4386        };
4387
4388        let autoscroll = if action.center_cursor {
4389            Autoscroll::center()
4390        } else {
4391            Autoscroll::fit()
4392        };
4393
4394        self.change_selections(Some(autoscroll), cx, |s| {
4395            let line_mode = s.line_mode;
4396            s.move_with(|map, selection| {
4397                if !selection.is_empty() && !line_mode {
4398                    selection.goal = SelectionGoal::None;
4399                }
4400                let (cursor, goal) =
4401                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4402                selection.collapse_to(cursor, goal);
4403            });
4404        });
4405    }
4406
4407    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4408        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4409            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4410        })
4411    }
4412
4413    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4414        self.take_rename(true, cx);
4415
4416        if let Some(context_menu) = self.context_menu.as_mut() {
4417            if context_menu.select_next(cx) {
4418                return;
4419            }
4420        }
4421
4422        if self.mode == EditorMode::SingleLine {
4423            cx.propagate_action();
4424            return;
4425        }
4426
4427        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4428            let line_mode = s.line_mode;
4429            s.move_with(|map, selection| {
4430                if !selection.is_empty() && !line_mode {
4431                    selection.goal = SelectionGoal::None;
4432                }
4433                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4434                selection.collapse_to(cursor, goal);
4435            });
4436        });
4437    }
4438
4439    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4440        if self.take_rename(true, cx).is_some() {
4441            return;
4442        }
4443
4444        if self
4445            .context_menu
4446            .as_mut()
4447            .map(|menu| menu.select_last(cx))
4448            .unwrap_or(false)
4449        {
4450            return;
4451        }
4452
4453        if matches!(self.mode, EditorMode::SingleLine) {
4454            cx.propagate_action();
4455            return;
4456        }
4457
4458        let row_count = if let Some(row_count) = self.visible_line_count() {
4459            row_count as u32 - 1
4460        } else {
4461            return;
4462        };
4463
4464        let autoscroll = if action.center_cursor {
4465            Autoscroll::center()
4466        } else {
4467            Autoscroll::fit()
4468        };
4469
4470        self.change_selections(Some(autoscroll), cx, |s| {
4471            let line_mode = s.line_mode;
4472            s.move_with(|map, selection| {
4473                if !selection.is_empty() && !line_mode {
4474                    selection.goal = SelectionGoal::None;
4475                }
4476                let (cursor, goal) =
4477                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4478                selection.collapse_to(cursor, goal);
4479            });
4480        });
4481    }
4482
4483    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4484        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4485            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4486        });
4487    }
4488
4489    pub fn move_to_previous_word_start(
4490        &mut self,
4491        _: &MoveToPreviousWordStart,
4492        cx: &mut ViewContext<Self>,
4493    ) {
4494        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4495            s.move_cursors_with(|map, head, _| {
4496                (
4497                    movement::previous_word_start(map, head),
4498                    SelectionGoal::None,
4499                )
4500            });
4501        })
4502    }
4503
4504    pub fn move_to_previous_subword_start(
4505        &mut self,
4506        _: &MoveToPreviousSubwordStart,
4507        cx: &mut ViewContext<Self>,
4508    ) {
4509        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4510            s.move_cursors_with(|map, head, _| {
4511                (
4512                    movement::previous_subword_start(map, head),
4513                    SelectionGoal::None,
4514                )
4515            });
4516        })
4517    }
4518
4519    pub fn select_to_previous_word_start(
4520        &mut self,
4521        _: &SelectToPreviousWordStart,
4522        cx: &mut ViewContext<Self>,
4523    ) {
4524        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4525            s.move_heads_with(|map, head, _| {
4526                (
4527                    movement::previous_word_start(map, head),
4528                    SelectionGoal::None,
4529                )
4530            });
4531        })
4532    }
4533
4534    pub fn select_to_previous_subword_start(
4535        &mut self,
4536        _: &SelectToPreviousSubwordStart,
4537        cx: &mut ViewContext<Self>,
4538    ) {
4539        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4540            s.move_heads_with(|map, head, _| {
4541                (
4542                    movement::previous_subword_start(map, head),
4543                    SelectionGoal::None,
4544                )
4545            });
4546        })
4547    }
4548
4549    pub fn delete_to_previous_word_start(
4550        &mut self,
4551        _: &DeleteToPreviousWordStart,
4552        cx: &mut ViewContext<Self>,
4553    ) {
4554        self.transact(cx, |this, cx| {
4555            this.select_autoclose_pair(cx);
4556            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4557                let line_mode = s.line_mode;
4558                s.move_with(|map, selection| {
4559                    if selection.is_empty() && !line_mode {
4560                        let cursor = movement::previous_word_start(map, selection.head());
4561                        selection.set_head(cursor, SelectionGoal::None);
4562                    }
4563                });
4564            });
4565            this.insert("", cx);
4566        });
4567    }
4568
4569    pub fn delete_to_previous_subword_start(
4570        &mut self,
4571        _: &DeleteToPreviousSubwordStart,
4572        cx: &mut ViewContext<Self>,
4573    ) {
4574        self.transact(cx, |this, cx| {
4575            this.select_autoclose_pair(cx);
4576            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4577                let line_mode = s.line_mode;
4578                s.move_with(|map, selection| {
4579                    if selection.is_empty() && !line_mode {
4580                        let cursor = movement::previous_subword_start(map, selection.head());
4581                        selection.set_head(cursor, SelectionGoal::None);
4582                    }
4583                });
4584            });
4585            this.insert("", cx);
4586        });
4587    }
4588
4589    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4590        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4591            s.move_cursors_with(|map, head, _| {
4592                (movement::next_word_end(map, head), SelectionGoal::None)
4593            });
4594        })
4595    }
4596
4597    pub fn move_to_next_subword_end(
4598        &mut self,
4599        _: &MoveToNextSubwordEnd,
4600        cx: &mut ViewContext<Self>,
4601    ) {
4602        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4603            s.move_cursors_with(|map, head, _| {
4604                (movement::next_subword_end(map, head), SelectionGoal::None)
4605            });
4606        })
4607    }
4608
4609    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4610        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4611            s.move_heads_with(|map, head, _| {
4612                (movement::next_word_end(map, head), SelectionGoal::None)
4613            });
4614        })
4615    }
4616
4617    pub fn select_to_next_subword_end(
4618        &mut self,
4619        _: &SelectToNextSubwordEnd,
4620        cx: &mut ViewContext<Self>,
4621    ) {
4622        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4623            s.move_heads_with(|map, head, _| {
4624                (movement::next_subword_end(map, head), SelectionGoal::None)
4625            });
4626        })
4627    }
4628
4629    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4630        self.transact(cx, |this, cx| {
4631            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4632                let line_mode = s.line_mode;
4633                s.move_with(|map, selection| {
4634                    if selection.is_empty() && !line_mode {
4635                        let cursor = movement::next_word_end(map, selection.head());
4636                        selection.set_head(cursor, SelectionGoal::None);
4637                    }
4638                });
4639            });
4640            this.insert("", cx);
4641        });
4642    }
4643
4644    pub fn delete_to_next_subword_end(
4645        &mut self,
4646        _: &DeleteToNextSubwordEnd,
4647        cx: &mut ViewContext<Self>,
4648    ) {
4649        self.transact(cx, |this, cx| {
4650            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4651                s.move_with(|map, selection| {
4652                    if selection.is_empty() {
4653                        let cursor = movement::next_subword_end(map, selection.head());
4654                        selection.set_head(cursor, SelectionGoal::None);
4655                    }
4656                });
4657            });
4658            this.insert("", cx);
4659        });
4660    }
4661
4662    pub fn move_to_beginning_of_line(
4663        &mut self,
4664        _: &MoveToBeginningOfLine,
4665        cx: &mut ViewContext<Self>,
4666    ) {
4667        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4668            s.move_cursors_with(|map, head, _| {
4669                (
4670                    movement::indented_line_beginning(map, head, true),
4671                    SelectionGoal::None,
4672                )
4673            });
4674        })
4675    }
4676
4677    pub fn select_to_beginning_of_line(
4678        &mut self,
4679        action: &SelectToBeginningOfLine,
4680        cx: &mut ViewContext<Self>,
4681    ) {
4682        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4683            s.move_heads_with(|map, head, _| {
4684                (
4685                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4686                    SelectionGoal::None,
4687                )
4688            });
4689        });
4690    }
4691
4692    pub fn delete_to_beginning_of_line(
4693        &mut self,
4694        _: &DeleteToBeginningOfLine,
4695        cx: &mut ViewContext<Self>,
4696    ) {
4697        self.transact(cx, |this, cx| {
4698            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4699                s.move_with(|_, selection| {
4700                    selection.reversed = true;
4701                });
4702            });
4703
4704            this.select_to_beginning_of_line(
4705                &SelectToBeginningOfLine {
4706                    stop_at_soft_wraps: false,
4707                },
4708                cx,
4709            );
4710            this.backspace(&Backspace, cx);
4711        });
4712    }
4713
4714    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4715        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4716            s.move_cursors_with(|map, head, _| {
4717                (movement::line_end(map, head, true), SelectionGoal::None)
4718            });
4719        })
4720    }
4721
4722    pub fn select_to_end_of_line(
4723        &mut self,
4724        action: &SelectToEndOfLine,
4725        cx: &mut ViewContext<Self>,
4726    ) {
4727        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4728            s.move_heads_with(|map, head, _| {
4729                (
4730                    movement::line_end(map, head, action.stop_at_soft_wraps),
4731                    SelectionGoal::None,
4732                )
4733            });
4734        })
4735    }
4736
4737    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4738        self.transact(cx, |this, cx| {
4739            this.select_to_end_of_line(
4740                &SelectToEndOfLine {
4741                    stop_at_soft_wraps: false,
4742                },
4743                cx,
4744            );
4745            this.delete(&Delete, cx);
4746        });
4747    }
4748
4749    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4750        self.transact(cx, |this, cx| {
4751            this.select_to_end_of_line(
4752                &SelectToEndOfLine {
4753                    stop_at_soft_wraps: false,
4754                },
4755                cx,
4756            );
4757            this.cut(&Cut, cx);
4758        });
4759    }
4760
4761    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4762        if matches!(self.mode, EditorMode::SingleLine) {
4763            cx.propagate_action();
4764            return;
4765        }
4766
4767        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4768            s.select_ranges(vec![0..0]);
4769        });
4770    }
4771
4772    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4773        let mut selection = self.selections.last::<Point>(cx);
4774        selection.set_head(Point::zero(), SelectionGoal::None);
4775
4776        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4777            s.select(vec![selection]);
4778        });
4779    }
4780
4781    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4782        if matches!(self.mode, EditorMode::SingleLine) {
4783            cx.propagate_action();
4784            return;
4785        }
4786
4787        let cursor = self.buffer.read(cx).read(cx).len();
4788        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4789            s.select_ranges(vec![cursor..cursor])
4790        });
4791    }
4792
4793    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4794        self.nav_history = nav_history;
4795    }
4796
4797    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4798        self.nav_history.as_ref()
4799    }
4800
4801    fn push_to_nav_history(
4802        &self,
4803        cursor_anchor: Anchor,
4804        new_position: Option<Point>,
4805        cx: &mut ViewContext<Self>,
4806    ) {
4807        if let Some(nav_history) = &self.nav_history {
4808            let buffer = self.buffer.read(cx).read(cx);
4809            let cursor_position = cursor_anchor.to_point(&buffer);
4810            let scroll_state = self.scroll_manager.anchor();
4811            let scroll_top_row = scroll_state.top_row(&buffer);
4812            drop(buffer);
4813
4814            if let Some(new_position) = new_position {
4815                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4816                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4817                    return;
4818                }
4819            }
4820
4821            nav_history.push(
4822                Some(NavigationData {
4823                    cursor_anchor,
4824                    cursor_position,
4825                    scroll_anchor: scroll_state,
4826                    scroll_top_row,
4827                }),
4828                cx,
4829            );
4830        }
4831    }
4832
4833    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4834        let buffer = self.buffer.read(cx).snapshot(cx);
4835        let mut selection = self.selections.first::<usize>(cx);
4836        selection.set_head(buffer.len(), SelectionGoal::None);
4837        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4838            s.select(vec![selection]);
4839        });
4840    }
4841
4842    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4843        let end = self.buffer.read(cx).read(cx).len();
4844        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4845            s.select_ranges(vec![0..end]);
4846        });
4847    }
4848
4849    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4850        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4851        let mut selections = self.selections.all::<Point>(cx);
4852        let max_point = display_map.buffer_snapshot.max_point();
4853        for selection in &mut selections {
4854            let rows = selection.spanned_rows(true, &display_map);
4855            selection.start = Point::new(rows.start, 0);
4856            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4857            selection.reversed = false;
4858        }
4859        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4860            s.select(selections);
4861        });
4862    }
4863
4864    pub fn split_selection_into_lines(
4865        &mut self,
4866        _: &SplitSelectionIntoLines,
4867        cx: &mut ViewContext<Self>,
4868    ) {
4869        let mut to_unfold = Vec::new();
4870        let mut new_selection_ranges = Vec::new();
4871        {
4872            let selections = self.selections.all::<Point>(cx);
4873            let buffer = self.buffer.read(cx).read(cx);
4874            for selection in selections {
4875                for row in selection.start.row..selection.end.row {
4876                    let cursor = Point::new(row, buffer.line_len(row));
4877                    new_selection_ranges.push(cursor..cursor);
4878                }
4879                new_selection_ranges.push(selection.end..selection.end);
4880                to_unfold.push(selection.start..selection.end);
4881            }
4882        }
4883        self.unfold_ranges(to_unfold, true, true, cx);
4884        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4885            s.select_ranges(new_selection_ranges);
4886        });
4887    }
4888
4889    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4890        self.add_selection(true, cx);
4891    }
4892
4893    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4894        self.add_selection(false, cx);
4895    }
4896
4897    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4898        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4899        let mut selections = self.selections.all::<Point>(cx);
4900        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4901            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4902            let range = oldest_selection.display_range(&display_map).sorted();
4903            let columns = cmp::min(range.start.column(), range.end.column())
4904                ..cmp::max(range.start.column(), range.end.column());
4905
4906            selections.clear();
4907            let mut stack = Vec::new();
4908            for row in range.start.row()..=range.end.row() {
4909                if let Some(selection) = self.selections.build_columnar_selection(
4910                    &display_map,
4911                    row,
4912                    &columns,
4913                    oldest_selection.reversed,
4914                ) {
4915                    stack.push(selection.id);
4916                    selections.push(selection);
4917                }
4918            }
4919
4920            if above {
4921                stack.reverse();
4922            }
4923
4924            AddSelectionsState { above, stack }
4925        });
4926
4927        let last_added_selection = *state.stack.last().unwrap();
4928        let mut new_selections = Vec::new();
4929        if above == state.above {
4930            let end_row = if above {
4931                0
4932            } else {
4933                display_map.max_point().row()
4934            };
4935
4936            'outer: for selection in selections {
4937                if selection.id == last_added_selection {
4938                    let range = selection.display_range(&display_map).sorted();
4939                    debug_assert_eq!(range.start.row(), range.end.row());
4940                    let mut row = range.start.row();
4941                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4942                    {
4943                        start..end
4944                    } else {
4945                        cmp::min(range.start.column(), range.end.column())
4946                            ..cmp::max(range.start.column(), range.end.column())
4947                    };
4948
4949                    while row != end_row {
4950                        if above {
4951                            row -= 1;
4952                        } else {
4953                            row += 1;
4954                        }
4955
4956                        if let Some(new_selection) = self.selections.build_columnar_selection(
4957                            &display_map,
4958                            row,
4959                            &columns,
4960                            selection.reversed,
4961                        ) {
4962                            state.stack.push(new_selection.id);
4963                            if above {
4964                                new_selections.push(new_selection);
4965                                new_selections.push(selection);
4966                            } else {
4967                                new_selections.push(selection);
4968                                new_selections.push(new_selection);
4969                            }
4970
4971                            continue 'outer;
4972                        }
4973                    }
4974                }
4975
4976                new_selections.push(selection);
4977            }
4978        } else {
4979            new_selections = selections;
4980            new_selections.retain(|s| s.id != last_added_selection);
4981            state.stack.pop();
4982        }
4983
4984        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4985            s.select(new_selections);
4986        });
4987        if state.stack.len() > 1 {
4988            self.add_selections_state = Some(state);
4989        }
4990    }
4991
4992    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4993        self.push_to_selection_history();
4994        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4995        let buffer = &display_map.buffer_snapshot;
4996        let mut selections = self.selections.all::<usize>(cx);
4997        if let Some(mut select_next_state) = self.select_next_state.take() {
4998            let query = &select_next_state.query;
4999            if !select_next_state.done {
5000                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5001                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5002                let mut next_selected_range = None;
5003
5004                let bytes_after_last_selection =
5005                    buffer.bytes_in_range(last_selection.end..buffer.len());
5006                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5007                let query_matches = query
5008                    .stream_find_iter(bytes_after_last_selection)
5009                    .map(|result| (last_selection.end, result))
5010                    .chain(
5011                        query
5012                            .stream_find_iter(bytes_before_first_selection)
5013                            .map(|result| (0, result)),
5014                    );
5015                for (start_offset, query_match) in query_matches {
5016                    let query_match = query_match.unwrap(); // can only fail due to I/O
5017                    let offset_range =
5018                        start_offset + query_match.start()..start_offset + query_match.end();
5019                    let display_range = offset_range.start.to_display_point(&display_map)
5020                        ..offset_range.end.to_display_point(&display_map);
5021
5022                    if !select_next_state.wordwise
5023                        || (!movement::is_inside_word(&display_map, display_range.start)
5024                            && !movement::is_inside_word(&display_map, display_range.end))
5025                    {
5026                        next_selected_range = Some(offset_range);
5027                        break;
5028                    }
5029                }
5030
5031                if let Some(next_selected_range) = next_selected_range {
5032                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5033                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5034                        if action.replace_newest {
5035                            s.delete(s.newest_anchor().id);
5036                        }
5037                        s.insert_range(next_selected_range);
5038                    });
5039                } else {
5040                    select_next_state.done = true;
5041                }
5042            }
5043
5044            self.select_next_state = Some(select_next_state);
5045        } else if selections.len() == 1 {
5046            let selection = selections.last_mut().unwrap();
5047            if selection.start == selection.end {
5048                let word_range = movement::surrounding_word(
5049                    &display_map,
5050                    selection.start.to_display_point(&display_map),
5051                );
5052                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5053                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5054                selection.goal = SelectionGoal::None;
5055                selection.reversed = false;
5056
5057                let query = buffer
5058                    .text_for_range(selection.start..selection.end)
5059                    .collect::<String>();
5060                let select_state = SelectNextState {
5061                    query: AhoCorasick::new_auto_configured(&[query]),
5062                    wordwise: true,
5063                    done: false,
5064                };
5065                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5066                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5067                    s.select(selections);
5068                });
5069                self.select_next_state = Some(select_state);
5070            } else {
5071                let query = buffer
5072                    .text_for_range(selection.start..selection.end)
5073                    .collect::<String>();
5074                self.select_next_state = Some(SelectNextState {
5075                    query: AhoCorasick::new_auto_configured(&[query]),
5076                    wordwise: false,
5077                    done: false,
5078                });
5079                self.select_next(action, cx);
5080            }
5081        }
5082    }
5083
5084    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5085        self.transact(cx, |this, cx| {
5086            let mut selections = this.selections.all::<Point>(cx);
5087            let mut edits = Vec::new();
5088            let mut selection_edit_ranges = Vec::new();
5089            let mut last_toggled_row = None;
5090            let snapshot = this.buffer.read(cx).read(cx);
5091            let empty_str: Arc<str> = "".into();
5092            let mut suffixes_inserted = Vec::new();
5093
5094            fn comment_prefix_range(
5095                snapshot: &MultiBufferSnapshot,
5096                row: u32,
5097                comment_prefix: &str,
5098                comment_prefix_whitespace: &str,
5099            ) -> Range<Point> {
5100                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5101
5102                let mut line_bytes = snapshot
5103                    .bytes_in_range(start..snapshot.max_point())
5104                    .flatten()
5105                    .copied();
5106
5107                // If this line currently begins with the line comment prefix, then record
5108                // the range containing the prefix.
5109                if line_bytes
5110                    .by_ref()
5111                    .take(comment_prefix.len())
5112                    .eq(comment_prefix.bytes())
5113                {
5114                    // Include any whitespace that matches the comment prefix.
5115                    let matching_whitespace_len = line_bytes
5116                        .zip(comment_prefix_whitespace.bytes())
5117                        .take_while(|(a, b)| a == b)
5118                        .count() as u32;
5119                    let end = Point::new(
5120                        start.row,
5121                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5122                    );
5123                    start..end
5124                } else {
5125                    start..start
5126                }
5127            }
5128
5129            fn comment_suffix_range(
5130                snapshot: &MultiBufferSnapshot,
5131                row: u32,
5132                comment_suffix: &str,
5133                comment_suffix_has_leading_space: bool,
5134            ) -> Range<Point> {
5135                let end = Point::new(row, snapshot.line_len(row));
5136                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5137
5138                let mut line_end_bytes = snapshot
5139                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5140                    .flatten()
5141                    .copied();
5142
5143                let leading_space_len = if suffix_start_column > 0
5144                    && line_end_bytes.next() == Some(b' ')
5145                    && comment_suffix_has_leading_space
5146                {
5147                    1
5148                } else {
5149                    0
5150                };
5151
5152                // If this line currently begins with the line comment prefix, then record
5153                // the range containing the prefix.
5154                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5155                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5156                    start..end
5157                } else {
5158                    end..end
5159                }
5160            }
5161
5162            // TODO: Handle selections that cross excerpts
5163            for selection in &mut selections {
5164                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5165                let language = if let Some(language) =
5166                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5167                {
5168                    language
5169                } else {
5170                    continue;
5171                };
5172
5173                selection_edit_ranges.clear();
5174
5175                // If multiple selections contain a given row, avoid processing that
5176                // row more than once.
5177                let mut start_row = selection.start.row;
5178                if last_toggled_row == Some(start_row) {
5179                    start_row += 1;
5180                }
5181                let end_row =
5182                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5183                        selection.end.row - 1
5184                    } else {
5185                        selection.end.row
5186                    };
5187                last_toggled_row = Some(end_row);
5188
5189                if start_row > end_row {
5190                    continue;
5191                }
5192
5193                // If the language has line comments, toggle those.
5194                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5195                    // Split the comment prefix's trailing whitespace into a separate string,
5196                    // as that portion won't be used for detecting if a line is a comment.
5197                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5198                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5199                    let mut all_selection_lines_are_comments = true;
5200
5201                    for row in start_row..=end_row {
5202                        if snapshot.is_line_blank(row) {
5203                            continue;
5204                        }
5205
5206                        let prefix_range = comment_prefix_range(
5207                            snapshot.deref(),
5208                            row,
5209                            comment_prefix,
5210                            comment_prefix_whitespace,
5211                        );
5212                        if prefix_range.is_empty() {
5213                            all_selection_lines_are_comments = false;
5214                        }
5215                        selection_edit_ranges.push(prefix_range);
5216                    }
5217
5218                    if all_selection_lines_are_comments {
5219                        edits.extend(
5220                            selection_edit_ranges
5221                                .iter()
5222                                .cloned()
5223                                .map(|range| (range, empty_str.clone())),
5224                        );
5225                    } else {
5226                        let min_column = selection_edit_ranges
5227                            .iter()
5228                            .map(|r| r.start.column)
5229                            .min()
5230                            .unwrap_or(0);
5231                        edits.extend(selection_edit_ranges.iter().map(|range| {
5232                            let position = Point::new(range.start.row, min_column);
5233                            (position..position, full_comment_prefix.clone())
5234                        }));
5235                    }
5236                } else if let Some((full_comment_prefix, comment_suffix)) =
5237                    language.block_comment_delimiters()
5238                {
5239                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5240                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5241                    let prefix_range = comment_prefix_range(
5242                        snapshot.deref(),
5243                        start_row,
5244                        comment_prefix,
5245                        comment_prefix_whitespace,
5246                    );
5247                    let suffix_range = comment_suffix_range(
5248                        snapshot.deref(),
5249                        end_row,
5250                        comment_suffix.trim_start_matches(' '),
5251                        comment_suffix.starts_with(' '),
5252                    );
5253
5254                    if prefix_range.is_empty() || suffix_range.is_empty() {
5255                        edits.push((
5256                            prefix_range.start..prefix_range.start,
5257                            full_comment_prefix.clone(),
5258                        ));
5259                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5260                        suffixes_inserted.push((end_row, comment_suffix.len()));
5261                    } else {
5262                        edits.push((prefix_range, empty_str.clone()));
5263                        edits.push((suffix_range, empty_str.clone()));
5264                    }
5265                } else {
5266                    continue;
5267                }
5268            }
5269
5270            drop(snapshot);
5271            this.buffer.update(cx, |buffer, cx| {
5272                buffer.edit(edits, None, cx);
5273            });
5274
5275            // Adjust selections so that they end before any comment suffixes that
5276            // were inserted.
5277            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5278            let mut selections = this.selections.all::<Point>(cx);
5279            let snapshot = this.buffer.read(cx).read(cx);
5280            for selection in &mut selections {
5281                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5282                    match row.cmp(&selection.end.row) {
5283                        Ordering::Less => {
5284                            suffixes_inserted.next();
5285                            continue;
5286                        }
5287                        Ordering::Greater => break,
5288                        Ordering::Equal => {
5289                            if selection.end.column == snapshot.line_len(row) {
5290                                if selection.is_empty() {
5291                                    selection.start.column -= suffix_len as u32;
5292                                }
5293                                selection.end.column -= suffix_len as u32;
5294                            }
5295                            break;
5296                        }
5297                    }
5298                }
5299            }
5300
5301            drop(snapshot);
5302            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5303
5304            let selections = this.selections.all::<Point>(cx);
5305            let selections_on_single_row = selections.windows(2).all(|selections| {
5306                selections[0].start.row == selections[1].start.row
5307                    && selections[0].end.row == selections[1].end.row
5308                    && selections[0].start.row == selections[0].end.row
5309            });
5310            let selections_selecting = selections
5311                .iter()
5312                .any(|selection| selection.start != selection.end);
5313            let advance_downwards = action.advance_downwards
5314                && selections_on_single_row
5315                && !selections_selecting
5316                && this.mode != EditorMode::SingleLine;
5317
5318            if advance_downwards {
5319                let snapshot = this.buffer.read(cx).snapshot(cx);
5320
5321                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5322                    s.move_cursors_with(|display_snapshot, display_point, _| {
5323                        let mut point = display_point.to_point(display_snapshot);
5324                        point.row += 1;
5325                        point = snapshot.clip_point(point, Bias::Left);
5326                        let display_point = point.to_display_point(display_snapshot);
5327                        (display_point, SelectionGoal::Column(display_point.column()))
5328                    })
5329                });
5330            }
5331        });
5332    }
5333
5334    pub fn select_larger_syntax_node(
5335        &mut self,
5336        _: &SelectLargerSyntaxNode,
5337        cx: &mut ViewContext<Self>,
5338    ) {
5339        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5340        let buffer = self.buffer.read(cx).snapshot(cx);
5341        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5342
5343        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5344        let mut selected_larger_node = false;
5345        let new_selections = old_selections
5346            .iter()
5347            .map(|selection| {
5348                let old_range = selection.start..selection.end;
5349                let mut new_range = old_range.clone();
5350                while let Some(containing_range) =
5351                    buffer.range_for_syntax_ancestor(new_range.clone())
5352                {
5353                    new_range = containing_range;
5354                    if !display_map.intersects_fold(new_range.start)
5355                        && !display_map.intersects_fold(new_range.end)
5356                    {
5357                        break;
5358                    }
5359                }
5360
5361                selected_larger_node |= new_range != old_range;
5362                Selection {
5363                    id: selection.id,
5364                    start: new_range.start,
5365                    end: new_range.end,
5366                    goal: SelectionGoal::None,
5367                    reversed: selection.reversed,
5368                }
5369            })
5370            .collect::<Vec<_>>();
5371
5372        if selected_larger_node {
5373            stack.push(old_selections);
5374            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5375                s.select(new_selections);
5376            });
5377        }
5378        self.select_larger_syntax_node_stack = stack;
5379    }
5380
5381    pub fn select_smaller_syntax_node(
5382        &mut self,
5383        _: &SelectSmallerSyntaxNode,
5384        cx: &mut ViewContext<Self>,
5385    ) {
5386        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5387        if let Some(selections) = stack.pop() {
5388            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5389                s.select(selections.to_vec());
5390            });
5391        }
5392        self.select_larger_syntax_node_stack = stack;
5393    }
5394
5395    pub fn move_to_enclosing_bracket(
5396        &mut self,
5397        _: &MoveToEnclosingBracket,
5398        cx: &mut ViewContext<Self>,
5399    ) {
5400        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5401            s.move_offsets_with(|snapshot, selection| {
5402                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5403                    return;
5404                };
5405
5406                let mut best_length = usize::MAX;
5407                let mut best_inside = false;
5408                let mut best_in_bracket_range = false;
5409                let mut best_destination = None;
5410                for (open, close) in enclosing_bracket_ranges {
5411                    let close = close.to_inclusive();
5412                    let length = close.end() - open.start;
5413                    let inside = selection.start >= open.end && selection.end <= *close.start();
5414                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5415
5416                    // If best is next to a bracket and current isn't, skip
5417                    if !in_bracket_range && best_in_bracket_range {
5418                        continue;
5419                    }
5420
5421                    // Prefer smaller lengths unless best is inside and current isn't
5422                    if length > best_length && (best_inside || !inside) {
5423                        continue;
5424                    }
5425
5426                    best_length = length;
5427                    best_inside = inside;
5428                    best_in_bracket_range = in_bracket_range;
5429                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5430                        if inside {
5431                            open.end
5432                        } else {
5433                            open.start
5434                        }
5435                    } else {
5436                        if inside {
5437                            *close.start()
5438                        } else {
5439                            *close.end()
5440                        }
5441                    });
5442                }
5443
5444                if let Some(destination) = best_destination {
5445                    selection.collapse_to(destination, SelectionGoal::None);
5446                }
5447            })
5448        });
5449    }
5450
5451    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5452        self.end_selection(cx);
5453        self.selection_history.mode = SelectionHistoryMode::Undoing;
5454        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5455            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5456            self.select_next_state = entry.select_next_state;
5457            self.add_selections_state = entry.add_selections_state;
5458            self.request_autoscroll(Autoscroll::newest(), cx);
5459        }
5460        self.selection_history.mode = SelectionHistoryMode::Normal;
5461    }
5462
5463    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5464        self.end_selection(cx);
5465        self.selection_history.mode = SelectionHistoryMode::Redoing;
5466        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5467            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5468            self.select_next_state = entry.select_next_state;
5469            self.add_selections_state = entry.add_selections_state;
5470            self.request_autoscroll(Autoscroll::newest(), cx);
5471        }
5472        self.selection_history.mode = SelectionHistoryMode::Normal;
5473    }
5474
5475    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5476        self.go_to_diagnostic_impl(Direction::Next, cx)
5477    }
5478
5479    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5480        self.go_to_diagnostic_impl(Direction::Prev, cx)
5481    }
5482
5483    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5484        let buffer = self.buffer.read(cx).snapshot(cx);
5485        let selection = self.selections.newest::<usize>(cx);
5486
5487        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5488        if direction == Direction::Next {
5489            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5490                let (group_id, jump_to) = popover.activation_info();
5491                if self.activate_diagnostics(group_id, cx) {
5492                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5493                        let mut new_selection = s.newest_anchor().clone();
5494                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5495                        s.select_anchors(vec![new_selection.clone()]);
5496                    });
5497                }
5498                return;
5499            }
5500        }
5501
5502        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5503            active_diagnostics
5504                .primary_range
5505                .to_offset(&buffer)
5506                .to_inclusive()
5507        });
5508        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5509            if active_primary_range.contains(&selection.head()) {
5510                *active_primary_range.end()
5511            } else {
5512                selection.head()
5513            }
5514        } else {
5515            selection.head()
5516        };
5517
5518        loop {
5519            let mut diagnostics = if direction == Direction::Prev {
5520                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5521            } else {
5522                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5523            };
5524            let group = diagnostics.find_map(|entry| {
5525                if entry.diagnostic.is_primary
5526                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5527                    && !entry.range.is_empty()
5528                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5529                {
5530                    Some((entry.range, entry.diagnostic.group_id))
5531                } else {
5532                    None
5533                }
5534            });
5535
5536            if let Some((primary_range, group_id)) = group {
5537                if self.activate_diagnostics(group_id, cx) {
5538                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5539                        s.select(vec![Selection {
5540                            id: selection.id,
5541                            start: primary_range.start,
5542                            end: primary_range.start,
5543                            reversed: false,
5544                            goal: SelectionGoal::None,
5545                        }]);
5546                    });
5547                }
5548                break;
5549            } else {
5550                // Cycle around to the start of the buffer, potentially moving back to the start of
5551                // the currently active diagnostic.
5552                active_primary_range.take();
5553                if direction == Direction::Prev {
5554                    if search_start == buffer.len() {
5555                        break;
5556                    } else {
5557                        search_start = buffer.len();
5558                    }
5559                } else if search_start == 0 {
5560                    break;
5561                } else {
5562                    search_start = 0;
5563                }
5564            }
5565        }
5566    }
5567
5568    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5569        let snapshot = self
5570            .display_map
5571            .update(cx, |display_map, cx| display_map.snapshot(cx));
5572        let selection = self.selections.newest::<Point>(cx);
5573
5574        if !self.seek_in_direction(
5575            &snapshot,
5576            selection.head(),
5577            false,
5578            snapshot
5579                .buffer_snapshot
5580                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5581            cx,
5582        ) {
5583            let wrapped_point = Point::zero();
5584            self.seek_in_direction(
5585                &snapshot,
5586                wrapped_point,
5587                true,
5588                snapshot
5589                    .buffer_snapshot
5590                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5591                cx,
5592            );
5593        }
5594    }
5595
5596    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5597        let snapshot = self
5598            .display_map
5599            .update(cx, |display_map, cx| display_map.snapshot(cx));
5600        let selection = self.selections.newest::<Point>(cx);
5601
5602        if !self.seek_in_direction(
5603            &snapshot,
5604            selection.head(),
5605            false,
5606            snapshot
5607                .buffer_snapshot
5608                .git_diff_hunks_in_range_rev(0..selection.head().row),
5609            cx,
5610        ) {
5611            let wrapped_point = snapshot.buffer_snapshot.max_point();
5612            self.seek_in_direction(
5613                &snapshot,
5614                wrapped_point,
5615                true,
5616                snapshot
5617                    .buffer_snapshot
5618                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5619                cx,
5620            );
5621        }
5622    }
5623
5624    fn seek_in_direction(
5625        &mut self,
5626        snapshot: &DisplaySnapshot,
5627        initial_point: Point,
5628        is_wrapped: bool,
5629        hunks: impl Iterator<Item = DiffHunk<u32>>,
5630        cx: &mut ViewContext<Editor>,
5631    ) -> bool {
5632        let display_point = initial_point.to_display_point(snapshot);
5633        let mut hunks = hunks
5634            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5635            .skip_while(|hunk| {
5636                if is_wrapped {
5637                    false
5638                } else {
5639                    hunk.contains_display_row(display_point.row())
5640                }
5641            })
5642            .dedup();
5643
5644        if let Some(hunk) = hunks.next() {
5645            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5646                let row = hunk.start_display_row();
5647                let point = DisplayPoint::new(row, 0);
5648                s.select_display_ranges([point..point]);
5649            });
5650
5651            true
5652        } else {
5653            false
5654        }
5655    }
5656
5657    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5658        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5659    }
5660
5661    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5662        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5663    }
5664
5665    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5666        let Some(workspace) = self.workspace(cx) else { return };
5667        let buffer = self.buffer.read(cx);
5668        let head = self.selections.newest::<usize>(cx).head();
5669        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5670            text_anchor
5671        } else {
5672            return;
5673        };
5674
5675        let project = workspace.read(cx).project().clone();
5676        let definitions = project.update(cx, |project, cx| match kind {
5677            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5678            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5679        });
5680
5681        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5682            let definitions = definitions.await?;
5683            editor.update(&mut cx, |editor, cx| {
5684                editor.navigate_to_definitions(definitions, cx);
5685            })?;
5686            Ok::<(), anyhow::Error>(())
5687        })
5688        .detach_and_log_err(cx);
5689    }
5690
5691    pub fn navigate_to_definitions(
5692        &mut self,
5693        mut definitions: Vec<LocationLink>,
5694        cx: &mut ViewContext<Editor>,
5695    ) {
5696        let Some(workspace) = self.workspace(cx) else { return };
5697        let pane = workspace.read(cx).active_pane().clone();
5698        // If there is one definition, just open it directly
5699        if definitions.len() == 1 {
5700            let definition = definitions.pop().unwrap();
5701            let range = definition
5702                .target
5703                .range
5704                .to_offset(definition.target.buffer.read(cx));
5705
5706            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
5707                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5708                    s.select_ranges([range]);
5709                });
5710            } else {
5711                cx.window_context().defer(move |cx| {
5712                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
5713                        workspace.open_project_item(definition.target.buffer.clone(), cx)
5714                    });
5715                    target_editor.update(cx, |target_editor, cx| {
5716                        // When selecting a definition in a different buffer, disable the nav history
5717                        // to avoid creating a history entry at the previous cursor location.
5718                        pane.update(cx, |pane, _| pane.disable_history());
5719                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5720                            s.select_ranges([range]);
5721                        });
5722                        pane.update(cx, |pane, _| pane.enable_history());
5723                    });
5724                });
5725            }
5726        } else if !definitions.is_empty() {
5727            let replica_id = self.replica_id(cx);
5728            cx.window_context().defer(move |cx| {
5729                let title = definitions
5730                    .iter()
5731                    .find(|definition| definition.origin.is_some())
5732                    .and_then(|definition| {
5733                        definition.origin.as_ref().map(|origin| {
5734                            let buffer = origin.buffer.read(cx);
5735                            format!(
5736                                "Definitions for {}",
5737                                buffer
5738                                    .text_for_range(origin.range.clone())
5739                                    .collect::<String>()
5740                            )
5741                        })
5742                    })
5743                    .unwrap_or("Definitions".to_owned());
5744                let locations = definitions
5745                    .into_iter()
5746                    .map(|definition| definition.target)
5747                    .collect();
5748                workspace.update(cx, |workspace, cx| {
5749                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5750                });
5751            });
5752        }
5753    }
5754
5755    pub fn find_all_references(
5756        workspace: &mut Workspace,
5757        _: &FindAllReferences,
5758        cx: &mut ViewContext<Workspace>,
5759    ) -> Option<Task<Result<()>>> {
5760        let active_item = workspace.active_item(cx)?;
5761        let editor_handle = active_item.act_as::<Self>(cx)?;
5762
5763        let editor = editor_handle.read(cx);
5764        let buffer = editor.buffer.read(cx);
5765        let head = editor.selections.newest::<usize>(cx).head();
5766        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5767        let replica_id = editor.replica_id(cx);
5768
5769        let project = workspace.project().clone();
5770        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5771        Some(cx.spawn_labeled(
5772            "Finding All References...",
5773            |workspace, mut cx| async move {
5774                let locations = references.await?;
5775                if locations.is_empty() {
5776                    return Ok(());
5777                }
5778
5779                workspace.update(&mut cx, |workspace, cx| {
5780                    let title = locations
5781                        .first()
5782                        .as_ref()
5783                        .map(|location| {
5784                            let buffer = location.buffer.read(cx);
5785                            format!(
5786                                "References to `{}`",
5787                                buffer
5788                                    .text_for_range(location.range.clone())
5789                                    .collect::<String>()
5790                            )
5791                        })
5792                        .unwrap();
5793                    Self::open_locations_in_multibuffer(
5794                        workspace, locations, replica_id, title, cx,
5795                    );
5796                })?;
5797
5798                Ok(())
5799            },
5800        ))
5801    }
5802
5803    /// Opens a multibuffer with the given project locations in it
5804    pub fn open_locations_in_multibuffer(
5805        workspace: &mut Workspace,
5806        mut locations: Vec<Location>,
5807        replica_id: ReplicaId,
5808        title: String,
5809        cx: &mut ViewContext<Workspace>,
5810    ) {
5811        // If there are multiple definitions, open them in a multibuffer
5812        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
5813        let mut locations = locations.into_iter().peekable();
5814        let mut ranges_to_highlight = Vec::new();
5815
5816        let excerpt_buffer = cx.add_model(|cx| {
5817            let mut multibuffer = MultiBuffer::new(replica_id);
5818            while let Some(location) = locations.next() {
5819                let buffer = location.buffer.read(cx);
5820                let mut ranges_for_buffer = Vec::new();
5821                let range = location.range.to_offset(buffer);
5822                ranges_for_buffer.push(range.clone());
5823
5824                while let Some(next_location) = locations.peek() {
5825                    if next_location.buffer == location.buffer {
5826                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5827                        locations.next();
5828                    } else {
5829                        break;
5830                    }
5831                }
5832
5833                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5834                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5835                    location.buffer.clone(),
5836                    ranges_for_buffer,
5837                    1,
5838                    cx,
5839                ))
5840            }
5841
5842            multibuffer.with_title(title)
5843        });
5844
5845        let editor = cx.add_view(|cx| {
5846            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5847        });
5848        editor.update(cx, |editor, cx| {
5849            editor.highlight_background::<Self>(
5850                ranges_to_highlight,
5851                |theme| theme.editor.highlighted_line_background,
5852                cx,
5853            );
5854        });
5855        workspace.add_item(Box::new(editor), cx);
5856    }
5857
5858    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5859        use language::ToOffset as _;
5860
5861        let project = self.project.clone()?;
5862        let selection = self.selections.newest_anchor().clone();
5863        let (cursor_buffer, cursor_buffer_position) = self
5864            .buffer
5865            .read(cx)
5866            .text_anchor_for_position(selection.head(), cx)?;
5867        let (tail_buffer, _) = self
5868            .buffer
5869            .read(cx)
5870            .text_anchor_for_position(selection.tail(), cx)?;
5871        if tail_buffer != cursor_buffer {
5872            return None;
5873        }
5874
5875        let snapshot = cursor_buffer.read(cx).snapshot();
5876        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5877        let prepare_rename = project.update(cx, |project, cx| {
5878            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5879        });
5880
5881        Some(cx.spawn(|this, mut cx| async move {
5882            let rename_range = if let Some(range) = prepare_rename.await? {
5883                Some(range)
5884            } else {
5885                this.read_with(&cx, |this, cx| {
5886                    let buffer = this.buffer.read(cx).snapshot(cx);
5887                    let mut buffer_highlights = this
5888                        .document_highlights_for_position(selection.head(), &buffer)
5889                        .filter(|highlight| {
5890                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5891                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5892                        });
5893                    buffer_highlights
5894                        .next()
5895                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5896                })?
5897            };
5898            if let Some(rename_range) = rename_range {
5899                let rename_buffer_range = rename_range.to_offset(&snapshot);
5900                let cursor_offset_in_rename_range =
5901                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5902
5903                this.update(&mut cx, |this, cx| {
5904                    this.take_rename(false, cx);
5905                    let style = this.style(cx);
5906                    let buffer = this.buffer.read(cx).read(cx);
5907                    let cursor_offset = selection.head().to_offset(&buffer);
5908                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5909                    let rename_end = rename_start + rename_buffer_range.len();
5910                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5911                    let mut old_highlight_id = None;
5912                    let old_name: Arc<str> = buffer
5913                        .chunks(rename_start..rename_end, true)
5914                        .map(|chunk| {
5915                            if old_highlight_id.is_none() {
5916                                old_highlight_id = chunk.syntax_highlight_id;
5917                            }
5918                            chunk.text
5919                        })
5920                        .collect::<String>()
5921                        .into();
5922
5923                    drop(buffer);
5924
5925                    // Position the selection in the rename editor so that it matches the current selection.
5926                    this.show_local_selections = false;
5927                    let rename_editor = cx.add_view(|cx| {
5928                        let mut editor = Editor::single_line(None, cx);
5929                        if let Some(old_highlight_id) = old_highlight_id {
5930                            editor.override_text_style =
5931                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5932                        }
5933                        editor.buffer.update(cx, |buffer, cx| {
5934                            buffer.edit([(0..0, old_name.clone())], None, cx)
5935                        });
5936                        editor.select_all(&SelectAll, cx);
5937                        editor
5938                    });
5939
5940                    let ranges = this
5941                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5942                        .into_iter()
5943                        .flat_map(|(_, ranges)| ranges)
5944                        .chain(
5945                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5946                                .into_iter()
5947                                .flat_map(|(_, ranges)| ranges),
5948                        )
5949                        .collect();
5950
5951                    this.highlight_text::<Rename>(
5952                        ranges,
5953                        HighlightStyle {
5954                            fade_out: Some(style.rename_fade),
5955                            ..Default::default()
5956                        },
5957                        cx,
5958                    );
5959                    cx.focus(&rename_editor);
5960                    let block_id = this.insert_blocks(
5961                        [BlockProperties {
5962                            style: BlockStyle::Flex,
5963                            position: range.start.clone(),
5964                            height: 1,
5965                            render: Arc::new({
5966                                let editor = rename_editor.clone();
5967                                move |cx: &mut BlockContext| {
5968                                    ChildView::new(&editor, cx)
5969                                        .contained()
5970                                        .with_padding_left(cx.anchor_x)
5971                                        .into_any()
5972                                }
5973                            }),
5974                            disposition: BlockDisposition::Below,
5975                        }],
5976                        cx,
5977                    )[0];
5978                    this.pending_rename = Some(RenameState {
5979                        range,
5980                        old_name,
5981                        editor: rename_editor,
5982                        block_id,
5983                    });
5984                })?;
5985            }
5986
5987            Ok(())
5988        }))
5989    }
5990
5991    pub fn confirm_rename(
5992        workspace: &mut Workspace,
5993        _: &ConfirmRename,
5994        cx: &mut ViewContext<Workspace>,
5995    ) -> Option<Task<Result<()>>> {
5996        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5997
5998        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5999            let rename = editor.take_rename(false, cx)?;
6000            let buffer = editor.buffer.read(cx);
6001            let (start_buffer, start) =
6002                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6003            let (end_buffer, end) =
6004                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6005            if start_buffer == end_buffer {
6006                let new_name = rename.editor.read(cx).text(cx);
6007                Some((start_buffer, start..end, rename.old_name, new_name))
6008            } else {
6009                None
6010            }
6011        })?;
6012
6013        let rename = workspace.project().clone().update(cx, |project, cx| {
6014            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6015        });
6016
6017        let editor = editor.downgrade();
6018        Some(cx.spawn(|workspace, mut cx| async move {
6019            let project_transaction = rename.await?;
6020            Self::open_project_transaction(
6021                &editor,
6022                workspace,
6023                project_transaction,
6024                format!("Rename: {}{}", old_name, new_name),
6025                cx.clone(),
6026            )
6027            .await?;
6028
6029            editor.update(&mut cx, |editor, cx| {
6030                editor.refresh_document_highlights(cx);
6031            })?;
6032            Ok(())
6033        }))
6034    }
6035
6036    fn take_rename(
6037        &mut self,
6038        moving_cursor: bool,
6039        cx: &mut ViewContext<Self>,
6040    ) -> Option<RenameState> {
6041        let rename = self.pending_rename.take()?;
6042        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
6043        self.clear_text_highlights::<Rename>(cx);
6044        self.show_local_selections = true;
6045
6046        if moving_cursor {
6047            let rename_editor = rename.editor.read(cx);
6048            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6049
6050            // Update the selection to match the position of the selection inside
6051            // the rename editor.
6052            let snapshot = self.buffer.read(cx).read(cx);
6053            let rename_range = rename.range.to_offset(&snapshot);
6054            let cursor_in_editor = snapshot
6055                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6056                .min(rename_range.end);
6057            drop(snapshot);
6058
6059            self.change_selections(None, cx, |s| {
6060                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6061            });
6062        } else {
6063            self.refresh_document_highlights(cx);
6064        }
6065
6066        Some(rename)
6067    }
6068
6069    #[cfg(any(test, feature = "test-support"))]
6070    pub fn pending_rename(&self) -> Option<&RenameState> {
6071        self.pending_rename.as_ref()
6072    }
6073
6074    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6075        let project = match &self.project {
6076            Some(project) => project.clone(),
6077            None => return None,
6078        };
6079
6080        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6081    }
6082
6083    fn perform_format(
6084        &mut self,
6085        project: ModelHandle<Project>,
6086        trigger: FormatTrigger,
6087        cx: &mut ViewContext<Self>,
6088    ) -> Task<Result<()>> {
6089        let buffer = self.buffer().clone();
6090        let buffers = buffer.read(cx).all_buffers();
6091
6092        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6093        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6094
6095        cx.spawn(|_, mut cx| async move {
6096            let transaction = futures::select_biased! {
6097                _ = timeout => {
6098                    log::warn!("timed out waiting for formatting");
6099                    None
6100                }
6101                transaction = format.log_err().fuse() => transaction,
6102            };
6103
6104            buffer.update(&mut cx, |buffer, cx| {
6105                if let Some(transaction) = transaction {
6106                    if !buffer.is_singleton() {
6107                        buffer.push_transaction(&transaction.0, cx);
6108                    }
6109                }
6110
6111                cx.notify();
6112            });
6113
6114            Ok(())
6115        })
6116    }
6117
6118    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6119        if let Some(project) = self.project.clone() {
6120            self.buffer.update(cx, |multi_buffer, cx| {
6121                project.update(cx, |project, cx| {
6122                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6123                });
6124            })
6125        }
6126    }
6127
6128    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6129        cx.show_character_palette();
6130    }
6131
6132    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6133        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6134            let buffer = self.buffer.read(cx).snapshot(cx);
6135            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6136            let is_valid = buffer
6137                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6138                .any(|entry| {
6139                    entry.diagnostic.is_primary
6140                        && !entry.range.is_empty()
6141                        && entry.range.start == primary_range_start
6142                        && entry.diagnostic.message == active_diagnostics.primary_message
6143                });
6144
6145            if is_valid != active_diagnostics.is_valid {
6146                active_diagnostics.is_valid = is_valid;
6147                let mut new_styles = HashMap::default();
6148                for (block_id, diagnostic) in &active_diagnostics.blocks {
6149                    new_styles.insert(
6150                        *block_id,
6151                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6152                    );
6153                }
6154                self.display_map
6155                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6156            }
6157        }
6158    }
6159
6160    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6161        self.dismiss_diagnostics(cx);
6162        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6163            let buffer = self.buffer.read(cx).snapshot(cx);
6164
6165            let mut primary_range = None;
6166            let mut primary_message = None;
6167            let mut group_end = Point::zero();
6168            let diagnostic_group = buffer
6169                .diagnostic_group::<Point>(group_id)
6170                .map(|entry| {
6171                    if entry.range.end > group_end {
6172                        group_end = entry.range.end;
6173                    }
6174                    if entry.diagnostic.is_primary {
6175                        primary_range = Some(entry.range.clone());
6176                        primary_message = Some(entry.diagnostic.message.clone());
6177                    }
6178                    entry
6179                })
6180                .collect::<Vec<_>>();
6181            let primary_range = primary_range?;
6182            let primary_message = primary_message?;
6183            let primary_range =
6184                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6185
6186            let blocks = display_map
6187                .insert_blocks(
6188                    diagnostic_group.iter().map(|entry| {
6189                        let diagnostic = entry.diagnostic.clone();
6190                        let message_height = diagnostic.message.lines().count() as u8;
6191                        BlockProperties {
6192                            style: BlockStyle::Fixed,
6193                            position: buffer.anchor_after(entry.range.start),
6194                            height: message_height,
6195                            render: diagnostic_block_renderer(diagnostic, true),
6196                            disposition: BlockDisposition::Below,
6197                        }
6198                    }),
6199                    cx,
6200                )
6201                .into_iter()
6202                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6203                .collect();
6204
6205            Some(ActiveDiagnosticGroup {
6206                primary_range,
6207                primary_message,
6208                blocks,
6209                is_valid: true,
6210            })
6211        });
6212        self.active_diagnostics.is_some()
6213    }
6214
6215    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6216        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6217            self.display_map.update(cx, |display_map, cx| {
6218                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6219            });
6220            cx.notify();
6221        }
6222    }
6223
6224    pub fn set_selections_from_remote(
6225        &mut self,
6226        selections: Vec<Selection<Anchor>>,
6227        pending_selection: Option<Selection<Anchor>>,
6228        cx: &mut ViewContext<Self>,
6229    ) {
6230        let old_cursor_position = self.selections.newest_anchor().head();
6231        self.selections.change_with(cx, |s| {
6232            s.select_anchors(selections);
6233            if let Some(pending_selection) = pending_selection {
6234                s.set_pending(pending_selection, SelectMode::Character);
6235            } else {
6236                s.clear_pending();
6237            }
6238        });
6239        self.selections_did_change(false, &old_cursor_position, cx);
6240    }
6241
6242    fn push_to_selection_history(&mut self) {
6243        self.selection_history.push(SelectionHistoryEntry {
6244            selections: self.selections.disjoint_anchors(),
6245            select_next_state: self.select_next_state.clone(),
6246            add_selections_state: self.add_selections_state.clone(),
6247        });
6248    }
6249
6250    pub fn transact(
6251        &mut self,
6252        cx: &mut ViewContext<Self>,
6253        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6254    ) -> Option<TransactionId> {
6255        self.start_transaction_at(Instant::now(), cx);
6256        update(self, cx);
6257        self.end_transaction_at(Instant::now(), cx)
6258    }
6259
6260    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6261        self.end_selection(cx);
6262        if let Some(tx_id) = self
6263            .buffer
6264            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6265        {
6266            self.selection_history
6267                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6268        }
6269    }
6270
6271    fn end_transaction_at(
6272        &mut self,
6273        now: Instant,
6274        cx: &mut ViewContext<Self>,
6275    ) -> Option<TransactionId> {
6276        if let Some(tx_id) = self
6277            .buffer
6278            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6279        {
6280            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6281                *end_selections = Some(self.selections.disjoint_anchors());
6282            } else {
6283                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6284            }
6285
6286            cx.emit(Event::Edited);
6287            Some(tx_id)
6288        } else {
6289            None
6290        }
6291    }
6292
6293    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6294        let mut fold_ranges = Vec::new();
6295
6296        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6297
6298        let selections = self.selections.all::<Point>(cx);
6299        for selection in selections {
6300            let range = selection.range().sorted();
6301            let buffer_start_row = range.start.row;
6302
6303            for row in (0..=range.end.row).rev() {
6304                let fold_range = display_map.foldable_range(row);
6305
6306                if let Some(fold_range) = fold_range {
6307                    if fold_range.end.row >= buffer_start_row {
6308                        fold_ranges.push(fold_range);
6309                        if row <= range.start.row {
6310                            break;
6311                        }
6312                    }
6313                }
6314            }
6315        }
6316
6317        self.fold_ranges(fold_ranges, true, cx);
6318    }
6319
6320    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6321        let buffer_row = fold_at.buffer_row;
6322        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6323
6324        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6325            let autoscroll = self
6326                .selections
6327                .all::<Point>(cx)
6328                .iter()
6329                .any(|selection| fold_range.overlaps(&selection.range()));
6330
6331            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6332        }
6333    }
6334
6335    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6336        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6337        let buffer = &display_map.buffer_snapshot;
6338        let selections = self.selections.all::<Point>(cx);
6339        let ranges = selections
6340            .iter()
6341            .map(|s| {
6342                let range = s.display_range(&display_map).sorted();
6343                let mut start = range.start.to_point(&display_map);
6344                let mut end = range.end.to_point(&display_map);
6345                start.column = 0;
6346                end.column = buffer.line_len(end.row);
6347                start..end
6348            })
6349            .collect::<Vec<_>>();
6350
6351        self.unfold_ranges(ranges, true, true, cx);
6352    }
6353
6354    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6355        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6356
6357        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6358            ..Point::new(
6359                unfold_at.buffer_row,
6360                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6361            );
6362
6363        let autoscroll = self
6364            .selections
6365            .all::<Point>(cx)
6366            .iter()
6367            .any(|selection| selection.range().overlaps(&intersection_range));
6368
6369        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6370    }
6371
6372    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6373        let selections = self.selections.all::<Point>(cx);
6374        let ranges = selections.into_iter().map(|s| s.start..s.end);
6375        self.fold_ranges(ranges, true, cx);
6376    }
6377
6378    pub fn fold_ranges<T: ToOffset + Clone>(
6379        &mut self,
6380        ranges: impl IntoIterator<Item = Range<T>>,
6381        auto_scroll: bool,
6382        cx: &mut ViewContext<Self>,
6383    ) {
6384        let mut ranges = ranges.into_iter().peekable();
6385        if ranges.peek().is_some() {
6386            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6387
6388            if auto_scroll {
6389                self.request_autoscroll(Autoscroll::fit(), cx);
6390            }
6391
6392            cx.notify();
6393        }
6394    }
6395
6396    pub fn unfold_ranges<T: ToOffset + Clone>(
6397        &mut self,
6398        ranges: impl IntoIterator<Item = Range<T>>,
6399        inclusive: bool,
6400        auto_scroll: bool,
6401        cx: &mut ViewContext<Self>,
6402    ) {
6403        let mut ranges = ranges.into_iter().peekable();
6404        if ranges.peek().is_some() {
6405            self.display_map
6406                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6407            if auto_scroll {
6408                self.request_autoscroll(Autoscroll::fit(), cx);
6409            }
6410
6411            cx.notify();
6412        }
6413    }
6414
6415    pub fn gutter_hover(
6416        &mut self,
6417        GutterHover { hovered }: &GutterHover,
6418        cx: &mut ViewContext<Self>,
6419    ) {
6420        self.gutter_hovered = *hovered;
6421        cx.notify();
6422    }
6423
6424    pub fn insert_blocks(
6425        &mut self,
6426        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6427        cx: &mut ViewContext<Self>,
6428    ) -> Vec<BlockId> {
6429        let blocks = self
6430            .display_map
6431            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6432        self.request_autoscroll(Autoscroll::fit(), cx);
6433        blocks
6434    }
6435
6436    pub fn replace_blocks(
6437        &mut self,
6438        blocks: HashMap<BlockId, RenderBlock>,
6439        cx: &mut ViewContext<Self>,
6440    ) {
6441        self.display_map
6442            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6443        self.request_autoscroll(Autoscroll::fit(), cx);
6444    }
6445
6446    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6447        self.display_map.update(cx, |display_map, cx| {
6448            display_map.remove_blocks(block_ids, cx)
6449        });
6450    }
6451
6452    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6453        self.display_map
6454            .update(cx, |map, cx| map.snapshot(cx))
6455            .longest_row()
6456    }
6457
6458    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6459        self.display_map
6460            .update(cx, |map, cx| map.snapshot(cx))
6461            .max_point()
6462    }
6463
6464    pub fn text(&self, cx: &AppContext) -> String {
6465        self.buffer.read(cx).read(cx).text()
6466    }
6467
6468    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6469        self.transact(cx, |this, cx| {
6470            this.buffer
6471                .read(cx)
6472                .as_singleton()
6473                .expect("you can only call set_text on editors for singleton buffers")
6474                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6475        });
6476    }
6477
6478    pub fn display_text(&self, cx: &mut AppContext) -> String {
6479        self.display_map
6480            .update(cx, |map, cx| map.snapshot(cx))
6481            .text()
6482    }
6483
6484    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6485        let language_name = self
6486            .buffer
6487            .read(cx)
6488            .as_singleton()
6489            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6490            .map(|l| l.name());
6491
6492        let settings = cx.global::<Settings>();
6493        let mode = self
6494            .soft_wrap_mode_override
6495            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6496        match mode {
6497            settings::SoftWrap::None => SoftWrap::None,
6498            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6499            settings::SoftWrap::PreferredLineLength => {
6500                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6501            }
6502        }
6503    }
6504
6505    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6506        self.soft_wrap_mode_override = Some(mode);
6507        cx.notify();
6508    }
6509
6510    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6511        self.display_map
6512            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6513    }
6514
6515    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6516        if self.soft_wrap_mode_override.is_some() {
6517            self.soft_wrap_mode_override.take();
6518        } else {
6519            let soft_wrap = match self.soft_wrap_mode(cx) {
6520                SoftWrap::None => settings::SoftWrap::EditorWidth,
6521                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
6522            };
6523            self.soft_wrap_mode_override = Some(soft_wrap);
6524        }
6525        cx.notify();
6526    }
6527
6528    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6529        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6530            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6531                cx.reveal_path(&file.abs_path(cx));
6532            }
6533        }
6534    }
6535
6536    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6537        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6538            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6539                if let Some(path) = file.abs_path(cx).to_str() {
6540                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6541                }
6542            }
6543        }
6544    }
6545
6546    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6547        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6548            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6549                if let Some(path) = file.path().to_str() {
6550                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6551                }
6552            }
6553        }
6554    }
6555
6556    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6557        self.highlighted_rows = rows;
6558    }
6559
6560    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6561        self.highlighted_rows.clone()
6562    }
6563
6564    pub fn highlight_background<T: 'static>(
6565        &mut self,
6566        ranges: Vec<Range<Anchor>>,
6567        color_fetcher: fn(&Theme) -> Color,
6568        cx: &mut ViewContext<Self>,
6569    ) {
6570        self.background_highlights
6571            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6572        cx.notify();
6573    }
6574
6575    #[allow(clippy::type_complexity)]
6576    pub fn clear_background_highlights<T: 'static>(
6577        &mut self,
6578        cx: &mut ViewContext<Self>,
6579    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6580        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6581        if highlights.is_some() {
6582            cx.notify();
6583        }
6584        highlights
6585    }
6586
6587    #[cfg(feature = "test-support")]
6588    pub fn all_background_highlights(
6589        &mut self,
6590        cx: &mut ViewContext<Self>,
6591    ) -> Vec<(Range<DisplayPoint>, Color)> {
6592        let snapshot = self.snapshot(cx);
6593        let buffer = &snapshot.buffer_snapshot;
6594        let start = buffer.anchor_before(0);
6595        let end = buffer.anchor_after(buffer.len());
6596        let theme = cx.global::<Settings>().theme.as_ref();
6597        self.background_highlights_in_range(start..end, &snapshot, theme)
6598    }
6599
6600    fn document_highlights_for_position<'a>(
6601        &'a self,
6602        position: Anchor,
6603        buffer: &'a MultiBufferSnapshot,
6604    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6605        let read_highlights = self
6606            .background_highlights
6607            .get(&TypeId::of::<DocumentHighlightRead>())
6608            .map(|h| &h.1);
6609        let write_highlights = self
6610            .background_highlights
6611            .get(&TypeId::of::<DocumentHighlightWrite>())
6612            .map(|h| &h.1);
6613        let left_position = position.bias_left(buffer);
6614        let right_position = position.bias_right(buffer);
6615        read_highlights
6616            .into_iter()
6617            .chain(write_highlights)
6618            .flat_map(move |ranges| {
6619                let start_ix = match ranges.binary_search_by(|probe| {
6620                    let cmp = probe.end.cmp(&left_position, buffer);
6621                    if cmp.is_ge() {
6622                        Ordering::Greater
6623                    } else {
6624                        Ordering::Less
6625                    }
6626                }) {
6627                    Ok(i) | Err(i) => i,
6628                };
6629
6630                let right_position = right_position.clone();
6631                ranges[start_ix..]
6632                    .iter()
6633                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6634            })
6635    }
6636
6637    pub fn background_highlights_in_range(
6638        &self,
6639        search_range: Range<Anchor>,
6640        display_snapshot: &DisplaySnapshot,
6641        theme: &Theme,
6642    ) -> Vec<(Range<DisplayPoint>, Color)> {
6643        let mut results = Vec::new();
6644        let buffer = &display_snapshot.buffer_snapshot;
6645        for (color_fetcher, ranges) in self.background_highlights.values() {
6646            let color = color_fetcher(theme);
6647            let start_ix = match ranges.binary_search_by(|probe| {
6648                let cmp = probe.end.cmp(&search_range.start, buffer);
6649                if cmp.is_gt() {
6650                    Ordering::Greater
6651                } else {
6652                    Ordering::Less
6653                }
6654            }) {
6655                Ok(i) | Err(i) => i,
6656            };
6657            for range in &ranges[start_ix..] {
6658                if range.start.cmp(&search_range.end, buffer).is_ge() {
6659                    break;
6660                }
6661                let start = range
6662                    .start
6663                    .to_point(buffer)
6664                    .to_display_point(display_snapshot);
6665                let end = range
6666                    .end
6667                    .to_point(buffer)
6668                    .to_display_point(display_snapshot);
6669                results.push((start..end, color))
6670            }
6671        }
6672        results
6673    }
6674
6675    pub fn highlight_text<T: 'static>(
6676        &mut self,
6677        ranges: Vec<Range<Anchor>>,
6678        style: HighlightStyle,
6679        cx: &mut ViewContext<Self>,
6680    ) {
6681        self.display_map.update(cx, |map, _| {
6682            map.highlight_text(TypeId::of::<T>(), ranges, style)
6683        });
6684        cx.notify();
6685    }
6686
6687    pub fn text_highlights<'a, T: 'static>(
6688        &'a self,
6689        cx: &'a AppContext,
6690    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6691        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6692    }
6693
6694    pub fn clear_text_highlights<T: 'static>(
6695        &mut self,
6696        cx: &mut ViewContext<Self>,
6697    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6698        let highlights = self
6699            .display_map
6700            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6701        if highlights.is_some() {
6702            cx.notify();
6703        }
6704        highlights
6705    }
6706
6707    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6708        self.blink_manager.read(cx).visible() && self.focused
6709    }
6710
6711    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6712        cx.notify();
6713    }
6714
6715    fn on_buffer_event(
6716        &mut self,
6717        _: ModelHandle<MultiBuffer>,
6718        event: &multi_buffer::Event,
6719        cx: &mut ViewContext<Self>,
6720    ) {
6721        match event {
6722            multi_buffer::Event::Edited => {
6723                self.refresh_active_diagnostics(cx);
6724                self.refresh_code_actions(cx);
6725                if self.has_active_copilot_suggestion(cx) {
6726                    self.update_visible_copilot_suggestion(cx);
6727                }
6728                cx.emit(Event::BufferEdited);
6729            }
6730            multi_buffer::Event::ExcerptsAdded {
6731                buffer,
6732                predecessor,
6733                excerpts,
6734            } => cx.emit(Event::ExcerptsAdded {
6735                buffer: buffer.clone(),
6736                predecessor: *predecessor,
6737                excerpts: excerpts.clone(),
6738            }),
6739            multi_buffer::Event::ExcerptsRemoved { ids } => {
6740                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6741            }
6742            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6743            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6744            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6745            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6746            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6747            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6748            multi_buffer::Event::DiagnosticsUpdated => {
6749                self.refresh_active_diagnostics(cx);
6750            }
6751            multi_buffer::Event::LanguageChanged => {}
6752        }
6753    }
6754
6755    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6756        cx.notify();
6757    }
6758
6759    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6760        self.refresh_copilot_suggestions(true, cx);
6761    }
6762
6763    pub fn set_searchable(&mut self, searchable: bool) {
6764        self.searchable = searchable;
6765    }
6766
6767    pub fn searchable(&self) -> bool {
6768        self.searchable
6769    }
6770
6771    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6772        let active_item = workspace.active_item(cx);
6773        let editor_handle = if let Some(editor) = active_item
6774            .as_ref()
6775            .and_then(|item| item.act_as::<Self>(cx))
6776        {
6777            editor
6778        } else {
6779            cx.propagate_action();
6780            return;
6781        };
6782
6783        let editor = editor_handle.read(cx);
6784        let buffer = editor.buffer.read(cx);
6785        if buffer.is_singleton() {
6786            cx.propagate_action();
6787            return;
6788        }
6789
6790        let mut new_selections_by_buffer = HashMap::default();
6791        for selection in editor.selections.all::<usize>(cx) {
6792            for (buffer, mut range) in
6793                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6794            {
6795                if selection.reversed {
6796                    mem::swap(&mut range.start, &mut range.end);
6797                }
6798                new_selections_by_buffer
6799                    .entry(buffer)
6800                    .or_insert(Vec::new())
6801                    .push(range)
6802            }
6803        }
6804
6805        editor_handle.update(cx, |editor, cx| {
6806            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6807        });
6808        let pane = workspace.active_pane().clone();
6809        pane.update(cx, |pane, _| pane.disable_history());
6810
6811        // We defer the pane interaction because we ourselves are a workspace item
6812        // and activating a new item causes the pane to call a method on us reentrantly,
6813        // which panics if we're on the stack.
6814        cx.defer(move |workspace, cx| {
6815            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6816                let editor = workspace.open_project_item::<Self>(buffer, cx);
6817                editor.update(cx, |editor, cx| {
6818                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6819                        s.select_ranges(ranges);
6820                    });
6821                });
6822            }
6823
6824            pane.update(cx, |pane, _| pane.enable_history());
6825        });
6826    }
6827
6828    fn jump(
6829        workspace: &mut Workspace,
6830        path: ProjectPath,
6831        position: Point,
6832        anchor: language::Anchor,
6833        cx: &mut ViewContext<Workspace>,
6834    ) {
6835        let editor = workspace.open_path(path, None, true, cx);
6836        cx.spawn(|_, mut cx| async move {
6837            let editor = editor
6838                .await?
6839                .downcast::<Editor>()
6840                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6841                .downgrade();
6842            editor.update(&mut cx, |editor, cx| {
6843                let buffer = editor
6844                    .buffer()
6845                    .read(cx)
6846                    .as_singleton()
6847                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6848                let buffer = buffer.read(cx);
6849                let cursor = if buffer.can_resolve(&anchor) {
6850                    language::ToPoint::to_point(&anchor, buffer)
6851                } else {
6852                    buffer.clip_point(position, Bias::Left)
6853                };
6854
6855                let nav_history = editor.nav_history.take();
6856                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6857                    s.select_ranges([cursor..cursor]);
6858                });
6859                editor.nav_history = nav_history;
6860
6861                anyhow::Ok(())
6862            })??;
6863
6864            anyhow::Ok(())
6865        })
6866        .detach_and_log_err(cx);
6867    }
6868
6869    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6870        let snapshot = self.buffer.read(cx).read(cx);
6871        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6872        Some(
6873            ranges
6874                .iter()
6875                .map(move |range| {
6876                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6877                })
6878                .collect(),
6879        )
6880    }
6881
6882    fn selection_replacement_ranges(
6883        &self,
6884        range: Range<OffsetUtf16>,
6885        cx: &AppContext,
6886    ) -> Vec<Range<OffsetUtf16>> {
6887        let selections = self.selections.all::<OffsetUtf16>(cx);
6888        let newest_selection = selections
6889            .iter()
6890            .max_by_key(|selection| selection.id)
6891            .unwrap();
6892        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6893        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6894        let snapshot = self.buffer.read(cx).read(cx);
6895        selections
6896            .into_iter()
6897            .map(|mut selection| {
6898                selection.start.0 =
6899                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6900                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6901                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6902                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6903            })
6904            .collect()
6905    }
6906
6907    fn report_copilot_event(
6908        &self,
6909        suggestion_id: Option<String>,
6910        suggestion_accepted: bool,
6911        cx: &AppContext,
6912    ) {
6913        let Some(project) = &self.project else {
6914            return
6915        };
6916
6917        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
6918        let file_extension = self
6919            .buffer
6920            .read(cx)
6921            .as_singleton()
6922            .and_then(|b| b.read(cx).file())
6923            .and_then(|file| Path::new(file.file_name(cx)).extension())
6924            .and_then(|e| e.to_str())
6925            .map(|a| a.to_string());
6926
6927        let telemetry = project.read(cx).client().telemetry().clone();
6928        let telemetry_settings = cx.global::<Settings>().telemetry();
6929
6930        let event = ClickhouseEvent::Copilot {
6931            suggestion_id,
6932            suggestion_accepted,
6933            file_extension,
6934        };
6935        telemetry.report_clickhouse_event(event, telemetry_settings);
6936    }
6937
6938    fn report_editor_event(
6939        &self,
6940        name: &'static str,
6941        file_extension: Option<String>,
6942        cx: &AppContext,
6943    ) {
6944        let Some(project) = &self.project else {
6945            return
6946        };
6947
6948        // If None, we are in a file without an extension
6949        let file_extension = file_extension.or(self
6950            .buffer
6951            .read(cx)
6952            .as_singleton()
6953            .and_then(|b| b.read(cx).file())
6954            .and_then(|file| Path::new(file.file_name(cx)).extension())
6955            .and_then(|e| e.to_str())
6956            .map(|a| a.to_string()));
6957
6958        let settings = cx.global::<Settings>();
6959
6960        let telemetry = project.read(cx).client().telemetry().clone();
6961        telemetry.report_mixpanel_event(
6962                match name {
6963                    "open" => "open editor",
6964                    "save" => "save editor",
6965                    _ => name,
6966                },
6967                json!({ "File Extension": file_extension, "Vim Mode": settings.vim_mode, "In Clickhouse": true  }),
6968                settings.telemetry(),
6969            );
6970        let event = ClickhouseEvent::Editor {
6971            file_extension,
6972            vim_mode: settings.vim_mode,
6973            operation: name,
6974            copilot_enabled: settings.features.copilot,
6975            copilot_enabled_for_language: settings.show_copilot_suggestions(
6976                self.language_at(0, cx)
6977                    .map(|language| language.name())
6978                    .as_deref(),
6979                self.file_at(0, cx)
6980                    .map(|file| file.path().clone())
6981                    .as_deref(),
6982            ),
6983        };
6984        telemetry.report_clickhouse_event(event, settings.telemetry())
6985    }
6986
6987    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6988    /// with each line being an array of {text, highlight} objects.
6989    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6990        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6991            return;
6992        };
6993
6994        #[derive(Serialize)]
6995        struct Chunk<'a> {
6996            text: String,
6997            highlight: Option<&'a str>,
6998        }
6999
7000        let snapshot = buffer.read(cx).snapshot();
7001        let range = self
7002            .selected_text_range(cx)
7003            .and_then(|selected_range| {
7004                if selected_range.is_empty() {
7005                    None
7006                } else {
7007                    Some(selected_range)
7008                }
7009            })
7010            .unwrap_or_else(|| 0..snapshot.len());
7011
7012        let chunks = snapshot.chunks(range, true);
7013        let mut lines = Vec::new();
7014        let mut line: VecDeque<Chunk> = VecDeque::new();
7015
7016        let theme = &cx.global::<Settings>().theme.editor.syntax;
7017
7018        for chunk in chunks {
7019            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7020            let mut chunk_lines = chunk.text.split("\n").peekable();
7021            while let Some(text) = chunk_lines.next() {
7022                let mut merged_with_last_token = false;
7023                if let Some(last_token) = line.back_mut() {
7024                    if last_token.highlight == highlight {
7025                        last_token.text.push_str(text);
7026                        merged_with_last_token = true;
7027                    }
7028                }
7029
7030                if !merged_with_last_token {
7031                    line.push_back(Chunk {
7032                        text: text.into(),
7033                        highlight,
7034                    });
7035                }
7036
7037                if chunk_lines.peek().is_some() {
7038                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7039                        line.pop_front();
7040                    }
7041                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7042                        line.pop_back();
7043                    }
7044
7045                    lines.push(mem::take(&mut line));
7046                }
7047            }
7048        }
7049
7050        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7051        cx.write_to_clipboard(ClipboardItem::new(lines));
7052    }
7053}
7054
7055fn consume_contiguous_rows(
7056    contiguous_row_selections: &mut Vec<Selection<Point>>,
7057    selection: &Selection<Point>,
7058    display_map: &DisplaySnapshot,
7059    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7060) -> (u32, u32) {
7061    contiguous_row_selections.push(selection.clone());
7062    let start_row = selection.start.row;
7063    let mut end_row = ending_row(selection, display_map);
7064
7065    while let Some(next_selection) = selections.peek() {
7066        if next_selection.start.row <= end_row {
7067            end_row = ending_row(next_selection, display_map);
7068            contiguous_row_selections.push(selections.next().unwrap().clone());
7069        } else {
7070            break;
7071        }
7072    }
7073    (start_row, end_row)
7074}
7075
7076fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7077    if next_selection.end.column > 0 || next_selection.is_empty() {
7078        display_map.next_line_boundary(next_selection.end).0.row + 1
7079    } else {
7080        next_selection.end.row
7081    }
7082}
7083
7084impl EditorSnapshot {
7085    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7086        self.display_snapshot.buffer_snapshot.language_at(position)
7087    }
7088
7089    pub fn is_focused(&self) -> bool {
7090        self.is_focused
7091    }
7092
7093    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7094        self.placeholder_text.as_ref()
7095    }
7096
7097    pub fn scroll_position(&self) -> Vector2F {
7098        self.scroll_anchor.scroll_position(&self.display_snapshot)
7099    }
7100}
7101
7102impl Deref for EditorSnapshot {
7103    type Target = DisplaySnapshot;
7104
7105    fn deref(&self) -> &Self::Target {
7106        &self.display_snapshot
7107    }
7108}
7109
7110#[derive(Clone, Debug, PartialEq, Eq)]
7111pub enum Event {
7112    InputIgnored {
7113        text: Arc<str>,
7114    },
7115    ExcerptsAdded {
7116        buffer: ModelHandle<Buffer>,
7117        predecessor: ExcerptId,
7118        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7119    },
7120    ExcerptsRemoved {
7121        ids: Vec<ExcerptId>,
7122    },
7123    BufferEdited,
7124    Edited,
7125    Reparsed,
7126    Blurred,
7127    DirtyChanged,
7128    Saved,
7129    TitleChanged,
7130    SelectionsChanged {
7131        local: bool,
7132    },
7133    ScrollPositionChanged {
7134        local: bool,
7135    },
7136    Closed,
7137}
7138
7139pub struct EditorFocused(pub ViewHandle<Editor>);
7140pub struct EditorBlurred(pub ViewHandle<Editor>);
7141pub struct EditorReleased(pub WeakViewHandle<Editor>);
7142
7143impl Entity for Editor {
7144    type Event = Event;
7145
7146    fn release(&mut self, cx: &mut AppContext) {
7147        cx.emit_global(EditorReleased(self.handle.clone()));
7148    }
7149}
7150
7151impl View for Editor {
7152    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7153        let style = self.style(cx);
7154        let font_changed = self.display_map.update(cx, |map, cx| {
7155            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7156            map.set_font(style.text.font_id, style.text.font_size, cx)
7157        });
7158
7159        if font_changed {
7160            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7161                hide_hover(editor, cx);
7162                hide_link_definition(editor, cx);
7163            });
7164        }
7165
7166        Stack::new()
7167            .with_child(EditorElement::new(style.clone()))
7168            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7169            .into_any()
7170    }
7171
7172    fn ui_name() -> &'static str {
7173        "Editor"
7174    }
7175
7176    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7177        if cx.is_self_focused() {
7178            let focused_event = EditorFocused(cx.handle());
7179            cx.emit_global(focused_event);
7180        }
7181        if let Some(rename) = self.pending_rename.as_ref() {
7182            cx.focus(&rename.editor);
7183        } else {
7184            if !self.focused {
7185                self.blink_manager.update(cx, BlinkManager::enable);
7186            }
7187            self.focused = true;
7188            self.buffer.update(cx, |buffer, cx| {
7189                buffer.finalize_last_transaction(cx);
7190                if self.leader_replica_id.is_none() {
7191                    buffer.set_active_selections(
7192                        &self.selections.disjoint_anchors(),
7193                        self.selections.line_mode,
7194                        self.cursor_shape,
7195                        cx,
7196                    );
7197                }
7198            });
7199        }
7200    }
7201
7202    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7203        let blurred_event = EditorBlurred(cx.handle());
7204        cx.emit_global(blurred_event);
7205        self.focused = false;
7206        self.blink_manager.update(cx, BlinkManager::disable);
7207        self.buffer
7208            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7209        self.hide_context_menu(cx);
7210        hide_hover(self, cx);
7211        cx.emit(Event::Blurred);
7212        cx.notify();
7213    }
7214
7215    fn modifiers_changed(
7216        &mut self,
7217        event: &gpui::platform::ModifiersChangedEvent,
7218        cx: &mut ViewContext<Self>,
7219    ) -> bool {
7220        let pending_selection = self.has_pending_selection();
7221
7222        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7223            if event.cmd && !pending_selection {
7224                let snapshot = self.snapshot(cx);
7225                let kind = if event.shift {
7226                    LinkDefinitionKind::Type
7227                } else {
7228                    LinkDefinitionKind::Symbol
7229                };
7230
7231                show_link_definition(kind, self, point, snapshot, cx);
7232                return false;
7233            }
7234        }
7235
7236        {
7237            if self.link_go_to_definition_state.symbol_range.is_some()
7238                || !self.link_go_to_definition_state.definitions.is_empty()
7239            {
7240                self.link_go_to_definition_state.symbol_range.take();
7241                self.link_go_to_definition_state.definitions.clear();
7242                cx.notify();
7243            }
7244
7245            self.link_go_to_definition_state.task = None;
7246
7247            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7248        }
7249
7250        false
7251    }
7252
7253    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
7254        Self::reset_to_default_keymap_context(keymap);
7255        let mode = match self.mode {
7256            EditorMode::SingleLine => "single_line",
7257            EditorMode::AutoHeight { .. } => "auto_height",
7258            EditorMode::Full => "full",
7259        };
7260        keymap.add_key("mode", mode);
7261        if self.pending_rename.is_some() {
7262            keymap.add_identifier("renaming");
7263        }
7264        match self.context_menu.as_ref() {
7265            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7266            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7267            None => {}
7268        }
7269
7270        for layer in self.keymap_context_layers.values() {
7271            keymap.extend(layer);
7272        }
7273    }
7274
7275    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7276        Some(
7277            self.buffer
7278                .read(cx)
7279                .read(cx)
7280                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7281                .collect(),
7282        )
7283    }
7284
7285    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7286        // Prevent the IME menu from appearing when holding down an alphabetic key
7287        // while input is disabled.
7288        if !self.input_enabled {
7289            return None;
7290        }
7291
7292        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7293        Some(range.start.0..range.end.0)
7294    }
7295
7296    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7297        let snapshot = self.buffer.read(cx).read(cx);
7298        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7299        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7300    }
7301
7302    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7303        self.clear_text_highlights::<InputComposition>(cx);
7304        self.ime_transaction.take();
7305    }
7306
7307    fn replace_text_in_range(
7308        &mut self,
7309        range_utf16: Option<Range<usize>>,
7310        text: &str,
7311        cx: &mut ViewContext<Self>,
7312    ) {
7313        self.transact(cx, |this, cx| {
7314            if this.input_enabled {
7315                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7316                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7317                    Some(this.selection_replacement_ranges(range_utf16, cx))
7318                } else {
7319                    this.marked_text_ranges(cx)
7320                };
7321
7322                if let Some(new_selected_ranges) = new_selected_ranges {
7323                    this.change_selections(None, cx, |selections| {
7324                        selections.select_ranges(new_selected_ranges)
7325                    });
7326                }
7327            }
7328
7329            this.handle_input(text, cx);
7330        });
7331
7332        if !self.input_enabled {
7333            return;
7334        }
7335
7336        if let Some(transaction) = self.ime_transaction {
7337            self.buffer.update(cx, |buffer, cx| {
7338                buffer.group_until_transaction(transaction, cx);
7339            });
7340        }
7341
7342        self.unmark_text(cx);
7343    }
7344
7345    fn replace_and_mark_text_in_range(
7346        &mut self,
7347        range_utf16: Option<Range<usize>>,
7348        text: &str,
7349        new_selected_range_utf16: Option<Range<usize>>,
7350        cx: &mut ViewContext<Self>,
7351    ) {
7352        if !self.input_enabled {
7353            return;
7354        }
7355
7356        let transaction = self.transact(cx, |this, cx| {
7357            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7358                let snapshot = this.buffer.read(cx).read(cx);
7359                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7360                    for marked_range in &mut marked_ranges {
7361                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7362                        marked_range.start.0 += relative_range_utf16.start;
7363                        marked_range.start =
7364                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7365                        marked_range.end =
7366                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7367                    }
7368                }
7369                Some(marked_ranges)
7370            } else if let Some(range_utf16) = range_utf16 {
7371                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7372                Some(this.selection_replacement_ranges(range_utf16, cx))
7373            } else {
7374                None
7375            };
7376
7377            if let Some(ranges) = ranges_to_replace {
7378                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7379            }
7380
7381            let marked_ranges = {
7382                let snapshot = this.buffer.read(cx).read(cx);
7383                this.selections
7384                    .disjoint_anchors()
7385                    .iter()
7386                    .map(|selection| {
7387                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7388                    })
7389                    .collect::<Vec<_>>()
7390            };
7391
7392            if text.is_empty() {
7393                this.unmark_text(cx);
7394            } else {
7395                this.highlight_text::<InputComposition>(
7396                    marked_ranges.clone(),
7397                    this.style(cx).composition_mark,
7398                    cx,
7399                );
7400            }
7401
7402            this.handle_input(text, cx);
7403
7404            if let Some(new_selected_range) = new_selected_range_utf16 {
7405                let snapshot = this.buffer.read(cx).read(cx);
7406                let new_selected_ranges = marked_ranges
7407                    .into_iter()
7408                    .map(|marked_range| {
7409                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7410                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7411                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7412                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7413                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7414                    })
7415                    .collect::<Vec<_>>();
7416
7417                drop(snapshot);
7418                this.change_selections(None, cx, |selections| {
7419                    selections.select_ranges(new_selected_ranges)
7420                });
7421            }
7422        });
7423
7424        self.ime_transaction = self.ime_transaction.or(transaction);
7425        if let Some(transaction) = self.ime_transaction {
7426            self.buffer.update(cx, |buffer, cx| {
7427                buffer.group_until_transaction(transaction, cx);
7428            });
7429        }
7430
7431        if self.text_highlights::<InputComposition>(cx).is_none() {
7432            self.ime_transaction.take();
7433        }
7434    }
7435}
7436
7437fn build_style(
7438    settings: &Settings,
7439    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7440    override_text_style: Option<&OverrideTextStyle>,
7441    cx: &AppContext,
7442) -> EditorStyle {
7443    let font_cache = cx.font_cache();
7444
7445    let theme_id = settings.theme.meta.id;
7446    let mut theme = settings.theme.editor.clone();
7447    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7448        let field_editor_theme = get_field_editor_theme(&settings.theme);
7449        theme.text_color = field_editor_theme.text.color;
7450        theme.selection = field_editor_theme.selection;
7451        theme.background = field_editor_theme
7452            .container
7453            .background_color
7454            .unwrap_or_default();
7455        EditorStyle {
7456            text: field_editor_theme.text,
7457            placeholder_text: field_editor_theme.placeholder_text,
7458            theme,
7459            theme_id,
7460        }
7461    } else {
7462        let font_family_id = settings.buffer_font_family;
7463        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7464        let font_properties = Default::default();
7465        let font_id = font_cache
7466            .select_font(font_family_id, &font_properties)
7467            .unwrap();
7468        let font_size = settings.buffer_font_size;
7469        EditorStyle {
7470            text: TextStyle {
7471                color: settings.theme.editor.text_color,
7472                font_family_name,
7473                font_family_id,
7474                font_id,
7475                font_size,
7476                font_properties,
7477                underline: Default::default(),
7478            },
7479            placeholder_text: None,
7480            theme,
7481            theme_id,
7482        }
7483    };
7484
7485    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7486        if let Some(highlighted) = style
7487            .text
7488            .clone()
7489            .highlight(highlight_style, font_cache)
7490            .log_err()
7491        {
7492            style.text = highlighted;
7493        }
7494    }
7495
7496    style
7497}
7498
7499trait SelectionExt {
7500    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7501    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7502    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7503    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7504        -> Range<u32>;
7505}
7506
7507impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7508    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7509        let start = self.start.to_point(buffer);
7510        let end = self.end.to_point(buffer);
7511        if self.reversed {
7512            end..start
7513        } else {
7514            start..end
7515        }
7516    }
7517
7518    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7519        let start = self.start.to_offset(buffer);
7520        let end = self.end.to_offset(buffer);
7521        if self.reversed {
7522            end..start
7523        } else {
7524            start..end
7525        }
7526    }
7527
7528    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7529        let start = self
7530            .start
7531            .to_point(&map.buffer_snapshot)
7532            .to_display_point(map);
7533        let end = self
7534            .end
7535            .to_point(&map.buffer_snapshot)
7536            .to_display_point(map);
7537        if self.reversed {
7538            end..start
7539        } else {
7540            start..end
7541        }
7542    }
7543
7544    fn spanned_rows(
7545        &self,
7546        include_end_if_at_line_start: bool,
7547        map: &DisplaySnapshot,
7548    ) -> Range<u32> {
7549        let start = self.start.to_point(&map.buffer_snapshot);
7550        let mut end = self.end.to_point(&map.buffer_snapshot);
7551        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7552            end.row -= 1;
7553        }
7554
7555        let buffer_start = map.prev_line_boundary(start).0;
7556        let buffer_end = map.next_line_boundary(end).0;
7557        buffer_start.row..buffer_end.row + 1
7558    }
7559}
7560
7561impl<T: InvalidationRegion> InvalidationStack<T> {
7562    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7563    where
7564        S: Clone + ToOffset,
7565    {
7566        while let Some(region) = self.last() {
7567            let all_selections_inside_invalidation_ranges =
7568                if selections.len() == region.ranges().len() {
7569                    selections
7570                        .iter()
7571                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7572                        .all(|(selection, invalidation_range)| {
7573                            let head = selection.head().to_offset(buffer);
7574                            invalidation_range.start <= head && invalidation_range.end >= head
7575                        })
7576                } else {
7577                    false
7578                };
7579
7580            if all_selections_inside_invalidation_ranges {
7581                break;
7582            } else {
7583                self.pop();
7584            }
7585        }
7586    }
7587}
7588
7589impl<T> Default for InvalidationStack<T> {
7590    fn default() -> Self {
7591        Self(Default::default())
7592    }
7593}
7594
7595impl<T> Deref for InvalidationStack<T> {
7596    type Target = Vec<T>;
7597
7598    fn deref(&self) -> &Self::Target {
7599        &self.0
7600    }
7601}
7602
7603impl<T> DerefMut for InvalidationStack<T> {
7604    fn deref_mut(&mut self) -> &mut Self::Target {
7605        &mut self.0
7606    }
7607}
7608
7609impl InvalidationRegion for SnippetState {
7610    fn ranges(&self) -> &[Range<Anchor>] {
7611        &self.ranges[self.active_index]
7612    }
7613}
7614
7615impl Deref for EditorStyle {
7616    type Target = theme::Editor;
7617
7618    fn deref(&self) -> &Self::Target {
7619        &self.theme
7620    }
7621}
7622
7623pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7624    let mut highlighted_lines = Vec::new();
7625    for (index, line) in diagnostic.message.lines().enumerate() {
7626        let line = match &diagnostic.source {
7627            Some(source) if index == 0 => {
7628                let source_highlight = Vec::from_iter(0..source.len());
7629                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7630            }
7631
7632            _ => highlight_diagnostic_message(Vec::new(), line),
7633        };
7634        highlighted_lines.push(line);
7635    }
7636
7637    Arc::new(move |cx: &mut BlockContext| {
7638        let settings = cx.global::<Settings>();
7639        let theme = &settings.theme.editor;
7640        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7641        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7642        Flex::column()
7643            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7644                Label::new(
7645                    line.clone(),
7646                    style.message.clone().with_font_size(font_size),
7647                )
7648                .with_highlights(highlights.clone())
7649                .contained()
7650                .with_margin_left(cx.anchor_x)
7651            }))
7652            .aligned()
7653            .left()
7654            .into_any()
7655    })
7656}
7657
7658pub fn highlight_diagnostic_message(
7659    inital_highlights: Vec<usize>,
7660    message: &str,
7661) -> (String, Vec<usize>) {
7662    let mut message_without_backticks = String::new();
7663    let mut prev_offset = 0;
7664    let mut inside_block = false;
7665    let mut highlights = inital_highlights;
7666    for (match_ix, (offset, _)) in message
7667        .match_indices('`')
7668        .chain([(message.len(), "")])
7669        .enumerate()
7670    {
7671        message_without_backticks.push_str(&message[prev_offset..offset]);
7672        if inside_block {
7673            highlights.extend(prev_offset - match_ix..offset - match_ix);
7674        }
7675
7676        inside_block = !inside_block;
7677        prev_offset = offset + 1;
7678    }
7679
7680    (message_without_backticks, highlights)
7681}
7682
7683pub fn diagnostic_style(
7684    severity: DiagnosticSeverity,
7685    valid: bool,
7686    theme: &theme::Editor,
7687) -> DiagnosticStyle {
7688    match (severity, valid) {
7689        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7690        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7691        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7692        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7693        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7694        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7695        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7696        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7697        _ => theme.invalid_hint_diagnostic.clone(),
7698    }
7699}
7700
7701pub fn combine_syntax_and_fuzzy_match_highlights(
7702    text: &str,
7703    default_style: HighlightStyle,
7704    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7705    match_indices: &[usize],
7706) -> Vec<(Range<usize>, HighlightStyle)> {
7707    let mut result = Vec::new();
7708    let mut match_indices = match_indices.iter().copied().peekable();
7709
7710    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7711    {
7712        syntax_highlight.weight = None;
7713
7714        // Add highlights for any fuzzy match characters before the next
7715        // syntax highlight range.
7716        while let Some(&match_index) = match_indices.peek() {
7717            if match_index >= range.start {
7718                break;
7719            }
7720            match_indices.next();
7721            let end_index = char_ix_after(match_index, text);
7722            let mut match_style = default_style;
7723            match_style.weight = Some(fonts::Weight::BOLD);
7724            result.push((match_index..end_index, match_style));
7725        }
7726
7727        if range.start == usize::MAX {
7728            break;
7729        }
7730
7731        // Add highlights for any fuzzy match characters within the
7732        // syntax highlight range.
7733        let mut offset = range.start;
7734        while let Some(&match_index) = match_indices.peek() {
7735            if match_index >= range.end {
7736                break;
7737            }
7738
7739            match_indices.next();
7740            if match_index > offset {
7741                result.push((offset..match_index, syntax_highlight));
7742            }
7743
7744            let mut end_index = char_ix_after(match_index, text);
7745            while let Some(&next_match_index) = match_indices.peek() {
7746                if next_match_index == end_index && next_match_index < range.end {
7747                    end_index = char_ix_after(next_match_index, text);
7748                    match_indices.next();
7749                } else {
7750                    break;
7751                }
7752            }
7753
7754            let mut match_style = syntax_highlight;
7755            match_style.weight = Some(fonts::Weight::BOLD);
7756            result.push((match_index..end_index, match_style));
7757            offset = end_index;
7758        }
7759
7760        if offset < range.end {
7761            result.push((offset..range.end, syntax_highlight));
7762        }
7763    }
7764
7765    fn char_ix_after(ix: usize, text: &str) -> usize {
7766        ix + text[ix..].chars().next().unwrap().len_utf8()
7767    }
7768
7769    result
7770}
7771
7772pub fn styled_runs_for_code_label<'a>(
7773    label: &'a CodeLabel,
7774    syntax_theme: &'a theme::SyntaxTheme,
7775) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7776    let fade_out = HighlightStyle {
7777        fade_out: Some(0.35),
7778        ..Default::default()
7779    };
7780
7781    let mut prev_end = label.filter_range.end;
7782    label
7783        .runs
7784        .iter()
7785        .enumerate()
7786        .flat_map(move |(ix, (range, highlight_id))| {
7787            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7788                style
7789            } else {
7790                return Default::default();
7791            };
7792            let mut muted_style = style;
7793            muted_style.highlight(fade_out);
7794
7795            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7796            if range.start >= label.filter_range.end {
7797                if range.start > prev_end {
7798                    runs.push((prev_end..range.start, fade_out));
7799                }
7800                runs.push((range.clone(), muted_style));
7801            } else if range.end <= label.filter_range.end {
7802                runs.push((range.clone(), style));
7803            } else {
7804                runs.push((range.start..label.filter_range.end, style));
7805                runs.push((label.filter_range.end..range.end, muted_style));
7806            }
7807            prev_end = cmp::max(prev_end, range.end);
7808
7809            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7810                runs.push((prev_end..label.text.len(), fade_out));
7811            }
7812
7813            runs
7814        })
7815}
7816
7817pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7818    let mut index = 0;
7819    let mut codepoints = text.char_indices().peekable();
7820
7821    std::iter::from_fn(move || {
7822        let start_index = index;
7823        while let Some((new_index, codepoint)) = codepoints.next() {
7824            index = new_index + codepoint.len_utf8();
7825            let current_upper = codepoint.is_uppercase();
7826            let next_upper = codepoints
7827                .peek()
7828                .map(|(_, c)| c.is_uppercase())
7829                .unwrap_or(false);
7830
7831            if !current_upper && next_upper {
7832                return Some(&text[start_index..index]);
7833            }
7834        }
7835
7836        index = text.len();
7837        if start_index < text.len() {
7838            return Some(&text[start_index..]);
7839        }
7840        None
7841    })
7842    .flat_map(|word| word.split_inclusive('_'))
7843}
7844
7845trait RangeToAnchorExt {
7846    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7847}
7848
7849impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7850    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7851        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7852    }
7853}