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