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