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