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