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