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