editor.rs

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