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| {
4235            lines.reverse();
4236        })
4237    }
4238
4239    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4240        self.manipulate_lines(cx, |lines| {
4241            lines.shuffle(&mut thread_rng());
4242        })
4243    }
4244
4245    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4246    where
4247        Fn: FnMut(&mut [&str]),
4248    {
4249        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4250        let buffer = self.buffer.read(cx).snapshot(cx);
4251
4252        let mut edits = Vec::new();
4253
4254        let selections = self.selections.all::<Point>(cx);
4255        let mut selections = selections.iter().peekable();
4256        let mut contiguous_row_selections = Vec::new();
4257        let mut new_selections = Vec::new();
4258
4259        while let Some(selection) = selections.next() {
4260            let (start_row, end_row) = consume_contiguous_rows(
4261                &mut contiguous_row_selections,
4262                selection,
4263                &display_map,
4264                &mut selections,
4265            );
4266
4267            let start_point = Point::new(start_row, 0);
4268            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4269            let text = buffer
4270                .text_for_range(start_point..end_point)
4271                .collect::<String>();
4272            let mut text = text.split("\n").collect_vec();
4273
4274            let text_len = text.len();
4275            callback(&mut text);
4276
4277            // This is a current limitation with selections.
4278            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4279            debug_assert!(
4280                text.len() == text_len,
4281                "callback should not change the number of lines"
4282            );
4283
4284            edits.push((start_point..end_point, text.join("\n")));
4285            let start_anchor = buffer.anchor_after(start_point);
4286            let end_anchor = buffer.anchor_before(end_point);
4287
4288            // Make selection and push
4289            new_selections.push(Selection {
4290                id: selection.id,
4291                start: start_anchor.to_offset(&buffer),
4292                end: end_anchor.to_offset(&buffer),
4293                goal: SelectionGoal::None,
4294                reversed: selection.reversed,
4295            });
4296        }
4297
4298        self.transact(cx, |this, cx| {
4299            this.buffer.update(cx, |buffer, cx| {
4300                buffer.edit(edits, None, cx);
4301            });
4302
4303            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4304                s.select(new_selections);
4305            });
4306
4307            this.request_autoscroll(Autoscroll::fit(), cx);
4308        });
4309    }
4310
4311    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4312        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4313        let buffer = &display_map.buffer_snapshot;
4314        let selections = self.selections.all::<Point>(cx);
4315
4316        let mut edits = Vec::new();
4317        let mut selections_iter = selections.iter().peekable();
4318        while let Some(selection) = selections_iter.next() {
4319            // Avoid duplicating the same lines twice.
4320            let mut rows = selection.spanned_rows(false, &display_map);
4321
4322            while let Some(next_selection) = selections_iter.peek() {
4323                let next_rows = next_selection.spanned_rows(false, &display_map);
4324                if next_rows.start < rows.end {
4325                    rows.end = next_rows.end;
4326                    selections_iter.next().unwrap();
4327                } else {
4328                    break;
4329                }
4330            }
4331
4332            // Copy the text from the selected row region and splice it at the start of the region.
4333            let start = Point::new(rows.start, 0);
4334            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4335            let text = buffer
4336                .text_for_range(start..end)
4337                .chain(Some("\n"))
4338                .collect::<String>();
4339            edits.push((start..start, text));
4340        }
4341
4342        self.transact(cx, |this, cx| {
4343            this.buffer.update(cx, |buffer, cx| {
4344                buffer.edit(edits, None, cx);
4345            });
4346
4347            this.request_autoscroll(Autoscroll::fit(), cx);
4348        });
4349    }
4350
4351    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4352        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4353        let buffer = self.buffer.read(cx).snapshot(cx);
4354
4355        let mut edits = Vec::new();
4356        let mut unfold_ranges = Vec::new();
4357        let mut refold_ranges = Vec::new();
4358
4359        let selections = self.selections.all::<Point>(cx);
4360        let mut selections = selections.iter().peekable();
4361        let mut contiguous_row_selections = Vec::new();
4362        let mut new_selections = Vec::new();
4363
4364        while let Some(selection) = selections.next() {
4365            // Find all the selections that span a contiguous row range
4366            let (start_row, end_row) = consume_contiguous_rows(
4367                &mut contiguous_row_selections,
4368                selection,
4369                &display_map,
4370                &mut selections,
4371            );
4372
4373            // Move the text spanned by the row range to be before the line preceding the row range
4374            if start_row > 0 {
4375                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4376                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4377                let insertion_point = display_map
4378                    .prev_line_boundary(Point::new(start_row - 1, 0))
4379                    .0;
4380
4381                // Don't move lines across excerpts
4382                if buffer
4383                    .excerpt_boundaries_in_range((
4384                        Bound::Excluded(insertion_point),
4385                        Bound::Included(range_to_move.end),
4386                    ))
4387                    .next()
4388                    .is_none()
4389                {
4390                    let text = buffer
4391                        .text_for_range(range_to_move.clone())
4392                        .flat_map(|s| s.chars())
4393                        .skip(1)
4394                        .chain(['\n'])
4395                        .collect::<String>();
4396
4397                    edits.push((
4398                        buffer.anchor_after(range_to_move.start)
4399                            ..buffer.anchor_before(range_to_move.end),
4400                        String::new(),
4401                    ));
4402                    let insertion_anchor = buffer.anchor_after(insertion_point);
4403                    edits.push((insertion_anchor..insertion_anchor, text));
4404
4405                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4406
4407                    // Move selections up
4408                    new_selections.extend(contiguous_row_selections.drain(..).map(
4409                        |mut selection| {
4410                            selection.start.row -= row_delta;
4411                            selection.end.row -= row_delta;
4412                            selection
4413                        },
4414                    ));
4415
4416                    // Move folds up
4417                    unfold_ranges.push(range_to_move.clone());
4418                    for fold in display_map.folds_in_range(
4419                        buffer.anchor_before(range_to_move.start)
4420                            ..buffer.anchor_after(range_to_move.end),
4421                    ) {
4422                        let mut start = fold.start.to_point(&buffer);
4423                        let mut end = fold.end.to_point(&buffer);
4424                        start.row -= row_delta;
4425                        end.row -= row_delta;
4426                        refold_ranges.push(start..end);
4427                    }
4428                }
4429            }
4430
4431            // If we didn't move line(s), preserve the existing selections
4432            new_selections.append(&mut contiguous_row_selections);
4433        }
4434
4435        self.transact(cx, |this, cx| {
4436            this.unfold_ranges(unfold_ranges, true, true, cx);
4437            this.buffer.update(cx, |buffer, cx| {
4438                for (range, text) in edits {
4439                    buffer.edit([(range, text)], None, cx);
4440                }
4441            });
4442            this.fold_ranges(refold_ranges, true, cx);
4443            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4444                s.select(new_selections);
4445            })
4446        });
4447    }
4448
4449    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4450        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4451        let buffer = self.buffer.read(cx).snapshot(cx);
4452
4453        let mut edits = Vec::new();
4454        let mut unfold_ranges = Vec::new();
4455        let mut refold_ranges = Vec::new();
4456
4457        let selections = self.selections.all::<Point>(cx);
4458        let mut selections = selections.iter().peekable();
4459        let mut contiguous_row_selections = Vec::new();
4460        let mut new_selections = Vec::new();
4461
4462        while let Some(selection) = selections.next() {
4463            // Find all the selections that span a contiguous row range
4464            let (start_row, end_row) = consume_contiguous_rows(
4465                &mut contiguous_row_selections,
4466                selection,
4467                &display_map,
4468                &mut selections,
4469            );
4470
4471            // Move the text spanned by the row range to be after the last line of the row range
4472            if end_row <= buffer.max_point().row {
4473                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4474                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4475
4476                // Don't move lines across excerpt boundaries
4477                if buffer
4478                    .excerpt_boundaries_in_range((
4479                        Bound::Excluded(range_to_move.start),
4480                        Bound::Included(insertion_point),
4481                    ))
4482                    .next()
4483                    .is_none()
4484                {
4485                    let mut text = String::from("\n");
4486                    text.extend(buffer.text_for_range(range_to_move.clone()));
4487                    text.pop(); // Drop trailing newline
4488                    edits.push((
4489                        buffer.anchor_after(range_to_move.start)
4490                            ..buffer.anchor_before(range_to_move.end),
4491                        String::new(),
4492                    ));
4493                    let insertion_anchor = buffer.anchor_after(insertion_point);
4494                    edits.push((insertion_anchor..insertion_anchor, text));
4495
4496                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4497
4498                    // Move selections down
4499                    new_selections.extend(contiguous_row_selections.drain(..).map(
4500                        |mut selection| {
4501                            selection.start.row += row_delta;
4502                            selection.end.row += row_delta;
4503                            selection
4504                        },
4505                    ));
4506
4507                    // Move folds down
4508                    unfold_ranges.push(range_to_move.clone());
4509                    for fold in display_map.folds_in_range(
4510                        buffer.anchor_before(range_to_move.start)
4511                            ..buffer.anchor_after(range_to_move.end),
4512                    ) {
4513                        let mut start = fold.start.to_point(&buffer);
4514                        let mut end = fold.end.to_point(&buffer);
4515                        start.row += row_delta;
4516                        end.row += row_delta;
4517                        refold_ranges.push(start..end);
4518                    }
4519                }
4520            }
4521
4522            // If we didn't move line(s), preserve the existing selections
4523            new_selections.append(&mut contiguous_row_selections);
4524        }
4525
4526        self.transact(cx, |this, cx| {
4527            this.unfold_ranges(unfold_ranges, true, true, cx);
4528            this.buffer.update(cx, |buffer, cx| {
4529                for (range, text) in edits {
4530                    buffer.edit([(range, text)], None, cx);
4531                }
4532            });
4533            this.fold_ranges(refold_ranges, true, cx);
4534            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4535        });
4536    }
4537
4538    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4539        self.transact(cx, |this, cx| {
4540            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4541                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4542                let line_mode = s.line_mode;
4543                s.move_with(|display_map, selection| {
4544                    if !selection.is_empty() || line_mode {
4545                        return;
4546                    }
4547
4548                    let mut head = selection.head();
4549                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4550                    if head.column() == display_map.line_len(head.row()) {
4551                        transpose_offset = display_map
4552                            .buffer_snapshot
4553                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4554                    }
4555
4556                    if transpose_offset == 0 {
4557                        return;
4558                    }
4559
4560                    *head.column_mut() += 1;
4561                    head = display_map.clip_point(head, Bias::Right);
4562                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4563
4564                    let transpose_start = display_map
4565                        .buffer_snapshot
4566                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4567                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4568                        let transpose_end = display_map
4569                            .buffer_snapshot
4570                            .clip_offset(transpose_offset + 1, Bias::Right);
4571                        if let Some(ch) =
4572                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4573                        {
4574                            edits.push((transpose_start..transpose_offset, String::new()));
4575                            edits.push((transpose_end..transpose_end, ch.to_string()));
4576                        }
4577                    }
4578                });
4579                edits
4580            });
4581            this.buffer
4582                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4583            let selections = this.selections.all::<usize>(cx);
4584            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4585                s.select(selections);
4586            });
4587        });
4588    }
4589
4590    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4591        let mut text = String::new();
4592        let buffer = self.buffer.read(cx).snapshot(cx);
4593        let mut selections = self.selections.all::<Point>(cx);
4594        let mut clipboard_selections = Vec::with_capacity(selections.len());
4595        {
4596            let max_point = buffer.max_point();
4597            for selection in &mut selections {
4598                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4599                if is_entire_line {
4600                    selection.start = Point::new(selection.start.row, 0);
4601                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4602                    selection.goal = SelectionGoal::None;
4603                }
4604                let mut len = 0;
4605                for chunk in buffer.text_for_range(selection.start..selection.end) {
4606                    text.push_str(chunk);
4607                    len += chunk.len();
4608                }
4609                clipboard_selections.push(ClipboardSelection {
4610                    len,
4611                    is_entire_line,
4612                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4613                });
4614            }
4615        }
4616
4617        self.transact(cx, |this, cx| {
4618            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4619                s.select(selections);
4620            });
4621            this.insert("", cx);
4622            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4623        });
4624    }
4625
4626    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4627        let selections = self.selections.all::<Point>(cx);
4628        let buffer = self.buffer.read(cx).read(cx);
4629        let mut text = String::new();
4630
4631        let mut clipboard_selections = Vec::with_capacity(selections.len());
4632        {
4633            let max_point = buffer.max_point();
4634            for selection in selections.iter() {
4635                let mut start = selection.start;
4636                let mut end = selection.end;
4637                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4638                if is_entire_line {
4639                    start = Point::new(start.row, 0);
4640                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4641                }
4642                let mut len = 0;
4643                for chunk in buffer.text_for_range(start..end) {
4644                    text.push_str(chunk);
4645                    len += chunk.len();
4646                }
4647                clipboard_selections.push(ClipboardSelection {
4648                    len,
4649                    is_entire_line,
4650                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4651                });
4652            }
4653        }
4654
4655        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4656    }
4657
4658    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4659        self.transact(cx, |this, cx| {
4660            if let Some(item) = cx.read_from_clipboard() {
4661                let mut clipboard_text = Cow::Borrowed(item.text());
4662                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4663                    let old_selections = this.selections.all::<usize>(cx);
4664                    let all_selections_were_entire_line =
4665                        clipboard_selections.iter().all(|s| s.is_entire_line);
4666                    let first_selection_indent_column =
4667                        clipboard_selections.first().map(|s| s.first_line_indent);
4668                    if clipboard_selections.len() != old_selections.len() {
4669                        let mut newline_separated_text = String::new();
4670                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4671                        let mut ix = 0;
4672                        while let Some(clipboard_selection) = clipboard_selections.next() {
4673                            newline_separated_text
4674                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4675                            ix += clipboard_selection.len;
4676                            if clipboard_selections.peek().is_some() {
4677                                newline_separated_text.push('\n');
4678                            }
4679                        }
4680                        clipboard_text = Cow::Owned(newline_separated_text);
4681                    }
4682
4683                    this.buffer.update(cx, |buffer, cx| {
4684                        let snapshot = buffer.read(cx);
4685                        let mut start_offset = 0;
4686                        let mut edits = Vec::new();
4687                        let mut original_indent_columns = Vec::new();
4688                        let line_mode = this.selections.line_mode;
4689                        for (ix, selection) in old_selections.iter().enumerate() {
4690                            let to_insert;
4691                            let entire_line;
4692                            let original_indent_column;
4693                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4694                                let end_offset = start_offset + clipboard_selection.len;
4695                                to_insert = &clipboard_text[start_offset..end_offset];
4696                                entire_line = clipboard_selection.is_entire_line;
4697                                start_offset = end_offset;
4698                                original_indent_column =
4699                                    Some(clipboard_selection.first_line_indent);
4700                            } else {
4701                                to_insert = clipboard_text.as_str();
4702                                entire_line = all_selections_were_entire_line;
4703                                original_indent_column = first_selection_indent_column
4704                            }
4705
4706                            // If the corresponding selection was empty when this slice of the
4707                            // clipboard text was written, then the entire line containing the
4708                            // selection was copied. If this selection is also currently empty,
4709                            // then paste the line before the current line of the buffer.
4710                            let range = if selection.is_empty() && !line_mode && entire_line {
4711                                let column = selection.start.to_point(&snapshot).column as usize;
4712                                let line_start = selection.start - column;
4713                                line_start..line_start
4714                            } else {
4715                                selection.range()
4716                            };
4717
4718                            edits.push((range, to_insert));
4719                            original_indent_columns.extend(original_indent_column);
4720                        }
4721                        drop(snapshot);
4722
4723                        buffer.edit(
4724                            edits,
4725                            Some(AutoindentMode::Block {
4726                                original_indent_columns,
4727                            }),
4728                            cx,
4729                        );
4730                    });
4731
4732                    let selections = this.selections.all::<usize>(cx);
4733                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4734                } else {
4735                    this.insert(&clipboard_text, cx);
4736                }
4737            }
4738        });
4739    }
4740
4741    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4742        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4743            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4744                self.change_selections(None, cx, |s| {
4745                    s.select_anchors(selections.to_vec());
4746                });
4747            }
4748            self.request_autoscroll(Autoscroll::fit(), cx);
4749            self.unmark_text(cx);
4750            self.refresh_copilot_suggestions(true, cx);
4751            cx.emit(Event::Edited);
4752        }
4753    }
4754
4755    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4756        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4757            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4758            {
4759                self.change_selections(None, cx, |s| {
4760                    s.select_anchors(selections.to_vec());
4761                });
4762            }
4763            self.request_autoscroll(Autoscroll::fit(), cx);
4764            self.unmark_text(cx);
4765            self.refresh_copilot_suggestions(true, cx);
4766            cx.emit(Event::Edited);
4767        }
4768    }
4769
4770    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4771        self.buffer
4772            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4773    }
4774
4775    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4776        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4777            let line_mode = s.line_mode;
4778            s.move_with(|map, selection| {
4779                let cursor = if selection.is_empty() && !line_mode {
4780                    movement::left(map, selection.start)
4781                } else {
4782                    selection.start
4783                };
4784                selection.collapse_to(cursor, SelectionGoal::None);
4785            });
4786        })
4787    }
4788
4789    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4790        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4791            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4792        })
4793    }
4794
4795    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4796        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4797            let line_mode = s.line_mode;
4798            s.move_with(|map, selection| {
4799                let cursor = if selection.is_empty() && !line_mode {
4800                    movement::right(map, selection.end)
4801                } else {
4802                    selection.end
4803                };
4804                selection.collapse_to(cursor, SelectionGoal::None)
4805            });
4806        })
4807    }
4808
4809    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4810        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4811            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4812        })
4813    }
4814
4815    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4816        if self.take_rename(true, cx).is_some() {
4817            return;
4818        }
4819
4820        if let Some(context_menu) = self.context_menu.as_mut() {
4821            if context_menu.select_prev(cx) {
4822                return;
4823            }
4824        }
4825
4826        if matches!(self.mode, EditorMode::SingleLine) {
4827            cx.propagate_action();
4828            return;
4829        }
4830
4831        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4832            let line_mode = s.line_mode;
4833            s.move_with(|map, selection| {
4834                if !selection.is_empty() && !line_mode {
4835                    selection.goal = SelectionGoal::None;
4836                }
4837                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4838                selection.collapse_to(cursor, goal);
4839            });
4840        })
4841    }
4842
4843    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4844        if self.take_rename(true, cx).is_some() {
4845            return;
4846        }
4847
4848        if self
4849            .context_menu
4850            .as_mut()
4851            .map(|menu| menu.select_first(cx))
4852            .unwrap_or(false)
4853        {
4854            return;
4855        }
4856
4857        if matches!(self.mode, EditorMode::SingleLine) {
4858            cx.propagate_action();
4859            return;
4860        }
4861
4862        let row_count = if let Some(row_count) = self.visible_line_count() {
4863            row_count as u32 - 1
4864        } else {
4865            return;
4866        };
4867
4868        let autoscroll = if action.center_cursor {
4869            Autoscroll::center()
4870        } else {
4871            Autoscroll::fit()
4872        };
4873
4874        self.change_selections(Some(autoscroll), cx, |s| {
4875            let line_mode = s.line_mode;
4876            s.move_with(|map, selection| {
4877                if !selection.is_empty() && !line_mode {
4878                    selection.goal = SelectionGoal::None;
4879                }
4880                let (cursor, goal) =
4881                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4882                selection.collapse_to(cursor, goal);
4883            });
4884        });
4885    }
4886
4887    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4888        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4889            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4890        })
4891    }
4892
4893    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4894        self.take_rename(true, cx);
4895
4896        if let Some(context_menu) = self.context_menu.as_mut() {
4897            if context_menu.select_next(cx) {
4898                return;
4899            }
4900        }
4901
4902        if self.mode == EditorMode::SingleLine {
4903            cx.propagate_action();
4904            return;
4905        }
4906
4907        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4908            let line_mode = s.line_mode;
4909            s.move_with(|map, selection| {
4910                if !selection.is_empty() && !line_mode {
4911                    selection.goal = SelectionGoal::None;
4912                }
4913                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4914                selection.collapse_to(cursor, goal);
4915            });
4916        });
4917    }
4918
4919    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4920        if self.take_rename(true, cx).is_some() {
4921            return;
4922        }
4923
4924        if self
4925            .context_menu
4926            .as_mut()
4927            .map(|menu| menu.select_last(cx))
4928            .unwrap_or(false)
4929        {
4930            return;
4931        }
4932
4933        if matches!(self.mode, EditorMode::SingleLine) {
4934            cx.propagate_action();
4935            return;
4936        }
4937
4938        let row_count = if let Some(row_count) = self.visible_line_count() {
4939            row_count as u32 - 1
4940        } else {
4941            return;
4942        };
4943
4944        let autoscroll = if action.center_cursor {
4945            Autoscroll::center()
4946        } else {
4947            Autoscroll::fit()
4948        };
4949
4950        self.change_selections(Some(autoscroll), cx, |s| {
4951            let line_mode = s.line_mode;
4952            s.move_with(|map, selection| {
4953                if !selection.is_empty() && !line_mode {
4954                    selection.goal = SelectionGoal::None;
4955                }
4956                let (cursor, goal) =
4957                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4958                selection.collapse_to(cursor, goal);
4959            });
4960        });
4961    }
4962
4963    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4964        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4965            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4966        });
4967    }
4968
4969    pub fn move_to_previous_word_start(
4970        &mut self,
4971        _: &MoveToPreviousWordStart,
4972        cx: &mut ViewContext<Self>,
4973    ) {
4974        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4975            s.move_cursors_with(|map, head, _| {
4976                (
4977                    movement::previous_word_start(map, head),
4978                    SelectionGoal::None,
4979                )
4980            });
4981        })
4982    }
4983
4984    pub fn move_to_previous_subword_start(
4985        &mut self,
4986        _: &MoveToPreviousSubwordStart,
4987        cx: &mut ViewContext<Self>,
4988    ) {
4989        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4990            s.move_cursors_with(|map, head, _| {
4991                (
4992                    movement::previous_subword_start(map, head),
4993                    SelectionGoal::None,
4994                )
4995            });
4996        })
4997    }
4998
4999    pub fn select_to_previous_word_start(
5000        &mut self,
5001        _: &SelectToPreviousWordStart,
5002        cx: &mut ViewContext<Self>,
5003    ) {
5004        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5005            s.move_heads_with(|map, head, _| {
5006                (
5007                    movement::previous_word_start(map, head),
5008                    SelectionGoal::None,
5009                )
5010            });
5011        })
5012    }
5013
5014    pub fn select_to_previous_subword_start(
5015        &mut self,
5016        _: &SelectToPreviousSubwordStart,
5017        cx: &mut ViewContext<Self>,
5018    ) {
5019        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5020            s.move_heads_with(|map, head, _| {
5021                (
5022                    movement::previous_subword_start(map, head),
5023                    SelectionGoal::None,
5024                )
5025            });
5026        })
5027    }
5028
5029    pub fn delete_to_previous_word_start(
5030        &mut self,
5031        _: &DeleteToPreviousWordStart,
5032        cx: &mut ViewContext<Self>,
5033    ) {
5034        self.transact(cx, |this, cx| {
5035            this.select_autoclose_pair(cx);
5036            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5037                let line_mode = s.line_mode;
5038                s.move_with(|map, selection| {
5039                    if selection.is_empty() && !line_mode {
5040                        let cursor = movement::previous_word_start(map, selection.head());
5041                        selection.set_head(cursor, SelectionGoal::None);
5042                    }
5043                });
5044            });
5045            this.insert("", cx);
5046        });
5047    }
5048
5049    pub fn delete_to_previous_subword_start(
5050        &mut self,
5051        _: &DeleteToPreviousSubwordStart,
5052        cx: &mut ViewContext<Self>,
5053    ) {
5054        self.transact(cx, |this, cx| {
5055            this.select_autoclose_pair(cx);
5056            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5057                let line_mode = s.line_mode;
5058                s.move_with(|map, selection| {
5059                    if selection.is_empty() && !line_mode {
5060                        let cursor = movement::previous_subword_start(map, selection.head());
5061                        selection.set_head(cursor, SelectionGoal::None);
5062                    }
5063                });
5064            });
5065            this.insert("", cx);
5066        });
5067    }
5068
5069    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5070        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5071            s.move_cursors_with(|map, head, _| {
5072                (movement::next_word_end(map, head), SelectionGoal::None)
5073            });
5074        })
5075    }
5076
5077    pub fn move_to_next_subword_end(
5078        &mut self,
5079        _: &MoveToNextSubwordEnd,
5080        cx: &mut ViewContext<Self>,
5081    ) {
5082        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5083            s.move_cursors_with(|map, head, _| {
5084                (movement::next_subword_end(map, head), SelectionGoal::None)
5085            });
5086        })
5087    }
5088
5089    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5090        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5091            s.move_heads_with(|map, head, _| {
5092                (movement::next_word_end(map, head), SelectionGoal::None)
5093            });
5094        })
5095    }
5096
5097    pub fn select_to_next_subword_end(
5098        &mut self,
5099        _: &SelectToNextSubwordEnd,
5100        cx: &mut ViewContext<Self>,
5101    ) {
5102        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5103            s.move_heads_with(|map, head, _| {
5104                (movement::next_subword_end(map, head), SelectionGoal::None)
5105            });
5106        })
5107    }
5108
5109    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5110        self.transact(cx, |this, cx| {
5111            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5112                let line_mode = s.line_mode;
5113                s.move_with(|map, selection| {
5114                    if selection.is_empty() && !line_mode {
5115                        let cursor = movement::next_word_end(map, selection.head());
5116                        selection.set_head(cursor, SelectionGoal::None);
5117                    }
5118                });
5119            });
5120            this.insert("", cx);
5121        });
5122    }
5123
5124    pub fn delete_to_next_subword_end(
5125        &mut self,
5126        _: &DeleteToNextSubwordEnd,
5127        cx: &mut ViewContext<Self>,
5128    ) {
5129        self.transact(cx, |this, cx| {
5130            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5131                s.move_with(|map, selection| {
5132                    if selection.is_empty() {
5133                        let cursor = movement::next_subword_end(map, selection.head());
5134                        selection.set_head(cursor, SelectionGoal::None);
5135                    }
5136                });
5137            });
5138            this.insert("", cx);
5139        });
5140    }
5141
5142    pub fn move_to_beginning_of_line(
5143        &mut self,
5144        _: &MoveToBeginningOfLine,
5145        cx: &mut ViewContext<Self>,
5146    ) {
5147        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5148            s.move_cursors_with(|map, head, _| {
5149                (
5150                    movement::indented_line_beginning(map, head, true),
5151                    SelectionGoal::None,
5152                )
5153            });
5154        })
5155    }
5156
5157    pub fn select_to_beginning_of_line(
5158        &mut self,
5159        action: &SelectToBeginningOfLine,
5160        cx: &mut ViewContext<Self>,
5161    ) {
5162        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5163            s.move_heads_with(|map, head, _| {
5164                (
5165                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5166                    SelectionGoal::None,
5167                )
5168            });
5169        });
5170    }
5171
5172    pub fn delete_to_beginning_of_line(
5173        &mut self,
5174        _: &DeleteToBeginningOfLine,
5175        cx: &mut ViewContext<Self>,
5176    ) {
5177        self.transact(cx, |this, cx| {
5178            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5179                s.move_with(|_, selection| {
5180                    selection.reversed = true;
5181                });
5182            });
5183
5184            this.select_to_beginning_of_line(
5185                &SelectToBeginningOfLine {
5186                    stop_at_soft_wraps: false,
5187                },
5188                cx,
5189            );
5190            this.backspace(&Backspace, cx);
5191        });
5192    }
5193
5194    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5195        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5196            s.move_cursors_with(|map, head, _| {
5197                (movement::line_end(map, head, true), SelectionGoal::None)
5198            });
5199        })
5200    }
5201
5202    pub fn select_to_end_of_line(
5203        &mut self,
5204        action: &SelectToEndOfLine,
5205        cx: &mut ViewContext<Self>,
5206    ) {
5207        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5208            s.move_heads_with(|map, head, _| {
5209                (
5210                    movement::line_end(map, head, action.stop_at_soft_wraps),
5211                    SelectionGoal::None,
5212                )
5213            });
5214        })
5215    }
5216
5217    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5218        self.transact(cx, |this, cx| {
5219            this.select_to_end_of_line(
5220                &SelectToEndOfLine {
5221                    stop_at_soft_wraps: false,
5222                },
5223                cx,
5224            );
5225            this.delete(&Delete, cx);
5226        });
5227    }
5228
5229    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5230        self.transact(cx, |this, cx| {
5231            this.select_to_end_of_line(
5232                &SelectToEndOfLine {
5233                    stop_at_soft_wraps: false,
5234                },
5235                cx,
5236            );
5237            this.cut(&Cut, cx);
5238        });
5239    }
5240
5241    pub fn move_to_start_of_paragraph(
5242        &mut self,
5243        _: &MoveToStartOfParagraph,
5244        cx: &mut ViewContext<Self>,
5245    ) {
5246        if matches!(self.mode, EditorMode::SingleLine) {
5247            cx.propagate_action();
5248            return;
5249        }
5250
5251        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5252            s.move_with(|map, selection| {
5253                selection.collapse_to(
5254                    movement::start_of_paragraph(map, selection.head(), 1),
5255                    SelectionGoal::None,
5256                )
5257            });
5258        })
5259    }
5260
5261    pub fn move_to_end_of_paragraph(
5262        &mut self,
5263        _: &MoveToEndOfParagraph,
5264        cx: &mut ViewContext<Self>,
5265    ) {
5266        if matches!(self.mode, EditorMode::SingleLine) {
5267            cx.propagate_action();
5268            return;
5269        }
5270
5271        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5272            s.move_with(|map, selection| {
5273                selection.collapse_to(
5274                    movement::end_of_paragraph(map, selection.head(), 1),
5275                    SelectionGoal::None,
5276                )
5277            });
5278        })
5279    }
5280
5281    pub fn select_to_start_of_paragraph(
5282        &mut self,
5283        _: &SelectToStartOfParagraph,
5284        cx: &mut ViewContext<Self>,
5285    ) {
5286        if matches!(self.mode, EditorMode::SingleLine) {
5287            cx.propagate_action();
5288            return;
5289        }
5290
5291        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5292            s.move_heads_with(|map, head, _| {
5293                (
5294                    movement::start_of_paragraph(map, head, 1),
5295                    SelectionGoal::None,
5296                )
5297            });
5298        })
5299    }
5300
5301    pub fn select_to_end_of_paragraph(
5302        &mut self,
5303        _: &SelectToEndOfParagraph,
5304        cx: &mut ViewContext<Self>,
5305    ) {
5306        if matches!(self.mode, EditorMode::SingleLine) {
5307            cx.propagate_action();
5308            return;
5309        }
5310
5311        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5312            s.move_heads_with(|map, head, _| {
5313                (
5314                    movement::end_of_paragraph(map, head, 1),
5315                    SelectionGoal::None,
5316                )
5317            });
5318        })
5319    }
5320
5321    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5322        if matches!(self.mode, EditorMode::SingleLine) {
5323            cx.propagate_action();
5324            return;
5325        }
5326
5327        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5328            s.select_ranges(vec![0..0]);
5329        });
5330    }
5331
5332    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5333        let mut selection = self.selections.last::<Point>(cx);
5334        selection.set_head(Point::zero(), SelectionGoal::None);
5335
5336        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5337            s.select(vec![selection]);
5338        });
5339    }
5340
5341    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5342        if matches!(self.mode, EditorMode::SingleLine) {
5343            cx.propagate_action();
5344            return;
5345        }
5346
5347        let cursor = self.buffer.read(cx).read(cx).len();
5348        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5349            s.select_ranges(vec![cursor..cursor])
5350        });
5351    }
5352
5353    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5354        self.nav_history = nav_history;
5355    }
5356
5357    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5358        self.nav_history.as_ref()
5359    }
5360
5361    fn push_to_nav_history(
5362        &mut self,
5363        cursor_anchor: Anchor,
5364        new_position: Option<Point>,
5365        cx: &mut ViewContext<Self>,
5366    ) {
5367        if let Some(nav_history) = self.nav_history.as_mut() {
5368            let buffer = self.buffer.read(cx).read(cx);
5369            let cursor_position = cursor_anchor.to_point(&buffer);
5370            let scroll_state = self.scroll_manager.anchor();
5371            let scroll_top_row = scroll_state.top_row(&buffer);
5372            drop(buffer);
5373
5374            if let Some(new_position) = new_position {
5375                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5376                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5377                    return;
5378                }
5379            }
5380
5381            nav_history.push(
5382                Some(NavigationData {
5383                    cursor_anchor,
5384                    cursor_position,
5385                    scroll_anchor: scroll_state,
5386                    scroll_top_row,
5387                }),
5388                cx,
5389            );
5390        }
5391    }
5392
5393    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5394        let buffer = self.buffer.read(cx).snapshot(cx);
5395        let mut selection = self.selections.first::<usize>(cx);
5396        selection.set_head(buffer.len(), SelectionGoal::None);
5397        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5398            s.select(vec![selection]);
5399        });
5400    }
5401
5402    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5403        let end = self.buffer.read(cx).read(cx).len();
5404        self.change_selections(None, cx, |s| {
5405            s.select_ranges(vec![0..end]);
5406        });
5407    }
5408
5409    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5410        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5411        let mut selections = self.selections.all::<Point>(cx);
5412        let max_point = display_map.buffer_snapshot.max_point();
5413        for selection in &mut selections {
5414            let rows = selection.spanned_rows(true, &display_map);
5415            selection.start = Point::new(rows.start, 0);
5416            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5417            selection.reversed = false;
5418        }
5419        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5420            s.select(selections);
5421        });
5422    }
5423
5424    pub fn split_selection_into_lines(
5425        &mut self,
5426        _: &SplitSelectionIntoLines,
5427        cx: &mut ViewContext<Self>,
5428    ) {
5429        let mut to_unfold = Vec::new();
5430        let mut new_selection_ranges = Vec::new();
5431        {
5432            let selections = self.selections.all::<Point>(cx);
5433            let buffer = self.buffer.read(cx).read(cx);
5434            for selection in selections {
5435                for row in selection.start.row..selection.end.row {
5436                    let cursor = Point::new(row, buffer.line_len(row));
5437                    new_selection_ranges.push(cursor..cursor);
5438                }
5439                new_selection_ranges.push(selection.end..selection.end);
5440                to_unfold.push(selection.start..selection.end);
5441            }
5442        }
5443        self.unfold_ranges(to_unfold, true, true, cx);
5444        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5445            s.select_ranges(new_selection_ranges);
5446        });
5447    }
5448
5449    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5450        self.add_selection(true, cx);
5451    }
5452
5453    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5454        self.add_selection(false, cx);
5455    }
5456
5457    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5458        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5459        let mut selections = self.selections.all::<Point>(cx);
5460        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5461            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5462            let range = oldest_selection.display_range(&display_map).sorted();
5463            let columns = cmp::min(range.start.column(), range.end.column())
5464                ..cmp::max(range.start.column(), range.end.column());
5465
5466            selections.clear();
5467            let mut stack = Vec::new();
5468            for row in range.start.row()..=range.end.row() {
5469                if let Some(selection) = self.selections.build_columnar_selection(
5470                    &display_map,
5471                    row,
5472                    &columns,
5473                    oldest_selection.reversed,
5474                ) {
5475                    stack.push(selection.id);
5476                    selections.push(selection);
5477                }
5478            }
5479
5480            if above {
5481                stack.reverse();
5482            }
5483
5484            AddSelectionsState { above, stack }
5485        });
5486
5487        let last_added_selection = *state.stack.last().unwrap();
5488        let mut new_selections = Vec::new();
5489        if above == state.above {
5490            let end_row = if above {
5491                0
5492            } else {
5493                display_map.max_point().row()
5494            };
5495
5496            'outer: for selection in selections {
5497                if selection.id == last_added_selection {
5498                    let range = selection.display_range(&display_map).sorted();
5499                    debug_assert_eq!(range.start.row(), range.end.row());
5500                    let mut row = range.start.row();
5501                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5502                    {
5503                        start..end
5504                    } else {
5505                        cmp::min(range.start.column(), range.end.column())
5506                            ..cmp::max(range.start.column(), range.end.column())
5507                    };
5508
5509                    while row != end_row {
5510                        if above {
5511                            row -= 1;
5512                        } else {
5513                            row += 1;
5514                        }
5515
5516                        if let Some(new_selection) = self.selections.build_columnar_selection(
5517                            &display_map,
5518                            row,
5519                            &columns,
5520                            selection.reversed,
5521                        ) {
5522                            state.stack.push(new_selection.id);
5523                            if above {
5524                                new_selections.push(new_selection);
5525                                new_selections.push(selection);
5526                            } else {
5527                                new_selections.push(selection);
5528                                new_selections.push(new_selection);
5529                            }
5530
5531                            continue 'outer;
5532                        }
5533                    }
5534                }
5535
5536                new_selections.push(selection);
5537            }
5538        } else {
5539            new_selections = selections;
5540            new_selections.retain(|s| s.id != last_added_selection);
5541            state.stack.pop();
5542        }
5543
5544        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5545            s.select(new_selections);
5546        });
5547        if state.stack.len() > 1 {
5548            self.add_selections_state = Some(state);
5549        }
5550    }
5551
5552    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5553        self.push_to_selection_history();
5554        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5555        let buffer = &display_map.buffer_snapshot;
5556        let mut selections = self.selections.all::<usize>(cx);
5557        if let Some(mut select_next_state) = self.select_next_state.take() {
5558            let query = &select_next_state.query;
5559            if !select_next_state.done {
5560                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5561                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5562                let mut next_selected_range = None;
5563
5564                let bytes_after_last_selection =
5565                    buffer.bytes_in_range(last_selection.end..buffer.len());
5566                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5567                let query_matches = query
5568                    .stream_find_iter(bytes_after_last_selection)
5569                    .map(|result| (last_selection.end, result))
5570                    .chain(
5571                        query
5572                            .stream_find_iter(bytes_before_first_selection)
5573                            .map(|result| (0, result)),
5574                    );
5575                for (start_offset, query_match) in query_matches {
5576                    let query_match = query_match.unwrap(); // can only fail due to I/O
5577                    let offset_range =
5578                        start_offset + query_match.start()..start_offset + query_match.end();
5579                    let display_range = offset_range.start.to_display_point(&display_map)
5580                        ..offset_range.end.to_display_point(&display_map);
5581
5582                    if !select_next_state.wordwise
5583                        || (!movement::is_inside_word(&display_map, display_range.start)
5584                            && !movement::is_inside_word(&display_map, display_range.end))
5585                    {
5586                        next_selected_range = Some(offset_range);
5587                        break;
5588                    }
5589                }
5590
5591                if let Some(next_selected_range) = next_selected_range {
5592                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5593                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5594                        if action.replace_newest {
5595                            s.delete(s.newest_anchor().id);
5596                        }
5597                        s.insert_range(next_selected_range);
5598                    });
5599                } else {
5600                    select_next_state.done = true;
5601                }
5602            }
5603
5604            self.select_next_state = Some(select_next_state);
5605        } else if selections.len() == 1 {
5606            let selection = selections.last_mut().unwrap();
5607            if selection.start == selection.end {
5608                let word_range = movement::surrounding_word(
5609                    &display_map,
5610                    selection.start.to_display_point(&display_map),
5611                );
5612                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5613                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5614                selection.goal = SelectionGoal::None;
5615                selection.reversed = false;
5616
5617                let query = buffer
5618                    .text_for_range(selection.start..selection.end)
5619                    .collect::<String>();
5620                let select_state = SelectNextState {
5621                    query: AhoCorasick::new_auto_configured(&[query]),
5622                    wordwise: true,
5623                    done: false,
5624                };
5625                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5626                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5627                    s.select(selections);
5628                });
5629                self.select_next_state = Some(select_state);
5630            } else {
5631                let query = buffer
5632                    .text_for_range(selection.start..selection.end)
5633                    .collect::<String>();
5634                self.select_next_state = Some(SelectNextState {
5635                    query: AhoCorasick::new_auto_configured(&[query]),
5636                    wordwise: false,
5637                    done: false,
5638                });
5639                self.select_next(action, cx);
5640            }
5641        }
5642    }
5643
5644    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5645        self.push_to_selection_history();
5646        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5647        let buffer = &display_map.buffer_snapshot;
5648        let mut selections = self.selections.all::<usize>(cx);
5649        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5650            let query = &select_prev_state.query;
5651            if !select_prev_state.done {
5652                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5653                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5654                let mut next_selected_range = None;
5655                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5656                let bytes_before_last_selection =
5657                    buffer.reversed_bytes_in_range(0..last_selection.start);
5658                let bytes_after_first_selection =
5659                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5660                let query_matches = query
5661                    .stream_find_iter(bytes_before_last_selection)
5662                    .map(|result| (last_selection.start, result))
5663                    .chain(
5664                        query
5665                            .stream_find_iter(bytes_after_first_selection)
5666                            .map(|result| (buffer.len(), result)),
5667                    );
5668                for (end_offset, query_match) in query_matches {
5669                    let query_match = query_match.unwrap(); // can only fail due to I/O
5670                    let offset_range =
5671                        end_offset - query_match.end()..end_offset - query_match.start();
5672                    let display_range = offset_range.start.to_display_point(&display_map)
5673                        ..offset_range.end.to_display_point(&display_map);
5674
5675                    if !select_prev_state.wordwise
5676                        || (!movement::is_inside_word(&display_map, display_range.start)
5677                            && !movement::is_inside_word(&display_map, display_range.end))
5678                    {
5679                        next_selected_range = Some(offset_range);
5680                        break;
5681                    }
5682                }
5683
5684                if let Some(next_selected_range) = next_selected_range {
5685                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5686                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5687                        if action.replace_newest {
5688                            s.delete(s.newest_anchor().id);
5689                        }
5690                        s.insert_range(next_selected_range);
5691                    });
5692                } else {
5693                    select_prev_state.done = true;
5694                }
5695            }
5696
5697            self.select_prev_state = Some(select_prev_state);
5698        } else if selections.len() == 1 {
5699            let selection = selections.last_mut().unwrap();
5700            if selection.start == selection.end {
5701                let word_range = movement::surrounding_word(
5702                    &display_map,
5703                    selection.start.to_display_point(&display_map),
5704                );
5705                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5706                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5707                selection.goal = SelectionGoal::None;
5708                selection.reversed = false;
5709
5710                let query = buffer
5711                    .text_for_range(selection.start..selection.end)
5712                    .collect::<String>();
5713                let query = query.chars().rev().collect::<String>();
5714                let select_state = SelectNextState {
5715                    query: AhoCorasick::new_auto_configured(&[query]),
5716                    wordwise: true,
5717                    done: false,
5718                };
5719                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5720                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5721                    s.select(selections);
5722                });
5723                self.select_prev_state = Some(select_state);
5724            } else {
5725                let query = buffer
5726                    .text_for_range(selection.start..selection.end)
5727                    .collect::<String>();
5728                let query = query.chars().rev().collect::<String>();
5729                self.select_prev_state = Some(SelectNextState {
5730                    query: AhoCorasick::new_auto_configured(&[query]),
5731                    wordwise: false,
5732                    done: false,
5733                });
5734                self.select_previous(action, cx);
5735            }
5736        }
5737    }
5738
5739    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5740        self.transact(cx, |this, cx| {
5741            let mut selections = this.selections.all::<Point>(cx);
5742            let mut edits = Vec::new();
5743            let mut selection_edit_ranges = Vec::new();
5744            let mut last_toggled_row = None;
5745            let snapshot = this.buffer.read(cx).read(cx);
5746            let empty_str: Arc<str> = "".into();
5747            let mut suffixes_inserted = Vec::new();
5748
5749            fn comment_prefix_range(
5750                snapshot: &MultiBufferSnapshot,
5751                row: u32,
5752                comment_prefix: &str,
5753                comment_prefix_whitespace: &str,
5754            ) -> Range<Point> {
5755                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5756
5757                let mut line_bytes = snapshot
5758                    .bytes_in_range(start..snapshot.max_point())
5759                    .flatten()
5760                    .copied();
5761
5762                // If this line currently begins with the line comment prefix, then record
5763                // the range containing the prefix.
5764                if line_bytes
5765                    .by_ref()
5766                    .take(comment_prefix.len())
5767                    .eq(comment_prefix.bytes())
5768                {
5769                    // Include any whitespace that matches the comment prefix.
5770                    let matching_whitespace_len = line_bytes
5771                        .zip(comment_prefix_whitespace.bytes())
5772                        .take_while(|(a, b)| a == b)
5773                        .count() as u32;
5774                    let end = Point::new(
5775                        start.row,
5776                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5777                    );
5778                    start..end
5779                } else {
5780                    start..start
5781                }
5782            }
5783
5784            fn comment_suffix_range(
5785                snapshot: &MultiBufferSnapshot,
5786                row: u32,
5787                comment_suffix: &str,
5788                comment_suffix_has_leading_space: bool,
5789            ) -> Range<Point> {
5790                let end = Point::new(row, snapshot.line_len(row));
5791                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5792
5793                let mut line_end_bytes = snapshot
5794                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5795                    .flatten()
5796                    .copied();
5797
5798                let leading_space_len = if suffix_start_column > 0
5799                    && line_end_bytes.next() == Some(b' ')
5800                    && comment_suffix_has_leading_space
5801                {
5802                    1
5803                } else {
5804                    0
5805                };
5806
5807                // If this line currently begins with the line comment prefix, then record
5808                // the range containing the prefix.
5809                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5810                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5811                    start..end
5812                } else {
5813                    end..end
5814                }
5815            }
5816
5817            // TODO: Handle selections that cross excerpts
5818            for selection in &mut selections {
5819                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5820                let language = if let Some(language) =
5821                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5822                {
5823                    language
5824                } else {
5825                    continue;
5826                };
5827
5828                selection_edit_ranges.clear();
5829
5830                // If multiple selections contain a given row, avoid processing that
5831                // row more than once.
5832                let mut start_row = selection.start.row;
5833                if last_toggled_row == Some(start_row) {
5834                    start_row += 1;
5835                }
5836                let end_row =
5837                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5838                        selection.end.row - 1
5839                    } else {
5840                        selection.end.row
5841                    };
5842                last_toggled_row = Some(end_row);
5843
5844                if start_row > end_row {
5845                    continue;
5846                }
5847
5848                // If the language has line comments, toggle those.
5849                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5850                    // Split the comment prefix's trailing whitespace into a separate string,
5851                    // as that portion won't be used for detecting if a line is a comment.
5852                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5853                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5854                    let mut all_selection_lines_are_comments = true;
5855
5856                    for row in start_row..=end_row {
5857                        if snapshot.is_line_blank(row) && start_row < end_row {
5858                            continue;
5859                        }
5860
5861                        let prefix_range = comment_prefix_range(
5862                            snapshot.deref(),
5863                            row,
5864                            comment_prefix,
5865                            comment_prefix_whitespace,
5866                        );
5867                        if prefix_range.is_empty() {
5868                            all_selection_lines_are_comments = false;
5869                        }
5870                        selection_edit_ranges.push(prefix_range);
5871                    }
5872
5873                    if all_selection_lines_are_comments {
5874                        edits.extend(
5875                            selection_edit_ranges
5876                                .iter()
5877                                .cloned()
5878                                .map(|range| (range, empty_str.clone())),
5879                        );
5880                    } else {
5881                        let min_column = selection_edit_ranges
5882                            .iter()
5883                            .map(|r| r.start.column)
5884                            .min()
5885                            .unwrap_or(0);
5886                        edits.extend(selection_edit_ranges.iter().map(|range| {
5887                            let position = Point::new(range.start.row, min_column);
5888                            (position..position, full_comment_prefix.clone())
5889                        }));
5890                    }
5891                } else if let Some((full_comment_prefix, comment_suffix)) =
5892                    language.block_comment_delimiters()
5893                {
5894                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5895                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5896                    let prefix_range = comment_prefix_range(
5897                        snapshot.deref(),
5898                        start_row,
5899                        comment_prefix,
5900                        comment_prefix_whitespace,
5901                    );
5902                    let suffix_range = comment_suffix_range(
5903                        snapshot.deref(),
5904                        end_row,
5905                        comment_suffix.trim_start_matches(' '),
5906                        comment_suffix.starts_with(' '),
5907                    );
5908
5909                    if prefix_range.is_empty() || suffix_range.is_empty() {
5910                        edits.push((
5911                            prefix_range.start..prefix_range.start,
5912                            full_comment_prefix.clone(),
5913                        ));
5914                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5915                        suffixes_inserted.push((end_row, comment_suffix.len()));
5916                    } else {
5917                        edits.push((prefix_range, empty_str.clone()));
5918                        edits.push((suffix_range, empty_str.clone()));
5919                    }
5920                } else {
5921                    continue;
5922                }
5923            }
5924
5925            drop(snapshot);
5926            this.buffer.update(cx, |buffer, cx| {
5927                buffer.edit(edits, None, cx);
5928            });
5929
5930            // Adjust selections so that they end before any comment suffixes that
5931            // were inserted.
5932            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5933            let mut selections = this.selections.all::<Point>(cx);
5934            let snapshot = this.buffer.read(cx).read(cx);
5935            for selection in &mut selections {
5936                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5937                    match row.cmp(&selection.end.row) {
5938                        Ordering::Less => {
5939                            suffixes_inserted.next();
5940                            continue;
5941                        }
5942                        Ordering::Greater => break,
5943                        Ordering::Equal => {
5944                            if selection.end.column == snapshot.line_len(row) {
5945                                if selection.is_empty() {
5946                                    selection.start.column -= suffix_len as u32;
5947                                }
5948                                selection.end.column -= suffix_len as u32;
5949                            }
5950                            break;
5951                        }
5952                    }
5953                }
5954            }
5955
5956            drop(snapshot);
5957            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5958
5959            let selections = this.selections.all::<Point>(cx);
5960            let selections_on_single_row = selections.windows(2).all(|selections| {
5961                selections[0].start.row == selections[1].start.row
5962                    && selections[0].end.row == selections[1].end.row
5963                    && selections[0].start.row == selections[0].end.row
5964            });
5965            let selections_selecting = selections
5966                .iter()
5967                .any(|selection| selection.start != selection.end);
5968            let advance_downwards = action.advance_downwards
5969                && selections_on_single_row
5970                && !selections_selecting
5971                && this.mode != EditorMode::SingleLine;
5972
5973            if advance_downwards {
5974                let snapshot = this.buffer.read(cx).snapshot(cx);
5975
5976                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5977                    s.move_cursors_with(|display_snapshot, display_point, _| {
5978                        let mut point = display_point.to_point(display_snapshot);
5979                        point.row += 1;
5980                        point = snapshot.clip_point(point, Bias::Left);
5981                        let display_point = point.to_display_point(display_snapshot);
5982                        (display_point, SelectionGoal::Column(display_point.column()))
5983                    })
5984                });
5985            }
5986        });
5987    }
5988
5989    pub fn select_larger_syntax_node(
5990        &mut self,
5991        _: &SelectLargerSyntaxNode,
5992        cx: &mut ViewContext<Self>,
5993    ) {
5994        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5995        let buffer = self.buffer.read(cx).snapshot(cx);
5996        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5997
5998        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5999        let mut selected_larger_node = false;
6000        let new_selections = old_selections
6001            .iter()
6002            .map(|selection| {
6003                let old_range = selection.start..selection.end;
6004                let mut new_range = old_range.clone();
6005                while let Some(containing_range) =
6006                    buffer.range_for_syntax_ancestor(new_range.clone())
6007                {
6008                    new_range = containing_range;
6009                    if !display_map.intersects_fold(new_range.start)
6010                        && !display_map.intersects_fold(new_range.end)
6011                    {
6012                        break;
6013                    }
6014                }
6015
6016                selected_larger_node |= new_range != old_range;
6017                Selection {
6018                    id: selection.id,
6019                    start: new_range.start,
6020                    end: new_range.end,
6021                    goal: SelectionGoal::None,
6022                    reversed: selection.reversed,
6023                }
6024            })
6025            .collect::<Vec<_>>();
6026
6027        if selected_larger_node {
6028            stack.push(old_selections);
6029            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6030                s.select(new_selections);
6031            });
6032        }
6033        self.select_larger_syntax_node_stack = stack;
6034    }
6035
6036    pub fn select_smaller_syntax_node(
6037        &mut self,
6038        _: &SelectSmallerSyntaxNode,
6039        cx: &mut ViewContext<Self>,
6040    ) {
6041        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6042        if let Some(selections) = stack.pop() {
6043            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6044                s.select(selections.to_vec());
6045            });
6046        }
6047        self.select_larger_syntax_node_stack = stack;
6048    }
6049
6050    pub fn move_to_enclosing_bracket(
6051        &mut self,
6052        _: &MoveToEnclosingBracket,
6053        cx: &mut ViewContext<Self>,
6054    ) {
6055        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6056            s.move_offsets_with(|snapshot, selection| {
6057                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
6058                    return;
6059                };
6060
6061                let mut best_length = usize::MAX;
6062                let mut best_inside = false;
6063                let mut best_in_bracket_range = false;
6064                let mut best_destination = None;
6065                for (open, close) in enclosing_bracket_ranges {
6066                    let close = close.to_inclusive();
6067                    let length = close.end() - open.start;
6068                    let inside = selection.start >= open.end && selection.end <= *close.start();
6069                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
6070
6071                    // If best is next to a bracket and current isn't, skip
6072                    if !in_bracket_range && best_in_bracket_range {
6073                        continue;
6074                    }
6075
6076                    // Prefer smaller lengths unless best is inside and current isn't
6077                    if length > best_length && (best_inside || !inside) {
6078                        continue;
6079                    }
6080
6081                    best_length = length;
6082                    best_inside = inside;
6083                    best_in_bracket_range = in_bracket_range;
6084                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
6085                        if inside {
6086                            open.end
6087                        } else {
6088                            open.start
6089                        }
6090                    } else {
6091                        if inside {
6092                            *close.start()
6093                        } else {
6094                            *close.end()
6095                        }
6096                    });
6097                }
6098
6099                if let Some(destination) = best_destination {
6100                    selection.collapse_to(destination, SelectionGoal::None);
6101                }
6102            })
6103        });
6104    }
6105
6106    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6107        self.end_selection(cx);
6108        self.selection_history.mode = SelectionHistoryMode::Undoing;
6109        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6110            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6111            self.select_next_state = entry.select_next_state;
6112            self.select_prev_state = entry.select_prev_state;
6113            self.add_selections_state = entry.add_selections_state;
6114            self.request_autoscroll(Autoscroll::newest(), cx);
6115        }
6116        self.selection_history.mode = SelectionHistoryMode::Normal;
6117    }
6118
6119    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6120        self.end_selection(cx);
6121        self.selection_history.mode = SelectionHistoryMode::Redoing;
6122        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6123            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6124            self.select_next_state = entry.select_next_state;
6125            self.select_prev_state = entry.select_prev_state;
6126            self.add_selections_state = entry.add_selections_state;
6127            self.request_autoscroll(Autoscroll::newest(), cx);
6128        }
6129        self.selection_history.mode = SelectionHistoryMode::Normal;
6130    }
6131
6132    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6133        self.go_to_diagnostic_impl(Direction::Next, cx)
6134    }
6135
6136    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6137        self.go_to_diagnostic_impl(Direction::Prev, cx)
6138    }
6139
6140    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6141        let buffer = self.buffer.read(cx).snapshot(cx);
6142        let selection = self.selections.newest::<usize>(cx);
6143
6144        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6145        if direction == Direction::Next {
6146            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6147                let (group_id, jump_to) = popover.activation_info();
6148                if self.activate_diagnostics(group_id, cx) {
6149                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6150                        let mut new_selection = s.newest_anchor().clone();
6151                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6152                        s.select_anchors(vec![new_selection.clone()]);
6153                    });
6154                }
6155                return;
6156            }
6157        }
6158
6159        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6160            active_diagnostics
6161                .primary_range
6162                .to_offset(&buffer)
6163                .to_inclusive()
6164        });
6165        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6166            if active_primary_range.contains(&selection.head()) {
6167                *active_primary_range.end()
6168            } else {
6169                selection.head()
6170            }
6171        } else {
6172            selection.head()
6173        };
6174
6175        loop {
6176            let mut diagnostics = if direction == Direction::Prev {
6177                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6178            } else {
6179                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6180            };
6181            let group = diagnostics.find_map(|entry| {
6182                if entry.diagnostic.is_primary
6183                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6184                    && !entry.range.is_empty()
6185                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6186                {
6187                    Some((entry.range, entry.diagnostic.group_id))
6188                } else {
6189                    None
6190                }
6191            });
6192
6193            if let Some((primary_range, group_id)) = group {
6194                if self.activate_diagnostics(group_id, cx) {
6195                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6196                        s.select(vec![Selection {
6197                            id: selection.id,
6198                            start: primary_range.start,
6199                            end: primary_range.start,
6200                            reversed: false,
6201                            goal: SelectionGoal::None,
6202                        }]);
6203                    });
6204                }
6205                break;
6206            } else {
6207                // Cycle around to the start of the buffer, potentially moving back to the start of
6208                // the currently active diagnostic.
6209                active_primary_range.take();
6210                if direction == Direction::Prev {
6211                    if search_start == buffer.len() {
6212                        break;
6213                    } else {
6214                        search_start = buffer.len();
6215                    }
6216                } else if search_start == 0 {
6217                    break;
6218                } else {
6219                    search_start = 0;
6220                }
6221            }
6222        }
6223    }
6224
6225    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6226        let snapshot = self
6227            .display_map
6228            .update(cx, |display_map, cx| display_map.snapshot(cx));
6229        let selection = self.selections.newest::<Point>(cx);
6230
6231        if !self.seek_in_direction(
6232            &snapshot,
6233            selection.head(),
6234            false,
6235            snapshot
6236                .buffer_snapshot
6237                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6238            cx,
6239        ) {
6240            let wrapped_point = Point::zero();
6241            self.seek_in_direction(
6242                &snapshot,
6243                wrapped_point,
6244                true,
6245                snapshot
6246                    .buffer_snapshot
6247                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6248                cx,
6249            );
6250        }
6251    }
6252
6253    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6254        let snapshot = self
6255            .display_map
6256            .update(cx, |display_map, cx| display_map.snapshot(cx));
6257        let selection = self.selections.newest::<Point>(cx);
6258
6259        if !self.seek_in_direction(
6260            &snapshot,
6261            selection.head(),
6262            false,
6263            snapshot
6264                .buffer_snapshot
6265                .git_diff_hunks_in_range_rev(0..selection.head().row),
6266            cx,
6267        ) {
6268            let wrapped_point = snapshot.buffer_snapshot.max_point();
6269            self.seek_in_direction(
6270                &snapshot,
6271                wrapped_point,
6272                true,
6273                snapshot
6274                    .buffer_snapshot
6275                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6276                cx,
6277            );
6278        }
6279    }
6280
6281    fn seek_in_direction(
6282        &mut self,
6283        snapshot: &DisplaySnapshot,
6284        initial_point: Point,
6285        is_wrapped: bool,
6286        hunks: impl Iterator<Item = DiffHunk<u32>>,
6287        cx: &mut ViewContext<Editor>,
6288    ) -> bool {
6289        let display_point = initial_point.to_display_point(snapshot);
6290        let mut hunks = hunks
6291            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6292            .skip_while(|hunk| {
6293                if is_wrapped {
6294                    false
6295                } else {
6296                    hunk.contains_display_row(display_point.row())
6297                }
6298            })
6299            .dedup();
6300
6301        if let Some(hunk) = hunks.next() {
6302            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6303                let row = hunk.start_display_row();
6304                let point = DisplayPoint::new(row, 0);
6305                s.select_display_ranges([point..point]);
6306            });
6307
6308            true
6309        } else {
6310            false
6311        }
6312    }
6313
6314    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6315        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6316    }
6317
6318    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6319        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6320    }
6321
6322    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6323        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6324    }
6325
6326    pub fn go_to_type_definition_split(
6327        &mut self,
6328        _: &GoToTypeDefinitionSplit,
6329        cx: &mut ViewContext<Self>,
6330    ) {
6331        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6332    }
6333
6334    fn go_to_definition_of_kind(
6335        &mut self,
6336        kind: GotoDefinitionKind,
6337        split: bool,
6338        cx: &mut ViewContext<Self>,
6339    ) {
6340        let Some(workspace) = self.workspace(cx) else { return };
6341        let buffer = self.buffer.read(cx);
6342        let head = self.selections.newest::<usize>(cx).head();
6343        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6344            text_anchor
6345        } else {
6346            return;
6347        };
6348
6349        let project = workspace.read(cx).project().clone();
6350        let definitions = project.update(cx, |project, cx| match kind {
6351            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6352            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6353        });
6354
6355        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6356            let definitions = definitions.await?;
6357            editor.update(&mut cx, |editor, cx| {
6358                editor.navigate_to_definitions(definitions, split, cx);
6359            })?;
6360            Ok::<(), anyhow::Error>(())
6361        })
6362        .detach_and_log_err(cx);
6363    }
6364
6365    pub fn navigate_to_definitions(
6366        &mut self,
6367        mut definitions: Vec<LocationLink>,
6368        split: bool,
6369        cx: &mut ViewContext<Editor>,
6370    ) {
6371        let Some(workspace) = self.workspace(cx) else { return };
6372        let pane = workspace.read(cx).active_pane().clone();
6373        // If there is one definition, just open it directly
6374        if definitions.len() == 1 {
6375            let definition = definitions.pop().unwrap();
6376            let range = definition
6377                .target
6378                .range
6379                .to_offset(definition.target.buffer.read(cx));
6380
6381            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6382                let range = self.range_for_match(&range);
6383                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6384                    s.select_ranges([range]);
6385                });
6386            } else {
6387                cx.window_context().defer(move |cx| {
6388                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6389                        if split {
6390                            workspace.split_project_item(definition.target.buffer.clone(), cx)
6391                        } else {
6392                            workspace.open_project_item(definition.target.buffer.clone(), cx)
6393                        }
6394                    });
6395                    target_editor.update(cx, |target_editor, cx| {
6396                        // When selecting a definition in a different buffer, disable the nav history
6397                        // to avoid creating a history entry at the previous cursor location.
6398                        pane.update(cx, |pane, _| pane.disable_history());
6399                        let range = target_editor.range_for_match(&range);
6400                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6401                            s.select_ranges([range]);
6402                        });
6403                        pane.update(cx, |pane, _| pane.enable_history());
6404                    });
6405                });
6406            }
6407        } else if !definitions.is_empty() {
6408            let replica_id = self.replica_id(cx);
6409            cx.window_context().defer(move |cx| {
6410                let title = definitions
6411                    .iter()
6412                    .find(|definition| definition.origin.is_some())
6413                    .and_then(|definition| {
6414                        definition.origin.as_ref().map(|origin| {
6415                            let buffer = origin.buffer.read(cx);
6416                            format!(
6417                                "Definitions for {}",
6418                                buffer
6419                                    .text_for_range(origin.range.clone())
6420                                    .collect::<String>()
6421                            )
6422                        })
6423                    })
6424                    .unwrap_or("Definitions".to_owned());
6425                let locations = definitions
6426                    .into_iter()
6427                    .map(|definition| definition.target)
6428                    .collect();
6429                workspace.update(cx, |workspace, cx| {
6430                    Self::open_locations_in_multibuffer(
6431                        workspace, locations, replica_id, title, split, cx,
6432                    )
6433                });
6434            });
6435        }
6436    }
6437
6438    pub fn find_all_references(
6439        workspace: &mut Workspace,
6440        _: &FindAllReferences,
6441        cx: &mut ViewContext<Workspace>,
6442    ) -> Option<Task<Result<()>>> {
6443        let active_item = workspace.active_item(cx)?;
6444        let editor_handle = active_item.act_as::<Self>(cx)?;
6445
6446        let editor = editor_handle.read(cx);
6447        let buffer = editor.buffer.read(cx);
6448        let head = editor.selections.newest::<usize>(cx).head();
6449        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6450        let replica_id = editor.replica_id(cx);
6451
6452        let project = workspace.project().clone();
6453        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6454        Some(cx.spawn_labeled(
6455            "Finding All References...",
6456            |workspace, mut cx| async move {
6457                let locations = references.await?;
6458                if locations.is_empty() {
6459                    return Ok(());
6460                }
6461
6462                workspace.update(&mut cx, |workspace, cx| {
6463                    let title = locations
6464                        .first()
6465                        .as_ref()
6466                        .map(|location| {
6467                            let buffer = location.buffer.read(cx);
6468                            format!(
6469                                "References to `{}`",
6470                                buffer
6471                                    .text_for_range(location.range.clone())
6472                                    .collect::<String>()
6473                            )
6474                        })
6475                        .unwrap();
6476                    Self::open_locations_in_multibuffer(
6477                        workspace, locations, replica_id, title, false, cx,
6478                    );
6479                })?;
6480
6481                Ok(())
6482            },
6483        ))
6484    }
6485
6486    /// Opens a multibuffer with the given project locations in it
6487    pub fn open_locations_in_multibuffer(
6488        workspace: &mut Workspace,
6489        mut locations: Vec<Location>,
6490        replica_id: ReplicaId,
6491        title: String,
6492        split: bool,
6493        cx: &mut ViewContext<Workspace>,
6494    ) {
6495        // If there are multiple definitions, open them in a multibuffer
6496        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6497        let mut locations = locations.into_iter().peekable();
6498        let mut ranges_to_highlight = Vec::new();
6499
6500        let excerpt_buffer = cx.add_model(|cx| {
6501            let mut multibuffer = MultiBuffer::new(replica_id);
6502            while let Some(location) = locations.next() {
6503                let buffer = location.buffer.read(cx);
6504                let mut ranges_for_buffer = Vec::new();
6505                let range = location.range.to_offset(buffer);
6506                ranges_for_buffer.push(range.clone());
6507
6508                while let Some(next_location) = locations.peek() {
6509                    if next_location.buffer == location.buffer {
6510                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6511                        locations.next();
6512                    } else {
6513                        break;
6514                    }
6515                }
6516
6517                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6518                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6519                    location.buffer.clone(),
6520                    ranges_for_buffer,
6521                    1,
6522                    cx,
6523                ))
6524            }
6525
6526            multibuffer.with_title(title)
6527        });
6528
6529        let editor = cx.add_view(|cx| {
6530            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6531        });
6532        editor.update(cx, |editor, cx| {
6533            editor.highlight_background::<Self>(
6534                ranges_to_highlight,
6535                |theme| theme.editor.highlighted_line_background,
6536                cx,
6537            );
6538        });
6539        if split {
6540            workspace.split_item(Box::new(editor), cx);
6541        } else {
6542            workspace.add_item(Box::new(editor), cx);
6543        }
6544    }
6545
6546    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6547        use language::ToOffset as _;
6548
6549        let project = self.project.clone()?;
6550        let selection = self.selections.newest_anchor().clone();
6551        let (cursor_buffer, cursor_buffer_position) = self
6552            .buffer
6553            .read(cx)
6554            .text_anchor_for_position(selection.head(), cx)?;
6555        let (tail_buffer, _) = self
6556            .buffer
6557            .read(cx)
6558            .text_anchor_for_position(selection.tail(), cx)?;
6559        if tail_buffer != cursor_buffer {
6560            return None;
6561        }
6562
6563        let snapshot = cursor_buffer.read(cx).snapshot();
6564        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6565        let prepare_rename = project.update(cx, |project, cx| {
6566            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6567        });
6568
6569        Some(cx.spawn(|this, mut cx| async move {
6570            let rename_range = if let Some(range) = prepare_rename.await? {
6571                Some(range)
6572            } else {
6573                this.read_with(&cx, |this, cx| {
6574                    let buffer = this.buffer.read(cx).snapshot(cx);
6575                    let mut buffer_highlights = this
6576                        .document_highlights_for_position(selection.head(), &buffer)
6577                        .filter(|highlight| {
6578                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6579                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6580                        });
6581                    buffer_highlights
6582                        .next()
6583                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6584                })?
6585            };
6586            if let Some(rename_range) = rename_range {
6587                let rename_buffer_range = rename_range.to_offset(&snapshot);
6588                let cursor_offset_in_rename_range =
6589                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6590
6591                this.update(&mut cx, |this, cx| {
6592                    this.take_rename(false, cx);
6593                    let style = this.style(cx);
6594                    let buffer = this.buffer.read(cx).read(cx);
6595                    let cursor_offset = selection.head().to_offset(&buffer);
6596                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6597                    let rename_end = rename_start + rename_buffer_range.len();
6598                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6599                    let mut old_highlight_id = None;
6600                    let old_name: Arc<str> = buffer
6601                        .chunks(rename_start..rename_end, true)
6602                        .map(|chunk| {
6603                            if old_highlight_id.is_none() {
6604                                old_highlight_id = chunk.syntax_highlight_id;
6605                            }
6606                            chunk.text
6607                        })
6608                        .collect::<String>()
6609                        .into();
6610
6611                    drop(buffer);
6612
6613                    // Position the selection in the rename editor so that it matches the current selection.
6614                    this.show_local_selections = false;
6615                    let rename_editor = cx.add_view(|cx| {
6616                        let mut editor = Editor::single_line(None, cx);
6617                        if let Some(old_highlight_id) = old_highlight_id {
6618                            editor.override_text_style =
6619                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6620                        }
6621                        editor.buffer.update(cx, |buffer, cx| {
6622                            buffer.edit([(0..0, old_name.clone())], None, cx)
6623                        });
6624                        editor.select_all(&SelectAll, cx);
6625                        editor
6626                    });
6627
6628                    let ranges = this
6629                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6630                        .into_iter()
6631                        .flat_map(|(_, ranges)| ranges)
6632                        .chain(
6633                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6634                                .into_iter()
6635                                .flat_map(|(_, ranges)| ranges),
6636                        )
6637                        .collect();
6638
6639                    this.highlight_text::<Rename>(
6640                        ranges,
6641                        HighlightStyle {
6642                            fade_out: Some(style.rename_fade),
6643                            ..Default::default()
6644                        },
6645                        cx,
6646                    );
6647                    cx.focus(&rename_editor);
6648                    let block_id = this.insert_blocks(
6649                        [BlockProperties {
6650                            style: BlockStyle::Flex,
6651                            position: range.start.clone(),
6652                            height: 1,
6653                            render: Arc::new({
6654                                let editor = rename_editor.clone();
6655                                move |cx: &mut BlockContext| {
6656                                    ChildView::new(&editor, cx)
6657                                        .contained()
6658                                        .with_padding_left(cx.anchor_x)
6659                                        .into_any()
6660                                }
6661                            }),
6662                            disposition: BlockDisposition::Below,
6663                        }],
6664                        Some(Autoscroll::fit()),
6665                        cx,
6666                    )[0];
6667                    this.pending_rename = Some(RenameState {
6668                        range,
6669                        old_name,
6670                        editor: rename_editor,
6671                        block_id,
6672                    });
6673                })?;
6674            }
6675
6676            Ok(())
6677        }))
6678    }
6679
6680    pub fn confirm_rename(
6681        workspace: &mut Workspace,
6682        _: &ConfirmRename,
6683        cx: &mut ViewContext<Workspace>,
6684    ) -> Option<Task<Result<()>>> {
6685        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6686
6687        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6688            let rename = editor.take_rename(false, cx)?;
6689            let buffer = editor.buffer.read(cx);
6690            let (start_buffer, start) =
6691                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6692            let (end_buffer, end) =
6693                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6694            if start_buffer == end_buffer {
6695                let new_name = rename.editor.read(cx).text(cx);
6696                Some((start_buffer, start..end, rename.old_name, new_name))
6697            } else {
6698                None
6699            }
6700        })?;
6701
6702        let rename = workspace.project().clone().update(cx, |project, cx| {
6703            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6704        });
6705
6706        let editor = editor.downgrade();
6707        Some(cx.spawn(|workspace, mut cx| async move {
6708            let project_transaction = rename.await?;
6709            Self::open_project_transaction(
6710                &editor,
6711                workspace,
6712                project_transaction,
6713                format!("Rename: {}{}", old_name, new_name),
6714                cx.clone(),
6715            )
6716            .await?;
6717
6718            editor.update(&mut cx, |editor, cx| {
6719                editor.refresh_document_highlights(cx);
6720            })?;
6721            Ok(())
6722        }))
6723    }
6724
6725    fn take_rename(
6726        &mut self,
6727        moving_cursor: bool,
6728        cx: &mut ViewContext<Self>,
6729    ) -> Option<RenameState> {
6730        let rename = self.pending_rename.take()?;
6731        self.remove_blocks(
6732            [rename.block_id].into_iter().collect(),
6733            Some(Autoscroll::fit()),
6734            cx,
6735        );
6736        self.clear_text_highlights::<Rename>(cx);
6737        self.show_local_selections = true;
6738
6739        if moving_cursor {
6740            let rename_editor = rename.editor.read(cx);
6741            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6742
6743            // Update the selection to match the position of the selection inside
6744            // the rename editor.
6745            let snapshot = self.buffer.read(cx).read(cx);
6746            let rename_range = rename.range.to_offset(&snapshot);
6747            let cursor_in_editor = snapshot
6748                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6749                .min(rename_range.end);
6750            drop(snapshot);
6751
6752            self.change_selections(None, cx, |s| {
6753                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6754            });
6755        } else {
6756            self.refresh_document_highlights(cx);
6757        }
6758
6759        Some(rename)
6760    }
6761
6762    #[cfg(any(test, feature = "test-support"))]
6763    pub fn pending_rename(&self) -> Option<&RenameState> {
6764        self.pending_rename.as_ref()
6765    }
6766
6767    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6768        let project = match &self.project {
6769            Some(project) => project.clone(),
6770            None => return None,
6771        };
6772
6773        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6774    }
6775
6776    fn perform_format(
6777        &mut self,
6778        project: ModelHandle<Project>,
6779        trigger: FormatTrigger,
6780        cx: &mut ViewContext<Self>,
6781    ) -> Task<Result<()>> {
6782        let buffer = self.buffer().clone();
6783        let buffers = buffer.read(cx).all_buffers();
6784
6785        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6786        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6787
6788        cx.spawn(|_, mut cx| async move {
6789            let transaction = futures::select_biased! {
6790                _ = timeout => {
6791                    log::warn!("timed out waiting for formatting");
6792                    None
6793                }
6794                transaction = format.log_err().fuse() => transaction,
6795            };
6796
6797            buffer.update(&mut cx, |buffer, cx| {
6798                if let Some(transaction) = transaction {
6799                    if !buffer.is_singleton() {
6800                        buffer.push_transaction(&transaction.0, cx);
6801                    }
6802                }
6803
6804                cx.notify();
6805            });
6806
6807            Ok(())
6808        })
6809    }
6810
6811    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6812        if let Some(project) = self.project.clone() {
6813            self.buffer.update(cx, |multi_buffer, cx| {
6814                project.update(cx, |project, cx| {
6815                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6816                });
6817            })
6818        }
6819    }
6820
6821    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6822        cx.show_character_palette();
6823    }
6824
6825    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6826        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6827            let buffer = self.buffer.read(cx).snapshot(cx);
6828            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6829            let is_valid = buffer
6830                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6831                .any(|entry| {
6832                    entry.diagnostic.is_primary
6833                        && !entry.range.is_empty()
6834                        && entry.range.start == primary_range_start
6835                        && entry.diagnostic.message == active_diagnostics.primary_message
6836                });
6837
6838            if is_valid != active_diagnostics.is_valid {
6839                active_diagnostics.is_valid = is_valid;
6840                let mut new_styles = HashMap::default();
6841                for (block_id, diagnostic) in &active_diagnostics.blocks {
6842                    new_styles.insert(
6843                        *block_id,
6844                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6845                    );
6846                }
6847                self.display_map
6848                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6849            }
6850        }
6851    }
6852
6853    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6854        self.dismiss_diagnostics(cx);
6855        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6856            let buffer = self.buffer.read(cx).snapshot(cx);
6857
6858            let mut primary_range = None;
6859            let mut primary_message = None;
6860            let mut group_end = Point::zero();
6861            let diagnostic_group = buffer
6862                .diagnostic_group::<Point>(group_id)
6863                .map(|entry| {
6864                    if entry.range.end > group_end {
6865                        group_end = entry.range.end;
6866                    }
6867                    if entry.diagnostic.is_primary {
6868                        primary_range = Some(entry.range.clone());
6869                        primary_message = Some(entry.diagnostic.message.clone());
6870                    }
6871                    entry
6872                })
6873                .collect::<Vec<_>>();
6874            let primary_range = primary_range?;
6875            let primary_message = primary_message?;
6876            let primary_range =
6877                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6878
6879            let blocks = display_map
6880                .insert_blocks(
6881                    diagnostic_group.iter().map(|entry| {
6882                        let diagnostic = entry.diagnostic.clone();
6883                        let message_height = diagnostic.message.lines().count() as u8;
6884                        BlockProperties {
6885                            style: BlockStyle::Fixed,
6886                            position: buffer.anchor_after(entry.range.start),
6887                            height: message_height,
6888                            render: diagnostic_block_renderer(diagnostic, true),
6889                            disposition: BlockDisposition::Below,
6890                        }
6891                    }),
6892                    cx,
6893                )
6894                .into_iter()
6895                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6896                .collect();
6897
6898            Some(ActiveDiagnosticGroup {
6899                primary_range,
6900                primary_message,
6901                blocks,
6902                is_valid: true,
6903            })
6904        });
6905        self.active_diagnostics.is_some()
6906    }
6907
6908    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6909        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6910            self.display_map.update(cx, |display_map, cx| {
6911                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6912            });
6913            cx.notify();
6914        }
6915    }
6916
6917    pub fn set_selections_from_remote(
6918        &mut self,
6919        selections: Vec<Selection<Anchor>>,
6920        pending_selection: Option<Selection<Anchor>>,
6921        cx: &mut ViewContext<Self>,
6922    ) {
6923        let old_cursor_position = self.selections.newest_anchor().head();
6924        self.selections.change_with(cx, |s| {
6925            s.select_anchors(selections);
6926            if let Some(pending_selection) = pending_selection {
6927                s.set_pending(pending_selection, SelectMode::Character);
6928            } else {
6929                s.clear_pending();
6930            }
6931        });
6932        self.selections_did_change(false, &old_cursor_position, cx);
6933    }
6934
6935    fn push_to_selection_history(&mut self) {
6936        self.selection_history.push(SelectionHistoryEntry {
6937            selections: self.selections.disjoint_anchors(),
6938            select_next_state: self.select_next_state.clone(),
6939            select_prev_state: self.select_prev_state.clone(),
6940            add_selections_state: self.add_selections_state.clone(),
6941        });
6942    }
6943
6944    pub fn transact(
6945        &mut self,
6946        cx: &mut ViewContext<Self>,
6947        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6948    ) -> Option<TransactionId> {
6949        self.start_transaction_at(Instant::now(), cx);
6950        update(self, cx);
6951        self.end_transaction_at(Instant::now(), cx)
6952    }
6953
6954    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6955        self.end_selection(cx);
6956        if let Some(tx_id) = self
6957            .buffer
6958            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6959        {
6960            self.selection_history
6961                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6962        }
6963    }
6964
6965    fn end_transaction_at(
6966        &mut self,
6967        now: Instant,
6968        cx: &mut ViewContext<Self>,
6969    ) -> Option<TransactionId> {
6970        if let Some(tx_id) = self
6971            .buffer
6972            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6973        {
6974            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6975                *end_selections = Some(self.selections.disjoint_anchors());
6976            } else {
6977                error!("unexpectedly ended a transaction that wasn't started by this editor");
6978            }
6979
6980            cx.emit(Event::Edited);
6981            Some(tx_id)
6982        } else {
6983            None
6984        }
6985    }
6986
6987    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6988        let mut fold_ranges = Vec::new();
6989
6990        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6991
6992        let selections = self.selections.all::<Point>(cx);
6993        for selection in selections {
6994            let range = selection.range().sorted();
6995            let buffer_start_row = range.start.row;
6996
6997            for row in (0..=range.end.row).rev() {
6998                let fold_range = display_map.foldable_range(row);
6999
7000                if let Some(fold_range) = fold_range {
7001                    if fold_range.end.row >= buffer_start_row {
7002                        fold_ranges.push(fold_range);
7003                        if row <= range.start.row {
7004                            break;
7005                        }
7006                    }
7007                }
7008            }
7009        }
7010
7011        self.fold_ranges(fold_ranges, true, cx);
7012    }
7013
7014    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7015        let buffer_row = fold_at.buffer_row;
7016        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7017
7018        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7019            let autoscroll = self
7020                .selections
7021                .all::<Point>(cx)
7022                .iter()
7023                .any(|selection| fold_range.overlaps(&selection.range()));
7024
7025            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7026        }
7027    }
7028
7029    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7030        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7031        let buffer = &display_map.buffer_snapshot;
7032        let selections = self.selections.all::<Point>(cx);
7033        let ranges = selections
7034            .iter()
7035            .map(|s| {
7036                let range = s.display_range(&display_map).sorted();
7037                let mut start = range.start.to_point(&display_map);
7038                let mut end = range.end.to_point(&display_map);
7039                start.column = 0;
7040                end.column = buffer.line_len(end.row);
7041                start..end
7042            })
7043            .collect::<Vec<_>>();
7044
7045        self.unfold_ranges(ranges, true, true, cx);
7046    }
7047
7048    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7049        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7050
7051        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7052            ..Point::new(
7053                unfold_at.buffer_row,
7054                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7055            );
7056
7057        let autoscroll = self
7058            .selections
7059            .all::<Point>(cx)
7060            .iter()
7061            .any(|selection| selection.range().overlaps(&intersection_range));
7062
7063        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7064    }
7065
7066    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7067        let selections = self.selections.all::<Point>(cx);
7068        let ranges = selections.into_iter().map(|s| s.start..s.end);
7069        self.fold_ranges(ranges, true, cx);
7070    }
7071
7072    pub fn fold_ranges<T: ToOffset + Clone>(
7073        &mut self,
7074        ranges: impl IntoIterator<Item = Range<T>>,
7075        auto_scroll: bool,
7076        cx: &mut ViewContext<Self>,
7077    ) {
7078        let mut ranges = ranges.into_iter().peekable();
7079        if ranges.peek().is_some() {
7080            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7081
7082            if auto_scroll {
7083                self.request_autoscroll(Autoscroll::fit(), cx);
7084            }
7085
7086            cx.notify();
7087        }
7088    }
7089
7090    pub fn unfold_ranges<T: ToOffset + Clone>(
7091        &mut self,
7092        ranges: impl IntoIterator<Item = Range<T>>,
7093        inclusive: bool,
7094        auto_scroll: bool,
7095        cx: &mut ViewContext<Self>,
7096    ) {
7097        let mut ranges = ranges.into_iter().peekable();
7098        if ranges.peek().is_some() {
7099            self.display_map
7100                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7101            if auto_scroll {
7102                self.request_autoscroll(Autoscroll::fit(), cx);
7103            }
7104
7105            cx.notify();
7106        }
7107    }
7108
7109    pub fn gutter_hover(
7110        &mut self,
7111        GutterHover { hovered }: &GutterHover,
7112        cx: &mut ViewContext<Self>,
7113    ) {
7114        self.gutter_hovered = *hovered;
7115        cx.notify();
7116    }
7117
7118    pub fn insert_blocks(
7119        &mut self,
7120        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7121        autoscroll: Option<Autoscroll>,
7122        cx: &mut ViewContext<Self>,
7123    ) -> Vec<BlockId> {
7124        let blocks = self
7125            .display_map
7126            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7127        if let Some(autoscroll) = autoscroll {
7128            self.request_autoscroll(autoscroll, cx);
7129        }
7130        blocks
7131    }
7132
7133    pub fn replace_blocks(
7134        &mut self,
7135        blocks: HashMap<BlockId, RenderBlock>,
7136        autoscroll: Option<Autoscroll>,
7137        cx: &mut ViewContext<Self>,
7138    ) {
7139        self.display_map
7140            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7141        if let Some(autoscroll) = autoscroll {
7142            self.request_autoscroll(autoscroll, cx);
7143        }
7144    }
7145
7146    pub fn remove_blocks(
7147        &mut self,
7148        block_ids: HashSet<BlockId>,
7149        autoscroll: Option<Autoscroll>,
7150        cx: &mut ViewContext<Self>,
7151    ) {
7152        self.display_map.update(cx, |display_map, cx| {
7153            display_map.remove_blocks(block_ids, cx)
7154        });
7155        if let Some(autoscroll) = autoscroll {
7156            self.request_autoscroll(autoscroll, cx);
7157        }
7158    }
7159
7160    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7161        self.display_map
7162            .update(cx, |map, cx| map.snapshot(cx))
7163            .longest_row()
7164    }
7165
7166    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7167        self.display_map
7168            .update(cx, |map, cx| map.snapshot(cx))
7169            .max_point()
7170    }
7171
7172    pub fn text(&self, cx: &AppContext) -> String {
7173        self.buffer.read(cx).read(cx).text()
7174    }
7175
7176    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7177        self.transact(cx, |this, cx| {
7178            this.buffer
7179                .read(cx)
7180                .as_singleton()
7181                .expect("you can only call set_text on editors for singleton buffers")
7182                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7183        });
7184    }
7185
7186    pub fn display_text(&self, cx: &mut AppContext) -> String {
7187        self.display_map
7188            .update(cx, |map, cx| map.snapshot(cx))
7189            .text()
7190    }
7191
7192    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7193        let mut wrap_guides = smallvec::smallvec![];
7194
7195        let settings = self.buffer.read(cx).settings_at(0, cx);
7196        if settings.show_wrap_guides {
7197            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7198                wrap_guides.push((soft_wrap as usize, true));
7199            }
7200            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7201        }
7202
7203        wrap_guides
7204    }
7205
7206    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7207        let settings = self.buffer.read(cx).settings_at(0, cx);
7208        let mode = self
7209            .soft_wrap_mode_override
7210            .unwrap_or_else(|| settings.soft_wrap);
7211        match mode {
7212            language_settings::SoftWrap::None => SoftWrap::None,
7213            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7214            language_settings::SoftWrap::PreferredLineLength => {
7215                SoftWrap::Column(settings.preferred_line_length)
7216            }
7217        }
7218    }
7219
7220    pub fn set_soft_wrap_mode(
7221        &mut self,
7222        mode: language_settings::SoftWrap,
7223        cx: &mut ViewContext<Self>,
7224    ) {
7225        self.soft_wrap_mode_override = Some(mode);
7226        cx.notify();
7227    }
7228
7229    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7230        self.display_map
7231            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7232    }
7233
7234    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7235        if self.soft_wrap_mode_override.is_some() {
7236            self.soft_wrap_mode_override.take();
7237        } else {
7238            let soft_wrap = match self.soft_wrap_mode(cx) {
7239                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7240                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7241            };
7242            self.soft_wrap_mode_override = Some(soft_wrap);
7243        }
7244        cx.notify();
7245    }
7246
7247    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7248        self.show_gutter = show_gutter;
7249        cx.notify();
7250    }
7251
7252    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7253        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7254            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7255                cx.reveal_path(&file.abs_path(cx));
7256            }
7257        }
7258    }
7259
7260    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7261        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7262            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7263                if let Some(path) = file.abs_path(cx).to_str() {
7264                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7265                }
7266            }
7267        }
7268    }
7269
7270    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7271        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7272            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7273                if let Some(path) = file.path().to_str() {
7274                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7275                }
7276            }
7277        }
7278    }
7279
7280    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7281        self.highlighted_rows = rows;
7282    }
7283
7284    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7285        self.highlighted_rows.clone()
7286    }
7287
7288    pub fn highlight_background<T: 'static>(
7289        &mut self,
7290        ranges: Vec<Range<Anchor>>,
7291        color_fetcher: fn(&Theme) -> Color,
7292        cx: &mut ViewContext<Self>,
7293    ) {
7294        self.background_highlights
7295            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7296        cx.notify();
7297    }
7298
7299    #[allow(clippy::type_complexity)]
7300    pub fn clear_background_highlights<T: 'static>(
7301        &mut self,
7302        cx: &mut ViewContext<Self>,
7303    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7304        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7305        if highlights.is_some() {
7306            cx.notify();
7307        }
7308        highlights
7309    }
7310
7311    #[cfg(feature = "test-support")]
7312    pub fn all_background_highlights(
7313        &mut self,
7314        cx: &mut ViewContext<Self>,
7315    ) -> Vec<(Range<DisplayPoint>, Color)> {
7316        let snapshot = self.snapshot(cx);
7317        let buffer = &snapshot.buffer_snapshot;
7318        let start = buffer.anchor_before(0);
7319        let end = buffer.anchor_after(buffer.len());
7320        let theme = theme::current(cx);
7321        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7322    }
7323
7324    fn document_highlights_for_position<'a>(
7325        &'a self,
7326        position: Anchor,
7327        buffer: &'a MultiBufferSnapshot,
7328    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7329        let read_highlights = self
7330            .background_highlights
7331            .get(&TypeId::of::<DocumentHighlightRead>())
7332            .map(|h| &h.1);
7333        let write_highlights = self
7334            .background_highlights
7335            .get(&TypeId::of::<DocumentHighlightWrite>())
7336            .map(|h| &h.1);
7337        let left_position = position.bias_left(buffer);
7338        let right_position = position.bias_right(buffer);
7339        read_highlights
7340            .into_iter()
7341            .chain(write_highlights)
7342            .flat_map(move |ranges| {
7343                let start_ix = match ranges.binary_search_by(|probe| {
7344                    let cmp = probe.end.cmp(&left_position, buffer);
7345                    if cmp.is_ge() {
7346                        Ordering::Greater
7347                    } else {
7348                        Ordering::Less
7349                    }
7350                }) {
7351                    Ok(i) | Err(i) => i,
7352                };
7353
7354                let right_position = right_position.clone();
7355                ranges[start_ix..]
7356                    .iter()
7357                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7358            })
7359    }
7360
7361    pub fn background_highlights_in_range(
7362        &self,
7363        search_range: Range<Anchor>,
7364        display_snapshot: &DisplaySnapshot,
7365        theme: &Theme,
7366    ) -> Vec<(Range<DisplayPoint>, Color)> {
7367        let mut results = Vec::new();
7368        let buffer = &display_snapshot.buffer_snapshot;
7369        for (color_fetcher, ranges) in self.background_highlights.values() {
7370            let color = color_fetcher(theme);
7371            let start_ix = match ranges.binary_search_by(|probe| {
7372                let cmp = probe.end.cmp(&search_range.start, buffer);
7373                if cmp.is_gt() {
7374                    Ordering::Greater
7375                } else {
7376                    Ordering::Less
7377                }
7378            }) {
7379                Ok(i) | Err(i) => i,
7380            };
7381            for range in &ranges[start_ix..] {
7382                if range.start.cmp(&search_range.end, buffer).is_ge() {
7383                    break;
7384                }
7385                let start = range
7386                    .start
7387                    .to_point(buffer)
7388                    .to_display_point(display_snapshot);
7389                let end = range
7390                    .end
7391                    .to_point(buffer)
7392                    .to_display_point(display_snapshot);
7393                results.push((start..end, color))
7394            }
7395        }
7396        results
7397    }
7398    pub fn background_highlights_in_range_for<T: 'static>(
7399        &self,
7400        search_range: Range<Anchor>,
7401        display_snapshot: &DisplaySnapshot,
7402        theme: &Theme,
7403    ) -> Vec<(Range<DisplayPoint>, Color)> {
7404        let mut results = Vec::new();
7405        let buffer = &display_snapshot.buffer_snapshot;
7406        let Some((color_fetcher, ranges)) = self.background_highlights
7407            .get(&TypeId::of::<T>()) else {
7408                return vec![];
7409            };
7410
7411        let color = color_fetcher(theme);
7412        let start_ix = match ranges.binary_search_by(|probe| {
7413            let cmp = probe.end.cmp(&search_range.start, buffer);
7414            if cmp.is_gt() {
7415                Ordering::Greater
7416            } else {
7417                Ordering::Less
7418            }
7419        }) {
7420            Ok(i) | Err(i) => i,
7421        };
7422        for range in &ranges[start_ix..] {
7423            if range.start.cmp(&search_range.end, buffer).is_ge() {
7424                break;
7425            }
7426            let start = range
7427                .start
7428                .to_point(buffer)
7429                .to_display_point(display_snapshot);
7430            let end = range
7431                .end
7432                .to_point(buffer)
7433                .to_display_point(display_snapshot);
7434            results.push((start..end, color))
7435        }
7436
7437        results
7438    }
7439
7440    pub fn highlight_text<T: 'static>(
7441        &mut self,
7442        ranges: Vec<Range<Anchor>>,
7443        style: HighlightStyle,
7444        cx: &mut ViewContext<Self>,
7445    ) {
7446        self.display_map.update(cx, |map, _| {
7447            map.highlight_text(TypeId::of::<T>(), ranges, style)
7448        });
7449        cx.notify();
7450    }
7451
7452    pub fn text_highlights<'a, T: 'static>(
7453        &'a self,
7454        cx: &'a AppContext,
7455    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7456        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7457    }
7458
7459    pub fn clear_text_highlights<T: 'static>(
7460        &mut self,
7461        cx: &mut ViewContext<Self>,
7462    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7463        let highlights = self
7464            .display_map
7465            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7466        if highlights.is_some() {
7467            cx.notify();
7468        }
7469        highlights
7470    }
7471
7472    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7473        self.blink_manager.read(cx).visible() && self.focused
7474    }
7475
7476    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7477        cx.notify();
7478    }
7479
7480    fn on_buffer_event(
7481        &mut self,
7482        multibuffer: ModelHandle<MultiBuffer>,
7483        event: &multi_buffer::Event,
7484        cx: &mut ViewContext<Self>,
7485    ) {
7486        match event {
7487            multi_buffer::Event::Edited => {
7488                self.refresh_active_diagnostics(cx);
7489                self.refresh_code_actions(cx);
7490                if self.has_active_copilot_suggestion(cx) {
7491                    self.update_visible_copilot_suggestion(cx);
7492                }
7493                cx.emit(Event::BufferEdited);
7494
7495                if let Some(project) = &self.project {
7496                    let project = project.read(cx);
7497                    let languages_affected = multibuffer
7498                        .read(cx)
7499                        .all_buffers()
7500                        .into_iter()
7501                        .filter_map(|buffer| {
7502                            let buffer = buffer.read(cx);
7503                            let language = buffer.language()?;
7504                            if project.is_local()
7505                                && project.language_servers_for_buffer(buffer, cx).count() == 0
7506                            {
7507                                None
7508                            } else {
7509                                Some(language)
7510                            }
7511                        })
7512                        .cloned()
7513                        .collect::<HashSet<_>>();
7514                    if !languages_affected.is_empty() {
7515                        self.refresh_inlays(
7516                            InlayRefreshReason::BufferEdited(languages_affected),
7517                            cx,
7518                        );
7519                    }
7520                }
7521            }
7522            multi_buffer::Event::ExcerptsAdded {
7523                buffer,
7524                predecessor,
7525                excerpts,
7526            } => cx.emit(Event::ExcerptsAdded {
7527                buffer: buffer.clone(),
7528                predecessor: *predecessor,
7529                excerpts: excerpts.clone(),
7530            }),
7531            multi_buffer::Event::ExcerptsRemoved { ids } => {
7532                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7533            }
7534            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7535            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7536            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7537            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7538            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7539            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7540            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7541            multi_buffer::Event::DiagnosticsUpdated => {
7542                self.refresh_active_diagnostics(cx);
7543            }
7544            _ => {}
7545        };
7546    }
7547
7548    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7549        cx.notify();
7550    }
7551
7552    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7553        self.refresh_copilot_suggestions(true, cx);
7554        self.refresh_inlays(
7555            InlayRefreshReason::SettingsChange(inlay_hint_settings(
7556                self.selections.newest_anchor().head(),
7557                &self.buffer.read(cx).snapshot(cx),
7558                cx,
7559            )),
7560            cx,
7561        );
7562    }
7563
7564    pub fn set_searchable(&mut self, searchable: bool) {
7565        self.searchable = searchable;
7566    }
7567
7568    pub fn searchable(&self) -> bool {
7569        self.searchable
7570    }
7571
7572    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7573        let active_item = workspace.active_item(cx);
7574        let editor_handle = if let Some(editor) = active_item
7575            .as_ref()
7576            .and_then(|item| item.act_as::<Self>(cx))
7577        {
7578            editor
7579        } else {
7580            cx.propagate_action();
7581            return;
7582        };
7583
7584        let editor = editor_handle.read(cx);
7585        let buffer = editor.buffer.read(cx);
7586        if buffer.is_singleton() {
7587            cx.propagate_action();
7588            return;
7589        }
7590
7591        let mut new_selections_by_buffer = HashMap::default();
7592        for selection in editor.selections.all::<usize>(cx) {
7593            for (buffer, mut range, _) in
7594                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7595            {
7596                if selection.reversed {
7597                    mem::swap(&mut range.start, &mut range.end);
7598                }
7599                new_selections_by_buffer
7600                    .entry(buffer)
7601                    .or_insert(Vec::new())
7602                    .push(range)
7603            }
7604        }
7605
7606        editor_handle.update(cx, |editor, cx| {
7607            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7608        });
7609        let pane = workspace.active_pane().clone();
7610        pane.update(cx, |pane, _| pane.disable_history());
7611
7612        // We defer the pane interaction because we ourselves are a workspace item
7613        // and activating a new item causes the pane to call a method on us reentrantly,
7614        // which panics if we're on the stack.
7615        cx.defer(move |workspace, cx| {
7616            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7617                let editor = workspace.open_project_item::<Self>(buffer, cx);
7618                editor.update(cx, |editor, cx| {
7619                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7620                        s.select_ranges(ranges);
7621                    });
7622                });
7623            }
7624
7625            pane.update(cx, |pane, _| pane.enable_history());
7626        });
7627    }
7628
7629    fn jump(
7630        workspace: &mut Workspace,
7631        path: ProjectPath,
7632        position: Point,
7633        anchor: language::Anchor,
7634        cx: &mut ViewContext<Workspace>,
7635    ) {
7636        let editor = workspace.open_path(path, None, true, cx);
7637        cx.spawn(|_, mut cx| async move {
7638            let editor = editor
7639                .await?
7640                .downcast::<Editor>()
7641                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7642                .downgrade();
7643            editor.update(&mut cx, |editor, cx| {
7644                let buffer = editor
7645                    .buffer()
7646                    .read(cx)
7647                    .as_singleton()
7648                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7649                let buffer = buffer.read(cx);
7650                let cursor = if buffer.can_resolve(&anchor) {
7651                    language::ToPoint::to_point(&anchor, buffer)
7652                } else {
7653                    buffer.clip_point(position, Bias::Left)
7654                };
7655
7656                let nav_history = editor.nav_history.take();
7657                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7658                    s.select_ranges([cursor..cursor]);
7659                });
7660                editor.nav_history = nav_history;
7661
7662                anyhow::Ok(())
7663            })??;
7664
7665            anyhow::Ok(())
7666        })
7667        .detach_and_log_err(cx);
7668    }
7669
7670    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7671        let snapshot = self.buffer.read(cx).read(cx);
7672        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7673        Some(
7674            ranges
7675                .iter()
7676                .map(move |range| {
7677                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7678                })
7679                .collect(),
7680        )
7681    }
7682
7683    fn selection_replacement_ranges(
7684        &self,
7685        range: Range<OffsetUtf16>,
7686        cx: &AppContext,
7687    ) -> Vec<Range<OffsetUtf16>> {
7688        let selections = self.selections.all::<OffsetUtf16>(cx);
7689        let newest_selection = selections
7690            .iter()
7691            .max_by_key(|selection| selection.id)
7692            .unwrap();
7693        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7694        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7695        let snapshot = self.buffer.read(cx).read(cx);
7696        selections
7697            .into_iter()
7698            .map(|mut selection| {
7699                selection.start.0 =
7700                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7701                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7702                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7703                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7704            })
7705            .collect()
7706    }
7707
7708    fn report_copilot_event(
7709        &self,
7710        suggestion_id: Option<String>,
7711        suggestion_accepted: bool,
7712        cx: &AppContext,
7713    ) {
7714        let Some(project) = &self.project else {
7715            return
7716        };
7717
7718        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7719        let file_extension = self
7720            .buffer
7721            .read(cx)
7722            .as_singleton()
7723            .and_then(|b| b.read(cx).file())
7724            .and_then(|file| Path::new(file.file_name(cx)).extension())
7725            .and_then(|e| e.to_str())
7726            .map(|a| a.to_string());
7727
7728        let telemetry = project.read(cx).client().telemetry().clone();
7729        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7730
7731        let event = ClickhouseEvent::Copilot {
7732            suggestion_id,
7733            suggestion_accepted,
7734            file_extension,
7735        };
7736        telemetry.report_clickhouse_event(event, telemetry_settings);
7737    }
7738
7739    fn report_editor_event(
7740        &self,
7741        operation: &'static str,
7742        file_extension: Option<String>,
7743        cx: &AppContext,
7744    ) {
7745        let Some(project) = &self.project else {
7746            return
7747        };
7748
7749        // If None, we are in a file without an extension
7750        let file = self
7751            .buffer
7752            .read(cx)
7753            .as_singleton()
7754            .and_then(|b| b.read(cx).file());
7755        let file_extension = file_extension.or(file
7756            .as_ref()
7757            .and_then(|file| Path::new(file.file_name(cx)).extension())
7758            .and_then(|e| e.to_str())
7759            .map(|a| a.to_string()));
7760
7761        let vim_mode = cx
7762            .global::<SettingsStore>()
7763            .raw_user_settings()
7764            .get("vim_mode")
7765            == Some(&serde_json::Value::Bool(true));
7766        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7767        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7768        let copilot_enabled_for_language = self
7769            .buffer
7770            .read(cx)
7771            .settings_at(0, cx)
7772            .show_copilot_suggestions;
7773
7774        let telemetry = project.read(cx).client().telemetry().clone();
7775        let event = ClickhouseEvent::Editor {
7776            file_extension,
7777            vim_mode,
7778            operation,
7779            copilot_enabled,
7780            copilot_enabled_for_language,
7781        };
7782        telemetry.report_clickhouse_event(event, telemetry_settings)
7783    }
7784
7785    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7786    /// with each line being an array of {text, highlight} objects.
7787    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7788        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7789            return;
7790        };
7791
7792        #[derive(Serialize)]
7793        struct Chunk<'a> {
7794            text: String,
7795            highlight: Option<&'a str>,
7796        }
7797
7798        let snapshot = buffer.read(cx).snapshot();
7799        let range = self
7800            .selected_text_range(cx)
7801            .and_then(|selected_range| {
7802                if selected_range.is_empty() {
7803                    None
7804                } else {
7805                    Some(selected_range)
7806                }
7807            })
7808            .unwrap_or_else(|| 0..snapshot.len());
7809
7810        let chunks = snapshot.chunks(range, true);
7811        let mut lines = Vec::new();
7812        let mut line: VecDeque<Chunk> = VecDeque::new();
7813
7814        let theme = &theme::current(cx).editor.syntax;
7815
7816        for chunk in chunks {
7817            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7818            let mut chunk_lines = chunk.text.split("\n").peekable();
7819            while let Some(text) = chunk_lines.next() {
7820                let mut merged_with_last_token = false;
7821                if let Some(last_token) = line.back_mut() {
7822                    if last_token.highlight == highlight {
7823                        last_token.text.push_str(text);
7824                        merged_with_last_token = true;
7825                    }
7826                }
7827
7828                if !merged_with_last_token {
7829                    line.push_back(Chunk {
7830                        text: text.into(),
7831                        highlight,
7832                    });
7833                }
7834
7835                if chunk_lines.peek().is_some() {
7836                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7837                        line.pop_front();
7838                    }
7839                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7840                        line.pop_back();
7841                    }
7842
7843                    lines.push(mem::take(&mut line));
7844                }
7845            }
7846        }
7847
7848        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7849        cx.write_to_clipboard(ClipboardItem::new(lines));
7850    }
7851
7852    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
7853        &self.inlay_hint_cache
7854    }
7855}
7856
7857fn inlay_hint_settings(
7858    location: Anchor,
7859    snapshot: &MultiBufferSnapshot,
7860    cx: &mut ViewContext<'_, '_, Editor>,
7861) -> InlayHintSettings {
7862    let file = snapshot.file_at(location);
7863    let language = snapshot.language_at(location);
7864    let settings = all_language_settings(file, cx);
7865    settings
7866        .language(language.map(|l| l.name()).as_deref())
7867        .inlay_hints
7868}
7869
7870fn consume_contiguous_rows(
7871    contiguous_row_selections: &mut Vec<Selection<Point>>,
7872    selection: &Selection<Point>,
7873    display_map: &DisplaySnapshot,
7874    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7875) -> (u32, u32) {
7876    contiguous_row_selections.push(selection.clone());
7877    let start_row = selection.start.row;
7878    let mut end_row = ending_row(selection, display_map);
7879
7880    while let Some(next_selection) = selections.peek() {
7881        if next_selection.start.row <= end_row {
7882            end_row = ending_row(next_selection, display_map);
7883            contiguous_row_selections.push(selections.next().unwrap().clone());
7884        } else {
7885            break;
7886        }
7887    }
7888    (start_row, end_row)
7889}
7890
7891fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7892    if next_selection.end.column > 0 || next_selection.is_empty() {
7893        display_map.next_line_boundary(next_selection.end).0.row + 1
7894    } else {
7895        next_selection.end.row
7896    }
7897}
7898
7899impl EditorSnapshot {
7900    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7901        self.display_snapshot.buffer_snapshot.language_at(position)
7902    }
7903
7904    pub fn is_focused(&self) -> bool {
7905        self.is_focused
7906    }
7907
7908    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7909        self.placeholder_text.as_ref()
7910    }
7911
7912    pub fn scroll_position(&self) -> Vector2F {
7913        self.scroll_anchor.scroll_position(&self.display_snapshot)
7914    }
7915}
7916
7917impl Deref for EditorSnapshot {
7918    type Target = DisplaySnapshot;
7919
7920    fn deref(&self) -> &Self::Target {
7921        &self.display_snapshot
7922    }
7923}
7924
7925#[derive(Clone, Debug, PartialEq, Eq)]
7926pub enum Event {
7927    InputIgnored {
7928        text: Arc<str>,
7929    },
7930    ExcerptsAdded {
7931        buffer: ModelHandle<Buffer>,
7932        predecessor: ExcerptId,
7933        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7934    },
7935    ExcerptsRemoved {
7936        ids: Vec<ExcerptId>,
7937    },
7938    BufferEdited,
7939    Edited,
7940    Reparsed,
7941    Focused,
7942    Blurred,
7943    DirtyChanged,
7944    Saved,
7945    TitleChanged,
7946    DiffBaseChanged,
7947    SelectionsChanged {
7948        local: bool,
7949    },
7950    ScrollPositionChanged {
7951        local: bool,
7952        autoscroll: bool,
7953    },
7954    Closed,
7955}
7956
7957pub struct EditorFocused(pub ViewHandle<Editor>);
7958pub struct EditorBlurred(pub ViewHandle<Editor>);
7959pub struct EditorReleased(pub WeakViewHandle<Editor>);
7960
7961impl Entity for Editor {
7962    type Event = Event;
7963
7964    fn release(&mut self, cx: &mut AppContext) {
7965        cx.emit_global(EditorReleased(self.handle.clone()));
7966    }
7967}
7968
7969impl View for Editor {
7970    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7971        let style = self.style(cx);
7972        let font_changed = self.display_map.update(cx, |map, cx| {
7973            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7974            map.set_font(style.text.font_id, style.text.font_size, cx)
7975        });
7976
7977        if font_changed {
7978            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7979                hide_hover(editor, cx);
7980                hide_link_definition(editor, cx);
7981            });
7982        }
7983
7984        Stack::new()
7985            .with_child(EditorElement::new(style.clone()))
7986            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7987            .into_any()
7988    }
7989
7990    fn ui_name() -> &'static str {
7991        "Editor"
7992    }
7993
7994    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7995        if cx.is_self_focused() {
7996            let focused_event = EditorFocused(cx.handle());
7997            cx.emit(Event::Focused);
7998            cx.emit_global(focused_event);
7999        }
8000        if let Some(rename) = self.pending_rename.as_ref() {
8001            cx.focus(&rename.editor);
8002        } else {
8003            if !self.focused {
8004                self.blink_manager.update(cx, BlinkManager::enable);
8005            }
8006            self.focused = true;
8007            self.buffer.update(cx, |buffer, cx| {
8008                buffer.finalize_last_transaction(cx);
8009                if self.leader_replica_id.is_none() {
8010                    buffer.set_active_selections(
8011                        &self.selections.disjoint_anchors(),
8012                        self.selections.line_mode,
8013                        self.cursor_shape,
8014                        cx,
8015                    );
8016                }
8017            });
8018        }
8019    }
8020
8021    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8022        let blurred_event = EditorBlurred(cx.handle());
8023        cx.emit_global(blurred_event);
8024        self.focused = false;
8025        self.blink_manager.update(cx, BlinkManager::disable);
8026        self.buffer
8027            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8028        self.hide_context_menu(cx);
8029        hide_hover(self, cx);
8030        cx.emit(Event::Blurred);
8031        cx.notify();
8032    }
8033
8034    fn modifiers_changed(
8035        &mut self,
8036        event: &gpui::platform::ModifiersChangedEvent,
8037        cx: &mut ViewContext<Self>,
8038    ) -> bool {
8039        let pending_selection = self.has_pending_selection();
8040
8041        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
8042            if event.cmd && !pending_selection {
8043                let snapshot = self.snapshot(cx);
8044                let kind = if event.shift {
8045                    LinkDefinitionKind::Type
8046                } else {
8047                    LinkDefinitionKind::Symbol
8048                };
8049
8050                show_link_definition(kind, self, point, snapshot, cx);
8051                return false;
8052            }
8053        }
8054
8055        {
8056            if self.link_go_to_definition_state.symbol_range.is_some()
8057                || !self.link_go_to_definition_state.definitions.is_empty()
8058            {
8059                self.link_go_to_definition_state.symbol_range.take();
8060                self.link_go_to_definition_state.definitions.clear();
8061                cx.notify();
8062            }
8063
8064            self.link_go_to_definition_state.task = None;
8065
8066            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8067        }
8068
8069        false
8070    }
8071
8072    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8073        Self::reset_to_default_keymap_context(keymap);
8074        let mode = match self.mode {
8075            EditorMode::SingleLine => "single_line",
8076            EditorMode::AutoHeight { .. } => "auto_height",
8077            EditorMode::Full => "full",
8078        };
8079        keymap.add_key("mode", mode);
8080        if self.pending_rename.is_some() {
8081            keymap.add_identifier("renaming");
8082        }
8083        match self.context_menu.as_ref() {
8084            Some(ContextMenu::Completions(_)) => {
8085                keymap.add_identifier("menu");
8086                keymap.add_identifier("showing_completions")
8087            }
8088            Some(ContextMenu::CodeActions(_)) => {
8089                keymap.add_identifier("menu");
8090                keymap.add_identifier("showing_code_actions")
8091            }
8092            None => {}
8093        }
8094        for layer in self.keymap_context_layers.values() {
8095            keymap.extend(layer);
8096        }
8097
8098        if let Some(extension) = self
8099            .buffer
8100            .read(cx)
8101            .as_singleton()
8102            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8103        {
8104            keymap.add_key("extension", extension.to_string());
8105        }
8106    }
8107
8108    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8109        Some(
8110            self.buffer
8111                .read(cx)
8112                .read(cx)
8113                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8114                .collect(),
8115        )
8116    }
8117
8118    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8119        // Prevent the IME menu from appearing when holding down an alphabetic key
8120        // while input is disabled.
8121        if !self.input_enabled {
8122            return None;
8123        }
8124
8125        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8126        Some(range.start.0..range.end.0)
8127    }
8128
8129    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8130        let snapshot = self.buffer.read(cx).read(cx);
8131        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8132        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8133    }
8134
8135    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8136        self.clear_text_highlights::<InputComposition>(cx);
8137        self.ime_transaction.take();
8138    }
8139
8140    fn replace_text_in_range(
8141        &mut self,
8142        range_utf16: Option<Range<usize>>,
8143        text: &str,
8144        cx: &mut ViewContext<Self>,
8145    ) {
8146        self.transact(cx, |this, cx| {
8147            if this.input_enabled {
8148                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8149                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8150                    Some(this.selection_replacement_ranges(range_utf16, cx))
8151                } else {
8152                    this.marked_text_ranges(cx)
8153                };
8154
8155                if let Some(new_selected_ranges) = new_selected_ranges {
8156                    this.change_selections(None, cx, |selections| {
8157                        selections.select_ranges(new_selected_ranges)
8158                    });
8159                }
8160            }
8161
8162            this.handle_input(text, cx);
8163        });
8164
8165        if !self.input_enabled {
8166            return;
8167        }
8168
8169        if let Some(transaction) = self.ime_transaction {
8170            self.buffer.update(cx, |buffer, cx| {
8171                buffer.group_until_transaction(transaction, cx);
8172            });
8173        }
8174
8175        self.unmark_text(cx);
8176    }
8177
8178    fn replace_and_mark_text_in_range(
8179        &mut self,
8180        range_utf16: Option<Range<usize>>,
8181        text: &str,
8182        new_selected_range_utf16: Option<Range<usize>>,
8183        cx: &mut ViewContext<Self>,
8184    ) {
8185        if !self.input_enabled {
8186            return;
8187        }
8188
8189        let transaction = self.transact(cx, |this, cx| {
8190            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8191                let snapshot = this.buffer.read(cx).read(cx);
8192                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8193                    for marked_range in &mut marked_ranges {
8194                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8195                        marked_range.start.0 += relative_range_utf16.start;
8196                        marked_range.start =
8197                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8198                        marked_range.end =
8199                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8200                    }
8201                }
8202                Some(marked_ranges)
8203            } else if let Some(range_utf16) = range_utf16 {
8204                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8205                Some(this.selection_replacement_ranges(range_utf16, cx))
8206            } else {
8207                None
8208            };
8209
8210            if let Some(ranges) = ranges_to_replace {
8211                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8212            }
8213
8214            let marked_ranges = {
8215                let snapshot = this.buffer.read(cx).read(cx);
8216                this.selections
8217                    .disjoint_anchors()
8218                    .iter()
8219                    .map(|selection| {
8220                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8221                    })
8222                    .collect::<Vec<_>>()
8223            };
8224
8225            if text.is_empty() {
8226                this.unmark_text(cx);
8227            } else {
8228                this.highlight_text::<InputComposition>(
8229                    marked_ranges.clone(),
8230                    this.style(cx).composition_mark,
8231                    cx,
8232                );
8233            }
8234
8235            this.handle_input(text, cx);
8236
8237            if let Some(new_selected_range) = new_selected_range_utf16 {
8238                let snapshot = this.buffer.read(cx).read(cx);
8239                let new_selected_ranges = marked_ranges
8240                    .into_iter()
8241                    .map(|marked_range| {
8242                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8243                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8244                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8245                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8246                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8247                    })
8248                    .collect::<Vec<_>>();
8249
8250                drop(snapshot);
8251                this.change_selections(None, cx, |selections| {
8252                    selections.select_ranges(new_selected_ranges)
8253                });
8254            }
8255        });
8256
8257        self.ime_transaction = self.ime_transaction.or(transaction);
8258        if let Some(transaction) = self.ime_transaction {
8259            self.buffer.update(cx, |buffer, cx| {
8260                buffer.group_until_transaction(transaction, cx);
8261            });
8262        }
8263
8264        if self.text_highlights::<InputComposition>(cx).is_none() {
8265            self.ime_transaction.take();
8266        }
8267    }
8268}
8269
8270fn build_style(
8271    settings: &ThemeSettings,
8272    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8273    override_text_style: Option<&OverrideTextStyle>,
8274    cx: &AppContext,
8275) -> EditorStyle {
8276    let font_cache = cx.font_cache();
8277    let line_height_scalar = settings.line_height();
8278    let theme_id = settings.theme.meta.id;
8279    let mut theme = settings.theme.editor.clone();
8280    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8281        let field_editor_theme = get_field_editor_theme(&settings.theme);
8282        theme.text_color = field_editor_theme.text.color;
8283        theme.selection = field_editor_theme.selection;
8284        theme.background = field_editor_theme
8285            .container
8286            .background_color
8287            .unwrap_or_default();
8288        EditorStyle {
8289            text: field_editor_theme.text,
8290            placeholder_text: field_editor_theme.placeholder_text,
8291            line_height_scalar,
8292            theme,
8293            theme_id,
8294        }
8295    } else {
8296        let font_family_id = settings.buffer_font_family;
8297        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8298        let font_properties = Default::default();
8299        let font_id = font_cache
8300            .select_font(font_family_id, &font_properties)
8301            .unwrap();
8302        let font_size = settings.buffer_font_size(cx);
8303        EditorStyle {
8304            text: TextStyle {
8305                color: settings.theme.editor.text_color,
8306                font_family_name,
8307                font_family_id,
8308                font_id,
8309                font_size,
8310                font_properties,
8311                underline: Default::default(),
8312            },
8313            placeholder_text: None,
8314            line_height_scalar,
8315            theme,
8316            theme_id,
8317        }
8318    };
8319
8320    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8321        if let Some(highlighted) = style
8322            .text
8323            .clone()
8324            .highlight(highlight_style, font_cache)
8325            .log_err()
8326        {
8327            style.text = highlighted;
8328        }
8329    }
8330
8331    style
8332}
8333
8334trait SelectionExt {
8335    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8336    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8337    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8338    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8339        -> Range<u32>;
8340}
8341
8342impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8343    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8344        let start = self.start.to_point(buffer);
8345        let end = self.end.to_point(buffer);
8346        if self.reversed {
8347            end..start
8348        } else {
8349            start..end
8350        }
8351    }
8352
8353    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8354        let start = self.start.to_offset(buffer);
8355        let end = self.end.to_offset(buffer);
8356        if self.reversed {
8357            end..start
8358        } else {
8359            start..end
8360        }
8361    }
8362
8363    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8364        let start = self
8365            .start
8366            .to_point(&map.buffer_snapshot)
8367            .to_display_point(map);
8368        let end = self
8369            .end
8370            .to_point(&map.buffer_snapshot)
8371            .to_display_point(map);
8372        if self.reversed {
8373            end..start
8374        } else {
8375            start..end
8376        }
8377    }
8378
8379    fn spanned_rows(
8380        &self,
8381        include_end_if_at_line_start: bool,
8382        map: &DisplaySnapshot,
8383    ) -> Range<u32> {
8384        let start = self.start.to_point(&map.buffer_snapshot);
8385        let mut end = self.end.to_point(&map.buffer_snapshot);
8386        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8387            end.row -= 1;
8388        }
8389
8390        let buffer_start = map.prev_line_boundary(start).0;
8391        let buffer_end = map.next_line_boundary(end).0;
8392        buffer_start.row..buffer_end.row + 1
8393    }
8394}
8395
8396impl<T: InvalidationRegion> InvalidationStack<T> {
8397    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8398    where
8399        S: Clone + ToOffset,
8400    {
8401        while let Some(region) = self.last() {
8402            let all_selections_inside_invalidation_ranges =
8403                if selections.len() == region.ranges().len() {
8404                    selections
8405                        .iter()
8406                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8407                        .all(|(selection, invalidation_range)| {
8408                            let head = selection.head().to_offset(buffer);
8409                            invalidation_range.start <= head && invalidation_range.end >= head
8410                        })
8411                } else {
8412                    false
8413                };
8414
8415            if all_selections_inside_invalidation_ranges {
8416                break;
8417            } else {
8418                self.pop();
8419            }
8420        }
8421    }
8422}
8423
8424impl<T> Default for InvalidationStack<T> {
8425    fn default() -> Self {
8426        Self(Default::default())
8427    }
8428}
8429
8430impl<T> Deref for InvalidationStack<T> {
8431    type Target = Vec<T>;
8432
8433    fn deref(&self) -> &Self::Target {
8434        &self.0
8435    }
8436}
8437
8438impl<T> DerefMut for InvalidationStack<T> {
8439    fn deref_mut(&mut self) -> &mut Self::Target {
8440        &mut self.0
8441    }
8442}
8443
8444impl InvalidationRegion for SnippetState {
8445    fn ranges(&self) -> &[Range<Anchor>] {
8446        &self.ranges[self.active_index]
8447    }
8448}
8449
8450impl Deref for EditorStyle {
8451    type Target = theme::Editor;
8452
8453    fn deref(&self) -> &Self::Target {
8454        &self.theme
8455    }
8456}
8457
8458pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8459    let mut highlighted_lines = Vec::new();
8460
8461    for (index, line) in diagnostic.message.lines().enumerate() {
8462        let line = match &diagnostic.source {
8463            Some(source) if index == 0 => {
8464                let source_highlight = Vec::from_iter(0..source.len());
8465                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8466            }
8467
8468            _ => highlight_diagnostic_message(Vec::new(), line),
8469        };
8470        highlighted_lines.push(line);
8471    }
8472    let message = diagnostic.message;
8473    Arc::new(move |cx: &mut BlockContext| {
8474        let message = message.clone();
8475        let settings = settings::get::<ThemeSettings>(cx);
8476        let tooltip_style = settings.theme.tooltip.clone();
8477        let theme = &settings.theme.editor;
8478        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8479        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8480        let anchor_x = cx.anchor_x;
8481        enum BlockContextToolip {}
8482        MouseEventHandler::<BlockContext, _>::new(cx.block_id, cx, |_, _| {
8483            Flex::column()
8484                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8485                    Label::new(
8486                        line.clone(),
8487                        style.message.clone().with_font_size(font_size),
8488                    )
8489                    .with_highlights(highlights.clone())
8490                    .contained()
8491                    .with_margin_left(anchor_x)
8492                }))
8493                .aligned()
8494                .left()
8495                .into_any()
8496        })
8497        .with_cursor_style(CursorStyle::PointingHand)
8498        .on_click(MouseButton::Left, move |_, _, cx| {
8499            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8500        })
8501        // We really need to rethink this ID system...
8502        .with_tooltip::<BlockContextToolip>(
8503            cx.block_id,
8504            "Copy diagnostic message".to_string(),
8505            None,
8506            tooltip_style,
8507            cx,
8508        )
8509        .into_any()
8510    })
8511}
8512
8513pub fn highlight_diagnostic_message(
8514    initial_highlights: Vec<usize>,
8515    message: &str,
8516) -> (String, Vec<usize>) {
8517    let mut message_without_backticks = String::new();
8518    let mut prev_offset = 0;
8519    let mut inside_block = false;
8520    let mut highlights = initial_highlights;
8521    for (match_ix, (offset, _)) in message
8522        .match_indices('`')
8523        .chain([(message.len(), "")])
8524        .enumerate()
8525    {
8526        message_without_backticks.push_str(&message[prev_offset..offset]);
8527        if inside_block {
8528            highlights.extend(prev_offset - match_ix..offset - match_ix);
8529        }
8530
8531        inside_block = !inside_block;
8532        prev_offset = offset + 1;
8533    }
8534
8535    (message_without_backticks, highlights)
8536}
8537
8538pub fn diagnostic_style(
8539    severity: DiagnosticSeverity,
8540    valid: bool,
8541    theme: &theme::Editor,
8542) -> DiagnosticStyle {
8543    match (severity, valid) {
8544        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8545        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8546        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8547        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8548        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8549        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8550        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8551        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8552        _ => theme.invalid_hint_diagnostic.clone(),
8553    }
8554}
8555
8556pub fn combine_syntax_and_fuzzy_match_highlights(
8557    text: &str,
8558    default_style: HighlightStyle,
8559    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8560    match_indices: &[usize],
8561) -> Vec<(Range<usize>, HighlightStyle)> {
8562    let mut result = Vec::new();
8563    let mut match_indices = match_indices.iter().copied().peekable();
8564
8565    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8566    {
8567        syntax_highlight.weight = None;
8568
8569        // Add highlights for any fuzzy match characters before the next
8570        // syntax highlight range.
8571        while let Some(&match_index) = match_indices.peek() {
8572            if match_index >= range.start {
8573                break;
8574            }
8575            match_indices.next();
8576            let end_index = char_ix_after(match_index, text);
8577            let mut match_style = default_style;
8578            match_style.weight = Some(fonts::Weight::BOLD);
8579            result.push((match_index..end_index, match_style));
8580        }
8581
8582        if range.start == usize::MAX {
8583            break;
8584        }
8585
8586        // Add highlights for any fuzzy match characters within the
8587        // syntax highlight range.
8588        let mut offset = range.start;
8589        while let Some(&match_index) = match_indices.peek() {
8590            if match_index >= range.end {
8591                break;
8592            }
8593
8594            match_indices.next();
8595            if match_index > offset {
8596                result.push((offset..match_index, syntax_highlight));
8597            }
8598
8599            let mut end_index = char_ix_after(match_index, text);
8600            while let Some(&next_match_index) = match_indices.peek() {
8601                if next_match_index == end_index && next_match_index < range.end {
8602                    end_index = char_ix_after(next_match_index, text);
8603                    match_indices.next();
8604                } else {
8605                    break;
8606                }
8607            }
8608
8609            let mut match_style = syntax_highlight;
8610            match_style.weight = Some(fonts::Weight::BOLD);
8611            result.push((match_index..end_index, match_style));
8612            offset = end_index;
8613        }
8614
8615        if offset < range.end {
8616            result.push((offset..range.end, syntax_highlight));
8617        }
8618    }
8619
8620    fn char_ix_after(ix: usize, text: &str) -> usize {
8621        ix + text[ix..].chars().next().unwrap().len_utf8()
8622    }
8623
8624    result
8625}
8626
8627pub fn styled_runs_for_code_label<'a>(
8628    label: &'a CodeLabel,
8629    syntax_theme: &'a theme::SyntaxTheme,
8630) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8631    let fade_out = HighlightStyle {
8632        fade_out: Some(0.35),
8633        ..Default::default()
8634    };
8635
8636    let mut prev_end = label.filter_range.end;
8637    label
8638        .runs
8639        .iter()
8640        .enumerate()
8641        .flat_map(move |(ix, (range, highlight_id))| {
8642            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8643                style
8644            } else {
8645                return Default::default();
8646            };
8647            let mut muted_style = style;
8648            muted_style.highlight(fade_out);
8649
8650            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8651            if range.start >= label.filter_range.end {
8652                if range.start > prev_end {
8653                    runs.push((prev_end..range.start, fade_out));
8654                }
8655                runs.push((range.clone(), muted_style));
8656            } else if range.end <= label.filter_range.end {
8657                runs.push((range.clone(), style));
8658            } else {
8659                runs.push((range.start..label.filter_range.end, style));
8660                runs.push((label.filter_range.end..range.end, muted_style));
8661            }
8662            prev_end = cmp::max(prev_end, range.end);
8663
8664            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8665                runs.push((prev_end..label.text.len(), fade_out));
8666            }
8667
8668            runs
8669        })
8670}
8671
8672pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8673    let mut index = 0;
8674    let mut codepoints = text.char_indices().peekable();
8675
8676    std::iter::from_fn(move || {
8677        let start_index = index;
8678        while let Some((new_index, codepoint)) = codepoints.next() {
8679            index = new_index + codepoint.len_utf8();
8680            let current_upper = codepoint.is_uppercase();
8681            let next_upper = codepoints
8682                .peek()
8683                .map(|(_, c)| c.is_uppercase())
8684                .unwrap_or(false);
8685
8686            if !current_upper && next_upper {
8687                return Some(&text[start_index..index]);
8688            }
8689        }
8690
8691        index = text.len();
8692        if start_index < text.len() {
8693            return Some(&text[start_index..]);
8694        }
8695        None
8696    })
8697    .flat_map(|word| word.split_inclusive('_'))
8698}
8699
8700trait RangeToAnchorExt {
8701    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8702}
8703
8704impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8705    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8706        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8707    }
8708}