editor.rs

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