editor.rs

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