editor.rs

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