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