editor.rs

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