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