editor.rs

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