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