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