editor.rs

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