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