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