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