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