editor.rs

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