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