editor.rs

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