editor.rs

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