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