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