editor.rs

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