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