editor.rs

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