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