editor.rs

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