editor.rs

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