editor.rs

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