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