editor.rs

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