editor.rs

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