editor.rs

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