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