editor.rs

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