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