editor.rs

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