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