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.inlay_hint_cache.update_settings(
2618                    &self.buffer,
2619                    new_settings,
2620                    get_update_state(self, cx),
2621                    cx,
2622                );
2623                if let Some(InlaySplice {
2624                    to_remove,
2625                    to_insert,
2626                }) = new_splice
2627                {
2628                    self.splice_inlay_hints(to_remove, to_insert, cx);
2629                }
2630                return;
2631            }
2632            InlayRefreshReason::NewLinesShown => false,
2633            InlayRefreshReason::ExcerptEdited => true,
2634        };
2635
2636        let excerpts_to_query = self
2637            .excerpt_visible_offsets(cx)
2638            .into_iter()
2639            .map(|(buffer, _, excerpt_id)| (excerpt_id, buffer.read(cx).remote_id()))
2640            .collect::<HashMap<_, _>>();
2641        self.inlay_hint_cache
2642            .spawn_hints_update(excerpts_to_query, invalidate_cache, cx)
2643    }
2644
2645    fn excerpt_visible_offsets(
2646        &self,
2647        cx: &mut ViewContext<'_, '_, Editor>,
2648    ) -> Vec<(ModelHandle<Buffer>, Range<usize>, ExcerptId)> {
2649        let multi_buffer = self.buffer().read(cx);
2650        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
2651        let multi_buffer_visible_start = self
2652            .scroll_manager
2653            .anchor()
2654            .anchor
2655            .to_point(&multi_buffer_snapshot);
2656        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
2657            multi_buffer_visible_start
2658                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
2659            Bias::Left,
2660        );
2661        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
2662
2663        multi_buffer.range_to_buffer_ranges(multi_buffer_visible_range, cx)
2664    }
2665
2666    fn splice_inlay_hints(
2667        &self,
2668        to_remove: Vec<InlayId>,
2669        to_insert: Vec<(Anchor, InlayId, project::InlayHint)>,
2670        cx: &mut ViewContext<Self>,
2671    ) {
2672        let buffer = self.buffer.read(cx).read(cx);
2673        let new_inlays = to_insert
2674            .into_iter()
2675            .map(|(position, id, hint)| {
2676                let mut text = hint.text();
2677                // TODO kb styling instead?
2678                if hint.padding_right {
2679                    text.push(' ');
2680                }
2681                if hint.padding_left {
2682                    text.insert(0, ' ');
2683                }
2684                (id, InlayProperties { position, text })
2685            })
2686            .collect();
2687        drop(buffer);
2688        self.display_map.update(cx, |display_map, cx| {
2689            display_map.splice_inlays(to_remove, new_inlays, cx);
2690        });
2691    }
2692
2693    fn trigger_on_type_formatting(
2694        &self,
2695        input: String,
2696        cx: &mut ViewContext<Self>,
2697    ) -> Option<Task<Result<()>>> {
2698        if input.len() != 1 {
2699            return None;
2700        }
2701
2702        let project = self.project.as_ref()?;
2703        let position = self.selections.newest_anchor().head();
2704        let (buffer, buffer_position) = self
2705            .buffer
2706            .read(cx)
2707            .text_anchor_for_position(position.clone(), cx)?;
2708
2709        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
2710        // hence we do LSP request & edit on host side only — add formats to host's history.
2711        let push_to_lsp_host_history = true;
2712        // If this is not the host, append its history with new edits.
2713        let push_to_client_history = project.read(cx).is_remote();
2714
2715        let on_type_formatting = project.update(cx, |project, cx| {
2716            project.on_type_format(
2717                buffer.clone(),
2718                buffer_position,
2719                input,
2720                push_to_lsp_host_history,
2721                cx,
2722            )
2723        });
2724        Some(cx.spawn(|editor, mut cx| async move {
2725            if let Some(transaction) = on_type_formatting.await? {
2726                if push_to_client_history {
2727                    buffer.update(&mut cx, |buffer, _| {
2728                        buffer.push_transaction(transaction, Instant::now());
2729                    });
2730                }
2731                editor.update(&mut cx, |editor, cx| {
2732                    editor.refresh_document_highlights(cx);
2733                })?;
2734            }
2735            Ok(())
2736        }))
2737    }
2738
2739    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2740        if self.pending_rename.is_some() {
2741            return;
2742        }
2743
2744        let project = if let Some(project) = self.project.clone() {
2745            project
2746        } else {
2747            return;
2748        };
2749
2750        let position = self.selections.newest_anchor().head();
2751        let (buffer, buffer_position) = if let Some(output) = self
2752            .buffer
2753            .read(cx)
2754            .text_anchor_for_position(position.clone(), cx)
2755        {
2756            output
2757        } else {
2758            return;
2759        };
2760
2761        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2762        let completions = project.update(cx, |project, cx| {
2763            project.completions(&buffer, buffer_position, cx)
2764        });
2765
2766        let id = post_inc(&mut self.next_completion_id);
2767        let task = cx.spawn(|this, mut cx| {
2768            async move {
2769                let menu = if let Some(completions) = completions.await.log_err() {
2770                    let mut menu = CompletionsMenu {
2771                        id,
2772                        initial_position: position,
2773                        match_candidates: completions
2774                            .iter()
2775                            .enumerate()
2776                            .map(|(id, completion)| {
2777                                StringMatchCandidate::new(
2778                                    id,
2779                                    completion.label.text[completion.label.filter_range.clone()]
2780                                        .into(),
2781                                )
2782                            })
2783                            .collect(),
2784                        buffer,
2785                        completions: completions.into(),
2786                        matches: Vec::new().into(),
2787                        selected_item: 0,
2788                        list: Default::default(),
2789                    };
2790                    menu.filter(query.as_deref(), cx.background()).await;
2791                    if menu.matches.is_empty() {
2792                        None
2793                    } else {
2794                        Some(menu)
2795                    }
2796                } else {
2797                    None
2798                };
2799
2800                this.update(&mut cx, |this, cx| {
2801                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2802
2803                    match this.context_menu.as_ref() {
2804                        None => {}
2805                        Some(ContextMenu::Completions(prev_menu)) => {
2806                            if prev_menu.id > id {
2807                                return;
2808                            }
2809                        }
2810                        _ => return,
2811                    }
2812
2813                    if this.focused && menu.is_some() {
2814                        let menu = menu.unwrap();
2815                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2816                    } else if this.completion_tasks.is_empty() {
2817                        // If there are no more completion tasks and the last menu was
2818                        // empty, we should hide it. If it was already hidden, we should
2819                        // also show the copilot suggestion when available.
2820                        if this.hide_context_menu(cx).is_none() {
2821                            this.update_visible_copilot_suggestion(cx);
2822                        }
2823                    }
2824                })?;
2825
2826                Ok::<_, anyhow::Error>(())
2827            }
2828            .log_err()
2829        });
2830        self.completion_tasks.push((id, task));
2831    }
2832
2833    pub fn confirm_completion(
2834        &mut self,
2835        action: &ConfirmCompletion,
2836        cx: &mut ViewContext<Self>,
2837    ) -> Option<Task<Result<()>>> {
2838        use language::ToOffset as _;
2839
2840        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2841            menu
2842        } else {
2843            return None;
2844        };
2845
2846        let mat = completions_menu
2847            .matches
2848            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2849        let buffer_handle = completions_menu.buffer;
2850        let completion = completions_menu.completions.get(mat.candidate_id)?;
2851
2852        let snippet;
2853        let text;
2854        if completion.is_snippet() {
2855            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2856            text = snippet.as_ref().unwrap().text.clone();
2857        } else {
2858            snippet = None;
2859            text = completion.new_text.clone();
2860        };
2861        let selections = self.selections.all::<usize>(cx);
2862        let buffer = buffer_handle.read(cx);
2863        let old_range = completion.old_range.to_offset(buffer);
2864        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2865
2866        let newest_selection = self.selections.newest_anchor();
2867        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2868            return None;
2869        }
2870
2871        let lookbehind = newest_selection
2872            .start
2873            .text_anchor
2874            .to_offset(buffer)
2875            .saturating_sub(old_range.start);
2876        let lookahead = old_range
2877            .end
2878            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2879        let mut common_prefix_len = old_text
2880            .bytes()
2881            .zip(text.bytes())
2882            .take_while(|(a, b)| a == b)
2883            .count();
2884
2885        let snapshot = self.buffer.read(cx).snapshot(cx);
2886        let mut ranges = Vec::new();
2887        for selection in &selections {
2888            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2889                let start = selection.start.saturating_sub(lookbehind);
2890                let end = selection.end + lookahead;
2891                ranges.push(start + common_prefix_len..end);
2892            } else {
2893                common_prefix_len = 0;
2894                ranges.clear();
2895                ranges.extend(selections.iter().map(|s| {
2896                    if s.id == newest_selection.id {
2897                        old_range.clone()
2898                    } else {
2899                        s.start..s.end
2900                    }
2901                }));
2902                break;
2903            }
2904        }
2905        let text = &text[common_prefix_len..];
2906
2907        self.transact(cx, |this, cx| {
2908            if let Some(mut snippet) = snippet {
2909                snippet.text = text.to_string();
2910                for tabstop in snippet.tabstops.iter_mut().flatten() {
2911                    tabstop.start -= common_prefix_len as isize;
2912                    tabstop.end -= common_prefix_len as isize;
2913                }
2914
2915                this.insert_snippet(&ranges, snippet, cx).log_err();
2916            } else {
2917                this.buffer.update(cx, |buffer, cx| {
2918                    buffer.edit(
2919                        ranges.iter().map(|range| (range.clone(), text)),
2920                        Some(AutoindentMode::EachLine),
2921                        cx,
2922                    );
2923                });
2924            }
2925
2926            this.refresh_copilot_suggestions(true, cx);
2927        });
2928
2929        let project = self.project.clone()?;
2930        let apply_edits = project.update(cx, |project, cx| {
2931            project.apply_additional_edits_for_completion(
2932                buffer_handle,
2933                completion.clone(),
2934                true,
2935                cx,
2936            )
2937        });
2938        Some(cx.foreground().spawn(async move {
2939            apply_edits.await?;
2940            Ok(())
2941        }))
2942    }
2943
2944    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2945        if matches!(
2946            self.context_menu.as_ref(),
2947            Some(ContextMenu::CodeActions(_))
2948        ) {
2949            self.context_menu.take();
2950            cx.notify();
2951            return;
2952        }
2953
2954        let deployed_from_indicator = action.deployed_from_indicator;
2955        let mut task = self.code_actions_task.take();
2956        cx.spawn(|this, mut cx| async move {
2957            while let Some(prev_task) = task {
2958                prev_task.await;
2959                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
2960            }
2961
2962            this.update(&mut cx, |this, cx| {
2963                if this.focused {
2964                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
2965                        this.show_context_menu(
2966                            ContextMenu::CodeActions(CodeActionsMenu {
2967                                buffer,
2968                                actions,
2969                                selected_item: Default::default(),
2970                                list: Default::default(),
2971                                deployed_from_indicator,
2972                            }),
2973                            cx,
2974                        );
2975                    }
2976                }
2977            })?;
2978
2979            Ok::<_, anyhow::Error>(())
2980        })
2981        .detach_and_log_err(cx);
2982    }
2983
2984    pub fn confirm_code_action(
2985        workspace: &mut Workspace,
2986        action: &ConfirmCodeAction,
2987        cx: &mut ViewContext<Workspace>,
2988    ) -> Option<Task<Result<()>>> {
2989        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2990        let actions_menu = if let ContextMenu::CodeActions(menu) =
2991            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2992        {
2993            menu
2994        } else {
2995            return None;
2996        };
2997        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2998        let action = actions_menu.actions.get(action_ix)?.clone();
2999        let title = action.lsp_action.title.clone();
3000        let buffer = actions_menu.buffer;
3001
3002        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3003            project.apply_code_action(buffer, action, true, cx)
3004        });
3005        let editor = editor.downgrade();
3006        Some(cx.spawn(|workspace, cx| async move {
3007            let project_transaction = apply_code_actions.await?;
3008            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3009        }))
3010    }
3011
3012    async fn open_project_transaction(
3013        this: &WeakViewHandle<Editor>,
3014        workspace: WeakViewHandle<Workspace>,
3015        transaction: ProjectTransaction,
3016        title: String,
3017        mut cx: AsyncAppContext,
3018    ) -> Result<()> {
3019        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3020
3021        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3022        entries.sort_unstable_by_key(|(buffer, _)| {
3023            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3024        });
3025
3026        // If the project transaction's edits are all contained within this editor, then
3027        // avoid opening a new editor to display them.
3028
3029        if let Some((buffer, transaction)) = entries.first() {
3030            if entries.len() == 1 {
3031                let excerpt = this.read_with(&cx, |editor, cx| {
3032                    editor
3033                        .buffer()
3034                        .read(cx)
3035                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3036                })?;
3037                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3038                    if excerpted_buffer == *buffer {
3039                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3040                            let excerpt_range = excerpt_range.to_offset(buffer);
3041                            buffer
3042                                .edited_ranges_for_transaction::<usize>(transaction)
3043                                .all(|range| {
3044                                    excerpt_range.start <= range.start
3045                                        && excerpt_range.end >= range.end
3046                                })
3047                        });
3048
3049                        if all_edits_within_excerpt {
3050                            return Ok(());
3051                        }
3052                    }
3053                }
3054            }
3055        } else {
3056            return Ok(());
3057        }
3058
3059        let mut ranges_to_highlight = Vec::new();
3060        let excerpt_buffer = cx.add_model(|cx| {
3061            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3062            for (buffer_handle, transaction) in &entries {
3063                let buffer = buffer_handle.read(cx);
3064                ranges_to_highlight.extend(
3065                    multibuffer.push_excerpts_with_context_lines(
3066                        buffer_handle.clone(),
3067                        buffer
3068                            .edited_ranges_for_transaction::<usize>(transaction)
3069                            .collect(),
3070                        1,
3071                        cx,
3072                    ),
3073                );
3074            }
3075            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3076            multibuffer
3077        });
3078
3079        workspace.update(&mut cx, |workspace, cx| {
3080            let project = workspace.project().clone();
3081            let editor =
3082                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3083            workspace.add_item(Box::new(editor.clone()), cx);
3084            editor.update(cx, |editor, cx| {
3085                editor.highlight_background::<Self>(
3086                    ranges_to_highlight,
3087                    |theme| theme.editor.highlighted_line_background,
3088                    cx,
3089                );
3090            });
3091        })?;
3092
3093        Ok(())
3094    }
3095
3096    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3097        let project = self.project.as_ref()?;
3098        let buffer = self.buffer.read(cx);
3099        let newest_selection = self.selections.newest_anchor().clone();
3100        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3101        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3102        if start_buffer != end_buffer {
3103            return None;
3104        }
3105
3106        let actions = project.update(cx, |project, cx| {
3107            project.code_actions(&start_buffer, start..end, cx)
3108        });
3109        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3110            let actions = actions.await;
3111            this.update(&mut cx, |this, cx| {
3112                this.available_code_actions = actions.log_err().and_then(|actions| {
3113                    if actions.is_empty() {
3114                        None
3115                    } else {
3116                        Some((start_buffer, actions.into()))
3117                    }
3118                });
3119                cx.notify();
3120            })
3121            .log_err();
3122        }));
3123        None
3124    }
3125
3126    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3127        if self.pending_rename.is_some() {
3128            return None;
3129        }
3130
3131        let project = self.project.as_ref()?;
3132        let buffer = self.buffer.read(cx);
3133        let newest_selection = self.selections.newest_anchor().clone();
3134        let cursor_position = newest_selection.head();
3135        let (cursor_buffer, cursor_buffer_position) =
3136            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3137        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3138        if cursor_buffer != tail_buffer {
3139            return None;
3140        }
3141
3142        let highlights = project.update(cx, |project, cx| {
3143            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3144        });
3145
3146        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3147            if let Some(highlights) = highlights.await.log_err() {
3148                this.update(&mut cx, |this, cx| {
3149                    if this.pending_rename.is_some() {
3150                        return;
3151                    }
3152
3153                    let buffer_id = cursor_position.buffer_id;
3154                    let buffer = this.buffer.read(cx);
3155                    if !buffer
3156                        .text_anchor_for_position(cursor_position, cx)
3157                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3158                    {
3159                        return;
3160                    }
3161
3162                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3163                    let mut write_ranges = Vec::new();
3164                    let mut read_ranges = Vec::new();
3165                    for highlight in highlights {
3166                        for (excerpt_id, excerpt_range) in
3167                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3168                        {
3169                            let start = highlight
3170                                .range
3171                                .start
3172                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3173                            let end = highlight
3174                                .range
3175                                .end
3176                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3177                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3178                                continue;
3179                            }
3180
3181                            let range = Anchor {
3182                                buffer_id,
3183                                excerpt_id: excerpt_id.clone(),
3184                                text_anchor: start,
3185                            }..Anchor {
3186                                buffer_id,
3187                                excerpt_id,
3188                                text_anchor: end,
3189                            };
3190                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3191                                write_ranges.push(range);
3192                            } else {
3193                                read_ranges.push(range);
3194                            }
3195                        }
3196                    }
3197
3198                    this.highlight_background::<DocumentHighlightRead>(
3199                        read_ranges,
3200                        |theme| theme.editor.document_highlight_read_background,
3201                        cx,
3202                    );
3203                    this.highlight_background::<DocumentHighlightWrite>(
3204                        write_ranges,
3205                        |theme| theme.editor.document_highlight_write_background,
3206                        cx,
3207                    );
3208                    cx.notify();
3209                })
3210                .log_err();
3211            }
3212        }));
3213        None
3214    }
3215
3216    fn refresh_copilot_suggestions(
3217        &mut self,
3218        debounce: bool,
3219        cx: &mut ViewContext<Self>,
3220    ) -> Option<()> {
3221        let copilot = Copilot::global(cx)?;
3222        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3223            self.clear_copilot_suggestions(cx);
3224            return None;
3225        }
3226        self.update_visible_copilot_suggestion(cx);
3227
3228        let snapshot = self.buffer.read(cx).snapshot(cx);
3229        let cursor = self.selections.newest_anchor().head();
3230        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3231            self.clear_copilot_suggestions(cx);
3232            return None;
3233        }
3234
3235        let (buffer, buffer_position) =
3236            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3237        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3238            if debounce {
3239                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3240            }
3241
3242            let completions = copilot
3243                .update(&mut cx, |copilot, cx| {
3244                    copilot.completions(&buffer, buffer_position, cx)
3245                })
3246                .await
3247                .log_err()
3248                .into_iter()
3249                .flatten()
3250                .collect_vec();
3251
3252            this.update(&mut cx, |this, cx| {
3253                if !completions.is_empty() {
3254                    this.copilot_state.cycled = false;
3255                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3256                    this.copilot_state.completions.clear();
3257                    this.copilot_state.active_completion_index = 0;
3258                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3259                    for completion in completions {
3260                        this.copilot_state.push_completion(completion);
3261                    }
3262                    this.update_visible_copilot_suggestion(cx);
3263                }
3264            })
3265            .log_err()?;
3266            Some(())
3267        });
3268
3269        Some(())
3270    }
3271
3272    fn cycle_copilot_suggestions(
3273        &mut self,
3274        direction: Direction,
3275        cx: &mut ViewContext<Self>,
3276    ) -> Option<()> {
3277        let copilot = Copilot::global(cx)?;
3278        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3279            return None;
3280        }
3281
3282        if self.copilot_state.cycled {
3283            self.copilot_state.cycle_completions(direction);
3284            self.update_visible_copilot_suggestion(cx);
3285        } else {
3286            let cursor = self.selections.newest_anchor().head();
3287            let (buffer, buffer_position) =
3288                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3289            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3290                let completions = copilot
3291                    .update(&mut cx, |copilot, cx| {
3292                        copilot.completions_cycling(&buffer, buffer_position, cx)
3293                    })
3294                    .await;
3295
3296                this.update(&mut cx, |this, cx| {
3297                    this.copilot_state.cycled = true;
3298                    for completion in completions.log_err().into_iter().flatten() {
3299                        this.copilot_state.push_completion(completion);
3300                    }
3301                    this.copilot_state.cycle_completions(direction);
3302                    this.update_visible_copilot_suggestion(cx);
3303                })
3304                .log_err()?;
3305
3306                Some(())
3307            });
3308        }
3309
3310        Some(())
3311    }
3312
3313    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3314        if !self.has_active_copilot_suggestion(cx) {
3315            self.refresh_copilot_suggestions(false, cx);
3316            return;
3317        }
3318
3319        self.update_visible_copilot_suggestion(cx);
3320    }
3321
3322    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3323        if self.has_active_copilot_suggestion(cx) {
3324            self.cycle_copilot_suggestions(Direction::Next, cx);
3325        } else {
3326            self.refresh_copilot_suggestions(false, cx);
3327        }
3328    }
3329
3330    fn previous_copilot_suggestion(
3331        &mut self,
3332        _: &copilot::PreviousSuggestion,
3333        cx: &mut ViewContext<Self>,
3334    ) {
3335        if self.has_active_copilot_suggestion(cx) {
3336            self.cycle_copilot_suggestions(Direction::Prev, cx);
3337        } else {
3338            self.refresh_copilot_suggestions(false, cx);
3339        }
3340    }
3341
3342    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3343        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3344            if let Some((copilot, completion)) =
3345                Copilot::global(cx).zip(self.copilot_state.active_completion())
3346            {
3347                copilot
3348                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3349                    .detach_and_log_err(cx);
3350
3351                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3352            }
3353            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3354            cx.notify();
3355            true
3356        } else {
3357            false
3358        }
3359    }
3360
3361    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3362        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3363            if let Some(copilot) = Copilot::global(cx) {
3364                copilot
3365                    .update(cx, |copilot, cx| {
3366                        copilot.discard_completions(&self.copilot_state.completions, cx)
3367                    })
3368                    .detach_and_log_err(cx);
3369
3370                self.report_copilot_event(None, false, cx)
3371            }
3372
3373            self.display_map.update(cx, |map, cx| {
3374                map.splice_inlays::<&str>(vec![suggestion.id], Vec::new(), cx)
3375            });
3376            cx.notify();
3377            true
3378        } else {
3379            false
3380        }
3381    }
3382
3383    fn is_copilot_enabled_at(
3384        &self,
3385        location: Anchor,
3386        snapshot: &MultiBufferSnapshot,
3387        cx: &mut ViewContext<Self>,
3388    ) -> bool {
3389        let file = snapshot.file_at(location);
3390        let language = snapshot.language_at(location);
3391        let settings = all_language_settings(file, cx);
3392        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3393    }
3394
3395    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3396        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3397            let buffer = self.buffer.read(cx).read(cx);
3398            suggestion.position.is_valid(&buffer)
3399        } else {
3400            false
3401        }
3402    }
3403
3404    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3405        let suggestion = self.copilot_state.suggestion.take()?;
3406        self.display_map.update(cx, |map, cx| {
3407            map.splice_inlays::<&str>(vec![suggestion.id], Default::default(), cx);
3408        });
3409        let buffer = self.buffer.read(cx).read(cx);
3410
3411        if suggestion.position.is_valid(&buffer) {
3412            Some(suggestion)
3413        } else {
3414            None
3415        }
3416    }
3417
3418    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3419        let snapshot = self.buffer.read(cx).snapshot(cx);
3420        let selection = self.selections.newest_anchor();
3421        let cursor = selection.head();
3422
3423        if self.context_menu.is_some()
3424            || !self.completion_tasks.is_empty()
3425            || selection.start != selection.end
3426        {
3427            self.discard_copilot_suggestion(cx);
3428        } else if let Some(text) = self
3429            .copilot_state
3430            .text_for_active_completion(cursor, &snapshot)
3431        {
3432            let text = Rope::from(text);
3433            let mut to_remove = Vec::new();
3434            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3435                to_remove.push(suggestion.id);
3436            }
3437
3438            let suggestion_inlay_id = self.next_inlay_id();
3439            let to_insert = vec![(
3440                suggestion_inlay_id,
3441                InlayProperties {
3442                    position: cursor,
3443                    text: text.clone(),
3444                },
3445            )];
3446            self.display_map.update(cx, move |map, cx| {
3447                map.splice_inlays(to_remove, to_insert, cx)
3448            });
3449            self.copilot_state.suggestion = Some(Inlay {
3450                id: suggestion_inlay_id,
3451                position: cursor,
3452                text,
3453            });
3454            cx.notify();
3455        } else {
3456            self.discard_copilot_suggestion(cx);
3457        }
3458    }
3459
3460    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3461        self.copilot_state = Default::default();
3462        self.discard_copilot_suggestion(cx);
3463    }
3464
3465    pub fn render_code_actions_indicator(
3466        &self,
3467        style: &EditorStyle,
3468        is_active: bool,
3469        cx: &mut ViewContext<Self>,
3470    ) -> Option<AnyElement<Self>> {
3471        if self.available_code_actions.is_some() {
3472            enum CodeActions {}
3473            Some(
3474                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3475                    Svg::new("icons/bolt_8.svg").with_color(
3476                        style
3477                            .code_actions
3478                            .indicator
3479                            .in_state(is_active)
3480                            .style_for(state)
3481                            .color,
3482                    )
3483                })
3484                .with_cursor_style(CursorStyle::PointingHand)
3485                .with_padding(Padding::uniform(3.))
3486                .on_down(MouseButton::Left, |_, this, cx| {
3487                    this.toggle_code_actions(
3488                        &ToggleCodeActions {
3489                            deployed_from_indicator: true,
3490                        },
3491                        cx,
3492                    );
3493                })
3494                .into_any(),
3495            )
3496        } else {
3497            None
3498        }
3499    }
3500
3501    pub fn render_fold_indicators(
3502        &self,
3503        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3504        style: &EditorStyle,
3505        gutter_hovered: bool,
3506        line_height: f32,
3507        gutter_margin: f32,
3508        cx: &mut ViewContext<Self>,
3509    ) -> Vec<Option<AnyElement<Self>>> {
3510        enum FoldIndicators {}
3511
3512        let style = style.folds.clone();
3513
3514        fold_data
3515            .iter()
3516            .enumerate()
3517            .map(|(ix, fold_data)| {
3518                fold_data
3519                    .map(|(fold_status, buffer_row, active)| {
3520                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3521                            MouseEventHandler::<FoldIndicators, _>::new(
3522                                ix as usize,
3523                                cx,
3524                                |mouse_state, _| {
3525                                    Svg::new(match fold_status {
3526                                        FoldStatus::Folded => style.folded_icon.clone(),
3527                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3528                                    })
3529                                    .with_color(
3530                                        style
3531                                            .indicator
3532                                            .in_state(fold_status == FoldStatus::Folded)
3533                                            .style_for(mouse_state)
3534                                            .color,
3535                                    )
3536                                    .constrained()
3537                                    .with_width(gutter_margin * style.icon_margin_scale)
3538                                    .aligned()
3539                                    .constrained()
3540                                    .with_height(line_height)
3541                                    .with_width(gutter_margin)
3542                                    .aligned()
3543                                },
3544                            )
3545                            .with_cursor_style(CursorStyle::PointingHand)
3546                            .with_padding(Padding::uniform(3.))
3547                            .on_click(MouseButton::Left, {
3548                                move |_, editor, cx| match fold_status {
3549                                    FoldStatus::Folded => {
3550                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3551                                    }
3552                                    FoldStatus::Foldable => {
3553                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3554                                    }
3555                                }
3556                            })
3557                            .into_any()
3558                        })
3559                    })
3560                    .flatten()
3561            })
3562            .collect()
3563    }
3564
3565    pub fn context_menu_visible(&self) -> bool {
3566        self.context_menu
3567            .as_ref()
3568            .map_or(false, |menu| menu.visible())
3569    }
3570
3571    pub fn render_context_menu(
3572        &self,
3573        cursor_position: DisplayPoint,
3574        style: EditorStyle,
3575        cx: &mut ViewContext<Editor>,
3576    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3577        self.context_menu
3578            .as_ref()
3579            .map(|menu| menu.render(cursor_position, style, cx))
3580    }
3581
3582    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3583        if !matches!(menu, ContextMenu::Completions(_)) {
3584            self.completion_tasks.clear();
3585        }
3586        self.context_menu = Some(menu);
3587        self.discard_copilot_suggestion(cx);
3588        cx.notify();
3589    }
3590
3591    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3592        cx.notify();
3593        self.completion_tasks.clear();
3594        let context_menu = self.context_menu.take();
3595        if context_menu.is_some() {
3596            self.update_visible_copilot_suggestion(cx);
3597        }
3598        context_menu
3599    }
3600
3601    pub fn insert_snippet(
3602        &mut self,
3603        insertion_ranges: &[Range<usize>],
3604        snippet: Snippet,
3605        cx: &mut ViewContext<Self>,
3606    ) -> Result<()> {
3607        let tabstops = self.buffer.update(cx, |buffer, cx| {
3608            let snippet_text: Arc<str> = snippet.text.clone().into();
3609            buffer.edit(
3610                insertion_ranges
3611                    .iter()
3612                    .cloned()
3613                    .map(|range| (range, snippet_text.clone())),
3614                Some(AutoindentMode::EachLine),
3615                cx,
3616            );
3617
3618            let snapshot = &*buffer.read(cx);
3619            let snippet = &snippet;
3620            snippet
3621                .tabstops
3622                .iter()
3623                .map(|tabstop| {
3624                    let mut tabstop_ranges = tabstop
3625                        .iter()
3626                        .flat_map(|tabstop_range| {
3627                            let mut delta = 0_isize;
3628                            insertion_ranges.iter().map(move |insertion_range| {
3629                                let insertion_start = insertion_range.start as isize + delta;
3630                                delta +=
3631                                    snippet.text.len() as isize - insertion_range.len() as isize;
3632
3633                                let start = snapshot.anchor_before(
3634                                    (insertion_start + tabstop_range.start) as usize,
3635                                );
3636                                let end = snapshot
3637                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3638                                start..end
3639                            })
3640                        })
3641                        .collect::<Vec<_>>();
3642                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3643                    tabstop_ranges
3644                })
3645                .collect::<Vec<_>>()
3646        });
3647
3648        if let Some(tabstop) = tabstops.first() {
3649            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3650                s.select_ranges(tabstop.iter().cloned());
3651            });
3652            self.snippet_stack.push(SnippetState {
3653                active_index: 0,
3654                ranges: tabstops,
3655            });
3656        }
3657
3658        Ok(())
3659    }
3660
3661    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3662        self.move_to_snippet_tabstop(Bias::Right, cx)
3663    }
3664
3665    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3666        self.move_to_snippet_tabstop(Bias::Left, cx)
3667    }
3668
3669    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3670        if let Some(mut snippet) = self.snippet_stack.pop() {
3671            match bias {
3672                Bias::Left => {
3673                    if snippet.active_index > 0 {
3674                        snippet.active_index -= 1;
3675                    } else {
3676                        self.snippet_stack.push(snippet);
3677                        return false;
3678                    }
3679                }
3680                Bias::Right => {
3681                    if snippet.active_index + 1 < snippet.ranges.len() {
3682                        snippet.active_index += 1;
3683                    } else {
3684                        self.snippet_stack.push(snippet);
3685                        return false;
3686                    }
3687                }
3688            }
3689            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3690                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3691                    s.select_anchor_ranges(current_ranges.iter().cloned())
3692                });
3693                // If snippet state is not at the last tabstop, push it back on the stack
3694                if snippet.active_index + 1 < snippet.ranges.len() {
3695                    self.snippet_stack.push(snippet);
3696                }
3697                return true;
3698            }
3699        }
3700
3701        false
3702    }
3703
3704    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3705        self.transact(cx, |this, cx| {
3706            this.select_all(&SelectAll, cx);
3707            this.insert("", cx);
3708        });
3709    }
3710
3711    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3712        self.transact(cx, |this, cx| {
3713            this.select_autoclose_pair(cx);
3714            let mut selections = this.selections.all::<Point>(cx);
3715            if !this.selections.line_mode {
3716                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3717                for selection in &mut selections {
3718                    if selection.is_empty() {
3719                        let old_head = selection.head();
3720                        let mut new_head =
3721                            movement::left(&display_map, old_head.to_display_point(&display_map))
3722                                .to_point(&display_map);
3723                        if let Some((buffer, line_buffer_range)) = display_map
3724                            .buffer_snapshot
3725                            .buffer_line_for_row(old_head.row)
3726                        {
3727                            let indent_size =
3728                                buffer.indent_size_for_line(line_buffer_range.start.row);
3729                            let indent_len = match indent_size.kind {
3730                                IndentKind::Space => {
3731                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3732                                }
3733                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3734                            };
3735                            if old_head.column <= indent_size.len && old_head.column > 0 {
3736                                let indent_len = indent_len.get();
3737                                new_head = cmp::min(
3738                                    new_head,
3739                                    Point::new(
3740                                        old_head.row,
3741                                        ((old_head.column - 1) / indent_len) * indent_len,
3742                                    ),
3743                                );
3744                            }
3745                        }
3746
3747                        selection.set_head(new_head, SelectionGoal::None);
3748                    }
3749                }
3750            }
3751
3752            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3753            this.insert("", cx);
3754            this.refresh_copilot_suggestions(true, cx);
3755        });
3756    }
3757
3758    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3759        self.transact(cx, |this, cx| {
3760            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3761                let line_mode = s.line_mode;
3762                s.move_with(|map, selection| {
3763                    if selection.is_empty() && !line_mode {
3764                        let cursor = movement::right(map, selection.head());
3765                        selection.end = cursor;
3766                        selection.reversed = true;
3767                        selection.goal = SelectionGoal::None;
3768                    }
3769                })
3770            });
3771            this.insert("", cx);
3772            this.refresh_copilot_suggestions(true, cx);
3773        });
3774    }
3775
3776    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3777        if self.move_to_prev_snippet_tabstop(cx) {
3778            return;
3779        }
3780
3781        self.outdent(&Outdent, cx);
3782    }
3783
3784    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3785        if self.move_to_next_snippet_tabstop(cx) {
3786            return;
3787        }
3788
3789        let mut selections = self.selections.all_adjusted(cx);
3790        let buffer = self.buffer.read(cx);
3791        let snapshot = buffer.snapshot(cx);
3792        let rows_iter = selections.iter().map(|s| s.head().row);
3793        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3794
3795        let mut edits = Vec::new();
3796        let mut prev_edited_row = 0;
3797        let mut row_delta = 0;
3798        for selection in &mut selections {
3799            if selection.start.row != prev_edited_row {
3800                row_delta = 0;
3801            }
3802            prev_edited_row = selection.end.row;
3803
3804            // If the selection is non-empty, then increase the indentation of the selected lines.
3805            if !selection.is_empty() {
3806                row_delta =
3807                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3808                continue;
3809            }
3810
3811            // If the selection is empty and the cursor is in the leading whitespace before the
3812            // suggested indentation, then auto-indent the line.
3813            let cursor = selection.head();
3814            let current_indent = snapshot.indent_size_for_line(cursor.row);
3815            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3816                if cursor.column < suggested_indent.len
3817                    && cursor.column <= current_indent.len
3818                    && current_indent.len <= suggested_indent.len
3819                {
3820                    selection.start = Point::new(cursor.row, suggested_indent.len);
3821                    selection.end = selection.start;
3822                    if row_delta == 0 {
3823                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3824                            cursor.row,
3825                            current_indent,
3826                            suggested_indent,
3827                        ));
3828                        row_delta = suggested_indent.len - current_indent.len;
3829                    }
3830                    continue;
3831                }
3832            }
3833
3834            // Accept copilot suggestion if there is only one selection and the cursor is not
3835            // in the leading whitespace.
3836            if self.selections.count() == 1
3837                && cursor.column >= current_indent.len
3838                && self.has_active_copilot_suggestion(cx)
3839            {
3840                self.accept_copilot_suggestion(cx);
3841                return;
3842            }
3843
3844            // Otherwise, insert a hard or soft tab.
3845            let settings = buffer.settings_at(cursor, cx);
3846            let tab_size = if settings.hard_tabs {
3847                IndentSize::tab()
3848            } else {
3849                let tab_size = settings.tab_size.get();
3850                let char_column = snapshot
3851                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3852                    .flat_map(str::chars)
3853                    .count()
3854                    + row_delta as usize;
3855                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3856                IndentSize::spaces(chars_to_next_tab_stop)
3857            };
3858            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3859            selection.end = selection.start;
3860            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3861            row_delta += tab_size.len;
3862        }
3863
3864        self.transact(cx, |this, cx| {
3865            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3866            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3867            this.refresh_copilot_suggestions(true, cx);
3868        });
3869    }
3870
3871    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3872        let mut selections = self.selections.all::<Point>(cx);
3873        let mut prev_edited_row = 0;
3874        let mut row_delta = 0;
3875        let mut edits = Vec::new();
3876        let buffer = self.buffer.read(cx);
3877        let snapshot = buffer.snapshot(cx);
3878        for selection in &mut selections {
3879            if selection.start.row != prev_edited_row {
3880                row_delta = 0;
3881            }
3882            prev_edited_row = selection.end.row;
3883
3884            row_delta =
3885                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3886        }
3887
3888        self.transact(cx, |this, cx| {
3889            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3890            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3891        });
3892    }
3893
3894    fn indent_selection(
3895        buffer: &MultiBuffer,
3896        snapshot: &MultiBufferSnapshot,
3897        selection: &mut Selection<Point>,
3898        edits: &mut Vec<(Range<Point>, String)>,
3899        delta_for_start_row: u32,
3900        cx: &AppContext,
3901    ) -> u32 {
3902        let settings = buffer.settings_at(selection.start, cx);
3903        let tab_size = settings.tab_size.get();
3904        let indent_kind = if settings.hard_tabs {
3905            IndentKind::Tab
3906        } else {
3907            IndentKind::Space
3908        };
3909        let mut start_row = selection.start.row;
3910        let mut end_row = selection.end.row + 1;
3911
3912        // If a selection ends at the beginning of a line, don't indent
3913        // that last line.
3914        if selection.end.column == 0 {
3915            end_row -= 1;
3916        }
3917
3918        // Avoid re-indenting a row that has already been indented by a
3919        // previous selection, but still update this selection's column
3920        // to reflect that indentation.
3921        if delta_for_start_row > 0 {
3922            start_row += 1;
3923            selection.start.column += delta_for_start_row;
3924            if selection.end.row == selection.start.row {
3925                selection.end.column += delta_for_start_row;
3926            }
3927        }
3928
3929        let mut delta_for_end_row = 0;
3930        for row in start_row..end_row {
3931            let current_indent = snapshot.indent_size_for_line(row);
3932            let indent_delta = match (current_indent.kind, indent_kind) {
3933                (IndentKind::Space, IndentKind::Space) => {
3934                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3935                    IndentSize::spaces(columns_to_next_tab_stop)
3936                }
3937                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3938                (_, IndentKind::Tab) => IndentSize::tab(),
3939            };
3940
3941            let row_start = Point::new(row, 0);
3942            edits.push((
3943                row_start..row_start,
3944                indent_delta.chars().collect::<String>(),
3945            ));
3946
3947            // Update this selection's endpoints to reflect the indentation.
3948            if row == selection.start.row {
3949                selection.start.column += indent_delta.len;
3950            }
3951            if row == selection.end.row {
3952                selection.end.column += indent_delta.len;
3953                delta_for_end_row = indent_delta.len;
3954            }
3955        }
3956
3957        if selection.start.row == selection.end.row {
3958            delta_for_start_row + delta_for_end_row
3959        } else {
3960            delta_for_end_row
3961        }
3962    }
3963
3964    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3965        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3966        let selections = self.selections.all::<Point>(cx);
3967        let mut deletion_ranges = Vec::new();
3968        let mut last_outdent = None;
3969        {
3970            let buffer = self.buffer.read(cx);
3971            let snapshot = buffer.snapshot(cx);
3972            for selection in &selections {
3973                let settings = buffer.settings_at(selection.start, cx);
3974                let tab_size = settings.tab_size.get();
3975                let mut rows = selection.spanned_rows(false, &display_map);
3976
3977                // Avoid re-outdenting a row that has already been outdented by a
3978                // previous selection.
3979                if let Some(last_row) = last_outdent {
3980                    if last_row == rows.start {
3981                        rows.start += 1;
3982                    }
3983                }
3984
3985                for row in rows {
3986                    let indent_size = snapshot.indent_size_for_line(row);
3987                    if indent_size.len > 0 {
3988                        let deletion_len = match indent_size.kind {
3989                            IndentKind::Space => {
3990                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3991                                if columns_to_prev_tab_stop == 0 {
3992                                    tab_size
3993                                } else {
3994                                    columns_to_prev_tab_stop
3995                                }
3996                            }
3997                            IndentKind::Tab => 1,
3998                        };
3999                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4000                        last_outdent = Some(row);
4001                    }
4002                }
4003            }
4004        }
4005
4006        self.transact(cx, |this, cx| {
4007            this.buffer.update(cx, |buffer, cx| {
4008                let empty_str: Arc<str> = "".into();
4009                buffer.edit(
4010                    deletion_ranges
4011                        .into_iter()
4012                        .map(|range| (range, empty_str.clone())),
4013                    None,
4014                    cx,
4015                );
4016            });
4017            let selections = this.selections.all::<usize>(cx);
4018            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4019        });
4020    }
4021
4022    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4023        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4024        let selections = self.selections.all::<Point>(cx);
4025
4026        let mut new_cursors = Vec::new();
4027        let mut edit_ranges = Vec::new();
4028        let mut selections = selections.iter().peekable();
4029        while let Some(selection) = selections.next() {
4030            let mut rows = selection.spanned_rows(false, &display_map);
4031            let goal_display_column = selection.head().to_display_point(&display_map).column();
4032
4033            // Accumulate contiguous regions of rows that we want to delete.
4034            while let Some(next_selection) = selections.peek() {
4035                let next_rows = next_selection.spanned_rows(false, &display_map);
4036                if next_rows.start <= rows.end {
4037                    rows.end = next_rows.end;
4038                    selections.next().unwrap();
4039                } else {
4040                    break;
4041                }
4042            }
4043
4044            let buffer = &display_map.buffer_snapshot;
4045            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4046            let edit_end;
4047            let cursor_buffer_row;
4048            if buffer.max_point().row >= rows.end {
4049                // If there's a line after the range, delete the \n from the end of the row range
4050                // and position the cursor on the next line.
4051                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4052                cursor_buffer_row = rows.end;
4053            } else {
4054                // If there isn't a line after the range, delete the \n from the line before the
4055                // start of the row range and position the cursor there.
4056                edit_start = edit_start.saturating_sub(1);
4057                edit_end = buffer.len();
4058                cursor_buffer_row = rows.start.saturating_sub(1);
4059            }
4060
4061            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4062            *cursor.column_mut() =
4063                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4064
4065            new_cursors.push((
4066                selection.id,
4067                buffer.anchor_after(cursor.to_point(&display_map)),
4068            ));
4069            edit_ranges.push(edit_start..edit_end);
4070        }
4071
4072        self.transact(cx, |this, cx| {
4073            let buffer = this.buffer.update(cx, |buffer, cx| {
4074                let empty_str: Arc<str> = "".into();
4075                buffer.edit(
4076                    edit_ranges
4077                        .into_iter()
4078                        .map(|range| (range, empty_str.clone())),
4079                    None,
4080                    cx,
4081                );
4082                buffer.snapshot(cx)
4083            });
4084            let new_selections = new_cursors
4085                .into_iter()
4086                .map(|(id, cursor)| {
4087                    let cursor = cursor.to_point(&buffer);
4088                    Selection {
4089                        id,
4090                        start: cursor,
4091                        end: cursor,
4092                        reversed: false,
4093                        goal: SelectionGoal::None,
4094                    }
4095                })
4096                .collect();
4097
4098            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4099                s.select(new_selections);
4100            });
4101        });
4102    }
4103
4104    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4105        let mut row_ranges = Vec::<Range<u32>>::new();
4106        for selection in self.selections.all::<Point>(cx) {
4107            let start = selection.start.row;
4108            let end = if selection.start.row == selection.end.row {
4109                selection.start.row + 1
4110            } else {
4111                selection.end.row
4112            };
4113
4114            if let Some(last_row_range) = row_ranges.last_mut() {
4115                if start <= last_row_range.end {
4116                    last_row_range.end = end;
4117                    continue;
4118                }
4119            }
4120            row_ranges.push(start..end);
4121        }
4122
4123        let snapshot = self.buffer.read(cx).snapshot(cx);
4124        let mut cursor_positions = Vec::new();
4125        for row_range in &row_ranges {
4126            let anchor = snapshot.anchor_before(Point::new(
4127                row_range.end - 1,
4128                snapshot.line_len(row_range.end - 1),
4129            ));
4130            cursor_positions.push(anchor.clone()..anchor);
4131        }
4132
4133        self.transact(cx, |this, cx| {
4134            for row_range in row_ranges.into_iter().rev() {
4135                for row in row_range.rev() {
4136                    let end_of_line = Point::new(row, snapshot.line_len(row));
4137                    let indent = snapshot.indent_size_for_line(row + 1);
4138                    let start_of_next_line = Point::new(row + 1, indent.len);
4139
4140                    let replace = if snapshot.line_len(row + 1) > indent.len {
4141                        " "
4142                    } else {
4143                        ""
4144                    };
4145
4146                    this.buffer.update(cx, |buffer, cx| {
4147                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4148                    });
4149                }
4150            }
4151
4152            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4153                s.select_anchor_ranges(cursor_positions)
4154            });
4155        });
4156    }
4157
4158    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4159        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4160        let buffer = &display_map.buffer_snapshot;
4161        let selections = self.selections.all::<Point>(cx);
4162
4163        let mut edits = Vec::new();
4164        let mut selections_iter = selections.iter().peekable();
4165        while let Some(selection) = selections_iter.next() {
4166            // Avoid duplicating the same lines twice.
4167            let mut rows = selection.spanned_rows(false, &display_map);
4168
4169            while let Some(next_selection) = selections_iter.peek() {
4170                let next_rows = next_selection.spanned_rows(false, &display_map);
4171                if next_rows.start < rows.end {
4172                    rows.end = next_rows.end;
4173                    selections_iter.next().unwrap();
4174                } else {
4175                    break;
4176                }
4177            }
4178
4179            // Copy the text from the selected row region and splice it at the start of the region.
4180            let start = Point::new(rows.start, 0);
4181            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4182            let text = buffer
4183                .text_for_range(start..end)
4184                .chain(Some("\n"))
4185                .collect::<String>();
4186            edits.push((start..start, text));
4187        }
4188
4189        self.transact(cx, |this, cx| {
4190            this.buffer.update(cx, |buffer, cx| {
4191                buffer.edit(edits, None, cx);
4192            });
4193
4194            this.request_autoscroll(Autoscroll::fit(), cx);
4195        });
4196    }
4197
4198    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4199        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4200        let buffer = self.buffer.read(cx).snapshot(cx);
4201
4202        let mut edits = Vec::new();
4203        let mut unfold_ranges = Vec::new();
4204        let mut refold_ranges = Vec::new();
4205
4206        let selections = self.selections.all::<Point>(cx);
4207        let mut selections = selections.iter().peekable();
4208        let mut contiguous_row_selections = Vec::new();
4209        let mut new_selections = Vec::new();
4210
4211        while let Some(selection) = selections.next() {
4212            // Find all the selections that span a contiguous row range
4213            let (start_row, end_row) = consume_contiguous_rows(
4214                &mut contiguous_row_selections,
4215                selection,
4216                &display_map,
4217                &mut selections,
4218            );
4219
4220            // Move the text spanned by the row range to be before the line preceding the row range
4221            if start_row > 0 {
4222                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4223                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4224                let insertion_point = display_map
4225                    .prev_line_boundary(Point::new(start_row - 1, 0))
4226                    .0;
4227
4228                // Don't move lines across excerpts
4229                if buffer
4230                    .excerpt_boundaries_in_range((
4231                        Bound::Excluded(insertion_point),
4232                        Bound::Included(range_to_move.end),
4233                    ))
4234                    .next()
4235                    .is_none()
4236                {
4237                    let text = buffer
4238                        .text_for_range(range_to_move.clone())
4239                        .flat_map(|s| s.chars())
4240                        .skip(1)
4241                        .chain(['\n'])
4242                        .collect::<String>();
4243
4244                    edits.push((
4245                        buffer.anchor_after(range_to_move.start)
4246                            ..buffer.anchor_before(range_to_move.end),
4247                        String::new(),
4248                    ));
4249                    let insertion_anchor = buffer.anchor_after(insertion_point);
4250                    edits.push((insertion_anchor..insertion_anchor, text));
4251
4252                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4253
4254                    // Move selections up
4255                    new_selections.extend(contiguous_row_selections.drain(..).map(
4256                        |mut selection| {
4257                            selection.start.row -= row_delta;
4258                            selection.end.row -= row_delta;
4259                            selection
4260                        },
4261                    ));
4262
4263                    // Move folds up
4264                    unfold_ranges.push(range_to_move.clone());
4265                    for fold in display_map.folds_in_range(
4266                        buffer.anchor_before(range_to_move.start)
4267                            ..buffer.anchor_after(range_to_move.end),
4268                    ) {
4269                        let mut start = fold.start.to_point(&buffer);
4270                        let mut end = fold.end.to_point(&buffer);
4271                        start.row -= row_delta;
4272                        end.row -= row_delta;
4273                        refold_ranges.push(start..end);
4274                    }
4275                }
4276            }
4277
4278            // If we didn't move line(s), preserve the existing selections
4279            new_selections.append(&mut contiguous_row_selections);
4280        }
4281
4282        self.transact(cx, |this, cx| {
4283            this.unfold_ranges(unfold_ranges, true, true, cx);
4284            this.buffer.update(cx, |buffer, cx| {
4285                for (range, text) in edits {
4286                    buffer.edit([(range, text)], None, cx);
4287                }
4288            });
4289            this.fold_ranges(refold_ranges, true, cx);
4290            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4291                s.select(new_selections);
4292            })
4293        });
4294    }
4295
4296    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4298        let buffer = self.buffer.read(cx).snapshot(cx);
4299
4300        let mut edits = Vec::new();
4301        let mut unfold_ranges = Vec::new();
4302        let mut refold_ranges = Vec::new();
4303
4304        let selections = self.selections.all::<Point>(cx);
4305        let mut selections = selections.iter().peekable();
4306        let mut contiguous_row_selections = Vec::new();
4307        let mut new_selections = Vec::new();
4308
4309        while let Some(selection) = selections.next() {
4310            // Find all the selections that span a contiguous row range
4311            let (start_row, end_row) = consume_contiguous_rows(
4312                &mut contiguous_row_selections,
4313                selection,
4314                &display_map,
4315                &mut selections,
4316            );
4317
4318            // Move the text spanned by the row range to be after the last line of the row range
4319            if end_row <= buffer.max_point().row {
4320                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4321                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4322
4323                // Don't move lines across excerpt boundaries
4324                if buffer
4325                    .excerpt_boundaries_in_range((
4326                        Bound::Excluded(range_to_move.start),
4327                        Bound::Included(insertion_point),
4328                    ))
4329                    .next()
4330                    .is_none()
4331                {
4332                    let mut text = String::from("\n");
4333                    text.extend(buffer.text_for_range(range_to_move.clone()));
4334                    text.pop(); // Drop trailing newline
4335                    edits.push((
4336                        buffer.anchor_after(range_to_move.start)
4337                            ..buffer.anchor_before(range_to_move.end),
4338                        String::new(),
4339                    ));
4340                    let insertion_anchor = buffer.anchor_after(insertion_point);
4341                    edits.push((insertion_anchor..insertion_anchor, text));
4342
4343                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4344
4345                    // Move selections down
4346                    new_selections.extend(contiguous_row_selections.drain(..).map(
4347                        |mut selection| {
4348                            selection.start.row += row_delta;
4349                            selection.end.row += row_delta;
4350                            selection
4351                        },
4352                    ));
4353
4354                    // Move folds down
4355                    unfold_ranges.push(range_to_move.clone());
4356                    for fold in display_map.folds_in_range(
4357                        buffer.anchor_before(range_to_move.start)
4358                            ..buffer.anchor_after(range_to_move.end),
4359                    ) {
4360                        let mut start = fold.start.to_point(&buffer);
4361                        let mut end = fold.end.to_point(&buffer);
4362                        start.row += row_delta;
4363                        end.row += row_delta;
4364                        refold_ranges.push(start..end);
4365                    }
4366                }
4367            }
4368
4369            // If we didn't move line(s), preserve the existing selections
4370            new_selections.append(&mut contiguous_row_selections);
4371        }
4372
4373        self.transact(cx, |this, cx| {
4374            this.unfold_ranges(unfold_ranges, true, true, cx);
4375            this.buffer.update(cx, |buffer, cx| {
4376                for (range, text) in edits {
4377                    buffer.edit([(range, text)], None, cx);
4378                }
4379            });
4380            this.fold_ranges(refold_ranges, true, cx);
4381            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4382        });
4383    }
4384
4385    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4386        self.transact(cx, |this, cx| {
4387            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4388                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4389                let line_mode = s.line_mode;
4390                s.move_with(|display_map, selection| {
4391                    if !selection.is_empty() || line_mode {
4392                        return;
4393                    }
4394
4395                    let mut head = selection.head();
4396                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4397                    if head.column() == display_map.line_len(head.row()) {
4398                        transpose_offset = display_map
4399                            .buffer_snapshot
4400                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4401                    }
4402
4403                    if transpose_offset == 0 {
4404                        return;
4405                    }
4406
4407                    *head.column_mut() += 1;
4408                    head = display_map.clip_point(head, Bias::Right);
4409                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4410
4411                    let transpose_start = display_map
4412                        .buffer_snapshot
4413                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4414                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4415                        let transpose_end = display_map
4416                            .buffer_snapshot
4417                            .clip_offset(transpose_offset + 1, Bias::Right);
4418                        if let Some(ch) =
4419                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4420                        {
4421                            edits.push((transpose_start..transpose_offset, String::new()));
4422                            edits.push((transpose_end..transpose_end, ch.to_string()));
4423                        }
4424                    }
4425                });
4426                edits
4427            });
4428            this.buffer
4429                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4430            let selections = this.selections.all::<usize>(cx);
4431            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4432                s.select(selections);
4433            });
4434        });
4435    }
4436
4437    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4438        let mut text = String::new();
4439        let buffer = self.buffer.read(cx).snapshot(cx);
4440        let mut selections = self.selections.all::<Point>(cx);
4441        let mut clipboard_selections = Vec::with_capacity(selections.len());
4442        {
4443            let max_point = buffer.max_point();
4444            for selection in &mut selections {
4445                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4446                if is_entire_line {
4447                    selection.start = Point::new(selection.start.row, 0);
4448                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4449                    selection.goal = SelectionGoal::None;
4450                }
4451                let mut len = 0;
4452                for chunk in buffer.text_for_range(selection.start..selection.end) {
4453                    text.push_str(chunk);
4454                    len += chunk.len();
4455                }
4456                clipboard_selections.push(ClipboardSelection {
4457                    len,
4458                    is_entire_line,
4459                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4460                });
4461            }
4462        }
4463
4464        self.transact(cx, |this, cx| {
4465            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4466                s.select(selections);
4467            });
4468            this.insert("", cx);
4469            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4470        });
4471    }
4472
4473    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4474        let selections = self.selections.all::<Point>(cx);
4475        let buffer = self.buffer.read(cx).read(cx);
4476        let mut text = String::new();
4477
4478        let mut clipboard_selections = Vec::with_capacity(selections.len());
4479        {
4480            let max_point = buffer.max_point();
4481            for selection in selections.iter() {
4482                let mut start = selection.start;
4483                let mut end = selection.end;
4484                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4485                if is_entire_line {
4486                    start = Point::new(start.row, 0);
4487                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4488                }
4489                let mut len = 0;
4490                for chunk in buffer.text_for_range(start..end) {
4491                    text.push_str(chunk);
4492                    len += chunk.len();
4493                }
4494                clipboard_selections.push(ClipboardSelection {
4495                    len,
4496                    is_entire_line,
4497                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4498                });
4499            }
4500        }
4501
4502        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4503    }
4504
4505    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4506        self.transact(cx, |this, cx| {
4507            if let Some(item) = cx.read_from_clipboard() {
4508                let mut clipboard_text = Cow::Borrowed(item.text());
4509                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4510                    let old_selections = this.selections.all::<usize>(cx);
4511                    let all_selections_were_entire_line =
4512                        clipboard_selections.iter().all(|s| s.is_entire_line);
4513                    let first_selection_indent_column =
4514                        clipboard_selections.first().map(|s| s.first_line_indent);
4515                    if clipboard_selections.len() != old_selections.len() {
4516                        let mut newline_separated_text = String::new();
4517                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4518                        let mut ix = 0;
4519                        while let Some(clipboard_selection) = clipboard_selections.next() {
4520                            newline_separated_text
4521                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4522                            ix += clipboard_selection.len;
4523                            if clipboard_selections.peek().is_some() {
4524                                newline_separated_text.push('\n');
4525                            }
4526                        }
4527                        clipboard_text = Cow::Owned(newline_separated_text);
4528                    }
4529
4530                    this.buffer.update(cx, |buffer, cx| {
4531                        let snapshot = buffer.read(cx);
4532                        let mut start_offset = 0;
4533                        let mut edits = Vec::new();
4534                        let mut original_indent_columns = Vec::new();
4535                        let line_mode = this.selections.line_mode;
4536                        for (ix, selection) in old_selections.iter().enumerate() {
4537                            let to_insert;
4538                            let entire_line;
4539                            let original_indent_column;
4540                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4541                                let end_offset = start_offset + clipboard_selection.len;
4542                                to_insert = &clipboard_text[start_offset..end_offset];
4543                                entire_line = clipboard_selection.is_entire_line;
4544                                start_offset = end_offset;
4545                                original_indent_column =
4546                                    Some(clipboard_selection.first_line_indent);
4547                            } else {
4548                                to_insert = clipboard_text.as_str();
4549                                entire_line = all_selections_were_entire_line;
4550                                original_indent_column = first_selection_indent_column
4551                            }
4552
4553                            // If the corresponding selection was empty when this slice of the
4554                            // clipboard text was written, then the entire line containing the
4555                            // selection was copied. If this selection is also currently empty,
4556                            // then paste the line before the current line of the buffer.
4557                            let range = if selection.is_empty() && !line_mode && entire_line {
4558                                let column = selection.start.to_point(&snapshot).column as usize;
4559                                let line_start = selection.start - column;
4560                                line_start..line_start
4561                            } else {
4562                                selection.range()
4563                            };
4564
4565                            edits.push((range, to_insert));
4566                            original_indent_columns.extend(original_indent_column);
4567                        }
4568                        drop(snapshot);
4569
4570                        buffer.edit(
4571                            edits,
4572                            Some(AutoindentMode::Block {
4573                                original_indent_columns,
4574                            }),
4575                            cx,
4576                        );
4577                    });
4578
4579                    let selections = this.selections.all::<usize>(cx);
4580                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4581                } else {
4582                    this.insert(&clipboard_text, cx);
4583                }
4584            }
4585        });
4586    }
4587
4588    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4589        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4590            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4591                self.change_selections(None, cx, |s| {
4592                    s.select_anchors(selections.to_vec());
4593                });
4594            }
4595            self.request_autoscroll(Autoscroll::fit(), cx);
4596            self.unmark_text(cx);
4597            self.refresh_copilot_suggestions(true, cx);
4598            cx.emit(Event::Edited);
4599        }
4600    }
4601
4602    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4603        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4604            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4605            {
4606                self.change_selections(None, cx, |s| {
4607                    s.select_anchors(selections.to_vec());
4608                });
4609            }
4610            self.request_autoscroll(Autoscroll::fit(), cx);
4611            self.unmark_text(cx);
4612            self.refresh_copilot_suggestions(true, cx);
4613            cx.emit(Event::Edited);
4614        }
4615    }
4616
4617    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4618        self.buffer
4619            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4620    }
4621
4622    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4623        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4624            let line_mode = s.line_mode;
4625            s.move_with(|map, selection| {
4626                let cursor = if selection.is_empty() && !line_mode {
4627                    movement::left(map, selection.start)
4628                } else {
4629                    selection.start
4630                };
4631                selection.collapse_to(cursor, SelectionGoal::None);
4632            });
4633        })
4634    }
4635
4636    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4637        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4638            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4639        })
4640    }
4641
4642    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4643        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4644            let line_mode = s.line_mode;
4645            s.move_with(|map, selection| {
4646                let cursor = if selection.is_empty() && !line_mode {
4647                    movement::right(map, selection.end)
4648                } else {
4649                    selection.end
4650                };
4651                selection.collapse_to(cursor, SelectionGoal::None)
4652            });
4653        })
4654    }
4655
4656    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4657        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4658            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4659        })
4660    }
4661
4662    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4663        if self.take_rename(true, cx).is_some() {
4664            return;
4665        }
4666
4667        if let Some(context_menu) = self.context_menu.as_mut() {
4668            if context_menu.select_prev(cx) {
4669                return;
4670            }
4671        }
4672
4673        if matches!(self.mode, EditorMode::SingleLine) {
4674            cx.propagate_action();
4675            return;
4676        }
4677
4678        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4679            let line_mode = s.line_mode;
4680            s.move_with(|map, selection| {
4681                if !selection.is_empty() && !line_mode {
4682                    selection.goal = SelectionGoal::None;
4683                }
4684                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4685                selection.collapse_to(cursor, goal);
4686            });
4687        })
4688    }
4689
4690    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4691        if self.take_rename(true, cx).is_some() {
4692            return;
4693        }
4694
4695        if self
4696            .context_menu
4697            .as_mut()
4698            .map(|menu| menu.select_first(cx))
4699            .unwrap_or(false)
4700        {
4701            return;
4702        }
4703
4704        if matches!(self.mode, EditorMode::SingleLine) {
4705            cx.propagate_action();
4706            return;
4707        }
4708
4709        let row_count = if let Some(row_count) = self.visible_line_count() {
4710            row_count as u32 - 1
4711        } else {
4712            return;
4713        };
4714
4715        let autoscroll = if action.center_cursor {
4716            Autoscroll::center()
4717        } else {
4718            Autoscroll::fit()
4719        };
4720
4721        self.change_selections(Some(autoscroll), cx, |s| {
4722            let line_mode = s.line_mode;
4723            s.move_with(|map, selection| {
4724                if !selection.is_empty() && !line_mode {
4725                    selection.goal = SelectionGoal::None;
4726                }
4727                let (cursor, goal) =
4728                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4729                selection.collapse_to(cursor, goal);
4730            });
4731        });
4732    }
4733
4734    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4735        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4736            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4737        })
4738    }
4739
4740    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4741        self.take_rename(true, cx);
4742
4743        if let Some(context_menu) = self.context_menu.as_mut() {
4744            if context_menu.select_next(cx) {
4745                return;
4746            }
4747        }
4748
4749        if self.mode == EditorMode::SingleLine {
4750            cx.propagate_action();
4751            return;
4752        }
4753
4754        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4755            let line_mode = s.line_mode;
4756            s.move_with(|map, selection| {
4757                if !selection.is_empty() && !line_mode {
4758                    selection.goal = SelectionGoal::None;
4759                }
4760                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4761                selection.collapse_to(cursor, goal);
4762            });
4763        });
4764    }
4765
4766    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4767        if self.take_rename(true, cx).is_some() {
4768            return;
4769        }
4770
4771        if self
4772            .context_menu
4773            .as_mut()
4774            .map(|menu| menu.select_last(cx))
4775            .unwrap_or(false)
4776        {
4777            return;
4778        }
4779
4780        if matches!(self.mode, EditorMode::SingleLine) {
4781            cx.propagate_action();
4782            return;
4783        }
4784
4785        let row_count = if let Some(row_count) = self.visible_line_count() {
4786            row_count as u32 - 1
4787        } else {
4788            return;
4789        };
4790
4791        let autoscroll = if action.center_cursor {
4792            Autoscroll::center()
4793        } else {
4794            Autoscroll::fit()
4795        };
4796
4797        self.change_selections(Some(autoscroll), cx, |s| {
4798            let line_mode = s.line_mode;
4799            s.move_with(|map, selection| {
4800                if !selection.is_empty() && !line_mode {
4801                    selection.goal = SelectionGoal::None;
4802                }
4803                let (cursor, goal) =
4804                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4805                selection.collapse_to(cursor, goal);
4806            });
4807        });
4808    }
4809
4810    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4811        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4812            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4813        });
4814    }
4815
4816    pub fn move_to_previous_word_start(
4817        &mut self,
4818        _: &MoveToPreviousWordStart,
4819        cx: &mut ViewContext<Self>,
4820    ) {
4821        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4822            s.move_cursors_with(|map, head, _| {
4823                (
4824                    movement::previous_word_start(map, head),
4825                    SelectionGoal::None,
4826                )
4827            });
4828        })
4829    }
4830
4831    pub fn move_to_previous_subword_start(
4832        &mut self,
4833        _: &MoveToPreviousSubwordStart,
4834        cx: &mut ViewContext<Self>,
4835    ) {
4836        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4837            s.move_cursors_with(|map, head, _| {
4838                (
4839                    movement::previous_subword_start(map, head),
4840                    SelectionGoal::None,
4841                )
4842            });
4843        })
4844    }
4845
4846    pub fn select_to_previous_word_start(
4847        &mut self,
4848        _: &SelectToPreviousWordStart,
4849        cx: &mut ViewContext<Self>,
4850    ) {
4851        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4852            s.move_heads_with(|map, head, _| {
4853                (
4854                    movement::previous_word_start(map, head),
4855                    SelectionGoal::None,
4856                )
4857            });
4858        })
4859    }
4860
4861    pub fn select_to_previous_subword_start(
4862        &mut self,
4863        _: &SelectToPreviousSubwordStart,
4864        cx: &mut ViewContext<Self>,
4865    ) {
4866        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4867            s.move_heads_with(|map, head, _| {
4868                (
4869                    movement::previous_subword_start(map, head),
4870                    SelectionGoal::None,
4871                )
4872            });
4873        })
4874    }
4875
4876    pub fn delete_to_previous_word_start(
4877        &mut self,
4878        _: &DeleteToPreviousWordStart,
4879        cx: &mut ViewContext<Self>,
4880    ) {
4881        self.transact(cx, |this, cx| {
4882            this.select_autoclose_pair(cx);
4883            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4884                let line_mode = s.line_mode;
4885                s.move_with(|map, selection| {
4886                    if selection.is_empty() && !line_mode {
4887                        let cursor = movement::previous_word_start(map, selection.head());
4888                        selection.set_head(cursor, SelectionGoal::None);
4889                    }
4890                });
4891            });
4892            this.insert("", cx);
4893        });
4894    }
4895
4896    pub fn delete_to_previous_subword_start(
4897        &mut self,
4898        _: &DeleteToPreviousSubwordStart,
4899        cx: &mut ViewContext<Self>,
4900    ) {
4901        self.transact(cx, |this, cx| {
4902            this.select_autoclose_pair(cx);
4903            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4904                let line_mode = s.line_mode;
4905                s.move_with(|map, selection| {
4906                    if selection.is_empty() && !line_mode {
4907                        let cursor = movement::previous_subword_start(map, selection.head());
4908                        selection.set_head(cursor, SelectionGoal::None);
4909                    }
4910                });
4911            });
4912            this.insert("", cx);
4913        });
4914    }
4915
4916    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4917        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4918            s.move_cursors_with(|map, head, _| {
4919                (movement::next_word_end(map, head), SelectionGoal::None)
4920            });
4921        })
4922    }
4923
4924    pub fn move_to_next_subword_end(
4925        &mut self,
4926        _: &MoveToNextSubwordEnd,
4927        cx: &mut ViewContext<Self>,
4928    ) {
4929        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4930            s.move_cursors_with(|map, head, _| {
4931                (movement::next_subword_end(map, head), SelectionGoal::None)
4932            });
4933        })
4934    }
4935
4936    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4937        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4938            s.move_heads_with(|map, head, _| {
4939                (movement::next_word_end(map, head), SelectionGoal::None)
4940            });
4941        })
4942    }
4943
4944    pub fn select_to_next_subword_end(
4945        &mut self,
4946        _: &SelectToNextSubwordEnd,
4947        cx: &mut ViewContext<Self>,
4948    ) {
4949        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4950            s.move_heads_with(|map, head, _| {
4951                (movement::next_subword_end(map, head), SelectionGoal::None)
4952            });
4953        })
4954    }
4955
4956    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4957        self.transact(cx, |this, cx| {
4958            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4959                let line_mode = s.line_mode;
4960                s.move_with(|map, selection| {
4961                    if selection.is_empty() && !line_mode {
4962                        let cursor = movement::next_word_end(map, selection.head());
4963                        selection.set_head(cursor, SelectionGoal::None);
4964                    }
4965                });
4966            });
4967            this.insert("", cx);
4968        });
4969    }
4970
4971    pub fn delete_to_next_subword_end(
4972        &mut self,
4973        _: &DeleteToNextSubwordEnd,
4974        cx: &mut ViewContext<Self>,
4975    ) {
4976        self.transact(cx, |this, cx| {
4977            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4978                s.move_with(|map, selection| {
4979                    if selection.is_empty() {
4980                        let cursor = movement::next_subword_end(map, selection.head());
4981                        selection.set_head(cursor, SelectionGoal::None);
4982                    }
4983                });
4984            });
4985            this.insert("", cx);
4986        });
4987    }
4988
4989    pub fn move_to_beginning_of_line(
4990        &mut self,
4991        _: &MoveToBeginningOfLine,
4992        cx: &mut ViewContext<Self>,
4993    ) {
4994        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4995            s.move_cursors_with(|map, head, _| {
4996                (
4997                    movement::indented_line_beginning(map, head, true),
4998                    SelectionGoal::None,
4999                )
5000            });
5001        })
5002    }
5003
5004    pub fn select_to_beginning_of_line(
5005        &mut self,
5006        action: &SelectToBeginningOfLine,
5007        cx: &mut ViewContext<Self>,
5008    ) {
5009        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5010            s.move_heads_with(|map, head, _| {
5011                (
5012                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5013                    SelectionGoal::None,
5014                )
5015            });
5016        });
5017    }
5018
5019    pub fn delete_to_beginning_of_line(
5020        &mut self,
5021        _: &DeleteToBeginningOfLine,
5022        cx: &mut ViewContext<Self>,
5023    ) {
5024        self.transact(cx, |this, cx| {
5025            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5026                s.move_with(|_, selection| {
5027                    selection.reversed = true;
5028                });
5029            });
5030
5031            this.select_to_beginning_of_line(
5032                &SelectToBeginningOfLine {
5033                    stop_at_soft_wraps: false,
5034                },
5035                cx,
5036            );
5037            this.backspace(&Backspace, cx);
5038        });
5039    }
5040
5041    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5042        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5043            s.move_cursors_with(|map, head, _| {
5044                (movement::line_end(map, head, true), SelectionGoal::None)
5045            });
5046        })
5047    }
5048
5049    pub fn select_to_end_of_line(
5050        &mut self,
5051        action: &SelectToEndOfLine,
5052        cx: &mut ViewContext<Self>,
5053    ) {
5054        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5055            s.move_heads_with(|map, head, _| {
5056                (
5057                    movement::line_end(map, head, action.stop_at_soft_wraps),
5058                    SelectionGoal::None,
5059                )
5060            });
5061        })
5062    }
5063
5064    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5065        self.transact(cx, |this, cx| {
5066            this.select_to_end_of_line(
5067                &SelectToEndOfLine {
5068                    stop_at_soft_wraps: false,
5069                },
5070                cx,
5071            );
5072            this.delete(&Delete, cx);
5073        });
5074    }
5075
5076    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5077        self.transact(cx, |this, cx| {
5078            this.select_to_end_of_line(
5079                &SelectToEndOfLine {
5080                    stop_at_soft_wraps: false,
5081                },
5082                cx,
5083            );
5084            this.cut(&Cut, cx);
5085        });
5086    }
5087
5088    pub fn move_to_start_of_paragraph(
5089        &mut self,
5090        _: &MoveToStartOfParagraph,
5091        cx: &mut ViewContext<Self>,
5092    ) {
5093        if matches!(self.mode, EditorMode::SingleLine) {
5094            cx.propagate_action();
5095            return;
5096        }
5097
5098        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5099            s.move_with(|map, selection| {
5100                selection.collapse_to(
5101                    movement::start_of_paragraph(map, selection.head()),
5102                    SelectionGoal::None,
5103                )
5104            });
5105        })
5106    }
5107
5108    pub fn move_to_end_of_paragraph(
5109        &mut self,
5110        _: &MoveToEndOfParagraph,
5111        cx: &mut ViewContext<Self>,
5112    ) {
5113        if matches!(self.mode, EditorMode::SingleLine) {
5114            cx.propagate_action();
5115            return;
5116        }
5117
5118        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5119            s.move_with(|map, selection| {
5120                selection.collapse_to(
5121                    movement::end_of_paragraph(map, selection.head()),
5122                    SelectionGoal::None,
5123                )
5124            });
5125        })
5126    }
5127
5128    pub fn select_to_start_of_paragraph(
5129        &mut self,
5130        _: &SelectToStartOfParagraph,
5131        cx: &mut ViewContext<Self>,
5132    ) {
5133        if matches!(self.mode, EditorMode::SingleLine) {
5134            cx.propagate_action();
5135            return;
5136        }
5137
5138        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5139            s.move_heads_with(|map, head, _| {
5140                (movement::start_of_paragraph(map, head), SelectionGoal::None)
5141            });
5142        })
5143    }
5144
5145    pub fn select_to_end_of_paragraph(
5146        &mut self,
5147        _: &SelectToEndOfParagraph,
5148        cx: &mut ViewContext<Self>,
5149    ) {
5150        if matches!(self.mode, EditorMode::SingleLine) {
5151            cx.propagate_action();
5152            return;
5153        }
5154
5155        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5156            s.move_heads_with(|map, head, _| {
5157                (movement::end_of_paragraph(map, head), SelectionGoal::None)
5158            });
5159        })
5160    }
5161
5162    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5163        if matches!(self.mode, EditorMode::SingleLine) {
5164            cx.propagate_action();
5165            return;
5166        }
5167
5168        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5169            s.select_ranges(vec![0..0]);
5170        });
5171    }
5172
5173    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5174        let mut selection = self.selections.last::<Point>(cx);
5175        selection.set_head(Point::zero(), SelectionGoal::None);
5176
5177        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5178            s.select(vec![selection]);
5179        });
5180    }
5181
5182    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5183        if matches!(self.mode, EditorMode::SingleLine) {
5184            cx.propagate_action();
5185            return;
5186        }
5187
5188        let cursor = self.buffer.read(cx).read(cx).len();
5189        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5190            s.select_ranges(vec![cursor..cursor])
5191        });
5192    }
5193
5194    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5195        self.nav_history = nav_history;
5196    }
5197
5198    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5199        self.nav_history.as_ref()
5200    }
5201
5202    fn push_to_nav_history(
5203        &mut self,
5204        cursor_anchor: Anchor,
5205        new_position: Option<Point>,
5206        cx: &mut ViewContext<Self>,
5207    ) {
5208        if let Some(nav_history) = self.nav_history.as_mut() {
5209            let buffer = self.buffer.read(cx).read(cx);
5210            let cursor_position = cursor_anchor.to_point(&buffer);
5211            let scroll_state = self.scroll_manager.anchor();
5212            let scroll_top_row = scroll_state.top_row(&buffer);
5213            drop(buffer);
5214
5215            if let Some(new_position) = new_position {
5216                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5217                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5218                    return;
5219                }
5220            }
5221
5222            nav_history.push(
5223                Some(NavigationData {
5224                    cursor_anchor,
5225                    cursor_position,
5226                    scroll_anchor: scroll_state,
5227                    scroll_top_row,
5228                }),
5229                cx,
5230            );
5231        }
5232    }
5233
5234    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5235        let buffer = self.buffer.read(cx).snapshot(cx);
5236        let mut selection = self.selections.first::<usize>(cx);
5237        selection.set_head(buffer.len(), SelectionGoal::None);
5238        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5239            s.select(vec![selection]);
5240        });
5241    }
5242
5243    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5244        let end = self.buffer.read(cx).read(cx).len();
5245        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5246            s.select_ranges(vec![0..end]);
5247        });
5248    }
5249
5250    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5251        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5252        let mut selections = self.selections.all::<Point>(cx);
5253        let max_point = display_map.buffer_snapshot.max_point();
5254        for selection in &mut selections {
5255            let rows = selection.spanned_rows(true, &display_map);
5256            selection.start = Point::new(rows.start, 0);
5257            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5258            selection.reversed = false;
5259        }
5260        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5261            s.select(selections);
5262        });
5263    }
5264
5265    pub fn split_selection_into_lines(
5266        &mut self,
5267        _: &SplitSelectionIntoLines,
5268        cx: &mut ViewContext<Self>,
5269    ) {
5270        let mut to_unfold = Vec::new();
5271        let mut new_selection_ranges = Vec::new();
5272        {
5273            let selections = self.selections.all::<Point>(cx);
5274            let buffer = self.buffer.read(cx).read(cx);
5275            for selection in selections {
5276                for row in selection.start.row..selection.end.row {
5277                    let cursor = Point::new(row, buffer.line_len(row));
5278                    new_selection_ranges.push(cursor..cursor);
5279                }
5280                new_selection_ranges.push(selection.end..selection.end);
5281                to_unfold.push(selection.start..selection.end);
5282            }
5283        }
5284        self.unfold_ranges(to_unfold, true, true, cx);
5285        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5286            s.select_ranges(new_selection_ranges);
5287        });
5288    }
5289
5290    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5291        self.add_selection(true, cx);
5292    }
5293
5294    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5295        self.add_selection(false, cx);
5296    }
5297
5298    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5299        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5300        let mut selections = self.selections.all::<Point>(cx);
5301        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5302            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5303            let range = oldest_selection.display_range(&display_map).sorted();
5304            let columns = cmp::min(range.start.column(), range.end.column())
5305                ..cmp::max(range.start.column(), range.end.column());
5306
5307            selections.clear();
5308            let mut stack = Vec::new();
5309            for row in range.start.row()..=range.end.row() {
5310                if let Some(selection) = self.selections.build_columnar_selection(
5311                    &display_map,
5312                    row,
5313                    &columns,
5314                    oldest_selection.reversed,
5315                ) {
5316                    stack.push(selection.id);
5317                    selections.push(selection);
5318                }
5319            }
5320
5321            if above {
5322                stack.reverse();
5323            }
5324
5325            AddSelectionsState { above, stack }
5326        });
5327
5328        let last_added_selection = *state.stack.last().unwrap();
5329        let mut new_selections = Vec::new();
5330        if above == state.above {
5331            let end_row = if above {
5332                0
5333            } else {
5334                display_map.max_point().row()
5335            };
5336
5337            'outer: for selection in selections {
5338                if selection.id == last_added_selection {
5339                    let range = selection.display_range(&display_map).sorted();
5340                    debug_assert_eq!(range.start.row(), range.end.row());
5341                    let mut row = range.start.row();
5342                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5343                    {
5344                        start..end
5345                    } else {
5346                        cmp::min(range.start.column(), range.end.column())
5347                            ..cmp::max(range.start.column(), range.end.column())
5348                    };
5349
5350                    while row != end_row {
5351                        if above {
5352                            row -= 1;
5353                        } else {
5354                            row += 1;
5355                        }
5356
5357                        if let Some(new_selection) = self.selections.build_columnar_selection(
5358                            &display_map,
5359                            row,
5360                            &columns,
5361                            selection.reversed,
5362                        ) {
5363                            state.stack.push(new_selection.id);
5364                            if above {
5365                                new_selections.push(new_selection);
5366                                new_selections.push(selection);
5367                            } else {
5368                                new_selections.push(selection);
5369                                new_selections.push(new_selection);
5370                            }
5371
5372                            continue 'outer;
5373                        }
5374                    }
5375                }
5376
5377                new_selections.push(selection);
5378            }
5379        } else {
5380            new_selections = selections;
5381            new_selections.retain(|s| s.id != last_added_selection);
5382            state.stack.pop();
5383        }
5384
5385        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5386            s.select(new_selections);
5387        });
5388        if state.stack.len() > 1 {
5389            self.add_selections_state = Some(state);
5390        }
5391    }
5392
5393    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5394        self.push_to_selection_history();
5395        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5396        let buffer = &display_map.buffer_snapshot;
5397        let mut selections = self.selections.all::<usize>(cx);
5398        if let Some(mut select_next_state) = self.select_next_state.take() {
5399            let query = &select_next_state.query;
5400            if !select_next_state.done {
5401                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5402                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5403                let mut next_selected_range = None;
5404
5405                let bytes_after_last_selection =
5406                    buffer.bytes_in_range(last_selection.end..buffer.len());
5407                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5408                let query_matches = query
5409                    .stream_find_iter(bytes_after_last_selection)
5410                    .map(|result| (last_selection.end, result))
5411                    .chain(
5412                        query
5413                            .stream_find_iter(bytes_before_first_selection)
5414                            .map(|result| (0, result)),
5415                    );
5416                for (start_offset, query_match) in query_matches {
5417                    let query_match = query_match.unwrap(); // can only fail due to I/O
5418                    let offset_range =
5419                        start_offset + query_match.start()..start_offset + query_match.end();
5420                    let display_range = offset_range.start.to_display_point(&display_map)
5421                        ..offset_range.end.to_display_point(&display_map);
5422
5423                    if !select_next_state.wordwise
5424                        || (!movement::is_inside_word(&display_map, display_range.start)
5425                            && !movement::is_inside_word(&display_map, display_range.end))
5426                    {
5427                        next_selected_range = Some(offset_range);
5428                        break;
5429                    }
5430                }
5431
5432                if let Some(next_selected_range) = next_selected_range {
5433                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5434                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5435                        if action.replace_newest {
5436                            s.delete(s.newest_anchor().id);
5437                        }
5438                        s.insert_range(next_selected_range);
5439                    });
5440                } else {
5441                    select_next_state.done = true;
5442                }
5443            }
5444
5445            self.select_next_state = Some(select_next_state);
5446        } else if selections.len() == 1 {
5447            let selection = selections.last_mut().unwrap();
5448            if selection.start == selection.end {
5449                let word_range = movement::surrounding_word(
5450                    &display_map,
5451                    selection.start.to_display_point(&display_map),
5452                );
5453                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5454                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5455                selection.goal = SelectionGoal::None;
5456                selection.reversed = false;
5457
5458                let query = buffer
5459                    .text_for_range(selection.start..selection.end)
5460                    .collect::<String>();
5461                let select_state = SelectNextState {
5462                    query: AhoCorasick::new_auto_configured(&[query]),
5463                    wordwise: true,
5464                    done: false,
5465                };
5466                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5467                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5468                    s.select(selections);
5469                });
5470                self.select_next_state = Some(select_state);
5471            } else {
5472                let query = buffer
5473                    .text_for_range(selection.start..selection.end)
5474                    .collect::<String>();
5475                self.select_next_state = Some(SelectNextState {
5476                    query: AhoCorasick::new_auto_configured(&[query]),
5477                    wordwise: false,
5478                    done: false,
5479                });
5480                self.select_next(action, cx);
5481            }
5482        }
5483    }
5484
5485    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5486        self.push_to_selection_history();
5487        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5488        let buffer = &display_map.buffer_snapshot;
5489        let mut selections = self.selections.all::<usize>(cx);
5490        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5491            let query = &select_prev_state.query;
5492            if !select_prev_state.done {
5493                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5494                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5495                let mut next_selected_range = None;
5496                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5497                let bytes_before_last_selection =
5498                    buffer.reversed_bytes_in_range(0..last_selection.start);
5499                let bytes_after_first_selection =
5500                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5501                let query_matches = query
5502                    .stream_find_iter(bytes_before_last_selection)
5503                    .map(|result| (last_selection.start, result))
5504                    .chain(
5505                        query
5506                            .stream_find_iter(bytes_after_first_selection)
5507                            .map(|result| (buffer.len(), result)),
5508                    );
5509                for (end_offset, query_match) in query_matches {
5510                    let query_match = query_match.unwrap(); // can only fail due to I/O
5511                    let offset_range =
5512                        end_offset - query_match.end()..end_offset - query_match.start();
5513                    let display_range = offset_range.start.to_display_point(&display_map)
5514                        ..offset_range.end.to_display_point(&display_map);
5515
5516                    if !select_prev_state.wordwise
5517                        || (!movement::is_inside_word(&display_map, display_range.start)
5518                            && !movement::is_inside_word(&display_map, display_range.end))
5519                    {
5520                        next_selected_range = Some(offset_range);
5521                        break;
5522                    }
5523                }
5524
5525                if let Some(next_selected_range) = next_selected_range {
5526                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5527                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5528                        if action.replace_newest {
5529                            s.delete(s.newest_anchor().id);
5530                        }
5531                        s.insert_range(next_selected_range);
5532                    });
5533                } else {
5534                    select_prev_state.done = true;
5535                }
5536            }
5537
5538            self.select_prev_state = Some(select_prev_state);
5539        } else if selections.len() == 1 {
5540            let selection = selections.last_mut().unwrap();
5541            if selection.start == selection.end {
5542                let word_range = movement::surrounding_word(
5543                    &display_map,
5544                    selection.start.to_display_point(&display_map),
5545                );
5546                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5547                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5548                selection.goal = SelectionGoal::None;
5549                selection.reversed = false;
5550
5551                let query = buffer
5552                    .text_for_range(selection.start..selection.end)
5553                    .collect::<String>();
5554                let query = query.chars().rev().collect::<String>();
5555                let select_state = SelectNextState {
5556                    query: AhoCorasick::new_auto_configured(&[query]),
5557                    wordwise: true,
5558                    done: false,
5559                };
5560                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5561                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5562                    s.select(selections);
5563                });
5564                self.select_prev_state = Some(select_state);
5565            } else {
5566                let query = buffer
5567                    .text_for_range(selection.start..selection.end)
5568                    .collect::<String>();
5569                let query = query.chars().rev().collect::<String>();
5570                self.select_prev_state = Some(SelectNextState {
5571                    query: AhoCorasick::new_auto_configured(&[query]),
5572                    wordwise: false,
5573                    done: false,
5574                });
5575                self.select_previous(action, cx);
5576            }
5577        }
5578    }
5579
5580    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5581        self.transact(cx, |this, cx| {
5582            let mut selections = this.selections.all::<Point>(cx);
5583            let mut edits = Vec::new();
5584            let mut selection_edit_ranges = Vec::new();
5585            let mut last_toggled_row = None;
5586            let snapshot = this.buffer.read(cx).read(cx);
5587            let empty_str: Arc<str> = "".into();
5588            let mut suffixes_inserted = Vec::new();
5589
5590            fn comment_prefix_range(
5591                snapshot: &MultiBufferSnapshot,
5592                row: u32,
5593                comment_prefix: &str,
5594                comment_prefix_whitespace: &str,
5595            ) -> Range<Point> {
5596                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5597
5598                let mut line_bytes = snapshot
5599                    .bytes_in_range(start..snapshot.max_point())
5600                    .flatten()
5601                    .copied();
5602
5603                // If this line currently begins with the line comment prefix, then record
5604                // the range containing the prefix.
5605                if line_bytes
5606                    .by_ref()
5607                    .take(comment_prefix.len())
5608                    .eq(comment_prefix.bytes())
5609                {
5610                    // Include any whitespace that matches the comment prefix.
5611                    let matching_whitespace_len = line_bytes
5612                        .zip(comment_prefix_whitespace.bytes())
5613                        .take_while(|(a, b)| a == b)
5614                        .count() as u32;
5615                    let end = Point::new(
5616                        start.row,
5617                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5618                    );
5619                    start..end
5620                } else {
5621                    start..start
5622                }
5623            }
5624
5625            fn comment_suffix_range(
5626                snapshot: &MultiBufferSnapshot,
5627                row: u32,
5628                comment_suffix: &str,
5629                comment_suffix_has_leading_space: bool,
5630            ) -> Range<Point> {
5631                let end = Point::new(row, snapshot.line_len(row));
5632                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5633
5634                let mut line_end_bytes = snapshot
5635                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5636                    .flatten()
5637                    .copied();
5638
5639                let leading_space_len = if suffix_start_column > 0
5640                    && line_end_bytes.next() == Some(b' ')
5641                    && comment_suffix_has_leading_space
5642                {
5643                    1
5644                } else {
5645                    0
5646                };
5647
5648                // If this line currently begins with the line comment prefix, then record
5649                // the range containing the prefix.
5650                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5651                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5652                    start..end
5653                } else {
5654                    end..end
5655                }
5656            }
5657
5658            // TODO: Handle selections that cross excerpts
5659            // TODO: Handle selections that cross excerpts
5660            for selection in &mut selections {
5661                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5662                let language = if let Some(language) =
5663                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5664                {
5665                    language
5666                } else {
5667                    continue;
5668                };
5669
5670                selection_edit_ranges.clear();
5671
5672                // If multiple selections contain a given row, avoid processing that
5673                // row more than once.
5674                let mut start_row = selection.start.row;
5675                if last_toggled_row == Some(start_row) {
5676                    start_row += 1;
5677                }
5678                let end_row =
5679                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5680                        selection.end.row - 1
5681                    } else {
5682                        selection.end.row
5683                    };
5684                last_toggled_row = Some(end_row);
5685
5686                if start_row > end_row {
5687                    continue;
5688                }
5689
5690                // If the language has line comments, toggle those.
5691                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5692                    // Split the comment prefix's trailing whitespace into a separate string,
5693                    // as that portion won't be used for detecting if a line is a comment.
5694                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5695                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5696                    let mut all_selection_lines_are_comments = true;
5697
5698                    for row in start_row..=end_row {
5699                        if snapshot.is_line_blank(row) && start_row < end_row {
5700                            continue;
5701                        }
5702
5703                        let prefix_range = comment_prefix_range(
5704                            snapshot.deref(),
5705                            row,
5706                            comment_prefix,
5707                            comment_prefix_whitespace,
5708                        );
5709                        if prefix_range.is_empty() {
5710                            all_selection_lines_are_comments = false;
5711                        }
5712                        selection_edit_ranges.push(prefix_range);
5713                    }
5714
5715                    if all_selection_lines_are_comments {
5716                        edits.extend(
5717                            selection_edit_ranges
5718                                .iter()
5719                                .cloned()
5720                                .map(|range| (range, empty_str.clone())),
5721                        );
5722                    } else {
5723                        let min_column = selection_edit_ranges
5724                            .iter()
5725                            .map(|r| r.start.column)
5726                            .min()
5727                            .unwrap_or(0);
5728                        edits.extend(selection_edit_ranges.iter().map(|range| {
5729                            let position = Point::new(range.start.row, min_column);
5730                            (position..position, full_comment_prefix.clone())
5731                        }));
5732                    }
5733                } else if let Some((full_comment_prefix, comment_suffix)) =
5734                    language.block_comment_delimiters()
5735                {
5736                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5737                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5738                    let prefix_range = comment_prefix_range(
5739                        snapshot.deref(),
5740                        start_row,
5741                        comment_prefix,
5742                        comment_prefix_whitespace,
5743                    );
5744                    let suffix_range = comment_suffix_range(
5745                        snapshot.deref(),
5746                        end_row,
5747                        comment_suffix.trim_start_matches(' '),
5748                        comment_suffix.starts_with(' '),
5749                    );
5750
5751                    if prefix_range.is_empty() || suffix_range.is_empty() {
5752                        edits.push((
5753                            prefix_range.start..prefix_range.start,
5754                            full_comment_prefix.clone(),
5755                        ));
5756                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5757                        suffixes_inserted.push((end_row, comment_suffix.len()));
5758                    } else {
5759                        edits.push((prefix_range, empty_str.clone()));
5760                        edits.push((suffix_range, empty_str.clone()));
5761                    }
5762                } else {
5763                    continue;
5764                }
5765            }
5766
5767            drop(snapshot);
5768            this.buffer.update(cx, |buffer, cx| {
5769                buffer.edit(edits, None, cx);
5770            });
5771
5772            // Adjust selections so that they end before any comment suffixes that
5773            // were inserted.
5774            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5775            let mut selections = this.selections.all::<Point>(cx);
5776            let snapshot = this.buffer.read(cx).read(cx);
5777            for selection in &mut selections {
5778                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5779                    match row.cmp(&selection.end.row) {
5780                        Ordering::Less => {
5781                            suffixes_inserted.next();
5782                            continue;
5783                        }
5784                        Ordering::Greater => break,
5785                        Ordering::Equal => {
5786                            if selection.end.column == snapshot.line_len(row) {
5787                                if selection.is_empty() {
5788                                    selection.start.column -= suffix_len as u32;
5789                                }
5790                                selection.end.column -= suffix_len as u32;
5791                            }
5792                            break;
5793                        }
5794                    }
5795                }
5796            }
5797
5798            drop(snapshot);
5799            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5800
5801            let selections = this.selections.all::<Point>(cx);
5802            let selections_on_single_row = selections.windows(2).all(|selections| {
5803                selections[0].start.row == selections[1].start.row
5804                    && selections[0].end.row == selections[1].end.row
5805                    && selections[0].start.row == selections[0].end.row
5806            });
5807            let selections_selecting = selections
5808                .iter()
5809                .any(|selection| selection.start != selection.end);
5810            let advance_downwards = action.advance_downwards
5811                && selections_on_single_row
5812                && !selections_selecting
5813                && this.mode != EditorMode::SingleLine;
5814
5815            if advance_downwards {
5816                let snapshot = this.buffer.read(cx).snapshot(cx);
5817
5818                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5819                    s.move_cursors_with(|display_snapshot, display_point, _| {
5820                        let mut point = display_point.to_point(display_snapshot);
5821                        point.row += 1;
5822                        point = snapshot.clip_point(point, Bias::Left);
5823                        let display_point = point.to_display_point(display_snapshot);
5824                        (display_point, SelectionGoal::Column(display_point.column()))
5825                    })
5826                });
5827            }
5828        });
5829    }
5830
5831    pub fn select_larger_syntax_node(
5832        &mut self,
5833        _: &SelectLargerSyntaxNode,
5834        cx: &mut ViewContext<Self>,
5835    ) {
5836        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5837        let buffer = self.buffer.read(cx).snapshot(cx);
5838        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5839
5840        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5841        let mut selected_larger_node = false;
5842        let new_selections = old_selections
5843            .iter()
5844            .map(|selection| {
5845                let old_range = selection.start..selection.end;
5846                let mut new_range = old_range.clone();
5847                while let Some(containing_range) =
5848                    buffer.range_for_syntax_ancestor(new_range.clone())
5849                {
5850                    new_range = containing_range;
5851                    if !display_map.intersects_fold(new_range.start)
5852                        && !display_map.intersects_fold(new_range.end)
5853                    {
5854                        break;
5855                    }
5856                }
5857
5858                selected_larger_node |= new_range != old_range;
5859                Selection {
5860                    id: selection.id,
5861                    start: new_range.start,
5862                    end: new_range.end,
5863                    goal: SelectionGoal::None,
5864                    reversed: selection.reversed,
5865                }
5866            })
5867            .collect::<Vec<_>>();
5868
5869        if selected_larger_node {
5870            stack.push(old_selections);
5871            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5872                s.select(new_selections);
5873            });
5874        }
5875        self.select_larger_syntax_node_stack = stack;
5876    }
5877
5878    pub fn select_smaller_syntax_node(
5879        &mut self,
5880        _: &SelectSmallerSyntaxNode,
5881        cx: &mut ViewContext<Self>,
5882    ) {
5883        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5884        if let Some(selections) = stack.pop() {
5885            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5886                s.select(selections.to_vec());
5887            });
5888        }
5889        self.select_larger_syntax_node_stack = stack;
5890    }
5891
5892    pub fn move_to_enclosing_bracket(
5893        &mut self,
5894        _: &MoveToEnclosingBracket,
5895        cx: &mut ViewContext<Self>,
5896    ) {
5897        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5898            s.move_offsets_with(|snapshot, selection| {
5899                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5900                    return;
5901                };
5902
5903                let mut best_length = usize::MAX;
5904                let mut best_inside = false;
5905                let mut best_in_bracket_range = false;
5906                let mut best_destination = None;
5907                for (open, close) in enclosing_bracket_ranges {
5908                    let close = close.to_inclusive();
5909                    let length = close.end() - open.start;
5910                    let inside = selection.start >= open.end && selection.end <= *close.start();
5911                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5912
5913                    // If best is next to a bracket and current isn't, skip
5914                    if !in_bracket_range && best_in_bracket_range {
5915                        continue;
5916                    }
5917
5918                    // Prefer smaller lengths unless best is inside and current isn't
5919                    if length > best_length && (best_inside || !inside) {
5920                        continue;
5921                    }
5922
5923                    best_length = length;
5924                    best_inside = inside;
5925                    best_in_bracket_range = in_bracket_range;
5926                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5927                        if inside {
5928                            open.end
5929                        } else {
5930                            open.start
5931                        }
5932                    } else {
5933                        if inside {
5934                            *close.start()
5935                        } else {
5936                            *close.end()
5937                        }
5938                    });
5939                }
5940
5941                if let Some(destination) = best_destination {
5942                    selection.collapse_to(destination, SelectionGoal::None);
5943                }
5944            })
5945        });
5946    }
5947
5948    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5949        self.end_selection(cx);
5950        self.selection_history.mode = SelectionHistoryMode::Undoing;
5951        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5952            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5953            self.select_next_state = entry.select_next_state;
5954            self.select_prev_state = entry.select_prev_state;
5955            self.add_selections_state = entry.add_selections_state;
5956            self.request_autoscroll(Autoscroll::newest(), cx);
5957        }
5958        self.selection_history.mode = SelectionHistoryMode::Normal;
5959    }
5960
5961    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5962        self.end_selection(cx);
5963        self.selection_history.mode = SelectionHistoryMode::Redoing;
5964        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5965            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5966            self.select_next_state = entry.select_next_state;
5967            self.select_prev_state = entry.select_prev_state;
5968            self.add_selections_state = entry.add_selections_state;
5969            self.request_autoscroll(Autoscroll::newest(), cx);
5970        }
5971        self.selection_history.mode = SelectionHistoryMode::Normal;
5972    }
5973
5974    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5975        self.go_to_diagnostic_impl(Direction::Next, cx)
5976    }
5977
5978    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5979        self.go_to_diagnostic_impl(Direction::Prev, cx)
5980    }
5981
5982    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5983        let buffer = self.buffer.read(cx).snapshot(cx);
5984        let selection = self.selections.newest::<usize>(cx);
5985
5986        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5987        if direction == Direction::Next {
5988            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5989                let (group_id, jump_to) = popover.activation_info();
5990                if self.activate_diagnostics(group_id, cx) {
5991                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5992                        let mut new_selection = s.newest_anchor().clone();
5993                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5994                        s.select_anchors(vec![new_selection.clone()]);
5995                    });
5996                }
5997                return;
5998            }
5999        }
6000
6001        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6002            active_diagnostics
6003                .primary_range
6004                .to_offset(&buffer)
6005                .to_inclusive()
6006        });
6007        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6008            if active_primary_range.contains(&selection.head()) {
6009                *active_primary_range.end()
6010            } else {
6011                selection.head()
6012            }
6013        } else {
6014            selection.head()
6015        };
6016
6017        loop {
6018            let mut diagnostics = if direction == Direction::Prev {
6019                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6020            } else {
6021                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6022            };
6023            let group = diagnostics.find_map(|entry| {
6024                if entry.diagnostic.is_primary
6025                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6026                    && !entry.range.is_empty()
6027                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6028                {
6029                    Some((entry.range, entry.diagnostic.group_id))
6030                } else {
6031                    None
6032                }
6033            });
6034
6035            if let Some((primary_range, group_id)) = group {
6036                if self.activate_diagnostics(group_id, cx) {
6037                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6038                        s.select(vec![Selection {
6039                            id: selection.id,
6040                            start: primary_range.start,
6041                            end: primary_range.start,
6042                            reversed: false,
6043                            goal: SelectionGoal::None,
6044                        }]);
6045                    });
6046                }
6047                break;
6048            } else {
6049                // Cycle around to the start of the buffer, potentially moving back to the start of
6050                // the currently active diagnostic.
6051                active_primary_range.take();
6052                if direction == Direction::Prev {
6053                    if search_start == buffer.len() {
6054                        break;
6055                    } else {
6056                        search_start = buffer.len();
6057                    }
6058                } else if search_start == 0 {
6059                    break;
6060                } else {
6061                    search_start = 0;
6062                }
6063            }
6064        }
6065    }
6066
6067    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6068        let snapshot = self
6069            .display_map
6070            .update(cx, |display_map, cx| display_map.snapshot(cx));
6071        let selection = self.selections.newest::<Point>(cx);
6072
6073        if !self.seek_in_direction(
6074            &snapshot,
6075            selection.head(),
6076            false,
6077            snapshot
6078                .buffer_snapshot
6079                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6080            cx,
6081        ) {
6082            let wrapped_point = Point::zero();
6083            self.seek_in_direction(
6084                &snapshot,
6085                wrapped_point,
6086                true,
6087                snapshot
6088                    .buffer_snapshot
6089                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6090                cx,
6091            );
6092        }
6093    }
6094
6095    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6096        let snapshot = self
6097            .display_map
6098            .update(cx, |display_map, cx| display_map.snapshot(cx));
6099        let selection = self.selections.newest::<Point>(cx);
6100
6101        if !self.seek_in_direction(
6102            &snapshot,
6103            selection.head(),
6104            false,
6105            snapshot
6106                .buffer_snapshot
6107                .git_diff_hunks_in_range_rev(0..selection.head().row),
6108            cx,
6109        ) {
6110            let wrapped_point = snapshot.buffer_snapshot.max_point();
6111            self.seek_in_direction(
6112                &snapshot,
6113                wrapped_point,
6114                true,
6115                snapshot
6116                    .buffer_snapshot
6117                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6118                cx,
6119            );
6120        }
6121    }
6122
6123    fn seek_in_direction(
6124        &mut self,
6125        snapshot: &DisplaySnapshot,
6126        initial_point: Point,
6127        is_wrapped: bool,
6128        hunks: impl Iterator<Item = DiffHunk<u32>>,
6129        cx: &mut ViewContext<Editor>,
6130    ) -> bool {
6131        let display_point = initial_point.to_display_point(snapshot);
6132        let mut hunks = hunks
6133            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6134            .skip_while(|hunk| {
6135                if is_wrapped {
6136                    false
6137                } else {
6138                    hunk.contains_display_row(display_point.row())
6139                }
6140            })
6141            .dedup();
6142
6143        if let Some(hunk) = hunks.next() {
6144            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6145                let row = hunk.start_display_row();
6146                let point = DisplayPoint::new(row, 0);
6147                s.select_display_ranges([point..point]);
6148            });
6149
6150            true
6151        } else {
6152            false
6153        }
6154    }
6155
6156    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6157        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
6158    }
6159
6160    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6161        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
6162    }
6163
6164    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
6165        let Some(workspace) = self.workspace(cx) else { return };
6166        let buffer = self.buffer.read(cx);
6167        let head = self.selections.newest::<usize>(cx).head();
6168        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6169            text_anchor
6170        } else {
6171            return;
6172        };
6173
6174        let project = workspace.read(cx).project().clone();
6175        let definitions = project.update(cx, |project, cx| match kind {
6176            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6177            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6178        });
6179
6180        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6181            let definitions = definitions.await?;
6182            editor.update(&mut cx, |editor, cx| {
6183                editor.navigate_to_definitions(definitions, cx);
6184            })?;
6185            Ok::<(), anyhow::Error>(())
6186        })
6187        .detach_and_log_err(cx);
6188    }
6189
6190    pub fn navigate_to_definitions(
6191        &mut self,
6192        mut definitions: Vec<LocationLink>,
6193        cx: &mut ViewContext<Editor>,
6194    ) {
6195        let Some(workspace) = self.workspace(cx) else { return };
6196        let pane = workspace.read(cx).active_pane().clone();
6197        // If there is one definition, just open it directly
6198        if definitions.len() == 1 {
6199            let definition = definitions.pop().unwrap();
6200            let range = definition
6201                .target
6202                .range
6203                .to_offset(definition.target.buffer.read(cx));
6204
6205            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6206                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6207                    s.select_ranges([range]);
6208                });
6209            } else {
6210                cx.window_context().defer(move |cx| {
6211                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6212                        workspace.open_project_item(definition.target.buffer.clone(), cx)
6213                    });
6214                    target_editor.update(cx, |target_editor, cx| {
6215                        // When selecting a definition in a different buffer, disable the nav history
6216                        // to avoid creating a history entry at the previous cursor location.
6217                        pane.update(cx, |pane, _| pane.disable_history());
6218                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6219                            s.select_ranges([range]);
6220                        });
6221                        pane.update(cx, |pane, _| pane.enable_history());
6222                    });
6223                });
6224            }
6225        } else if !definitions.is_empty() {
6226            let replica_id = self.replica_id(cx);
6227            cx.window_context().defer(move |cx| {
6228                let title = definitions
6229                    .iter()
6230                    .find(|definition| definition.origin.is_some())
6231                    .and_then(|definition| {
6232                        definition.origin.as_ref().map(|origin| {
6233                            let buffer = origin.buffer.read(cx);
6234                            format!(
6235                                "Definitions for {}",
6236                                buffer
6237                                    .text_for_range(origin.range.clone())
6238                                    .collect::<String>()
6239                            )
6240                        })
6241                    })
6242                    .unwrap_or("Definitions".to_owned());
6243                let locations = definitions
6244                    .into_iter()
6245                    .map(|definition| definition.target)
6246                    .collect();
6247                workspace.update(cx, |workspace, cx| {
6248                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
6249                });
6250            });
6251        }
6252    }
6253
6254    pub fn find_all_references(
6255        workspace: &mut Workspace,
6256        _: &FindAllReferences,
6257        cx: &mut ViewContext<Workspace>,
6258    ) -> Option<Task<Result<()>>> {
6259        let active_item = workspace.active_item(cx)?;
6260        let editor_handle = active_item.act_as::<Self>(cx)?;
6261
6262        let editor = editor_handle.read(cx);
6263        let buffer = editor.buffer.read(cx);
6264        let head = editor.selections.newest::<usize>(cx).head();
6265        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6266        let replica_id = editor.replica_id(cx);
6267
6268        let project = workspace.project().clone();
6269        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6270        Some(cx.spawn_labeled(
6271            "Finding All References...",
6272            |workspace, mut cx| async move {
6273                let locations = references.await?;
6274                if locations.is_empty() {
6275                    return Ok(());
6276                }
6277
6278                workspace.update(&mut cx, |workspace, cx| {
6279                    let title = locations
6280                        .first()
6281                        .as_ref()
6282                        .map(|location| {
6283                            let buffer = location.buffer.read(cx);
6284                            format!(
6285                                "References to `{}`",
6286                                buffer
6287                                    .text_for_range(location.range.clone())
6288                                    .collect::<String>()
6289                            )
6290                        })
6291                        .unwrap();
6292                    Self::open_locations_in_multibuffer(
6293                        workspace, locations, replica_id, title, cx,
6294                    );
6295                })?;
6296
6297                Ok(())
6298            },
6299        ))
6300    }
6301
6302    /// Opens a multibuffer with the given project locations in it
6303    pub fn open_locations_in_multibuffer(
6304        workspace: &mut Workspace,
6305        mut locations: Vec<Location>,
6306        replica_id: ReplicaId,
6307        title: String,
6308        cx: &mut ViewContext<Workspace>,
6309    ) {
6310        // If there are multiple definitions, open them in a multibuffer
6311        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6312        let mut locations = locations.into_iter().peekable();
6313        let mut ranges_to_highlight = Vec::new();
6314
6315        let excerpt_buffer = cx.add_model(|cx| {
6316            let mut multibuffer = MultiBuffer::new(replica_id);
6317            while let Some(location) = locations.next() {
6318                let buffer = location.buffer.read(cx);
6319                let mut ranges_for_buffer = Vec::new();
6320                let range = location.range.to_offset(buffer);
6321                ranges_for_buffer.push(range.clone());
6322
6323                while let Some(next_location) = locations.peek() {
6324                    if next_location.buffer == location.buffer {
6325                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6326                        locations.next();
6327                    } else {
6328                        break;
6329                    }
6330                }
6331
6332                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6333                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6334                    location.buffer.clone(),
6335                    ranges_for_buffer,
6336                    1,
6337                    cx,
6338                ))
6339            }
6340
6341            multibuffer.with_title(title)
6342        });
6343
6344        let editor = cx.add_view(|cx| {
6345            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6346        });
6347        editor.update(cx, |editor, cx| {
6348            editor.highlight_background::<Self>(
6349                ranges_to_highlight,
6350                |theme| theme.editor.highlighted_line_background,
6351                cx,
6352            );
6353        });
6354        workspace.add_item(Box::new(editor), cx);
6355    }
6356
6357    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6358        use language::ToOffset as _;
6359
6360        let project = self.project.clone()?;
6361        let selection = self.selections.newest_anchor().clone();
6362        let (cursor_buffer, cursor_buffer_position) = self
6363            .buffer
6364            .read(cx)
6365            .text_anchor_for_position(selection.head(), cx)?;
6366        let (tail_buffer, _) = self
6367            .buffer
6368            .read(cx)
6369            .text_anchor_for_position(selection.tail(), cx)?;
6370        if tail_buffer != cursor_buffer {
6371            return None;
6372        }
6373
6374        let snapshot = cursor_buffer.read(cx).snapshot();
6375        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6376        let prepare_rename = project.update(cx, |project, cx| {
6377            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6378        });
6379
6380        Some(cx.spawn(|this, mut cx| async move {
6381            let rename_range = if let Some(range) = prepare_rename.await? {
6382                Some(range)
6383            } else {
6384                this.read_with(&cx, |this, cx| {
6385                    let buffer = this.buffer.read(cx).snapshot(cx);
6386                    let mut buffer_highlights = this
6387                        .document_highlights_for_position(selection.head(), &buffer)
6388                        .filter(|highlight| {
6389                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6390                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6391                        });
6392                    buffer_highlights
6393                        .next()
6394                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6395                })?
6396            };
6397            if let Some(rename_range) = rename_range {
6398                let rename_buffer_range = rename_range.to_offset(&snapshot);
6399                let cursor_offset_in_rename_range =
6400                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6401
6402                this.update(&mut cx, |this, cx| {
6403                    this.take_rename(false, cx);
6404                    let style = this.style(cx);
6405                    let buffer = this.buffer.read(cx).read(cx);
6406                    let cursor_offset = selection.head().to_offset(&buffer);
6407                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6408                    let rename_end = rename_start + rename_buffer_range.len();
6409                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6410                    let mut old_highlight_id = None;
6411                    let old_name: Arc<str> = buffer
6412                        .chunks(rename_start..rename_end, true)
6413                        .map(|chunk| {
6414                            if old_highlight_id.is_none() {
6415                                old_highlight_id = chunk.syntax_highlight_id;
6416                            }
6417                            chunk.text
6418                        })
6419                        .collect::<String>()
6420                        .into();
6421
6422                    drop(buffer);
6423
6424                    // Position the selection in the rename editor so that it matches the current selection.
6425                    this.show_local_selections = false;
6426                    let rename_editor = cx.add_view(|cx| {
6427                        let mut editor = Editor::single_line(None, cx);
6428                        if let Some(old_highlight_id) = old_highlight_id {
6429                            editor.override_text_style =
6430                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6431                        }
6432                        editor.buffer.update(cx, |buffer, cx| {
6433                            buffer.edit([(0..0, old_name.clone())], None, cx)
6434                        });
6435                        editor.select_all(&SelectAll, cx);
6436                        editor
6437                    });
6438
6439                    let ranges = this
6440                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6441                        .into_iter()
6442                        .flat_map(|(_, ranges)| ranges)
6443                        .chain(
6444                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6445                                .into_iter()
6446                                .flat_map(|(_, ranges)| ranges),
6447                        )
6448                        .collect();
6449
6450                    this.highlight_text::<Rename>(
6451                        ranges,
6452                        HighlightStyle {
6453                            fade_out: Some(style.rename_fade),
6454                            ..Default::default()
6455                        },
6456                        cx,
6457                    );
6458                    cx.focus(&rename_editor);
6459                    let block_id = this.insert_blocks(
6460                        [BlockProperties {
6461                            style: BlockStyle::Flex,
6462                            position: range.start.clone(),
6463                            height: 1,
6464                            render: Arc::new({
6465                                let editor = rename_editor.clone();
6466                                move |cx: &mut BlockContext| {
6467                                    ChildView::new(&editor, cx)
6468                                        .contained()
6469                                        .with_padding_left(cx.anchor_x)
6470                                        .into_any()
6471                                }
6472                            }),
6473                            disposition: BlockDisposition::Below,
6474                        }],
6475                        Some(Autoscroll::fit()),
6476                        cx,
6477                    )[0];
6478                    this.pending_rename = Some(RenameState {
6479                        range,
6480                        old_name,
6481                        editor: rename_editor,
6482                        block_id,
6483                    });
6484                })?;
6485            }
6486
6487            Ok(())
6488        }))
6489    }
6490
6491    pub fn confirm_rename(
6492        workspace: &mut Workspace,
6493        _: &ConfirmRename,
6494        cx: &mut ViewContext<Workspace>,
6495    ) -> Option<Task<Result<()>>> {
6496        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6497
6498        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6499            let rename = editor.take_rename(false, cx)?;
6500            let buffer = editor.buffer.read(cx);
6501            let (start_buffer, start) =
6502                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6503            let (end_buffer, end) =
6504                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6505            if start_buffer == end_buffer {
6506                let new_name = rename.editor.read(cx).text(cx);
6507                Some((start_buffer, start..end, rename.old_name, new_name))
6508            } else {
6509                None
6510            }
6511        })?;
6512
6513        let rename = workspace.project().clone().update(cx, |project, cx| {
6514            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6515        });
6516
6517        let editor = editor.downgrade();
6518        Some(cx.spawn(|workspace, mut cx| async move {
6519            let project_transaction = rename.await?;
6520            Self::open_project_transaction(
6521                &editor,
6522                workspace,
6523                project_transaction,
6524                format!("Rename: {}{}", old_name, new_name),
6525                cx.clone(),
6526            )
6527            .await?;
6528
6529            editor.update(&mut cx, |editor, cx| {
6530                editor.refresh_document_highlights(cx);
6531            })?;
6532            Ok(())
6533        }))
6534    }
6535
6536    fn take_rename(
6537        &mut self,
6538        moving_cursor: bool,
6539        cx: &mut ViewContext<Self>,
6540    ) -> Option<RenameState> {
6541        let rename = self.pending_rename.take()?;
6542        self.remove_blocks(
6543            [rename.block_id].into_iter().collect(),
6544            Some(Autoscroll::fit()),
6545            cx,
6546        );
6547        self.clear_text_highlights::<Rename>(cx);
6548        self.show_local_selections = true;
6549
6550        if moving_cursor {
6551            let rename_editor = rename.editor.read(cx);
6552            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6553
6554            // Update the selection to match the position of the selection inside
6555            // the rename editor.
6556            let snapshot = self.buffer.read(cx).read(cx);
6557            let rename_range = rename.range.to_offset(&snapshot);
6558            let cursor_in_editor = snapshot
6559                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6560                .min(rename_range.end);
6561            drop(snapshot);
6562
6563            self.change_selections(None, cx, |s| {
6564                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6565            });
6566        } else {
6567            self.refresh_document_highlights(cx);
6568        }
6569
6570        Some(rename)
6571    }
6572
6573    #[cfg(any(test, feature = "test-support"))]
6574    pub fn pending_rename(&self) -> Option<&RenameState> {
6575        self.pending_rename.as_ref()
6576    }
6577
6578    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6579        let project = match &self.project {
6580            Some(project) => project.clone(),
6581            None => return None,
6582        };
6583
6584        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6585    }
6586
6587    fn perform_format(
6588        &mut self,
6589        project: ModelHandle<Project>,
6590        trigger: FormatTrigger,
6591        cx: &mut ViewContext<Self>,
6592    ) -> Task<Result<()>> {
6593        let buffer = self.buffer().clone();
6594        let buffers = buffer.read(cx).all_buffers();
6595
6596        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6597        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6598
6599        cx.spawn(|_, mut cx| async move {
6600            let transaction = futures::select_biased! {
6601                _ = timeout => {
6602                    log::warn!("timed out waiting for formatting");
6603                    None
6604                }
6605                transaction = format.log_err().fuse() => transaction,
6606            };
6607
6608            buffer.update(&mut cx, |buffer, cx| {
6609                if let Some(transaction) = transaction {
6610                    if !buffer.is_singleton() {
6611                        buffer.push_transaction(&transaction.0, cx);
6612                    }
6613                }
6614
6615                cx.notify();
6616            });
6617
6618            Ok(())
6619        })
6620    }
6621
6622    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6623        if let Some(project) = self.project.clone() {
6624            self.buffer.update(cx, |multi_buffer, cx| {
6625                project.update(cx, |project, cx| {
6626                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6627                });
6628            })
6629        }
6630    }
6631
6632    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6633        cx.show_character_palette();
6634    }
6635
6636    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6637        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6638            let buffer = self.buffer.read(cx).snapshot(cx);
6639            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6640            let is_valid = buffer
6641                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6642                .any(|entry| {
6643                    entry.diagnostic.is_primary
6644                        && !entry.range.is_empty()
6645                        && entry.range.start == primary_range_start
6646                        && entry.diagnostic.message == active_diagnostics.primary_message
6647                });
6648
6649            if is_valid != active_diagnostics.is_valid {
6650                active_diagnostics.is_valid = is_valid;
6651                let mut new_styles = HashMap::default();
6652                for (block_id, diagnostic) in &active_diagnostics.blocks {
6653                    new_styles.insert(
6654                        *block_id,
6655                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6656                    );
6657                }
6658                self.display_map
6659                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6660            }
6661        }
6662    }
6663
6664    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6665        self.dismiss_diagnostics(cx);
6666        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6667            let buffer = self.buffer.read(cx).snapshot(cx);
6668
6669            let mut primary_range = None;
6670            let mut primary_message = None;
6671            let mut group_end = Point::zero();
6672            let diagnostic_group = buffer
6673                .diagnostic_group::<Point>(group_id)
6674                .map(|entry| {
6675                    if entry.range.end > group_end {
6676                        group_end = entry.range.end;
6677                    }
6678                    if entry.diagnostic.is_primary {
6679                        primary_range = Some(entry.range.clone());
6680                        primary_message = Some(entry.diagnostic.message.clone());
6681                    }
6682                    entry
6683                })
6684                .collect::<Vec<_>>();
6685            let primary_range = primary_range?;
6686            let primary_message = primary_message?;
6687            let primary_range =
6688                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6689
6690            let blocks = display_map
6691                .insert_blocks(
6692                    diagnostic_group.iter().map(|entry| {
6693                        let diagnostic = entry.diagnostic.clone();
6694                        let message_height = diagnostic.message.lines().count() as u8;
6695                        BlockProperties {
6696                            style: BlockStyle::Fixed,
6697                            position: buffer.anchor_after(entry.range.start),
6698                            height: message_height,
6699                            render: diagnostic_block_renderer(diagnostic, true),
6700                            disposition: BlockDisposition::Below,
6701                        }
6702                    }),
6703                    cx,
6704                )
6705                .into_iter()
6706                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6707                .collect();
6708
6709            Some(ActiveDiagnosticGroup {
6710                primary_range,
6711                primary_message,
6712                blocks,
6713                is_valid: true,
6714            })
6715        });
6716        self.active_diagnostics.is_some()
6717    }
6718
6719    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6720        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6721            self.display_map.update(cx, |display_map, cx| {
6722                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6723            });
6724            cx.notify();
6725        }
6726    }
6727
6728    pub fn set_selections_from_remote(
6729        &mut self,
6730        selections: Vec<Selection<Anchor>>,
6731        pending_selection: Option<Selection<Anchor>>,
6732        cx: &mut ViewContext<Self>,
6733    ) {
6734        let old_cursor_position = self.selections.newest_anchor().head();
6735        self.selections.change_with(cx, |s| {
6736            s.select_anchors(selections);
6737            if let Some(pending_selection) = pending_selection {
6738                s.set_pending(pending_selection, SelectMode::Character);
6739            } else {
6740                s.clear_pending();
6741            }
6742        });
6743        self.selections_did_change(false, &old_cursor_position, cx);
6744    }
6745
6746    fn push_to_selection_history(&mut self) {
6747        self.selection_history.push(SelectionHistoryEntry {
6748            selections: self.selections.disjoint_anchors(),
6749            select_next_state: self.select_next_state.clone(),
6750            select_prev_state: self.select_prev_state.clone(),
6751            add_selections_state: self.add_selections_state.clone(),
6752        });
6753    }
6754
6755    pub fn transact(
6756        &mut self,
6757        cx: &mut ViewContext<Self>,
6758        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6759    ) -> Option<TransactionId> {
6760        self.start_transaction_at(Instant::now(), cx);
6761        update(self, cx);
6762        self.end_transaction_at(Instant::now(), cx)
6763    }
6764
6765    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6766        self.end_selection(cx);
6767        if let Some(tx_id) = self
6768            .buffer
6769            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6770        {
6771            self.selection_history
6772                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6773        }
6774    }
6775
6776    fn end_transaction_at(
6777        &mut self,
6778        now: Instant,
6779        cx: &mut ViewContext<Self>,
6780    ) -> Option<TransactionId> {
6781        if let Some(tx_id) = self
6782            .buffer
6783            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6784        {
6785            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6786                *end_selections = Some(self.selections.disjoint_anchors());
6787            } else {
6788                error!("unexpectedly ended a transaction that wasn't started by this editor");
6789            }
6790
6791            cx.emit(Event::Edited);
6792            Some(tx_id)
6793        } else {
6794            None
6795        }
6796    }
6797
6798    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6799        let mut fold_ranges = Vec::new();
6800
6801        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6802
6803        let selections = self.selections.all::<Point>(cx);
6804        for selection in selections {
6805            let range = selection.range().sorted();
6806            let buffer_start_row = range.start.row;
6807
6808            for row in (0..=range.end.row).rev() {
6809                let fold_range = display_map.foldable_range(row);
6810
6811                if let Some(fold_range) = fold_range {
6812                    if fold_range.end.row >= buffer_start_row {
6813                        fold_ranges.push(fold_range);
6814                        if row <= range.start.row {
6815                            break;
6816                        }
6817                    }
6818                }
6819            }
6820        }
6821
6822        self.fold_ranges(fold_ranges, true, cx);
6823    }
6824
6825    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6826        let buffer_row = fold_at.buffer_row;
6827        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6828
6829        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6830            let autoscroll = self
6831                .selections
6832                .all::<Point>(cx)
6833                .iter()
6834                .any(|selection| fold_range.overlaps(&selection.range()));
6835
6836            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6837        }
6838    }
6839
6840    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6841        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6842        let buffer = &display_map.buffer_snapshot;
6843        let selections = self.selections.all::<Point>(cx);
6844        let ranges = selections
6845            .iter()
6846            .map(|s| {
6847                let range = s.display_range(&display_map).sorted();
6848                let mut start = range.start.to_point(&display_map);
6849                let mut end = range.end.to_point(&display_map);
6850                start.column = 0;
6851                end.column = buffer.line_len(end.row);
6852                start..end
6853            })
6854            .collect::<Vec<_>>();
6855
6856        self.unfold_ranges(ranges, true, true, cx);
6857    }
6858
6859    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6860        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6861
6862        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6863            ..Point::new(
6864                unfold_at.buffer_row,
6865                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6866            );
6867
6868        let autoscroll = self
6869            .selections
6870            .all::<Point>(cx)
6871            .iter()
6872            .any(|selection| selection.range().overlaps(&intersection_range));
6873
6874        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6875    }
6876
6877    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6878        let selections = self.selections.all::<Point>(cx);
6879        let ranges = selections.into_iter().map(|s| s.start..s.end);
6880        self.fold_ranges(ranges, true, cx);
6881    }
6882
6883    pub fn fold_ranges<T: ToOffset + Clone>(
6884        &mut self,
6885        ranges: impl IntoIterator<Item = Range<T>>,
6886        auto_scroll: bool,
6887        cx: &mut ViewContext<Self>,
6888    ) {
6889        let mut ranges = ranges.into_iter().peekable();
6890        if ranges.peek().is_some() {
6891            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6892
6893            if auto_scroll {
6894                self.request_autoscroll(Autoscroll::fit(), cx);
6895            }
6896
6897            cx.notify();
6898        }
6899    }
6900
6901    pub fn unfold_ranges<T: ToOffset + Clone>(
6902        &mut self,
6903        ranges: impl IntoIterator<Item = Range<T>>,
6904        inclusive: bool,
6905        auto_scroll: bool,
6906        cx: &mut ViewContext<Self>,
6907    ) {
6908        let mut ranges = ranges.into_iter().peekable();
6909        if ranges.peek().is_some() {
6910            self.display_map
6911                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6912            if auto_scroll {
6913                self.request_autoscroll(Autoscroll::fit(), cx);
6914            }
6915
6916            cx.notify();
6917        }
6918    }
6919
6920    pub fn gutter_hover(
6921        &mut self,
6922        GutterHover { hovered }: &GutterHover,
6923        cx: &mut ViewContext<Self>,
6924    ) {
6925        self.gutter_hovered = *hovered;
6926        cx.notify();
6927    }
6928
6929    pub fn insert_blocks(
6930        &mut self,
6931        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6932        autoscroll: Option<Autoscroll>,
6933        cx: &mut ViewContext<Self>,
6934    ) -> Vec<BlockId> {
6935        let blocks = self
6936            .display_map
6937            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6938        if let Some(autoscroll) = autoscroll {
6939            self.request_autoscroll(autoscroll, cx);
6940        }
6941        blocks
6942    }
6943
6944    pub fn replace_blocks(
6945        &mut self,
6946        blocks: HashMap<BlockId, RenderBlock>,
6947        autoscroll: Option<Autoscroll>,
6948        cx: &mut ViewContext<Self>,
6949    ) {
6950        self.display_map
6951            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6952        if let Some(autoscroll) = autoscroll {
6953            self.request_autoscroll(autoscroll, cx);
6954        }
6955    }
6956
6957    pub fn remove_blocks(
6958        &mut self,
6959        block_ids: HashSet<BlockId>,
6960        autoscroll: Option<Autoscroll>,
6961        cx: &mut ViewContext<Self>,
6962    ) {
6963        self.display_map.update(cx, |display_map, cx| {
6964            display_map.remove_blocks(block_ids, cx)
6965        });
6966        if let Some(autoscroll) = autoscroll {
6967            self.request_autoscroll(autoscroll, cx);
6968        }
6969    }
6970
6971    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6972        self.display_map
6973            .update(cx, |map, cx| map.snapshot(cx))
6974            .longest_row()
6975    }
6976
6977    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6978        self.display_map
6979            .update(cx, |map, cx| map.snapshot(cx))
6980            .max_point()
6981    }
6982
6983    pub fn text(&self, cx: &AppContext) -> String {
6984        self.buffer.read(cx).read(cx).text()
6985    }
6986
6987    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6988        self.transact(cx, |this, cx| {
6989            this.buffer
6990                .read(cx)
6991                .as_singleton()
6992                .expect("you can only call set_text on editors for singleton buffers")
6993                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6994        });
6995    }
6996
6997    pub fn display_text(&self, cx: &mut AppContext) -> String {
6998        self.display_map
6999            .update(cx, |map, cx| map.snapshot(cx))
7000            .text()
7001    }
7002
7003    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7004        let settings = self.buffer.read(cx).settings_at(0, cx);
7005        let mode = self
7006            .soft_wrap_mode_override
7007            .unwrap_or_else(|| settings.soft_wrap);
7008        match mode {
7009            language_settings::SoftWrap::None => SoftWrap::None,
7010            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7011            language_settings::SoftWrap::PreferredLineLength => {
7012                SoftWrap::Column(settings.preferred_line_length)
7013            }
7014        }
7015    }
7016
7017    pub fn set_soft_wrap_mode(
7018        &mut self,
7019        mode: language_settings::SoftWrap,
7020        cx: &mut ViewContext<Self>,
7021    ) {
7022        self.soft_wrap_mode_override = Some(mode);
7023        cx.notify();
7024    }
7025
7026    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7027        self.display_map
7028            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7029    }
7030
7031    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7032        if self.soft_wrap_mode_override.is_some() {
7033            self.soft_wrap_mode_override.take();
7034        } else {
7035            let soft_wrap = match self.soft_wrap_mode(cx) {
7036                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7037                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7038            };
7039            self.soft_wrap_mode_override = Some(soft_wrap);
7040        }
7041        cx.notify();
7042    }
7043
7044    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7045        self.show_gutter = show_gutter;
7046        cx.notify();
7047    }
7048
7049    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7050        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7051            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7052                cx.reveal_path(&file.abs_path(cx));
7053            }
7054        }
7055    }
7056
7057    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7058        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7059            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7060                if let Some(path) = file.abs_path(cx).to_str() {
7061                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7062                }
7063            }
7064        }
7065    }
7066
7067    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7068        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7069            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7070                if let Some(path) = file.path().to_str() {
7071                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7072                }
7073            }
7074        }
7075    }
7076
7077    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7078        self.highlighted_rows = rows;
7079    }
7080
7081    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7082        self.highlighted_rows.clone()
7083    }
7084
7085    pub fn highlight_background<T: 'static>(
7086        &mut self,
7087        ranges: Vec<Range<Anchor>>,
7088        color_fetcher: fn(&Theme) -> Color,
7089        cx: &mut ViewContext<Self>,
7090    ) {
7091        self.background_highlights
7092            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7093        cx.notify();
7094    }
7095
7096    #[allow(clippy::type_complexity)]
7097    pub fn clear_background_highlights<T: 'static>(
7098        &mut self,
7099        cx: &mut ViewContext<Self>,
7100    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7101        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7102        if highlights.is_some() {
7103            cx.notify();
7104        }
7105        highlights
7106    }
7107
7108    #[cfg(feature = "test-support")]
7109    pub fn all_background_highlights(
7110        &mut self,
7111        cx: &mut ViewContext<Self>,
7112    ) -> Vec<(Range<DisplayPoint>, Color)> {
7113        let snapshot = self.snapshot(cx);
7114        let buffer = &snapshot.buffer_snapshot;
7115        let start = buffer.anchor_before(0);
7116        let end = buffer.anchor_after(buffer.len());
7117        let theme = theme::current(cx);
7118        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7119    }
7120
7121    fn document_highlights_for_position<'a>(
7122        &'a self,
7123        position: Anchor,
7124        buffer: &'a MultiBufferSnapshot,
7125    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7126        let read_highlights = self
7127            .background_highlights
7128            .get(&TypeId::of::<DocumentHighlightRead>())
7129            .map(|h| &h.1);
7130        let write_highlights = self
7131            .background_highlights
7132            .get(&TypeId::of::<DocumentHighlightWrite>())
7133            .map(|h| &h.1);
7134        let left_position = position.bias_left(buffer);
7135        let right_position = position.bias_right(buffer);
7136        read_highlights
7137            .into_iter()
7138            .chain(write_highlights)
7139            .flat_map(move |ranges| {
7140                let start_ix = match ranges.binary_search_by(|probe| {
7141                    let cmp = probe.end.cmp(&left_position, buffer);
7142                    if cmp.is_ge() {
7143                        Ordering::Greater
7144                    } else {
7145                        Ordering::Less
7146                    }
7147                }) {
7148                    Ok(i) | Err(i) => i,
7149                };
7150
7151                let right_position = right_position.clone();
7152                ranges[start_ix..]
7153                    .iter()
7154                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7155            })
7156    }
7157
7158    pub fn background_highlights_in_range(
7159        &self,
7160        search_range: Range<Anchor>,
7161        display_snapshot: &DisplaySnapshot,
7162        theme: &Theme,
7163    ) -> Vec<(Range<DisplayPoint>, Color)> {
7164        let mut results = Vec::new();
7165        let buffer = &display_snapshot.buffer_snapshot;
7166        for (color_fetcher, ranges) in self.background_highlights.values() {
7167            let color = color_fetcher(theme);
7168            let start_ix = match ranges.binary_search_by(|probe| {
7169                let cmp = probe.end.cmp(&search_range.start, buffer);
7170                if cmp.is_gt() {
7171                    Ordering::Greater
7172                } else {
7173                    Ordering::Less
7174                }
7175            }) {
7176                Ok(i) | Err(i) => i,
7177            };
7178            for range in &ranges[start_ix..] {
7179                if range.start.cmp(&search_range.end, buffer).is_ge() {
7180                    break;
7181                }
7182                let start = range
7183                    .start
7184                    .to_point(buffer)
7185                    .to_display_point(display_snapshot);
7186                let end = range
7187                    .end
7188                    .to_point(buffer)
7189                    .to_display_point(display_snapshot);
7190                results.push((start..end, color))
7191            }
7192        }
7193        results
7194    }
7195
7196    pub fn highlight_text<T: 'static>(
7197        &mut self,
7198        ranges: Vec<Range<Anchor>>,
7199        style: HighlightStyle,
7200        cx: &mut ViewContext<Self>,
7201    ) {
7202        self.display_map.update(cx, |map, _| {
7203            map.highlight_text(TypeId::of::<T>(), ranges, style)
7204        });
7205        cx.notify();
7206    }
7207
7208    pub fn text_highlights<'a, T: 'static>(
7209        &'a self,
7210        cx: &'a AppContext,
7211    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7212        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7213    }
7214
7215    pub fn clear_text_highlights<T: 'static>(
7216        &mut self,
7217        cx: &mut ViewContext<Self>,
7218    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7219        let highlights = self
7220            .display_map
7221            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7222        if highlights.is_some() {
7223            cx.notify();
7224        }
7225        highlights
7226    }
7227
7228    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7229        self.blink_manager.read(cx).visible() && self.focused
7230    }
7231
7232    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7233        cx.notify();
7234    }
7235
7236    fn on_buffer_event(
7237        &mut self,
7238        _: ModelHandle<MultiBuffer>,
7239        event: &multi_buffer::Event,
7240        cx: &mut ViewContext<Self>,
7241    ) {
7242        match event {
7243            multi_buffer::Event::Edited => {
7244                self.refresh_active_diagnostics(cx);
7245                self.refresh_code_actions(cx);
7246                if self.has_active_copilot_suggestion(cx) {
7247                    self.update_visible_copilot_suggestion(cx);
7248                }
7249                cx.emit(Event::BufferEdited);
7250                self.refresh_inlays(InlayRefreshReason::ExcerptEdited, cx);
7251            }
7252            multi_buffer::Event::ExcerptsAdded {
7253                buffer,
7254                predecessor,
7255                excerpts,
7256            } => {
7257                cx.emit(Event::ExcerptsAdded {
7258                    buffer: buffer.clone(),
7259                    predecessor: *predecessor,
7260                    excerpts: excerpts.clone(),
7261                });
7262            }
7263            multi_buffer::Event::ExcerptsRemoved { ids } => {
7264                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() });
7265            }
7266            multi_buffer::Event::Reparsed => {
7267                cx.emit(Event::Reparsed);
7268            }
7269            multi_buffer::Event::DirtyChanged => {
7270                cx.emit(Event::DirtyChanged);
7271            }
7272            multi_buffer::Event::Saved => {
7273                cx.emit(Event::Saved);
7274            }
7275            multi_buffer::Event::FileHandleChanged => {
7276                cx.emit(Event::TitleChanged);
7277            }
7278            multi_buffer::Event::Reloaded => {
7279                cx.emit(Event::TitleChanged);
7280            }
7281            multi_buffer::Event::DiffBaseChanged => {
7282                cx.emit(Event::DiffBaseChanged);
7283            }
7284            multi_buffer::Event::Closed => {
7285                cx.emit(Event::Closed);
7286            }
7287            multi_buffer::Event::DiagnosticsUpdated => {
7288                self.refresh_active_diagnostics(cx);
7289            }
7290            _ => {}
7291        };
7292    }
7293
7294    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7295        cx.notify();
7296    }
7297
7298    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7299        self.refresh_copilot_suggestions(true, cx);
7300        self.refresh_inlays(
7301            InlayRefreshReason::SettingsChange(settings::get::<EditorSettings>(cx).inlay_hints),
7302            cx,
7303        );
7304    }
7305
7306    pub fn set_searchable(&mut self, searchable: bool) {
7307        self.searchable = searchable;
7308    }
7309
7310    pub fn searchable(&self) -> bool {
7311        self.searchable
7312    }
7313
7314    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7315        let active_item = workspace.active_item(cx);
7316        let editor_handle = if let Some(editor) = active_item
7317            .as_ref()
7318            .and_then(|item| item.act_as::<Self>(cx))
7319        {
7320            editor
7321        } else {
7322            cx.propagate_action();
7323            return;
7324        };
7325
7326        let editor = editor_handle.read(cx);
7327        let buffer = editor.buffer.read(cx);
7328        if buffer.is_singleton() {
7329            cx.propagate_action();
7330            return;
7331        }
7332
7333        let mut new_selections_by_buffer = HashMap::default();
7334        for selection in editor.selections.all::<usize>(cx) {
7335            for (buffer, mut range, _) in
7336                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7337            {
7338                if selection.reversed {
7339                    mem::swap(&mut range.start, &mut range.end);
7340                }
7341                new_selections_by_buffer
7342                    .entry(buffer)
7343                    .or_insert(Vec::new())
7344                    .push(range)
7345            }
7346        }
7347
7348        editor_handle.update(cx, |editor, cx| {
7349            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7350        });
7351        let pane = workspace.active_pane().clone();
7352        pane.update(cx, |pane, _| pane.disable_history());
7353
7354        // We defer the pane interaction because we ourselves are a workspace item
7355        // and activating a new item causes the pane to call a method on us reentrantly,
7356        // which panics if we're on the stack.
7357        cx.defer(move |workspace, cx| {
7358            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7359                let editor = workspace.open_project_item::<Self>(buffer, cx);
7360                editor.update(cx, |editor, cx| {
7361                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7362                        s.select_ranges(ranges);
7363                    });
7364                });
7365            }
7366
7367            pane.update(cx, |pane, _| pane.enable_history());
7368        });
7369    }
7370
7371    fn jump(
7372        workspace: &mut Workspace,
7373        path: ProjectPath,
7374        position: Point,
7375        anchor: language::Anchor,
7376        cx: &mut ViewContext<Workspace>,
7377    ) {
7378        let editor = workspace.open_path(path, None, true, cx);
7379        cx.spawn(|_, mut cx| async move {
7380            let editor = editor
7381                .await?
7382                .downcast::<Editor>()
7383                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7384                .downgrade();
7385            editor.update(&mut cx, |editor, cx| {
7386                let buffer = editor
7387                    .buffer()
7388                    .read(cx)
7389                    .as_singleton()
7390                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7391                let buffer = buffer.read(cx);
7392                let cursor = if buffer.can_resolve(&anchor) {
7393                    language::ToPoint::to_point(&anchor, buffer)
7394                } else {
7395                    buffer.clip_point(position, Bias::Left)
7396                };
7397
7398                let nav_history = editor.nav_history.take();
7399                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7400                    s.select_ranges([cursor..cursor]);
7401                });
7402                editor.nav_history = nav_history;
7403
7404                anyhow::Ok(())
7405            })??;
7406
7407            anyhow::Ok(())
7408        })
7409        .detach_and_log_err(cx);
7410    }
7411
7412    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7413        let snapshot = self.buffer.read(cx).read(cx);
7414        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7415        Some(
7416            ranges
7417                .iter()
7418                .map(move |range| {
7419                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7420                })
7421                .collect(),
7422        )
7423    }
7424
7425    fn selection_replacement_ranges(
7426        &self,
7427        range: Range<OffsetUtf16>,
7428        cx: &AppContext,
7429    ) -> Vec<Range<OffsetUtf16>> {
7430        let selections = self.selections.all::<OffsetUtf16>(cx);
7431        let newest_selection = selections
7432            .iter()
7433            .max_by_key(|selection| selection.id)
7434            .unwrap();
7435        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7436        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7437        let snapshot = self.buffer.read(cx).read(cx);
7438        selections
7439            .into_iter()
7440            .map(|mut selection| {
7441                selection.start.0 =
7442                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7443                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7444                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7445                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7446            })
7447            .collect()
7448    }
7449
7450    fn report_copilot_event(
7451        &self,
7452        suggestion_id: Option<String>,
7453        suggestion_accepted: bool,
7454        cx: &AppContext,
7455    ) {
7456        let Some(project) = &self.project else {
7457            return
7458        };
7459
7460        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7461        let file_extension = self
7462            .buffer
7463            .read(cx)
7464            .as_singleton()
7465            .and_then(|b| b.read(cx).file())
7466            .and_then(|file| Path::new(file.file_name(cx)).extension())
7467            .and_then(|e| e.to_str())
7468            .map(|a| a.to_string());
7469
7470        let telemetry = project.read(cx).client().telemetry().clone();
7471        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7472
7473        let event = ClickhouseEvent::Copilot {
7474            suggestion_id,
7475            suggestion_accepted,
7476            file_extension,
7477        };
7478        telemetry.report_clickhouse_event(event, telemetry_settings);
7479    }
7480
7481    fn report_editor_event(
7482        &self,
7483        name: &'static str,
7484        file_extension: Option<String>,
7485        cx: &AppContext,
7486    ) {
7487        let Some(project) = &self.project else {
7488            return
7489        };
7490
7491        // If None, we are in a file without an extension
7492        let file = self
7493            .buffer
7494            .read(cx)
7495            .as_singleton()
7496            .and_then(|b| b.read(cx).file());
7497        let file_extension = file_extension.or(file
7498            .as_ref()
7499            .and_then(|file| Path::new(file.file_name(cx)).extension())
7500            .and_then(|e| e.to_str())
7501            .map(|a| a.to_string()));
7502
7503        let vim_mode = cx
7504            .global::<SettingsStore>()
7505            .raw_user_settings()
7506            .get("vim_mode")
7507            == Some(&serde_json::Value::Bool(true));
7508        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7509        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7510        let copilot_enabled_for_language = self
7511            .buffer
7512            .read(cx)
7513            .settings_at(0, cx)
7514            .show_copilot_suggestions;
7515
7516        let telemetry = project.read(cx).client().telemetry().clone();
7517        let event = ClickhouseEvent::Editor {
7518            file_extension,
7519            vim_mode,
7520            operation: name,
7521            copilot_enabled,
7522            copilot_enabled_for_language,
7523        };
7524        telemetry.report_clickhouse_event(event, telemetry_settings)
7525    }
7526
7527    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7528    /// with each line being an array of {text, highlight} objects.
7529    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7530        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7531            return;
7532        };
7533
7534        #[derive(Serialize)]
7535        struct Chunk<'a> {
7536            text: String,
7537            highlight: Option<&'a str>,
7538        }
7539
7540        let snapshot = buffer.read(cx).snapshot();
7541        let range = self
7542            .selected_text_range(cx)
7543            .and_then(|selected_range| {
7544                if selected_range.is_empty() {
7545                    None
7546                } else {
7547                    Some(selected_range)
7548                }
7549            })
7550            .unwrap_or_else(|| 0..snapshot.len());
7551
7552        let chunks = snapshot.chunks(range, true);
7553        let mut lines = Vec::new();
7554        let mut line: VecDeque<Chunk> = VecDeque::new();
7555
7556        let theme = &theme::current(cx).editor.syntax;
7557
7558        for chunk in chunks {
7559            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7560            let mut chunk_lines = chunk.text.split("\n").peekable();
7561            while let Some(text) = chunk_lines.next() {
7562                let mut merged_with_last_token = false;
7563                if let Some(last_token) = line.back_mut() {
7564                    if last_token.highlight == highlight {
7565                        last_token.text.push_str(text);
7566                        merged_with_last_token = true;
7567                    }
7568                }
7569
7570                if !merged_with_last_token {
7571                    line.push_back(Chunk {
7572                        text: text.into(),
7573                        highlight,
7574                    });
7575                }
7576
7577                if chunk_lines.peek().is_some() {
7578                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7579                        line.pop_front();
7580                    }
7581                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7582                        line.pop_back();
7583                    }
7584
7585                    lines.push(mem::take(&mut line));
7586                }
7587            }
7588        }
7589
7590        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7591        cx.write_to_clipboard(ClipboardItem::new(lines));
7592    }
7593
7594    pub fn next_inlay_id(&mut self) -> InlayId {
7595        InlayId(post_inc(&mut self.next_inlay_id))
7596    }
7597}
7598
7599fn consume_contiguous_rows(
7600    contiguous_row_selections: &mut Vec<Selection<Point>>,
7601    selection: &Selection<Point>,
7602    display_map: &DisplaySnapshot,
7603    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7604) -> (u32, u32) {
7605    contiguous_row_selections.push(selection.clone());
7606    let start_row = selection.start.row;
7607    let mut end_row = ending_row(selection, display_map);
7608
7609    while let Some(next_selection) = selections.peek() {
7610        if next_selection.start.row <= end_row {
7611            end_row = ending_row(next_selection, display_map);
7612            contiguous_row_selections.push(selections.next().unwrap().clone());
7613        } else {
7614            break;
7615        }
7616    }
7617    (start_row, end_row)
7618}
7619
7620fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7621    if next_selection.end.column > 0 || next_selection.is_empty() {
7622        display_map.next_line_boundary(next_selection.end).0.row + 1
7623    } else {
7624        next_selection.end.row
7625    }
7626}
7627
7628impl EditorSnapshot {
7629    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7630        self.display_snapshot.buffer_snapshot.language_at(position)
7631    }
7632
7633    pub fn is_focused(&self) -> bool {
7634        self.is_focused
7635    }
7636
7637    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7638        self.placeholder_text.as_ref()
7639    }
7640
7641    pub fn scroll_position(&self) -> Vector2F {
7642        self.scroll_anchor.scroll_position(&self.display_snapshot)
7643    }
7644}
7645
7646impl Deref for EditorSnapshot {
7647    type Target = DisplaySnapshot;
7648
7649    fn deref(&self) -> &Self::Target {
7650        &self.display_snapshot
7651    }
7652}
7653
7654#[derive(Clone, Debug, PartialEq, Eq)]
7655pub enum Event {
7656    InputIgnored {
7657        text: Arc<str>,
7658    },
7659    ExcerptsAdded {
7660        buffer: ModelHandle<Buffer>,
7661        predecessor: ExcerptId,
7662        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7663    },
7664    ExcerptsRemoved {
7665        ids: Vec<ExcerptId>,
7666    },
7667    BufferEdited,
7668    Edited,
7669    Reparsed,
7670    Focused,
7671    Blurred,
7672    DirtyChanged,
7673    Saved,
7674    TitleChanged,
7675    DiffBaseChanged,
7676    SelectionsChanged {
7677        local: bool,
7678    },
7679    ScrollPositionChanged {
7680        local: bool,
7681        autoscroll: bool,
7682    },
7683    Closed,
7684}
7685
7686pub struct EditorFocused(pub ViewHandle<Editor>);
7687pub struct EditorBlurred(pub ViewHandle<Editor>);
7688pub struct EditorReleased(pub WeakViewHandle<Editor>);
7689
7690impl Entity for Editor {
7691    type Event = Event;
7692
7693    fn release(&mut self, cx: &mut AppContext) {
7694        cx.emit_global(EditorReleased(self.handle.clone()));
7695    }
7696}
7697
7698impl View for Editor {
7699    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7700        let style = self.style(cx);
7701        let font_changed = self.display_map.update(cx, |map, cx| {
7702            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7703            map.set_font(style.text.font_id, style.text.font_size, cx)
7704        });
7705
7706        if font_changed {
7707            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7708                hide_hover(editor, cx);
7709                hide_link_definition(editor, cx);
7710            });
7711        }
7712
7713        Stack::new()
7714            .with_child(EditorElement::new(style.clone()))
7715            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7716            .into_any()
7717    }
7718
7719    fn ui_name() -> &'static str {
7720        "Editor"
7721    }
7722
7723    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7724        if cx.is_self_focused() {
7725            let focused_event = EditorFocused(cx.handle());
7726            cx.emit(Event::Focused);
7727            cx.emit_global(focused_event);
7728        }
7729        if let Some(rename) = self.pending_rename.as_ref() {
7730            cx.focus(&rename.editor);
7731        } else {
7732            if !self.focused {
7733                self.blink_manager.update(cx, BlinkManager::enable);
7734            }
7735            self.focused = true;
7736            self.buffer.update(cx, |buffer, cx| {
7737                buffer.finalize_last_transaction(cx);
7738                if self.leader_replica_id.is_none() {
7739                    buffer.set_active_selections(
7740                        &self.selections.disjoint_anchors(),
7741                        self.selections.line_mode,
7742                        self.cursor_shape,
7743                        cx,
7744                    );
7745                }
7746            });
7747        }
7748    }
7749
7750    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7751        let blurred_event = EditorBlurred(cx.handle());
7752        cx.emit_global(blurred_event);
7753        self.focused = false;
7754        self.blink_manager.update(cx, BlinkManager::disable);
7755        self.buffer
7756            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7757        self.hide_context_menu(cx);
7758        hide_hover(self, cx);
7759        cx.emit(Event::Blurred);
7760        cx.notify();
7761    }
7762
7763    fn modifiers_changed(
7764        &mut self,
7765        event: &gpui::platform::ModifiersChangedEvent,
7766        cx: &mut ViewContext<Self>,
7767    ) -> bool {
7768        let pending_selection = self.has_pending_selection();
7769
7770        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7771            if event.cmd && !pending_selection {
7772                let snapshot = self.snapshot(cx);
7773                let kind = if event.shift {
7774                    LinkDefinitionKind::Type
7775                } else {
7776                    LinkDefinitionKind::Symbol
7777                };
7778
7779                show_link_definition(kind, self, point, snapshot, cx);
7780                return false;
7781            }
7782        }
7783
7784        {
7785            if self.link_go_to_definition_state.symbol_range.is_some()
7786                || !self.link_go_to_definition_state.definitions.is_empty()
7787            {
7788                self.link_go_to_definition_state.symbol_range.take();
7789                self.link_go_to_definition_state.definitions.clear();
7790                cx.notify();
7791            }
7792
7793            self.link_go_to_definition_state.task = None;
7794
7795            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7796        }
7797
7798        false
7799    }
7800
7801    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7802        Self::reset_to_default_keymap_context(keymap);
7803        let mode = match self.mode {
7804            EditorMode::SingleLine => "single_line",
7805            EditorMode::AutoHeight { .. } => "auto_height",
7806            EditorMode::Full => "full",
7807        };
7808        keymap.add_key("mode", mode);
7809        if self.pending_rename.is_some() {
7810            keymap.add_identifier("renaming");
7811        }
7812        match self.context_menu.as_ref() {
7813            Some(ContextMenu::Completions(_)) => {
7814                keymap.add_identifier("menu");
7815                keymap.add_identifier("showing_completions")
7816            }
7817            Some(ContextMenu::CodeActions(_)) => {
7818                keymap.add_identifier("menu");
7819                keymap.add_identifier("showing_code_actions")
7820            }
7821            None => {}
7822        }
7823        for layer in self.keymap_context_layers.values() {
7824            keymap.extend(layer);
7825        }
7826
7827        if let Some(extension) = self
7828            .buffer
7829            .read(cx)
7830            .as_singleton()
7831            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7832        {
7833            keymap.add_key("extension", extension.to_string());
7834        }
7835    }
7836
7837    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7838        Some(
7839            self.buffer
7840                .read(cx)
7841                .read(cx)
7842                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7843                .collect(),
7844        )
7845    }
7846
7847    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7848        // Prevent the IME menu from appearing when holding down an alphabetic key
7849        // while input is disabled.
7850        if !self.input_enabled {
7851            return None;
7852        }
7853
7854        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7855        Some(range.start.0..range.end.0)
7856    }
7857
7858    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7859        let snapshot = self.buffer.read(cx).read(cx);
7860        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7861        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7862    }
7863
7864    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7865        self.clear_text_highlights::<InputComposition>(cx);
7866        self.ime_transaction.take();
7867    }
7868
7869    fn replace_text_in_range(
7870        &mut self,
7871        range_utf16: Option<Range<usize>>,
7872        text: &str,
7873        cx: &mut ViewContext<Self>,
7874    ) {
7875        self.transact(cx, |this, cx| {
7876            if this.input_enabled {
7877                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7878                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7879                    Some(this.selection_replacement_ranges(range_utf16, cx))
7880                } else {
7881                    this.marked_text_ranges(cx)
7882                };
7883
7884                if let Some(new_selected_ranges) = new_selected_ranges {
7885                    this.change_selections(None, cx, |selections| {
7886                        selections.select_ranges(new_selected_ranges)
7887                    });
7888                }
7889            }
7890
7891            this.handle_input(text, cx);
7892        });
7893
7894        if !self.input_enabled {
7895            return;
7896        }
7897
7898        if let Some(transaction) = self.ime_transaction {
7899            self.buffer.update(cx, |buffer, cx| {
7900                buffer.group_until_transaction(transaction, cx);
7901            });
7902        }
7903
7904        self.unmark_text(cx);
7905    }
7906
7907    fn replace_and_mark_text_in_range(
7908        &mut self,
7909        range_utf16: Option<Range<usize>>,
7910        text: &str,
7911        new_selected_range_utf16: Option<Range<usize>>,
7912        cx: &mut ViewContext<Self>,
7913    ) {
7914        if !self.input_enabled {
7915            return;
7916        }
7917
7918        let transaction = self.transact(cx, |this, cx| {
7919            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7920                let snapshot = this.buffer.read(cx).read(cx);
7921                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7922                    for marked_range in &mut marked_ranges {
7923                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7924                        marked_range.start.0 += relative_range_utf16.start;
7925                        marked_range.start =
7926                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7927                        marked_range.end =
7928                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7929                    }
7930                }
7931                Some(marked_ranges)
7932            } else if let Some(range_utf16) = range_utf16 {
7933                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7934                Some(this.selection_replacement_ranges(range_utf16, cx))
7935            } else {
7936                None
7937            };
7938
7939            if let Some(ranges) = ranges_to_replace {
7940                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7941            }
7942
7943            let marked_ranges = {
7944                let snapshot = this.buffer.read(cx).read(cx);
7945                this.selections
7946                    .disjoint_anchors()
7947                    .iter()
7948                    .map(|selection| {
7949                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7950                    })
7951                    .collect::<Vec<_>>()
7952            };
7953
7954            if text.is_empty() {
7955                this.unmark_text(cx);
7956            } else {
7957                this.highlight_text::<InputComposition>(
7958                    marked_ranges.clone(),
7959                    this.style(cx).composition_mark,
7960                    cx,
7961                );
7962            }
7963
7964            this.handle_input(text, cx);
7965
7966            if let Some(new_selected_range) = new_selected_range_utf16 {
7967                let snapshot = this.buffer.read(cx).read(cx);
7968                let new_selected_ranges = marked_ranges
7969                    .into_iter()
7970                    .map(|marked_range| {
7971                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7972                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7973                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7974                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7975                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7976                    })
7977                    .collect::<Vec<_>>();
7978
7979                drop(snapshot);
7980                this.change_selections(None, cx, |selections| {
7981                    selections.select_ranges(new_selected_ranges)
7982                });
7983            }
7984        });
7985
7986        self.ime_transaction = self.ime_transaction.or(transaction);
7987        if let Some(transaction) = self.ime_transaction {
7988            self.buffer.update(cx, |buffer, cx| {
7989                buffer.group_until_transaction(transaction, cx);
7990            });
7991        }
7992
7993        if self.text_highlights::<InputComposition>(cx).is_none() {
7994            self.ime_transaction.take();
7995        }
7996    }
7997}
7998
7999fn build_style(
8000    settings: &ThemeSettings,
8001    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8002    override_text_style: Option<&OverrideTextStyle>,
8003    cx: &AppContext,
8004) -> EditorStyle {
8005    let font_cache = cx.font_cache();
8006
8007    let theme_id = settings.theme.meta.id;
8008    let mut theme = settings.theme.editor.clone();
8009    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8010        let field_editor_theme = get_field_editor_theme(&settings.theme);
8011        theme.text_color = field_editor_theme.text.color;
8012        theme.selection = field_editor_theme.selection;
8013        theme.background = field_editor_theme
8014            .container
8015            .background_color
8016            .unwrap_or_default();
8017        EditorStyle {
8018            text: field_editor_theme.text,
8019            placeholder_text: field_editor_theme.placeholder_text,
8020            theme,
8021            theme_id,
8022        }
8023    } else {
8024        let font_family_id = settings.buffer_font_family;
8025        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8026        let font_properties = Default::default();
8027        let font_id = font_cache
8028            .select_font(font_family_id, &font_properties)
8029            .unwrap();
8030        let font_size = settings.buffer_font_size(cx);
8031        EditorStyle {
8032            text: TextStyle {
8033                color: settings.theme.editor.text_color,
8034                font_family_name,
8035                font_family_id,
8036                font_id,
8037                font_size,
8038                font_properties,
8039                underline: Default::default(),
8040            },
8041            placeholder_text: None,
8042            theme,
8043            theme_id,
8044        }
8045    };
8046
8047    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8048        if let Some(highlighted) = style
8049            .text
8050            .clone()
8051            .highlight(highlight_style, font_cache)
8052            .log_err()
8053        {
8054            style.text = highlighted;
8055        }
8056    }
8057
8058    style
8059}
8060
8061trait SelectionExt {
8062    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8063    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8064    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8065    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8066        -> Range<u32>;
8067}
8068
8069impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8070    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8071        let start = self.start.to_point(buffer);
8072        let end = self.end.to_point(buffer);
8073        if self.reversed {
8074            end..start
8075        } else {
8076            start..end
8077        }
8078    }
8079
8080    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8081        let start = self.start.to_offset(buffer);
8082        let end = self.end.to_offset(buffer);
8083        if self.reversed {
8084            end..start
8085        } else {
8086            start..end
8087        }
8088    }
8089
8090    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8091        let start = self
8092            .start
8093            .to_point(&map.buffer_snapshot)
8094            .to_display_point(map);
8095        let end = self
8096            .end
8097            .to_point(&map.buffer_snapshot)
8098            .to_display_point(map);
8099        if self.reversed {
8100            end..start
8101        } else {
8102            start..end
8103        }
8104    }
8105
8106    fn spanned_rows(
8107        &self,
8108        include_end_if_at_line_start: bool,
8109        map: &DisplaySnapshot,
8110    ) -> Range<u32> {
8111        let start = self.start.to_point(&map.buffer_snapshot);
8112        let mut end = self.end.to_point(&map.buffer_snapshot);
8113        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8114            end.row -= 1;
8115        }
8116
8117        let buffer_start = map.prev_line_boundary(start).0;
8118        let buffer_end = map.next_line_boundary(end).0;
8119        buffer_start.row..buffer_end.row + 1
8120    }
8121}
8122
8123impl<T: InvalidationRegion> InvalidationStack<T> {
8124    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8125    where
8126        S: Clone + ToOffset,
8127    {
8128        while let Some(region) = self.last() {
8129            let all_selections_inside_invalidation_ranges =
8130                if selections.len() == region.ranges().len() {
8131                    selections
8132                        .iter()
8133                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8134                        .all(|(selection, invalidation_range)| {
8135                            let head = selection.head().to_offset(buffer);
8136                            invalidation_range.start <= head && invalidation_range.end >= head
8137                        })
8138                } else {
8139                    false
8140                };
8141
8142            if all_selections_inside_invalidation_ranges {
8143                break;
8144            } else {
8145                self.pop();
8146            }
8147        }
8148    }
8149}
8150
8151impl<T> Default for InvalidationStack<T> {
8152    fn default() -> Self {
8153        Self(Default::default())
8154    }
8155}
8156
8157impl<T> Deref for InvalidationStack<T> {
8158    type Target = Vec<T>;
8159
8160    fn deref(&self) -> &Self::Target {
8161        &self.0
8162    }
8163}
8164
8165impl<T> DerefMut for InvalidationStack<T> {
8166    fn deref_mut(&mut self) -> &mut Self::Target {
8167        &mut self.0
8168    }
8169}
8170
8171impl InvalidationRegion for SnippetState {
8172    fn ranges(&self) -> &[Range<Anchor>] {
8173        &self.ranges[self.active_index]
8174    }
8175}
8176
8177impl Deref for EditorStyle {
8178    type Target = theme::Editor;
8179
8180    fn deref(&self) -> &Self::Target {
8181        &self.theme
8182    }
8183}
8184
8185pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8186    let mut highlighted_lines = Vec::new();
8187
8188    for (index, line) in diagnostic.message.lines().enumerate() {
8189        let line = match &diagnostic.source {
8190            Some(source) if index == 0 => {
8191                let source_highlight = Vec::from_iter(0..source.len());
8192                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8193            }
8194
8195            _ => highlight_diagnostic_message(Vec::new(), line),
8196        };
8197        highlighted_lines.push(line);
8198    }
8199    let message = diagnostic.message;
8200    Arc::new(move |cx: &mut BlockContext| {
8201        let message = message.clone();
8202        let settings = settings::get::<ThemeSettings>(cx);
8203        let tooltip_style = settings.theme.tooltip.clone();
8204        let theme = &settings.theme.editor;
8205        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8206        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8207        let anchor_x = cx.anchor_x;
8208        enum BlockContextToolip {}
8209        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
8210            Flex::column()
8211                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8212                    Label::new(
8213                        line.clone(),
8214                        style.message.clone().with_font_size(font_size),
8215                    )
8216                    .with_highlights(highlights.clone())
8217                    .contained()
8218                    .with_margin_left(anchor_x)
8219                }))
8220                .aligned()
8221                .left()
8222                .into_any()
8223        })
8224        .with_cursor_style(CursorStyle::PointingHand)
8225        .on_click(MouseButton::Left, move |_, _, cx| {
8226            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8227        })
8228        // We really need to rethink this ID system...
8229        .with_tooltip::<BlockContextToolip>(
8230            cx.block_id,
8231            "Copy diagnostic message".to_string(),
8232            None,
8233            tooltip_style,
8234            cx,
8235        )
8236        .into_any()
8237    })
8238}
8239
8240pub fn highlight_diagnostic_message(
8241    initial_highlights: Vec<usize>,
8242    message: &str,
8243) -> (String, Vec<usize>) {
8244    let mut message_without_backticks = String::new();
8245    let mut prev_offset = 0;
8246    let mut inside_block = false;
8247    let mut highlights = initial_highlights;
8248    for (match_ix, (offset, _)) in message
8249        .match_indices('`')
8250        .chain([(message.len(), "")])
8251        .enumerate()
8252    {
8253        message_without_backticks.push_str(&message[prev_offset..offset]);
8254        if inside_block {
8255            highlights.extend(prev_offset - match_ix..offset - match_ix);
8256        }
8257
8258        inside_block = !inside_block;
8259        prev_offset = offset + 1;
8260    }
8261
8262    (message_without_backticks, highlights)
8263}
8264
8265pub fn diagnostic_style(
8266    severity: DiagnosticSeverity,
8267    valid: bool,
8268    theme: &theme::Editor,
8269) -> DiagnosticStyle {
8270    match (severity, valid) {
8271        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8272        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8273        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8274        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8275        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8276        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8277        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8278        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8279        _ => theme.invalid_hint_diagnostic.clone(),
8280    }
8281}
8282
8283pub fn combine_syntax_and_fuzzy_match_highlights(
8284    text: &str,
8285    default_style: HighlightStyle,
8286    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8287    match_indices: &[usize],
8288) -> Vec<(Range<usize>, HighlightStyle)> {
8289    let mut result = Vec::new();
8290    let mut match_indices = match_indices.iter().copied().peekable();
8291
8292    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8293    {
8294        syntax_highlight.weight = None;
8295
8296        // Add highlights for any fuzzy match characters before the next
8297        // syntax highlight range.
8298        while let Some(&match_index) = match_indices.peek() {
8299            if match_index >= range.start {
8300                break;
8301            }
8302            match_indices.next();
8303            let end_index = char_ix_after(match_index, text);
8304            let mut match_style = default_style;
8305            match_style.weight = Some(fonts::Weight::BOLD);
8306            result.push((match_index..end_index, match_style));
8307        }
8308
8309        if range.start == usize::MAX {
8310            break;
8311        }
8312
8313        // Add highlights for any fuzzy match characters within the
8314        // syntax highlight range.
8315        let mut offset = range.start;
8316        while let Some(&match_index) = match_indices.peek() {
8317            if match_index >= range.end {
8318                break;
8319            }
8320
8321            match_indices.next();
8322            if match_index > offset {
8323                result.push((offset..match_index, syntax_highlight));
8324            }
8325
8326            let mut end_index = char_ix_after(match_index, text);
8327            while let Some(&next_match_index) = match_indices.peek() {
8328                if next_match_index == end_index && next_match_index < range.end {
8329                    end_index = char_ix_after(next_match_index, text);
8330                    match_indices.next();
8331                } else {
8332                    break;
8333                }
8334            }
8335
8336            let mut match_style = syntax_highlight;
8337            match_style.weight = Some(fonts::Weight::BOLD);
8338            result.push((match_index..end_index, match_style));
8339            offset = end_index;
8340        }
8341
8342        if offset < range.end {
8343            result.push((offset..range.end, syntax_highlight));
8344        }
8345    }
8346
8347    fn char_ix_after(ix: usize, text: &str) -> usize {
8348        ix + text[ix..].chars().next().unwrap().len_utf8()
8349    }
8350
8351    result
8352}
8353
8354pub fn styled_runs_for_code_label<'a>(
8355    label: &'a CodeLabel,
8356    syntax_theme: &'a theme::SyntaxTheme,
8357) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8358    let fade_out = HighlightStyle {
8359        fade_out: Some(0.35),
8360        ..Default::default()
8361    };
8362
8363    let mut prev_end = label.filter_range.end;
8364    label
8365        .runs
8366        .iter()
8367        .enumerate()
8368        .flat_map(move |(ix, (range, highlight_id))| {
8369            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8370                style
8371            } else {
8372                return Default::default();
8373            };
8374            let mut muted_style = style;
8375            muted_style.highlight(fade_out);
8376
8377            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8378            if range.start >= label.filter_range.end {
8379                if range.start > prev_end {
8380                    runs.push((prev_end..range.start, fade_out));
8381                }
8382                runs.push((range.clone(), muted_style));
8383            } else if range.end <= label.filter_range.end {
8384                runs.push((range.clone(), style));
8385            } else {
8386                runs.push((range.start..label.filter_range.end, style));
8387                runs.push((label.filter_range.end..range.end, muted_style));
8388            }
8389            prev_end = cmp::max(prev_end, range.end);
8390
8391            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8392                runs.push((prev_end..label.text.len(), fade_out));
8393            }
8394
8395            runs
8396        })
8397}
8398
8399pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8400    let mut index = 0;
8401    let mut codepoints = text.char_indices().peekable();
8402
8403    std::iter::from_fn(move || {
8404        let start_index = index;
8405        while let Some((new_index, codepoint)) = codepoints.next() {
8406            index = new_index + codepoint.len_utf8();
8407            let current_upper = codepoint.is_uppercase();
8408            let next_upper = codepoints
8409                .peek()
8410                .map(|(_, c)| c.is_uppercase())
8411                .unwrap_or(false);
8412
8413            if !current_upper && next_upper {
8414                return Some(&text[start_index..index]);
8415            }
8416        }
8417
8418        index = text.len();
8419        if start_index < text.len() {
8420            return Some(&text[start_index..]);
8421        }
8422        None
8423    })
8424    .flat_map(|word| word.split_inclusive('_'))
8425}
8426
8427trait RangeToAnchorExt {
8428    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8429}
8430
8431impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8432    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8433        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8434    }
8435}