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    completions: Arc<[Completion]>,
 863    match_candidates: Vec<StringMatchCandidate>,
 864    matches: Arc<[StringMatch]>,
 865    selected_item: usize,
 866    list: UniformListState,
 867}
 868
 869impl CompletionsMenu {
 870    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 871        self.selected_item = 0;
 872        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 873        cx.notify();
 874    }
 875
 876    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 877        if self.selected_item > 0 {
 878            self.selected_item -= 1;
 879            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 880        }
 881        cx.notify();
 882    }
 883
 884    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 885        if self.selected_item + 1 < self.matches.len() {
 886            self.selected_item += 1;
 887            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 888        }
 889        cx.notify();
 890    }
 891
 892    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 893        self.selected_item = self.matches.len() - 1;
 894        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 895        cx.notify();
 896    }
 897
 898    fn visible(&self) -> bool {
 899        !self.matches.is_empty()
 900    }
 901
 902    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
 903        enum CompletionTag {}
 904
 905        let widest_completion_ix = self
 906            .matches
 907            .iter()
 908            .enumerate()
 909            .max_by_key(|(_, mat)| {
 910                let completion = &self.completions[mat.candidate_id];
 911                let documentation = &completion.lsp_completion.documentation;
 912
 913                let mut len = completion.label.text.chars().count();
 914                if let Some(lsp::Documentation::String(text)) = documentation {
 915                    len += text.chars().count();
 916                }
 917
 918                len
 919            })
 920            .map(|(ix, _)| ix);
 921
 922        let completions = self.completions.clone();
 923        let matches = self.matches.clone();
 924        let selected_item = self.selected_item;
 925
 926        let alongside_docs_text_style = TextStyle {
 927            soft_wrap: true,
 928            ..style.text.clone()
 929        };
 930        let alongside_docs_width = style.autocomplete.alongside_docs_width;
 931        let alongside_docs_container_style = style.autocomplete.alongside_docs_container;
 932        let outer_container_style = style.autocomplete.container;
 933
 934        let list = UniformList::new(
 935            self.list.clone(),
 936            matches.len(),
 937            cx,
 938            move |_, range, items, cx| {
 939                let start_ix = range.start;
 940                for (ix, mat) in matches[range].iter().enumerate() {
 941                    let completion = &completions[mat.candidate_id];
 942                    let documentation = &completion.lsp_completion.documentation;
 943                    let item_ix = start_ix + ix;
 944
 945                    items.push(
 946                        MouseEventHandler::new::<CompletionTag, _>(
 947                            mat.candidate_id,
 948                            cx,
 949                            |state, _| {
 950                                let item_style = if item_ix == selected_item {
 951                                    style.autocomplete.selected_item
 952                                } else if state.hovered() {
 953                                    style.autocomplete.hovered_item
 954                                } else {
 955                                    style.autocomplete.item
 956                                };
 957
 958                                let completion_label =
 959                                    Text::new(completion.label.text.clone(), style.text.clone())
 960                                        .with_soft_wrap(false)
 961                                        .with_highlights(
 962                                            combine_syntax_and_fuzzy_match_highlights(
 963                                                &completion.label.text,
 964                                                style.text.color.into(),
 965                                                styled_runs_for_code_label(
 966                                                    &completion.label,
 967                                                    &style.syntax,
 968                                                ),
 969                                                &mat.positions,
 970                                            ),
 971                                        );
 972
 973                                if let Some(lsp::Documentation::String(text)) = documentation {
 974                                    Flex::row()
 975                                        .with_child(completion_label)
 976                                        .with_children((|| {
 977                                            let text_style = TextStyle {
 978                                                color: style.autocomplete.inline_docs_color,
 979                                                font_size: style.text.font_size
 980                                                    * style.autocomplete.inline_docs_size_percent,
 981                                                ..style.text.clone()
 982                                            };
 983
 984                                            let label = Text::new(text.clone(), text_style)
 985                                                .aligned()
 986                                                .constrained()
 987                                                .dynamically(move |constraint, _, _| {
 988                                                    gpui::SizeConstraint {
 989                                                        min: constraint.min,
 990                                                        max: vec2f(
 991                                                            constraint.max.x(),
 992                                                            constraint.min.y(),
 993                                                        ),
 994                                                    }
 995                                                });
 996
 997                                            if Some(item_ix) == widest_completion_ix {
 998                                                Some(
 999                                                    label
1000                                                        .contained()
1001                                                        .with_style(
1002                                                            style
1003                                                                .autocomplete
1004                                                                .inline_docs_container,
1005                                                        )
1006                                                        .into_any(),
1007                                                )
1008                                            } else {
1009                                                Some(label.flex_float().into_any())
1010                                            }
1011                                        })())
1012                                        .into_any()
1013                                } else {
1014                                    completion_label.into_any()
1015                                }
1016                                .contained()
1017                                .with_style(item_style)
1018                                .constrained()
1019                                .dynamically(
1020                                    move |constraint, _, _| {
1021                                        if Some(item_ix) == widest_completion_ix {
1022                                            constraint
1023                                        } else {
1024                                            gpui::SizeConstraint {
1025                                                min: constraint.min,
1026                                                max: constraint.min,
1027                                            }
1028                                        }
1029                                    },
1030                                )
1031                            },
1032                        )
1033                        .with_cursor_style(CursorStyle::PointingHand)
1034                        .on_down(MouseButton::Left, move |_, this, cx| {
1035                            this.confirm_completion(
1036                                &ConfirmCompletion {
1037                                    item_ix: Some(item_ix),
1038                                },
1039                                cx,
1040                            )
1041                            .map(|task| task.detach());
1042                        })
1043                        .into_any(),
1044                    );
1045                }
1046            },
1047        )
1048        .with_width_from_item(widest_completion_ix);
1049
1050        Flex::row()
1051            .with_child(list)
1052            .with_children({
1053                let mat = &self.matches[selected_item];
1054                let completion = &self.completions[mat.candidate_id];
1055                let documentation = &completion.lsp_completion.documentation;
1056
1057                if let Some(lsp::Documentation::MarkupContent(content)) = documentation {
1058                    Some(
1059                        Text::new(content.value.clone(), alongside_docs_text_style)
1060                            .constrained()
1061                            .with_width(alongside_docs_width)
1062                            .contained()
1063                            .with_style(alongside_docs_container_style),
1064                    )
1065                } else {
1066                    None
1067                }
1068            })
1069            .contained()
1070            .with_style(outer_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 task = cx.spawn(|this, mut cx| {
3154            async move {
3155                let menu = if let Some(completions) = completions.await.log_err() {
3156                    let mut menu = CompletionsMenu {
3157                        id,
3158                        initial_position: position,
3159                        match_candidates: completions
3160                            .iter()
3161                            .enumerate()
3162                            .map(|(id, completion)| {
3163                                StringMatchCandidate::new(
3164                                    id,
3165                                    completion.label.text[completion.label.filter_range.clone()]
3166                                        .into(),
3167                                )
3168                            })
3169                            .collect(),
3170                        buffer,
3171                        completions: completions.into(),
3172                        matches: Vec::new().into(),
3173                        selected_item: 0,
3174                        list: Default::default(),
3175                    };
3176                    menu.filter(query.as_deref(), cx.background()).await;
3177                    if menu.matches.is_empty() {
3178                        None
3179                    } else {
3180                        Some(menu)
3181                    }
3182                } else {
3183                    None
3184                };
3185
3186                this.update(&mut cx, |this, cx| {
3187                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
3188
3189                    match this.context_menu.as_ref() {
3190                        None => {}
3191                        Some(ContextMenu::Completions(prev_menu)) => {
3192                            if prev_menu.id > id {
3193                                return;
3194                            }
3195                        }
3196                        _ => return,
3197                    }
3198
3199                    if this.focused && menu.is_some() {
3200                        let menu = menu.unwrap();
3201                        this.show_context_menu(ContextMenu::Completions(menu), cx);
3202                    } else if this.completion_tasks.is_empty() {
3203                        // If there are no more completion tasks and the last menu was
3204                        // empty, we should hide it. If it was already hidden, we should
3205                        // also show the copilot suggestion when available.
3206                        if this.hide_context_menu(cx).is_none() {
3207                            this.update_visible_copilot_suggestion(cx);
3208                        }
3209                    }
3210                })?;
3211
3212                Ok::<_, anyhow::Error>(())
3213            }
3214            .log_err()
3215        });
3216        self.completion_tasks.push((id, task));
3217    }
3218
3219    pub fn confirm_completion(
3220        &mut self,
3221        action: &ConfirmCompletion,
3222        cx: &mut ViewContext<Self>,
3223    ) -> Option<Task<Result<()>>> {
3224        use language::ToOffset as _;
3225
3226        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
3227            menu
3228        } else {
3229            return None;
3230        };
3231
3232        let mat = completions_menu
3233            .matches
3234            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
3235        let buffer_handle = completions_menu.buffer;
3236        let completion = completions_menu.completions.get(mat.candidate_id)?;
3237
3238        let snippet;
3239        let text;
3240        if completion.is_snippet() {
3241            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
3242            text = snippet.as_ref().unwrap().text.clone();
3243        } else {
3244            snippet = None;
3245            text = completion.new_text.clone();
3246        };
3247        let selections = self.selections.all::<usize>(cx);
3248        let buffer = buffer_handle.read(cx);
3249        let old_range = completion.old_range.to_offset(buffer);
3250        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
3251
3252        let newest_selection = self.selections.newest_anchor();
3253        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
3254            return None;
3255        }
3256
3257        let lookbehind = newest_selection
3258            .start
3259            .text_anchor
3260            .to_offset(buffer)
3261            .saturating_sub(old_range.start);
3262        let lookahead = old_range
3263            .end
3264            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
3265        let mut common_prefix_len = old_text
3266            .bytes()
3267            .zip(text.bytes())
3268            .take_while(|(a, b)| a == b)
3269            .count();
3270
3271        let snapshot = self.buffer.read(cx).snapshot(cx);
3272        let mut range_to_replace: Option<Range<isize>> = None;
3273        let mut ranges = Vec::new();
3274        for selection in &selections {
3275            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
3276                let start = selection.start.saturating_sub(lookbehind);
3277                let end = selection.end + lookahead;
3278                if selection.id == newest_selection.id {
3279                    range_to_replace = Some(
3280                        ((start + common_prefix_len) as isize - selection.start as isize)
3281                            ..(end as isize - selection.start as isize),
3282                    );
3283                }
3284                ranges.push(start + common_prefix_len..end);
3285            } else {
3286                common_prefix_len = 0;
3287                ranges.clear();
3288                ranges.extend(selections.iter().map(|s| {
3289                    if s.id == newest_selection.id {
3290                        range_to_replace = Some(
3291                            old_range.start.to_offset_utf16(&snapshot).0 as isize
3292                                - selection.start as isize
3293                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
3294                                    - selection.start as isize,
3295                        );
3296                        old_range.clone()
3297                    } else {
3298                        s.start..s.end
3299                    }
3300                }));
3301                break;
3302            }
3303        }
3304        let text = &text[common_prefix_len..];
3305
3306        cx.emit(Event::InputHandled {
3307            utf16_range_to_replace: range_to_replace,
3308            text: text.into(),
3309        });
3310
3311        self.transact(cx, |this, cx| {
3312            if let Some(mut snippet) = snippet {
3313                snippet.text = text.to_string();
3314                for tabstop in snippet.tabstops.iter_mut().flatten() {
3315                    tabstop.start -= common_prefix_len as isize;
3316                    tabstop.end -= common_prefix_len as isize;
3317                }
3318
3319                this.insert_snippet(&ranges, snippet, cx).log_err();
3320            } else {
3321                this.buffer.update(cx, |buffer, cx| {
3322                    buffer.edit(
3323                        ranges.iter().map(|range| (range.clone(), text)),
3324                        this.autoindent_mode.clone(),
3325                        cx,
3326                    );
3327                });
3328            }
3329
3330            this.refresh_copilot_suggestions(true, cx);
3331        });
3332
3333        let project = self.project.clone()?;
3334        let apply_edits = project.update(cx, |project, cx| {
3335            project.apply_additional_edits_for_completion(
3336                buffer_handle,
3337                completion.clone(),
3338                true,
3339                cx,
3340            )
3341        });
3342        Some(cx.foreground().spawn(async move {
3343            apply_edits.await?;
3344            Ok(())
3345        }))
3346    }
3347
3348    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3349        if matches!(
3350            self.context_menu.as_ref(),
3351            Some(ContextMenu::CodeActions(_))
3352        ) {
3353            self.context_menu.take();
3354            cx.notify();
3355            return;
3356        }
3357
3358        let deployed_from_indicator = action.deployed_from_indicator;
3359        let mut task = self.code_actions_task.take();
3360        cx.spawn(|this, mut cx| async move {
3361            while let Some(prev_task) = task {
3362                prev_task.await;
3363                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3364            }
3365
3366            this.update(&mut cx, |this, cx| {
3367                if this.focused {
3368                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3369                        this.show_context_menu(
3370                            ContextMenu::CodeActions(CodeActionsMenu {
3371                                buffer,
3372                                actions,
3373                                selected_item: Default::default(),
3374                                list: Default::default(),
3375                                deployed_from_indicator,
3376                            }),
3377                            cx,
3378                        );
3379                    }
3380                }
3381            })?;
3382
3383            Ok::<_, anyhow::Error>(())
3384        })
3385        .detach_and_log_err(cx);
3386    }
3387
3388    pub fn confirm_code_action(
3389        workspace: &mut Workspace,
3390        action: &ConfirmCodeAction,
3391        cx: &mut ViewContext<Workspace>,
3392    ) -> Option<Task<Result<()>>> {
3393        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3394        let actions_menu = if let ContextMenu::CodeActions(menu) =
3395            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3396        {
3397            menu
3398        } else {
3399            return None;
3400        };
3401        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3402        let action = actions_menu.actions.get(action_ix)?.clone();
3403        let title = action.lsp_action.title.clone();
3404        let buffer = actions_menu.buffer;
3405
3406        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3407            project.apply_code_action(buffer, action, true, cx)
3408        });
3409        let editor = editor.downgrade();
3410        Some(cx.spawn(|workspace, cx| async move {
3411            let project_transaction = apply_code_actions.await?;
3412            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3413        }))
3414    }
3415
3416    async fn open_project_transaction(
3417        this: &WeakViewHandle<Editor>,
3418        workspace: WeakViewHandle<Workspace>,
3419        transaction: ProjectTransaction,
3420        title: String,
3421        mut cx: AsyncAppContext,
3422    ) -> Result<()> {
3423        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3424
3425        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3426        entries.sort_unstable_by_key(|(buffer, _)| {
3427            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3428        });
3429
3430        // If the project transaction's edits are all contained within this editor, then
3431        // avoid opening a new editor to display them.
3432
3433        if let Some((buffer, transaction)) = entries.first() {
3434            if entries.len() == 1 {
3435                let excerpt = this.read_with(&cx, |editor, cx| {
3436                    editor
3437                        .buffer()
3438                        .read(cx)
3439                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3440                })?;
3441                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3442                    if excerpted_buffer == *buffer {
3443                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3444                            let excerpt_range = excerpt_range.to_offset(buffer);
3445                            buffer
3446                                .edited_ranges_for_transaction::<usize>(transaction)
3447                                .all(|range| {
3448                                    excerpt_range.start <= range.start
3449                                        && excerpt_range.end >= range.end
3450                                })
3451                        });
3452
3453                        if all_edits_within_excerpt {
3454                            return Ok(());
3455                        }
3456                    }
3457                }
3458            }
3459        } else {
3460            return Ok(());
3461        }
3462
3463        let mut ranges_to_highlight = Vec::new();
3464        let excerpt_buffer = cx.add_model(|cx| {
3465            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3466            for (buffer_handle, transaction) in &entries {
3467                let buffer = buffer_handle.read(cx);
3468                ranges_to_highlight.extend(
3469                    multibuffer.push_excerpts_with_context_lines(
3470                        buffer_handle.clone(),
3471                        buffer
3472                            .edited_ranges_for_transaction::<usize>(transaction)
3473                            .collect(),
3474                        1,
3475                        cx,
3476                    ),
3477                );
3478            }
3479            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3480            multibuffer
3481        });
3482
3483        workspace.update(&mut cx, |workspace, cx| {
3484            let project = workspace.project().clone();
3485            let editor =
3486                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3487            workspace.add_item(Box::new(editor.clone()), cx);
3488            editor.update(cx, |editor, cx| {
3489                editor.highlight_background::<Self>(
3490                    ranges_to_highlight,
3491                    |theme| theme.editor.highlighted_line_background,
3492                    cx,
3493                );
3494            });
3495        })?;
3496
3497        Ok(())
3498    }
3499
3500    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3501        let project = self.project.clone()?;
3502        let buffer = self.buffer.read(cx);
3503        let newest_selection = self.selections.newest_anchor().clone();
3504        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3505        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3506        if start_buffer != end_buffer {
3507            return None;
3508        }
3509
3510        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3511            cx.background().timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT).await;
3512
3513            let actions = project
3514                .update(&mut cx, |project, cx| {
3515                    project.code_actions(&start_buffer, start..end, cx)
3516                })
3517                .await;
3518
3519            this.update(&mut cx, |this, cx| {
3520                this.available_code_actions = actions.log_err().and_then(|actions| {
3521                    if actions.is_empty() {
3522                        None
3523                    } else {
3524                        Some((start_buffer, actions.into()))
3525                    }
3526                });
3527                cx.notify();
3528            })
3529            .log_err();
3530        }));
3531        None
3532    }
3533
3534    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3535        if self.pending_rename.is_some() {
3536            return None;
3537        }
3538
3539        let project = self.project.clone()?;
3540        let buffer = self.buffer.read(cx);
3541        let newest_selection = self.selections.newest_anchor().clone();
3542        let cursor_position = newest_selection.head();
3543        let (cursor_buffer, cursor_buffer_position) =
3544            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3545        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3546        if cursor_buffer != tail_buffer {
3547            return None;
3548        }
3549
3550        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3551            cx.background()
3552                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
3553                .await;
3554
3555            let highlights = project
3556                .update(&mut cx, |project, cx| {
3557                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3558                })
3559                .await
3560                .log_err();
3561
3562            if let Some(highlights) = highlights {
3563                this.update(&mut cx, |this, cx| {
3564                    if this.pending_rename.is_some() {
3565                        return;
3566                    }
3567
3568                    let buffer_id = cursor_position.buffer_id;
3569                    let buffer = this.buffer.read(cx);
3570                    if !buffer
3571                        .text_anchor_for_position(cursor_position, cx)
3572                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3573                    {
3574                        return;
3575                    }
3576
3577                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3578                    let mut write_ranges = Vec::new();
3579                    let mut read_ranges = Vec::new();
3580                    for highlight in highlights {
3581                        for (excerpt_id, excerpt_range) in
3582                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3583                        {
3584                            let start = highlight
3585                                .range
3586                                .start
3587                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3588                            let end = highlight
3589                                .range
3590                                .end
3591                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3592                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3593                                continue;
3594                            }
3595
3596                            let range = Anchor {
3597                                buffer_id,
3598                                excerpt_id: excerpt_id.clone(),
3599                                text_anchor: start,
3600                            }..Anchor {
3601                                buffer_id,
3602                                excerpt_id,
3603                                text_anchor: end,
3604                            };
3605                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3606                                write_ranges.push(range);
3607                            } else {
3608                                read_ranges.push(range);
3609                            }
3610                        }
3611                    }
3612
3613                    this.highlight_background::<DocumentHighlightRead>(
3614                        read_ranges,
3615                        |theme| theme.editor.document_highlight_read_background,
3616                        cx,
3617                    );
3618                    this.highlight_background::<DocumentHighlightWrite>(
3619                        write_ranges,
3620                        |theme| theme.editor.document_highlight_write_background,
3621                        cx,
3622                    );
3623                    cx.notify();
3624                })
3625                .log_err();
3626            }
3627        }));
3628        None
3629    }
3630
3631    fn refresh_copilot_suggestions(
3632        &mut self,
3633        debounce: bool,
3634        cx: &mut ViewContext<Self>,
3635    ) -> Option<()> {
3636        let copilot = Copilot::global(cx)?;
3637        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3638            self.clear_copilot_suggestions(cx);
3639            return None;
3640        }
3641        self.update_visible_copilot_suggestion(cx);
3642
3643        let snapshot = self.buffer.read(cx).snapshot(cx);
3644        let cursor = self.selections.newest_anchor().head();
3645        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3646            self.clear_copilot_suggestions(cx);
3647            return None;
3648        }
3649
3650        let (buffer, buffer_position) =
3651            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3652        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3653            if debounce {
3654                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3655            }
3656
3657            let completions = copilot
3658                .update(&mut cx, |copilot, cx| {
3659                    copilot.completions(&buffer, buffer_position, cx)
3660                })
3661                .await
3662                .log_err()
3663                .into_iter()
3664                .flatten()
3665                .collect_vec();
3666
3667            this.update(&mut cx, |this, cx| {
3668                if !completions.is_empty() {
3669                    this.copilot_state.cycled = false;
3670                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3671                    this.copilot_state.completions.clear();
3672                    this.copilot_state.active_completion_index = 0;
3673                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3674                    for completion in completions {
3675                        this.copilot_state.push_completion(completion);
3676                    }
3677                    this.update_visible_copilot_suggestion(cx);
3678                }
3679            })
3680            .log_err()?;
3681            Some(())
3682        });
3683
3684        Some(())
3685    }
3686
3687    fn cycle_copilot_suggestions(
3688        &mut self,
3689        direction: Direction,
3690        cx: &mut ViewContext<Self>,
3691    ) -> Option<()> {
3692        let copilot = Copilot::global(cx)?;
3693        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3694            return None;
3695        }
3696
3697        if self.copilot_state.cycled {
3698            self.copilot_state.cycle_completions(direction);
3699            self.update_visible_copilot_suggestion(cx);
3700        } else {
3701            let cursor = self.selections.newest_anchor().head();
3702            let (buffer, buffer_position) =
3703                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3704            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3705                let completions = copilot
3706                    .update(&mut cx, |copilot, cx| {
3707                        copilot.completions_cycling(&buffer, buffer_position, cx)
3708                    })
3709                    .await;
3710
3711                this.update(&mut cx, |this, cx| {
3712                    this.copilot_state.cycled = true;
3713                    for completion in completions.log_err().into_iter().flatten() {
3714                        this.copilot_state.push_completion(completion);
3715                    }
3716                    this.copilot_state.cycle_completions(direction);
3717                    this.update_visible_copilot_suggestion(cx);
3718                })
3719                .log_err()?;
3720
3721                Some(())
3722            });
3723        }
3724
3725        Some(())
3726    }
3727
3728    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3729        if !self.has_active_copilot_suggestion(cx) {
3730            self.refresh_copilot_suggestions(false, cx);
3731            return;
3732        }
3733
3734        self.update_visible_copilot_suggestion(cx);
3735    }
3736
3737    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3738        if self.has_active_copilot_suggestion(cx) {
3739            self.cycle_copilot_suggestions(Direction::Next, cx);
3740        } else {
3741            self.refresh_copilot_suggestions(false, cx);
3742        }
3743    }
3744
3745    fn previous_copilot_suggestion(
3746        &mut self,
3747        _: &copilot::PreviousSuggestion,
3748        cx: &mut ViewContext<Self>,
3749    ) {
3750        if self.has_active_copilot_suggestion(cx) {
3751            self.cycle_copilot_suggestions(Direction::Prev, cx);
3752        } else {
3753            self.refresh_copilot_suggestions(false, cx);
3754        }
3755    }
3756
3757    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3758        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3759            if let Some((copilot, completion)) =
3760                Copilot::global(cx).zip(self.copilot_state.active_completion())
3761            {
3762                copilot
3763                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3764                    .detach_and_log_err(cx);
3765
3766                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3767            }
3768            cx.emit(Event::InputHandled {
3769                utf16_range_to_replace: None,
3770                text: suggestion.text.to_string().into(),
3771            });
3772            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3773            cx.notify();
3774            true
3775        } else {
3776            false
3777        }
3778    }
3779
3780    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3781        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3782            if let Some(copilot) = Copilot::global(cx) {
3783                copilot
3784                    .update(cx, |copilot, cx| {
3785                        copilot.discard_completions(&self.copilot_state.completions, cx)
3786                    })
3787                    .detach_and_log_err(cx);
3788
3789                self.report_copilot_event(None, false, cx)
3790            }
3791
3792            self.display_map.update(cx, |map, cx| {
3793                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
3794            });
3795            cx.notify();
3796            true
3797        } else {
3798            false
3799        }
3800    }
3801
3802    fn is_copilot_enabled_at(
3803        &self,
3804        location: Anchor,
3805        snapshot: &MultiBufferSnapshot,
3806        cx: &mut ViewContext<Self>,
3807    ) -> bool {
3808        let file = snapshot.file_at(location);
3809        let language = snapshot.language_at(location);
3810        let settings = all_language_settings(file, cx);
3811        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3812    }
3813
3814    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3815        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3816            let buffer = self.buffer.read(cx).read(cx);
3817            suggestion.position.is_valid(&buffer)
3818        } else {
3819            false
3820        }
3821    }
3822
3823    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3824        let suggestion = self.copilot_state.suggestion.take()?;
3825        self.display_map.update(cx, |map, cx| {
3826            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
3827        });
3828        let buffer = self.buffer.read(cx).read(cx);
3829
3830        if suggestion.position.is_valid(&buffer) {
3831            Some(suggestion)
3832        } else {
3833            None
3834        }
3835    }
3836
3837    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3838        let snapshot = self.buffer.read(cx).snapshot(cx);
3839        let selection = self.selections.newest_anchor();
3840        let cursor = selection.head();
3841
3842        if self.context_menu.is_some()
3843            || !self.completion_tasks.is_empty()
3844            || selection.start != selection.end
3845        {
3846            self.discard_copilot_suggestion(cx);
3847        } else if let Some(text) = self
3848            .copilot_state
3849            .text_for_active_completion(cursor, &snapshot)
3850        {
3851            let text = Rope::from(text);
3852            let mut to_remove = Vec::new();
3853            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3854                to_remove.push(suggestion.id);
3855            }
3856
3857            let suggestion_inlay =
3858                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
3859            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
3860            self.display_map.update(cx, move |map, cx| {
3861                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
3862            });
3863            cx.notify();
3864        } else {
3865            self.discard_copilot_suggestion(cx);
3866        }
3867    }
3868
3869    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3870        self.copilot_state = Default::default();
3871        self.discard_copilot_suggestion(cx);
3872    }
3873
3874    pub fn render_code_actions_indicator(
3875        &self,
3876        style: &EditorStyle,
3877        is_active: bool,
3878        cx: &mut ViewContext<Self>,
3879    ) -> Option<AnyElement<Self>> {
3880        if self.available_code_actions.is_some() {
3881            enum CodeActions {}
3882            Some(
3883                MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
3884                    Svg::new("icons/bolt.svg").with_color(
3885                        style
3886                            .code_actions
3887                            .indicator
3888                            .in_state(is_active)
3889                            .style_for(state)
3890                            .color,
3891                    )
3892                })
3893                .with_cursor_style(CursorStyle::PointingHand)
3894                .with_padding(Padding::uniform(3.))
3895                .on_down(MouseButton::Left, |_, this, cx| {
3896                    this.toggle_code_actions(
3897                        &ToggleCodeActions {
3898                            deployed_from_indicator: true,
3899                        },
3900                        cx,
3901                    );
3902                })
3903                .into_any(),
3904            )
3905        } else {
3906            None
3907        }
3908    }
3909
3910    pub fn render_fold_indicators(
3911        &self,
3912        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3913        style: &EditorStyle,
3914        gutter_hovered: bool,
3915        line_height: f32,
3916        gutter_margin: f32,
3917        cx: &mut ViewContext<Self>,
3918    ) -> Vec<Option<AnyElement<Self>>> {
3919        enum FoldIndicators {}
3920
3921        let style = style.folds.clone();
3922
3923        fold_data
3924            .iter()
3925            .enumerate()
3926            .map(|(ix, fold_data)| {
3927                fold_data
3928                    .map(|(fold_status, buffer_row, active)| {
3929                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3930                            MouseEventHandler::new::<FoldIndicators, _>(
3931                                ix as usize,
3932                                cx,
3933                                |mouse_state, _| {
3934                                    Svg::new(match fold_status {
3935                                        FoldStatus::Folded => style.folded_icon.clone(),
3936                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3937                                    })
3938                                    .with_color(
3939                                        style
3940                                            .indicator
3941                                            .in_state(fold_status == FoldStatus::Folded)
3942                                            .style_for(mouse_state)
3943                                            .color,
3944                                    )
3945                                    .constrained()
3946                                    .with_width(gutter_margin * style.icon_margin_scale)
3947                                    .aligned()
3948                                    .constrained()
3949                                    .with_height(line_height)
3950                                    .with_width(gutter_margin)
3951                                    .aligned()
3952                                },
3953                            )
3954                            .with_cursor_style(CursorStyle::PointingHand)
3955                            .with_padding(Padding::uniform(3.))
3956                            .on_click(MouseButton::Left, {
3957                                move |_, editor, cx| match fold_status {
3958                                    FoldStatus::Folded => {
3959                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3960                                    }
3961                                    FoldStatus::Foldable => {
3962                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3963                                    }
3964                                }
3965                            })
3966                            .into_any()
3967                        })
3968                    })
3969                    .flatten()
3970            })
3971            .collect()
3972    }
3973
3974    pub fn context_menu_visible(&self) -> bool {
3975        self.context_menu
3976            .as_ref()
3977            .map_or(false, |menu| menu.visible())
3978    }
3979
3980    pub fn render_context_menu(
3981        &self,
3982        cursor_position: DisplayPoint,
3983        style: EditorStyle,
3984        cx: &mut ViewContext<Editor>,
3985    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3986        self.context_menu
3987            .as_ref()
3988            .map(|menu| menu.render(cursor_position, style, cx))
3989    }
3990
3991    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3992        if !matches!(menu, ContextMenu::Completions(_)) {
3993            self.completion_tasks.clear();
3994        }
3995        self.context_menu = Some(menu);
3996        self.discard_copilot_suggestion(cx);
3997        cx.notify();
3998    }
3999
4000    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
4001        cx.notify();
4002        self.completion_tasks.clear();
4003        let context_menu = self.context_menu.take();
4004        if context_menu.is_some() {
4005            self.update_visible_copilot_suggestion(cx);
4006        }
4007        context_menu
4008    }
4009
4010    pub fn insert_snippet(
4011        &mut self,
4012        insertion_ranges: &[Range<usize>],
4013        snippet: Snippet,
4014        cx: &mut ViewContext<Self>,
4015    ) -> Result<()> {
4016        let tabstops = self.buffer.update(cx, |buffer, cx| {
4017            let snippet_text: Arc<str> = snippet.text.clone().into();
4018            buffer.edit(
4019                insertion_ranges
4020                    .iter()
4021                    .cloned()
4022                    .map(|range| (range, snippet_text.clone())),
4023                Some(AutoindentMode::EachLine),
4024                cx,
4025            );
4026
4027            let snapshot = &*buffer.read(cx);
4028            let snippet = &snippet;
4029            snippet
4030                .tabstops
4031                .iter()
4032                .map(|tabstop| {
4033                    let mut tabstop_ranges = tabstop
4034                        .iter()
4035                        .flat_map(|tabstop_range| {
4036                            let mut delta = 0_isize;
4037                            insertion_ranges.iter().map(move |insertion_range| {
4038                                let insertion_start = insertion_range.start as isize + delta;
4039                                delta +=
4040                                    snippet.text.len() as isize - insertion_range.len() as isize;
4041
4042                                let start = snapshot.anchor_before(
4043                                    (insertion_start + tabstop_range.start) as usize,
4044                                );
4045                                let end = snapshot
4046                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
4047                                start..end
4048                            })
4049                        })
4050                        .collect::<Vec<_>>();
4051                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
4052                    tabstop_ranges
4053                })
4054                .collect::<Vec<_>>()
4055        });
4056
4057        if let Some(tabstop) = tabstops.first() {
4058            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4059                s.select_ranges(tabstop.iter().cloned());
4060            });
4061            self.snippet_stack.push(SnippetState {
4062                active_index: 0,
4063                ranges: tabstops,
4064            });
4065        }
4066
4067        Ok(())
4068    }
4069
4070    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4071        self.move_to_snippet_tabstop(Bias::Right, cx)
4072    }
4073
4074    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4075        self.move_to_snippet_tabstop(Bias::Left, cx)
4076    }
4077
4078    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
4079        if let Some(mut snippet) = self.snippet_stack.pop() {
4080            match bias {
4081                Bias::Left => {
4082                    if snippet.active_index > 0 {
4083                        snippet.active_index -= 1;
4084                    } else {
4085                        self.snippet_stack.push(snippet);
4086                        return false;
4087                    }
4088                }
4089                Bias::Right => {
4090                    if snippet.active_index + 1 < snippet.ranges.len() {
4091                        snippet.active_index += 1;
4092                    } else {
4093                        self.snippet_stack.push(snippet);
4094                        return false;
4095                    }
4096                }
4097            }
4098            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
4099                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4100                    s.select_anchor_ranges(current_ranges.iter().cloned())
4101                });
4102                // If snippet state is not at the last tabstop, push it back on the stack
4103                if snippet.active_index + 1 < snippet.ranges.len() {
4104                    self.snippet_stack.push(snippet);
4105                }
4106                return true;
4107            }
4108        }
4109
4110        false
4111    }
4112
4113    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
4114        self.transact(cx, |this, cx| {
4115            this.select_all(&SelectAll, cx);
4116            this.insert("", cx);
4117        });
4118    }
4119
4120    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
4121        self.transact(cx, |this, cx| {
4122            this.select_autoclose_pair(cx);
4123            let mut selections = this.selections.all::<Point>(cx);
4124            if !this.selections.line_mode {
4125                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
4126                for selection in &mut selections {
4127                    if selection.is_empty() {
4128                        let old_head = selection.head();
4129                        let mut new_head =
4130                            movement::left(&display_map, old_head.to_display_point(&display_map))
4131                                .to_point(&display_map);
4132                        if let Some((buffer, line_buffer_range)) = display_map
4133                            .buffer_snapshot
4134                            .buffer_line_for_row(old_head.row)
4135                        {
4136                            let indent_size =
4137                                buffer.indent_size_for_line(line_buffer_range.start.row);
4138                            let indent_len = match indent_size.kind {
4139                                IndentKind::Space => {
4140                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
4141                                }
4142                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
4143                            };
4144                            if old_head.column <= indent_size.len && old_head.column > 0 {
4145                                let indent_len = indent_len.get();
4146                                new_head = cmp::min(
4147                                    new_head,
4148                                    Point::new(
4149                                        old_head.row,
4150                                        ((old_head.column - 1) / indent_len) * indent_len,
4151                                    ),
4152                                );
4153                            }
4154                        }
4155
4156                        selection.set_head(new_head, SelectionGoal::None);
4157                    }
4158                }
4159            }
4160
4161            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4162            this.insert("", cx);
4163            this.refresh_copilot_suggestions(true, cx);
4164        });
4165    }
4166
4167    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
4168        self.transact(cx, |this, cx| {
4169            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4170                let line_mode = s.line_mode;
4171                s.move_with(|map, selection| {
4172                    if selection.is_empty() && !line_mode {
4173                        let cursor = movement::right(map, selection.head());
4174                        selection.end = cursor;
4175                        selection.reversed = true;
4176                        selection.goal = SelectionGoal::None;
4177                    }
4178                })
4179            });
4180            this.insert("", cx);
4181            this.refresh_copilot_suggestions(true, cx);
4182        });
4183    }
4184
4185    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
4186        if self.move_to_prev_snippet_tabstop(cx) {
4187            return;
4188        }
4189
4190        self.outdent(&Outdent, cx);
4191    }
4192
4193    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
4194        if self.move_to_next_snippet_tabstop(cx) {
4195            return;
4196        }
4197
4198        let mut selections = self.selections.all_adjusted(cx);
4199        let buffer = self.buffer.read(cx);
4200        let snapshot = buffer.snapshot(cx);
4201        let rows_iter = selections.iter().map(|s| s.head().row);
4202        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
4203
4204        let mut edits = Vec::new();
4205        let mut prev_edited_row = 0;
4206        let mut row_delta = 0;
4207        for selection in &mut selections {
4208            if selection.start.row != prev_edited_row {
4209                row_delta = 0;
4210            }
4211            prev_edited_row = selection.end.row;
4212
4213            // If the selection is non-empty, then increase the indentation of the selected lines.
4214            if !selection.is_empty() {
4215                row_delta =
4216                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4217                continue;
4218            }
4219
4220            // If the selection is empty and the cursor is in the leading whitespace before the
4221            // suggested indentation, then auto-indent the line.
4222            let cursor = selection.head();
4223            let current_indent = snapshot.indent_size_for_line(cursor.row);
4224            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
4225                if cursor.column < suggested_indent.len
4226                    && cursor.column <= current_indent.len
4227                    && current_indent.len <= suggested_indent.len
4228                {
4229                    selection.start = Point::new(cursor.row, suggested_indent.len);
4230                    selection.end = selection.start;
4231                    if row_delta == 0 {
4232                        edits.extend(Buffer::edit_for_indent_size_adjustment(
4233                            cursor.row,
4234                            current_indent,
4235                            suggested_indent,
4236                        ));
4237                        row_delta = suggested_indent.len - current_indent.len;
4238                    }
4239                    continue;
4240                }
4241            }
4242
4243            // Accept copilot suggestion if there is only one selection and the cursor is not
4244            // in the leading whitespace.
4245            if self.selections.count() == 1
4246                && cursor.column >= current_indent.len
4247                && self.has_active_copilot_suggestion(cx)
4248            {
4249                self.accept_copilot_suggestion(cx);
4250                return;
4251            }
4252
4253            // Otherwise, insert a hard or soft tab.
4254            let settings = buffer.settings_at(cursor, cx);
4255            let tab_size = if settings.hard_tabs {
4256                IndentSize::tab()
4257            } else {
4258                let tab_size = settings.tab_size.get();
4259                let char_column = snapshot
4260                    .text_for_range(Point::new(cursor.row, 0)..cursor)
4261                    .flat_map(str::chars)
4262                    .count()
4263                    + row_delta as usize;
4264                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
4265                IndentSize::spaces(chars_to_next_tab_stop)
4266            };
4267            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
4268            selection.end = selection.start;
4269            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
4270            row_delta += tab_size.len;
4271        }
4272
4273        self.transact(cx, |this, cx| {
4274            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4275            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4276            this.refresh_copilot_suggestions(true, cx);
4277        });
4278    }
4279
4280    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
4281        let mut selections = self.selections.all::<Point>(cx);
4282        let mut prev_edited_row = 0;
4283        let mut row_delta = 0;
4284        let mut edits = Vec::new();
4285        let buffer = self.buffer.read(cx);
4286        let snapshot = buffer.snapshot(cx);
4287        for selection in &mut selections {
4288            if selection.start.row != prev_edited_row {
4289                row_delta = 0;
4290            }
4291            prev_edited_row = selection.end.row;
4292
4293            row_delta =
4294                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4295        }
4296
4297        self.transact(cx, |this, cx| {
4298            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4299            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4300        });
4301    }
4302
4303    fn indent_selection(
4304        buffer: &MultiBuffer,
4305        snapshot: &MultiBufferSnapshot,
4306        selection: &mut Selection<Point>,
4307        edits: &mut Vec<(Range<Point>, String)>,
4308        delta_for_start_row: u32,
4309        cx: &AppContext,
4310    ) -> u32 {
4311        let settings = buffer.settings_at(selection.start, cx);
4312        let tab_size = settings.tab_size.get();
4313        let indent_kind = if settings.hard_tabs {
4314            IndentKind::Tab
4315        } else {
4316            IndentKind::Space
4317        };
4318        let mut start_row = selection.start.row;
4319        let mut end_row = selection.end.row + 1;
4320
4321        // If a selection ends at the beginning of a line, don't indent
4322        // that last line.
4323        if selection.end.column == 0 {
4324            end_row -= 1;
4325        }
4326
4327        // Avoid re-indenting a row that has already been indented by a
4328        // previous selection, but still update this selection's column
4329        // to reflect that indentation.
4330        if delta_for_start_row > 0 {
4331            start_row += 1;
4332            selection.start.column += delta_for_start_row;
4333            if selection.end.row == selection.start.row {
4334                selection.end.column += delta_for_start_row;
4335            }
4336        }
4337
4338        let mut delta_for_end_row = 0;
4339        for row in start_row..end_row {
4340            let current_indent = snapshot.indent_size_for_line(row);
4341            let indent_delta = match (current_indent.kind, indent_kind) {
4342                (IndentKind::Space, IndentKind::Space) => {
4343                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4344                    IndentSize::spaces(columns_to_next_tab_stop)
4345                }
4346                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4347                (_, IndentKind::Tab) => IndentSize::tab(),
4348            };
4349
4350            let row_start = Point::new(row, 0);
4351            edits.push((
4352                row_start..row_start,
4353                indent_delta.chars().collect::<String>(),
4354            ));
4355
4356            // Update this selection's endpoints to reflect the indentation.
4357            if row == selection.start.row {
4358                selection.start.column += indent_delta.len;
4359            }
4360            if row == selection.end.row {
4361                selection.end.column += indent_delta.len;
4362                delta_for_end_row = indent_delta.len;
4363            }
4364        }
4365
4366        if selection.start.row == selection.end.row {
4367            delta_for_start_row + delta_for_end_row
4368        } else {
4369            delta_for_end_row
4370        }
4371    }
4372
4373    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4374        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4375        let selections = self.selections.all::<Point>(cx);
4376        let mut deletion_ranges = Vec::new();
4377        let mut last_outdent = None;
4378        {
4379            let buffer = self.buffer.read(cx);
4380            let snapshot = buffer.snapshot(cx);
4381            for selection in &selections {
4382                let settings = buffer.settings_at(selection.start, cx);
4383                let tab_size = settings.tab_size.get();
4384                let mut rows = selection.spanned_rows(false, &display_map);
4385
4386                // Avoid re-outdenting a row that has already been outdented by a
4387                // previous selection.
4388                if let Some(last_row) = last_outdent {
4389                    if last_row == rows.start {
4390                        rows.start += 1;
4391                    }
4392                }
4393
4394                for row in rows {
4395                    let indent_size = snapshot.indent_size_for_line(row);
4396                    if indent_size.len > 0 {
4397                        let deletion_len = match indent_size.kind {
4398                            IndentKind::Space => {
4399                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4400                                if columns_to_prev_tab_stop == 0 {
4401                                    tab_size
4402                                } else {
4403                                    columns_to_prev_tab_stop
4404                                }
4405                            }
4406                            IndentKind::Tab => 1,
4407                        };
4408                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4409                        last_outdent = Some(row);
4410                    }
4411                }
4412            }
4413        }
4414
4415        self.transact(cx, |this, cx| {
4416            this.buffer.update(cx, |buffer, cx| {
4417                let empty_str: Arc<str> = "".into();
4418                buffer.edit(
4419                    deletion_ranges
4420                        .into_iter()
4421                        .map(|range| (range, empty_str.clone())),
4422                    None,
4423                    cx,
4424                );
4425            });
4426            let selections = this.selections.all::<usize>(cx);
4427            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4428        });
4429    }
4430
4431    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4432        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4433        let selections = self.selections.all::<Point>(cx);
4434
4435        let mut new_cursors = Vec::new();
4436        let mut edit_ranges = Vec::new();
4437        let mut selections = selections.iter().peekable();
4438        while let Some(selection) = selections.next() {
4439            let mut rows = selection.spanned_rows(false, &display_map);
4440            let goal_display_column = selection.head().to_display_point(&display_map).column();
4441
4442            // Accumulate contiguous regions of rows that we want to delete.
4443            while let Some(next_selection) = selections.peek() {
4444                let next_rows = next_selection.spanned_rows(false, &display_map);
4445                if next_rows.start <= rows.end {
4446                    rows.end = next_rows.end;
4447                    selections.next().unwrap();
4448                } else {
4449                    break;
4450                }
4451            }
4452
4453            let buffer = &display_map.buffer_snapshot;
4454            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4455            let edit_end;
4456            let cursor_buffer_row;
4457            if buffer.max_point().row >= rows.end {
4458                // If there's a line after the range, delete the \n from the end of the row range
4459                // and position the cursor on the next line.
4460                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4461                cursor_buffer_row = rows.end;
4462            } else {
4463                // If there isn't a line after the range, delete the \n from the line before the
4464                // start of the row range and position the cursor there.
4465                edit_start = edit_start.saturating_sub(1);
4466                edit_end = buffer.len();
4467                cursor_buffer_row = rows.start.saturating_sub(1);
4468            }
4469
4470            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4471            *cursor.column_mut() =
4472                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4473
4474            new_cursors.push((
4475                selection.id,
4476                buffer.anchor_after(cursor.to_point(&display_map)),
4477            ));
4478            edit_ranges.push(edit_start..edit_end);
4479        }
4480
4481        self.transact(cx, |this, cx| {
4482            let buffer = this.buffer.update(cx, |buffer, cx| {
4483                let empty_str: Arc<str> = "".into();
4484                buffer.edit(
4485                    edit_ranges
4486                        .into_iter()
4487                        .map(|range| (range, empty_str.clone())),
4488                    None,
4489                    cx,
4490                );
4491                buffer.snapshot(cx)
4492            });
4493            let new_selections = new_cursors
4494                .into_iter()
4495                .map(|(id, cursor)| {
4496                    let cursor = cursor.to_point(&buffer);
4497                    Selection {
4498                        id,
4499                        start: cursor,
4500                        end: cursor,
4501                        reversed: false,
4502                        goal: SelectionGoal::None,
4503                    }
4504                })
4505                .collect();
4506
4507            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4508                s.select(new_selections);
4509            });
4510        });
4511    }
4512
4513    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4514        let mut row_ranges = Vec::<Range<u32>>::new();
4515        for selection in self.selections.all::<Point>(cx) {
4516            let start = selection.start.row;
4517            let end = if selection.start.row == selection.end.row {
4518                selection.start.row + 1
4519            } else {
4520                selection.end.row
4521            };
4522
4523            if let Some(last_row_range) = row_ranges.last_mut() {
4524                if start <= last_row_range.end {
4525                    last_row_range.end = end;
4526                    continue;
4527                }
4528            }
4529            row_ranges.push(start..end);
4530        }
4531
4532        let snapshot = self.buffer.read(cx).snapshot(cx);
4533        let mut cursor_positions = Vec::new();
4534        for row_range in &row_ranges {
4535            let anchor = snapshot.anchor_before(Point::new(
4536                row_range.end - 1,
4537                snapshot.line_len(row_range.end - 1),
4538            ));
4539            cursor_positions.push(anchor.clone()..anchor);
4540        }
4541
4542        self.transact(cx, |this, cx| {
4543            for row_range in row_ranges.into_iter().rev() {
4544                for row in row_range.rev() {
4545                    let end_of_line = Point::new(row, snapshot.line_len(row));
4546                    let indent = snapshot.indent_size_for_line(row + 1);
4547                    let start_of_next_line = Point::new(row + 1, indent.len);
4548
4549                    let replace = if snapshot.line_len(row + 1) > indent.len {
4550                        " "
4551                    } else {
4552                        ""
4553                    };
4554
4555                    this.buffer.update(cx, |buffer, cx| {
4556                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4557                    });
4558                }
4559            }
4560
4561            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4562                s.select_anchor_ranges(cursor_positions)
4563            });
4564        });
4565    }
4566
4567    pub fn sort_lines_case_sensitive(
4568        &mut self,
4569        _: &SortLinesCaseSensitive,
4570        cx: &mut ViewContext<Self>,
4571    ) {
4572        self.manipulate_lines(cx, |lines| lines.sort())
4573    }
4574
4575    pub fn sort_lines_case_insensitive(
4576        &mut self,
4577        _: &SortLinesCaseInsensitive,
4578        cx: &mut ViewContext<Self>,
4579    ) {
4580        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4581    }
4582
4583    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4584        self.manipulate_lines(cx, |lines| lines.reverse())
4585    }
4586
4587    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4588        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4589    }
4590
4591    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4592    where
4593        Fn: FnMut(&mut [&str]),
4594    {
4595        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4596        let buffer = self.buffer.read(cx).snapshot(cx);
4597
4598        let mut edits = Vec::new();
4599
4600        let selections = self.selections.all::<Point>(cx);
4601        let mut selections = selections.iter().peekable();
4602        let mut contiguous_row_selections = Vec::new();
4603        let mut new_selections = Vec::new();
4604
4605        while let Some(selection) = selections.next() {
4606            let (start_row, end_row) = consume_contiguous_rows(
4607                &mut contiguous_row_selections,
4608                selection,
4609                &display_map,
4610                &mut selections,
4611            );
4612
4613            let start_point = Point::new(start_row, 0);
4614            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4615            let text = buffer
4616                .text_for_range(start_point..end_point)
4617                .collect::<String>();
4618            let mut lines = text.split("\n").collect_vec();
4619
4620            let lines_len = lines.len();
4621            callback(&mut lines);
4622
4623            // This is a current limitation with selections.
4624            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4625            debug_assert!(
4626                lines.len() == lines_len,
4627                "callback should not change the number of lines"
4628            );
4629
4630            edits.push((start_point..end_point, lines.join("\n")));
4631            let start_anchor = buffer.anchor_after(start_point);
4632            let end_anchor = buffer.anchor_before(end_point);
4633
4634            // Make selection and push
4635            new_selections.push(Selection {
4636                id: selection.id,
4637                start: start_anchor.to_offset(&buffer),
4638                end: end_anchor.to_offset(&buffer),
4639                goal: SelectionGoal::None,
4640                reversed: selection.reversed,
4641            });
4642        }
4643
4644        self.transact(cx, |this, cx| {
4645            this.buffer.update(cx, |buffer, cx| {
4646                buffer.edit(edits, None, cx);
4647            });
4648
4649            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4650                s.select(new_selections);
4651            });
4652
4653            this.request_autoscroll(Autoscroll::fit(), cx);
4654        });
4655    }
4656
4657    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
4658        self.manipulate_text(cx, |text| text.to_uppercase())
4659    }
4660
4661    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
4662        self.manipulate_text(cx, |text| text.to_lowercase())
4663    }
4664
4665    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
4666        self.manipulate_text(cx, |text| {
4667            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4668            // https://github.com/rutrum/convert-case/issues/16
4669            text.split("\n")
4670                .map(|line| line.to_case(Case::Title))
4671                .join("\n")
4672        })
4673    }
4674
4675    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
4676        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
4677    }
4678
4679    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
4680        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
4681    }
4682
4683    pub fn convert_to_upper_camel_case(
4684        &mut self,
4685        _: &ConvertToUpperCamelCase,
4686        cx: &mut ViewContext<Self>,
4687    ) {
4688        self.manipulate_text(cx, |text| {
4689            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4690            // https://github.com/rutrum/convert-case/issues/16
4691            text.split("\n")
4692                .map(|line| line.to_case(Case::UpperCamel))
4693                .join("\n")
4694        })
4695    }
4696
4697    pub fn convert_to_lower_camel_case(
4698        &mut self,
4699        _: &ConvertToLowerCamelCase,
4700        cx: &mut ViewContext<Self>,
4701    ) {
4702        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
4703    }
4704
4705    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4706    where
4707        Fn: FnMut(&str) -> String,
4708    {
4709        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4710        let buffer = self.buffer.read(cx).snapshot(cx);
4711
4712        let mut new_selections = Vec::new();
4713        let mut edits = Vec::new();
4714        let mut selection_adjustment = 0i32;
4715
4716        for selection in self.selections.all::<usize>(cx) {
4717            let selection_is_empty = selection.is_empty();
4718
4719            let (start, end) = if selection_is_empty {
4720                let word_range = movement::surrounding_word(
4721                    &display_map,
4722                    selection.start.to_display_point(&display_map),
4723                );
4724                let start = word_range.start.to_offset(&display_map, Bias::Left);
4725                let end = word_range.end.to_offset(&display_map, Bias::Left);
4726                (start, end)
4727            } else {
4728                (selection.start, selection.end)
4729            };
4730
4731            let text = buffer.text_for_range(start..end).collect::<String>();
4732            let old_length = text.len() as i32;
4733            let text = callback(&text);
4734
4735            new_selections.push(Selection {
4736                start: (start as i32 - selection_adjustment) as usize,
4737                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
4738                goal: SelectionGoal::None,
4739                ..selection
4740            });
4741
4742            selection_adjustment += old_length - text.len() as i32;
4743
4744            edits.push((start..end, text));
4745        }
4746
4747        self.transact(cx, |this, cx| {
4748            this.buffer.update(cx, |buffer, cx| {
4749                buffer.edit(edits, None, cx);
4750            });
4751
4752            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4753                s.select(new_selections);
4754            });
4755
4756            this.request_autoscroll(Autoscroll::fit(), cx);
4757        });
4758    }
4759
4760    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4761        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4762        let buffer = &display_map.buffer_snapshot;
4763        let selections = self.selections.all::<Point>(cx);
4764
4765        let mut edits = Vec::new();
4766        let mut selections_iter = selections.iter().peekable();
4767        while let Some(selection) = selections_iter.next() {
4768            // Avoid duplicating the same lines twice.
4769            let mut rows = selection.spanned_rows(false, &display_map);
4770
4771            while let Some(next_selection) = selections_iter.peek() {
4772                let next_rows = next_selection.spanned_rows(false, &display_map);
4773                if next_rows.start < rows.end {
4774                    rows.end = next_rows.end;
4775                    selections_iter.next().unwrap();
4776                } else {
4777                    break;
4778                }
4779            }
4780
4781            // Copy the text from the selected row region and splice it at the start of the region.
4782            let start = Point::new(rows.start, 0);
4783            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4784            let text = buffer
4785                .text_for_range(start..end)
4786                .chain(Some("\n"))
4787                .collect::<String>();
4788            edits.push((start..start, text));
4789        }
4790
4791        self.transact(cx, |this, cx| {
4792            this.buffer.update(cx, |buffer, cx| {
4793                buffer.edit(edits, None, cx);
4794            });
4795
4796            this.request_autoscroll(Autoscroll::fit(), cx);
4797        });
4798    }
4799
4800    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4801        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4802        let buffer = self.buffer.read(cx).snapshot(cx);
4803
4804        let mut edits = Vec::new();
4805        let mut unfold_ranges = Vec::new();
4806        let mut refold_ranges = Vec::new();
4807
4808        let selections = self.selections.all::<Point>(cx);
4809        let mut selections = selections.iter().peekable();
4810        let mut contiguous_row_selections = Vec::new();
4811        let mut new_selections = Vec::new();
4812
4813        while let Some(selection) = selections.next() {
4814            // Find all the selections that span a contiguous row range
4815            let (start_row, end_row) = consume_contiguous_rows(
4816                &mut contiguous_row_selections,
4817                selection,
4818                &display_map,
4819                &mut selections,
4820            );
4821
4822            // Move the text spanned by the row range to be before the line preceding the row range
4823            if start_row > 0 {
4824                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4825                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4826                let insertion_point = display_map
4827                    .prev_line_boundary(Point::new(start_row - 1, 0))
4828                    .0;
4829
4830                // Don't move lines across excerpts
4831                if buffer
4832                    .excerpt_boundaries_in_range((
4833                        Bound::Excluded(insertion_point),
4834                        Bound::Included(range_to_move.end),
4835                    ))
4836                    .next()
4837                    .is_none()
4838                {
4839                    let text = buffer
4840                        .text_for_range(range_to_move.clone())
4841                        .flat_map(|s| s.chars())
4842                        .skip(1)
4843                        .chain(['\n'])
4844                        .collect::<String>();
4845
4846                    edits.push((
4847                        buffer.anchor_after(range_to_move.start)
4848                            ..buffer.anchor_before(range_to_move.end),
4849                        String::new(),
4850                    ));
4851                    let insertion_anchor = buffer.anchor_after(insertion_point);
4852                    edits.push((insertion_anchor..insertion_anchor, text));
4853
4854                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4855
4856                    // Move selections up
4857                    new_selections.extend(contiguous_row_selections.drain(..).map(
4858                        |mut selection| {
4859                            selection.start.row -= row_delta;
4860                            selection.end.row -= row_delta;
4861                            selection
4862                        },
4863                    ));
4864
4865                    // Move folds up
4866                    unfold_ranges.push(range_to_move.clone());
4867                    for fold in display_map.folds_in_range(
4868                        buffer.anchor_before(range_to_move.start)
4869                            ..buffer.anchor_after(range_to_move.end),
4870                    ) {
4871                        let mut start = fold.start.to_point(&buffer);
4872                        let mut end = fold.end.to_point(&buffer);
4873                        start.row -= row_delta;
4874                        end.row -= row_delta;
4875                        refold_ranges.push(start..end);
4876                    }
4877                }
4878            }
4879
4880            // If we didn't move line(s), preserve the existing selections
4881            new_selections.append(&mut contiguous_row_selections);
4882        }
4883
4884        self.transact(cx, |this, cx| {
4885            this.unfold_ranges(unfold_ranges, true, true, cx);
4886            this.buffer.update(cx, |buffer, cx| {
4887                for (range, text) in edits {
4888                    buffer.edit([(range, text)], None, cx);
4889                }
4890            });
4891            this.fold_ranges(refold_ranges, true, cx);
4892            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4893                s.select(new_selections);
4894            })
4895        });
4896    }
4897
4898    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4899        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4900        let buffer = self.buffer.read(cx).snapshot(cx);
4901
4902        let mut edits = Vec::new();
4903        let mut unfold_ranges = Vec::new();
4904        let mut refold_ranges = Vec::new();
4905
4906        let selections = self.selections.all::<Point>(cx);
4907        let mut selections = selections.iter().peekable();
4908        let mut contiguous_row_selections = Vec::new();
4909        let mut new_selections = Vec::new();
4910
4911        while let Some(selection) = selections.next() {
4912            // Find all the selections that span a contiguous row range
4913            let (start_row, end_row) = consume_contiguous_rows(
4914                &mut contiguous_row_selections,
4915                selection,
4916                &display_map,
4917                &mut selections,
4918            );
4919
4920            // Move the text spanned by the row range to be after the last line of the row range
4921            if end_row <= buffer.max_point().row {
4922                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4923                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4924
4925                // Don't move lines across excerpt boundaries
4926                if buffer
4927                    .excerpt_boundaries_in_range((
4928                        Bound::Excluded(range_to_move.start),
4929                        Bound::Included(insertion_point),
4930                    ))
4931                    .next()
4932                    .is_none()
4933                {
4934                    let mut text = String::from("\n");
4935                    text.extend(buffer.text_for_range(range_to_move.clone()));
4936                    text.pop(); // Drop trailing newline
4937                    edits.push((
4938                        buffer.anchor_after(range_to_move.start)
4939                            ..buffer.anchor_before(range_to_move.end),
4940                        String::new(),
4941                    ));
4942                    let insertion_anchor = buffer.anchor_after(insertion_point);
4943                    edits.push((insertion_anchor..insertion_anchor, text));
4944
4945                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4946
4947                    // Move selections down
4948                    new_selections.extend(contiguous_row_selections.drain(..).map(
4949                        |mut selection| {
4950                            selection.start.row += row_delta;
4951                            selection.end.row += row_delta;
4952                            selection
4953                        },
4954                    ));
4955
4956                    // Move folds down
4957                    unfold_ranges.push(range_to_move.clone());
4958                    for fold in display_map.folds_in_range(
4959                        buffer.anchor_before(range_to_move.start)
4960                            ..buffer.anchor_after(range_to_move.end),
4961                    ) {
4962                        let mut start = fold.start.to_point(&buffer);
4963                        let mut end = fold.end.to_point(&buffer);
4964                        start.row += row_delta;
4965                        end.row += row_delta;
4966                        refold_ranges.push(start..end);
4967                    }
4968                }
4969            }
4970
4971            // If we didn't move line(s), preserve the existing selections
4972            new_selections.append(&mut contiguous_row_selections);
4973        }
4974
4975        self.transact(cx, |this, cx| {
4976            this.unfold_ranges(unfold_ranges, true, true, cx);
4977            this.buffer.update(cx, |buffer, cx| {
4978                for (range, text) in edits {
4979                    buffer.edit([(range, text)], None, cx);
4980                }
4981            });
4982            this.fold_ranges(refold_ranges, true, cx);
4983            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4984        });
4985    }
4986
4987    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4988        self.transact(cx, |this, cx| {
4989            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4990                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4991                let line_mode = s.line_mode;
4992                s.move_with(|display_map, selection| {
4993                    if !selection.is_empty() || line_mode {
4994                        return;
4995                    }
4996
4997                    let mut head = selection.head();
4998                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4999                    if head.column() == display_map.line_len(head.row()) {
5000                        transpose_offset = display_map
5001                            .buffer_snapshot
5002                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5003                    }
5004
5005                    if transpose_offset == 0 {
5006                        return;
5007                    }
5008
5009                    *head.column_mut() += 1;
5010                    head = display_map.clip_point(head, Bias::Right);
5011                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
5012
5013                    let transpose_start = display_map
5014                        .buffer_snapshot
5015                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5016                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
5017                        let transpose_end = display_map
5018                            .buffer_snapshot
5019                            .clip_offset(transpose_offset + 1, Bias::Right);
5020                        if let Some(ch) =
5021                            display_map.buffer_snapshot.chars_at(transpose_start).next()
5022                        {
5023                            edits.push((transpose_start..transpose_offset, String::new()));
5024                            edits.push((transpose_end..transpose_end, ch.to_string()));
5025                        }
5026                    }
5027                });
5028                edits
5029            });
5030            this.buffer
5031                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
5032            let selections = this.selections.all::<usize>(cx);
5033            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5034                s.select(selections);
5035            });
5036        });
5037    }
5038
5039    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
5040        let mut text = String::new();
5041        let buffer = self.buffer.read(cx).snapshot(cx);
5042        let mut selections = self.selections.all::<Point>(cx);
5043        let mut clipboard_selections = Vec::with_capacity(selections.len());
5044        {
5045            let max_point = buffer.max_point();
5046            let mut is_first = true;
5047            for selection in &mut selections {
5048                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5049                if is_entire_line {
5050                    selection.start = Point::new(selection.start.row, 0);
5051                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
5052                    selection.goal = SelectionGoal::None;
5053                }
5054                if is_first {
5055                    is_first = false;
5056                } else {
5057                    text += "\n";
5058                }
5059                let mut len = 0;
5060                for chunk in buffer.text_for_range(selection.start..selection.end) {
5061                    text.push_str(chunk);
5062                    len += chunk.len();
5063                }
5064                clipboard_selections.push(ClipboardSelection {
5065                    len,
5066                    is_entire_line,
5067                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
5068                });
5069            }
5070        }
5071
5072        self.transact(cx, |this, cx| {
5073            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5074                s.select(selections);
5075            });
5076            this.insert("", cx);
5077            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5078        });
5079    }
5080
5081    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
5082        let selections = self.selections.all::<Point>(cx);
5083        let buffer = self.buffer.read(cx).read(cx);
5084        let mut text = String::new();
5085
5086        let mut clipboard_selections = Vec::with_capacity(selections.len());
5087        {
5088            let max_point = buffer.max_point();
5089            let mut is_first = true;
5090            for selection in selections.iter() {
5091                let mut start = selection.start;
5092                let mut end = selection.end;
5093                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5094                if is_entire_line {
5095                    start = Point::new(start.row, 0);
5096                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
5097                }
5098                if is_first {
5099                    is_first = false;
5100                } else {
5101                    text += "\n";
5102                }
5103                let mut len = 0;
5104                for chunk in buffer.text_for_range(start..end) {
5105                    text.push_str(chunk);
5106                    len += chunk.len();
5107                }
5108                clipboard_selections.push(ClipboardSelection {
5109                    len,
5110                    is_entire_line,
5111                    first_line_indent: buffer.indent_size_for_line(start.row).len,
5112                });
5113            }
5114        }
5115
5116        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5117    }
5118
5119    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
5120        self.transact(cx, |this, cx| {
5121            if let Some(item) = cx.read_from_clipboard() {
5122                let clipboard_text = Cow::Borrowed(item.text());
5123                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
5124                    let old_selections = this.selections.all::<usize>(cx);
5125                    let all_selections_were_entire_line =
5126                        clipboard_selections.iter().all(|s| s.is_entire_line);
5127                    let first_selection_indent_column =
5128                        clipboard_selections.first().map(|s| s.first_line_indent);
5129                    if clipboard_selections.len() != old_selections.len() {
5130                        clipboard_selections.drain(..);
5131                    }
5132
5133                    this.buffer.update(cx, |buffer, cx| {
5134                        let snapshot = buffer.read(cx);
5135                        let mut start_offset = 0;
5136                        let mut edits = Vec::new();
5137                        let mut original_indent_columns = Vec::new();
5138                        let line_mode = this.selections.line_mode;
5139                        for (ix, selection) in old_selections.iter().enumerate() {
5140                            let to_insert;
5141                            let entire_line;
5142                            let original_indent_column;
5143                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
5144                                let end_offset = start_offset + clipboard_selection.len;
5145                                to_insert = &clipboard_text[start_offset..end_offset];
5146                                entire_line = clipboard_selection.is_entire_line;
5147                                start_offset = end_offset + 1;
5148                                original_indent_column =
5149                                    Some(clipboard_selection.first_line_indent);
5150                            } else {
5151                                to_insert = clipboard_text.as_str();
5152                                entire_line = all_selections_were_entire_line;
5153                                original_indent_column = first_selection_indent_column
5154                            }
5155
5156                            // If the corresponding selection was empty when this slice of the
5157                            // clipboard text was written, then the entire line containing the
5158                            // selection was copied. If this selection is also currently empty,
5159                            // then paste the line before the current line of the buffer.
5160                            let range = if selection.is_empty() && !line_mode && entire_line {
5161                                let column = selection.start.to_point(&snapshot).column as usize;
5162                                let line_start = selection.start - column;
5163                                line_start..line_start
5164                            } else {
5165                                selection.range()
5166                            };
5167
5168                            edits.push((range, to_insert));
5169                            original_indent_columns.extend(original_indent_column);
5170                        }
5171                        drop(snapshot);
5172
5173                        buffer.edit(
5174                            edits,
5175                            Some(AutoindentMode::Block {
5176                                original_indent_columns,
5177                            }),
5178                            cx,
5179                        );
5180                    });
5181
5182                    let selections = this.selections.all::<usize>(cx);
5183                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5184                } else {
5185                    this.insert(&clipboard_text, cx);
5186                }
5187            }
5188        });
5189    }
5190
5191    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
5192        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
5193            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
5194                self.change_selections(None, cx, |s| {
5195                    s.select_anchors(selections.to_vec());
5196                });
5197            }
5198            self.request_autoscroll(Autoscroll::fit(), cx);
5199            self.unmark_text(cx);
5200            self.refresh_copilot_suggestions(true, cx);
5201            cx.emit(Event::Edited);
5202        }
5203    }
5204
5205    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
5206        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
5207            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
5208            {
5209                self.change_selections(None, cx, |s| {
5210                    s.select_anchors(selections.to_vec());
5211                });
5212            }
5213            self.request_autoscroll(Autoscroll::fit(), cx);
5214            self.unmark_text(cx);
5215            self.refresh_copilot_suggestions(true, cx);
5216            cx.emit(Event::Edited);
5217        }
5218    }
5219
5220    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
5221        self.buffer
5222            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
5223    }
5224
5225    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
5226        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5227            let line_mode = s.line_mode;
5228            s.move_with(|map, selection| {
5229                let cursor = if selection.is_empty() && !line_mode {
5230                    movement::left(map, selection.start)
5231                } else {
5232                    selection.start
5233                };
5234                selection.collapse_to(cursor, SelectionGoal::None);
5235            });
5236        })
5237    }
5238
5239    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
5240        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5241            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
5242        })
5243    }
5244
5245    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
5246        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5247            let line_mode = s.line_mode;
5248            s.move_with(|map, selection| {
5249                let cursor = if selection.is_empty() && !line_mode {
5250                    movement::right(map, selection.end)
5251                } else {
5252                    selection.end
5253                };
5254                selection.collapse_to(cursor, SelectionGoal::None)
5255            });
5256        })
5257    }
5258
5259    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
5260        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5261            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
5262        })
5263    }
5264
5265    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
5266        if self.take_rename(true, cx).is_some() {
5267            return;
5268        }
5269
5270        if matches!(self.mode, EditorMode::SingleLine) {
5271            cx.propagate_action();
5272            return;
5273        }
5274
5275        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5276            let line_mode = s.line_mode;
5277            s.move_with(|map, selection| {
5278                if !selection.is_empty() && !line_mode {
5279                    selection.goal = SelectionGoal::None;
5280                }
5281                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
5282                selection.collapse_to(cursor, goal);
5283            });
5284        })
5285    }
5286
5287    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5288        if self.take_rename(true, cx).is_some() {
5289            return;
5290        }
5291
5292        if matches!(self.mode, EditorMode::SingleLine) {
5293            cx.propagate_action();
5294            return;
5295        }
5296
5297        let row_count = if let Some(row_count) = self.visible_line_count() {
5298            row_count as u32 - 1
5299        } else {
5300            return;
5301        };
5302
5303        let autoscroll = if action.center_cursor {
5304            Autoscroll::center()
5305        } else {
5306            Autoscroll::fit()
5307        };
5308
5309        self.change_selections(Some(autoscroll), cx, |s| {
5310            let line_mode = s.line_mode;
5311            s.move_with(|map, selection| {
5312                if !selection.is_empty() && !line_mode {
5313                    selection.goal = SelectionGoal::None;
5314                }
5315                let (cursor, goal) =
5316                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
5317                selection.collapse_to(cursor, goal);
5318            });
5319        });
5320    }
5321
5322    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5323        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5324            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
5325        })
5326    }
5327
5328    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5329        self.take_rename(true, cx);
5330
5331        if self.mode == EditorMode::SingleLine {
5332            cx.propagate_action();
5333            return;
5334        }
5335
5336        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5337            let line_mode = s.line_mode;
5338            s.move_with(|map, selection| {
5339                if !selection.is_empty() && !line_mode {
5340                    selection.goal = SelectionGoal::None;
5341                }
5342                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
5343                selection.collapse_to(cursor, goal);
5344            });
5345        });
5346    }
5347
5348    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5349        if self.take_rename(true, cx).is_some() {
5350            return;
5351        }
5352
5353        if self
5354            .context_menu
5355            .as_mut()
5356            .map(|menu| menu.select_last(cx))
5357            .unwrap_or(false)
5358        {
5359            return;
5360        }
5361
5362        if matches!(self.mode, EditorMode::SingleLine) {
5363            cx.propagate_action();
5364            return;
5365        }
5366
5367        let row_count = if let Some(row_count) = self.visible_line_count() {
5368            row_count as u32 - 1
5369        } else {
5370            return;
5371        };
5372
5373        let autoscroll = if action.center_cursor {
5374            Autoscroll::center()
5375        } else {
5376            Autoscroll::fit()
5377        };
5378
5379        self.change_selections(Some(autoscroll), cx, |s| {
5380            let line_mode = s.line_mode;
5381            s.move_with(|map, selection| {
5382                if !selection.is_empty() && !line_mode {
5383                    selection.goal = SelectionGoal::None;
5384                }
5385                let (cursor, goal) =
5386                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5387                selection.collapse_to(cursor, goal);
5388            });
5389        });
5390    }
5391
5392    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5393        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5394            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5395        });
5396    }
5397
5398    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
5399        if let Some(context_menu) = self.context_menu.as_mut() {
5400            context_menu.select_first(cx);
5401        }
5402    }
5403
5404    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
5405        if let Some(context_menu) = self.context_menu.as_mut() {
5406            context_menu.select_prev(cx);
5407        }
5408    }
5409
5410    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
5411        if let Some(context_menu) = self.context_menu.as_mut() {
5412            context_menu.select_next(cx);
5413        }
5414    }
5415
5416    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
5417        if let Some(context_menu) = self.context_menu.as_mut() {
5418            context_menu.select_last(cx);
5419        }
5420    }
5421
5422    pub fn move_to_previous_word_start(
5423        &mut self,
5424        _: &MoveToPreviousWordStart,
5425        cx: &mut ViewContext<Self>,
5426    ) {
5427        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5428            s.move_cursors_with(|map, head, _| {
5429                (
5430                    movement::previous_word_start(map, head),
5431                    SelectionGoal::None,
5432                )
5433            });
5434        })
5435    }
5436
5437    pub fn move_to_previous_subword_start(
5438        &mut self,
5439        _: &MoveToPreviousSubwordStart,
5440        cx: &mut ViewContext<Self>,
5441    ) {
5442        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5443            s.move_cursors_with(|map, head, _| {
5444                (
5445                    movement::previous_subword_start(map, head),
5446                    SelectionGoal::None,
5447                )
5448            });
5449        })
5450    }
5451
5452    pub fn select_to_previous_word_start(
5453        &mut self,
5454        _: &SelectToPreviousWordStart,
5455        cx: &mut ViewContext<Self>,
5456    ) {
5457        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5458            s.move_heads_with(|map, head, _| {
5459                (
5460                    movement::previous_word_start(map, head),
5461                    SelectionGoal::None,
5462                )
5463            });
5464        })
5465    }
5466
5467    pub fn select_to_previous_subword_start(
5468        &mut self,
5469        _: &SelectToPreviousSubwordStart,
5470        cx: &mut ViewContext<Self>,
5471    ) {
5472        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5473            s.move_heads_with(|map, head, _| {
5474                (
5475                    movement::previous_subword_start(map, head),
5476                    SelectionGoal::None,
5477                )
5478            });
5479        })
5480    }
5481
5482    pub fn delete_to_previous_word_start(
5483        &mut self,
5484        _: &DeleteToPreviousWordStart,
5485        cx: &mut ViewContext<Self>,
5486    ) {
5487        self.transact(cx, |this, cx| {
5488            this.select_autoclose_pair(cx);
5489            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5490                let line_mode = s.line_mode;
5491                s.move_with(|map, selection| {
5492                    if selection.is_empty() && !line_mode {
5493                        let cursor = movement::previous_word_start(map, selection.head());
5494                        selection.set_head(cursor, SelectionGoal::None);
5495                    }
5496                });
5497            });
5498            this.insert("", cx);
5499        });
5500    }
5501
5502    pub fn delete_to_previous_subword_start(
5503        &mut self,
5504        _: &DeleteToPreviousSubwordStart,
5505        cx: &mut ViewContext<Self>,
5506    ) {
5507        self.transact(cx, |this, cx| {
5508            this.select_autoclose_pair(cx);
5509            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5510                let line_mode = s.line_mode;
5511                s.move_with(|map, selection| {
5512                    if selection.is_empty() && !line_mode {
5513                        let cursor = movement::previous_subword_start(map, selection.head());
5514                        selection.set_head(cursor, SelectionGoal::None);
5515                    }
5516                });
5517            });
5518            this.insert("", cx);
5519        });
5520    }
5521
5522    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5523        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5524            s.move_cursors_with(|map, head, _| {
5525                (movement::next_word_end(map, head), SelectionGoal::None)
5526            });
5527        })
5528    }
5529
5530    pub fn move_to_next_subword_end(
5531        &mut self,
5532        _: &MoveToNextSubwordEnd,
5533        cx: &mut ViewContext<Self>,
5534    ) {
5535        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5536            s.move_cursors_with(|map, head, _| {
5537                (movement::next_subword_end(map, head), SelectionGoal::None)
5538            });
5539        })
5540    }
5541
5542    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5543        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5544            s.move_heads_with(|map, head, _| {
5545                (movement::next_word_end(map, head), SelectionGoal::None)
5546            });
5547        })
5548    }
5549
5550    pub fn select_to_next_subword_end(
5551        &mut self,
5552        _: &SelectToNextSubwordEnd,
5553        cx: &mut ViewContext<Self>,
5554    ) {
5555        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5556            s.move_heads_with(|map, head, _| {
5557                (movement::next_subword_end(map, head), SelectionGoal::None)
5558            });
5559        })
5560    }
5561
5562    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5563        self.transact(cx, |this, cx| {
5564            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5565                let line_mode = s.line_mode;
5566                s.move_with(|map, selection| {
5567                    if selection.is_empty() && !line_mode {
5568                        let cursor = movement::next_word_end(map, selection.head());
5569                        selection.set_head(cursor, SelectionGoal::None);
5570                    }
5571                });
5572            });
5573            this.insert("", cx);
5574        });
5575    }
5576
5577    pub fn delete_to_next_subword_end(
5578        &mut self,
5579        _: &DeleteToNextSubwordEnd,
5580        cx: &mut ViewContext<Self>,
5581    ) {
5582        self.transact(cx, |this, cx| {
5583            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5584                s.move_with(|map, selection| {
5585                    if selection.is_empty() {
5586                        let cursor = movement::next_subword_end(map, selection.head());
5587                        selection.set_head(cursor, SelectionGoal::None);
5588                    }
5589                });
5590            });
5591            this.insert("", cx);
5592        });
5593    }
5594
5595    pub fn move_to_beginning_of_line(
5596        &mut self,
5597        _: &MoveToBeginningOfLine,
5598        cx: &mut ViewContext<Self>,
5599    ) {
5600        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5601            s.move_cursors_with(|map, head, _| {
5602                (
5603                    movement::indented_line_beginning(map, head, true),
5604                    SelectionGoal::None,
5605                )
5606            });
5607        })
5608    }
5609
5610    pub fn select_to_beginning_of_line(
5611        &mut self,
5612        action: &SelectToBeginningOfLine,
5613        cx: &mut ViewContext<Self>,
5614    ) {
5615        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5616            s.move_heads_with(|map, head, _| {
5617                (
5618                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5619                    SelectionGoal::None,
5620                )
5621            });
5622        });
5623    }
5624
5625    pub fn delete_to_beginning_of_line(
5626        &mut self,
5627        _: &DeleteToBeginningOfLine,
5628        cx: &mut ViewContext<Self>,
5629    ) {
5630        self.transact(cx, |this, cx| {
5631            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5632                s.move_with(|_, selection| {
5633                    selection.reversed = true;
5634                });
5635            });
5636
5637            this.select_to_beginning_of_line(
5638                &SelectToBeginningOfLine {
5639                    stop_at_soft_wraps: false,
5640                },
5641                cx,
5642            );
5643            this.backspace(&Backspace, cx);
5644        });
5645    }
5646
5647    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5648        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5649            s.move_cursors_with(|map, head, _| {
5650                (movement::line_end(map, head, true), SelectionGoal::None)
5651            });
5652        })
5653    }
5654
5655    pub fn select_to_end_of_line(
5656        &mut self,
5657        action: &SelectToEndOfLine,
5658        cx: &mut ViewContext<Self>,
5659    ) {
5660        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5661            s.move_heads_with(|map, head, _| {
5662                (
5663                    movement::line_end(map, head, action.stop_at_soft_wraps),
5664                    SelectionGoal::None,
5665                )
5666            });
5667        })
5668    }
5669
5670    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5671        self.transact(cx, |this, cx| {
5672            this.select_to_end_of_line(
5673                &SelectToEndOfLine {
5674                    stop_at_soft_wraps: false,
5675                },
5676                cx,
5677            );
5678            this.delete(&Delete, cx);
5679        });
5680    }
5681
5682    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5683        self.transact(cx, |this, cx| {
5684            this.select_to_end_of_line(
5685                &SelectToEndOfLine {
5686                    stop_at_soft_wraps: false,
5687                },
5688                cx,
5689            );
5690            this.cut(&Cut, cx);
5691        });
5692    }
5693
5694    pub fn move_to_start_of_paragraph(
5695        &mut self,
5696        _: &MoveToStartOfParagraph,
5697        cx: &mut ViewContext<Self>,
5698    ) {
5699        if matches!(self.mode, EditorMode::SingleLine) {
5700            cx.propagate_action();
5701            return;
5702        }
5703
5704        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5705            s.move_with(|map, selection| {
5706                selection.collapse_to(
5707                    movement::start_of_paragraph(map, selection.head(), 1),
5708                    SelectionGoal::None,
5709                )
5710            });
5711        })
5712    }
5713
5714    pub fn move_to_end_of_paragraph(
5715        &mut self,
5716        _: &MoveToEndOfParagraph,
5717        cx: &mut ViewContext<Self>,
5718    ) {
5719        if matches!(self.mode, EditorMode::SingleLine) {
5720            cx.propagate_action();
5721            return;
5722        }
5723
5724        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5725            s.move_with(|map, selection| {
5726                selection.collapse_to(
5727                    movement::end_of_paragraph(map, selection.head(), 1),
5728                    SelectionGoal::None,
5729                )
5730            });
5731        })
5732    }
5733
5734    pub fn select_to_start_of_paragraph(
5735        &mut self,
5736        _: &SelectToStartOfParagraph,
5737        cx: &mut ViewContext<Self>,
5738    ) {
5739        if matches!(self.mode, EditorMode::SingleLine) {
5740            cx.propagate_action();
5741            return;
5742        }
5743
5744        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5745            s.move_heads_with(|map, head, _| {
5746                (
5747                    movement::start_of_paragraph(map, head, 1),
5748                    SelectionGoal::None,
5749                )
5750            });
5751        })
5752    }
5753
5754    pub fn select_to_end_of_paragraph(
5755        &mut self,
5756        _: &SelectToEndOfParagraph,
5757        cx: &mut ViewContext<Self>,
5758    ) {
5759        if matches!(self.mode, EditorMode::SingleLine) {
5760            cx.propagate_action();
5761            return;
5762        }
5763
5764        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5765            s.move_heads_with(|map, head, _| {
5766                (
5767                    movement::end_of_paragraph(map, head, 1),
5768                    SelectionGoal::None,
5769                )
5770            });
5771        })
5772    }
5773
5774    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5775        if matches!(self.mode, EditorMode::SingleLine) {
5776            cx.propagate_action();
5777            return;
5778        }
5779
5780        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5781            s.select_ranges(vec![0..0]);
5782        });
5783    }
5784
5785    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5786        let mut selection = self.selections.last::<Point>(cx);
5787        selection.set_head(Point::zero(), SelectionGoal::None);
5788
5789        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5790            s.select(vec![selection]);
5791        });
5792    }
5793
5794    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5795        if matches!(self.mode, EditorMode::SingleLine) {
5796            cx.propagate_action();
5797            return;
5798        }
5799
5800        let cursor = self.buffer.read(cx).read(cx).len();
5801        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5802            s.select_ranges(vec![cursor..cursor])
5803        });
5804    }
5805
5806    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5807        self.nav_history = nav_history;
5808    }
5809
5810    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5811        self.nav_history.as_ref()
5812    }
5813
5814    fn push_to_nav_history(
5815        &mut self,
5816        cursor_anchor: Anchor,
5817        new_position: Option<Point>,
5818        cx: &mut ViewContext<Self>,
5819    ) {
5820        if let Some(nav_history) = self.nav_history.as_mut() {
5821            let buffer = self.buffer.read(cx).read(cx);
5822            let cursor_position = cursor_anchor.to_point(&buffer);
5823            let scroll_state = self.scroll_manager.anchor();
5824            let scroll_top_row = scroll_state.top_row(&buffer);
5825            drop(buffer);
5826
5827            if let Some(new_position) = new_position {
5828                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5829                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5830                    return;
5831                }
5832            }
5833
5834            nav_history.push(
5835                Some(NavigationData {
5836                    cursor_anchor,
5837                    cursor_position,
5838                    scroll_anchor: scroll_state,
5839                    scroll_top_row,
5840                }),
5841                cx,
5842            );
5843        }
5844    }
5845
5846    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5847        let buffer = self.buffer.read(cx).snapshot(cx);
5848        let mut selection = self.selections.first::<usize>(cx);
5849        selection.set_head(buffer.len(), SelectionGoal::None);
5850        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5851            s.select(vec![selection]);
5852        });
5853    }
5854
5855    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5856        let end = self.buffer.read(cx).read(cx).len();
5857        self.change_selections(None, cx, |s| {
5858            s.select_ranges(vec![0..end]);
5859        });
5860    }
5861
5862    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5863        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5864        let mut selections = self.selections.all::<Point>(cx);
5865        let max_point = display_map.buffer_snapshot.max_point();
5866        for selection in &mut selections {
5867            let rows = selection.spanned_rows(true, &display_map);
5868            selection.start = Point::new(rows.start, 0);
5869            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5870            selection.reversed = false;
5871        }
5872        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5873            s.select(selections);
5874        });
5875    }
5876
5877    pub fn split_selection_into_lines(
5878        &mut self,
5879        _: &SplitSelectionIntoLines,
5880        cx: &mut ViewContext<Self>,
5881    ) {
5882        let mut to_unfold = Vec::new();
5883        let mut new_selection_ranges = Vec::new();
5884        {
5885            let selections = self.selections.all::<Point>(cx);
5886            let buffer = self.buffer.read(cx).read(cx);
5887            for selection in selections {
5888                for row in selection.start.row..selection.end.row {
5889                    let cursor = Point::new(row, buffer.line_len(row));
5890                    new_selection_ranges.push(cursor..cursor);
5891                }
5892                new_selection_ranges.push(selection.end..selection.end);
5893                to_unfold.push(selection.start..selection.end);
5894            }
5895        }
5896        self.unfold_ranges(to_unfold, true, true, cx);
5897        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5898            s.select_ranges(new_selection_ranges);
5899        });
5900    }
5901
5902    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5903        self.add_selection(true, cx);
5904    }
5905
5906    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5907        self.add_selection(false, cx);
5908    }
5909
5910    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5911        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5912        let mut selections = self.selections.all::<Point>(cx);
5913        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5914            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5915            let range = oldest_selection.display_range(&display_map).sorted();
5916            let columns = cmp::min(range.start.column(), range.end.column())
5917                ..cmp::max(range.start.column(), range.end.column());
5918
5919            selections.clear();
5920            let mut stack = Vec::new();
5921            for row in range.start.row()..=range.end.row() {
5922                if let Some(selection) = self.selections.build_columnar_selection(
5923                    &display_map,
5924                    row,
5925                    &columns,
5926                    oldest_selection.reversed,
5927                ) {
5928                    stack.push(selection.id);
5929                    selections.push(selection);
5930                }
5931            }
5932
5933            if above {
5934                stack.reverse();
5935            }
5936
5937            AddSelectionsState { above, stack }
5938        });
5939
5940        let last_added_selection = *state.stack.last().unwrap();
5941        let mut new_selections = Vec::new();
5942        if above == state.above {
5943            let end_row = if above {
5944                0
5945            } else {
5946                display_map.max_point().row()
5947            };
5948
5949            'outer: for selection in selections {
5950                if selection.id == last_added_selection {
5951                    let range = selection.display_range(&display_map).sorted();
5952                    debug_assert_eq!(range.start.row(), range.end.row());
5953                    let mut row = range.start.row();
5954                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5955                    {
5956                        start..end
5957                    } else {
5958                        cmp::min(range.start.column(), range.end.column())
5959                            ..cmp::max(range.start.column(), range.end.column())
5960                    };
5961
5962                    while row != end_row {
5963                        if above {
5964                            row -= 1;
5965                        } else {
5966                            row += 1;
5967                        }
5968
5969                        if let Some(new_selection) = self.selections.build_columnar_selection(
5970                            &display_map,
5971                            row,
5972                            &columns,
5973                            selection.reversed,
5974                        ) {
5975                            state.stack.push(new_selection.id);
5976                            if above {
5977                                new_selections.push(new_selection);
5978                                new_selections.push(selection);
5979                            } else {
5980                                new_selections.push(selection);
5981                                new_selections.push(new_selection);
5982                            }
5983
5984                            continue 'outer;
5985                        }
5986                    }
5987                }
5988
5989                new_selections.push(selection);
5990            }
5991        } else {
5992            new_selections = selections;
5993            new_selections.retain(|s| s.id != last_added_selection);
5994            state.stack.pop();
5995        }
5996
5997        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5998            s.select(new_selections);
5999        });
6000        if state.stack.len() > 1 {
6001            self.add_selections_state = Some(state);
6002        }
6003    }
6004
6005    pub fn select_next_match_internal(
6006        &mut self,
6007        display_map: &DisplaySnapshot,
6008        replace_newest: bool,
6009        autoscroll: Option<Autoscroll>,
6010        cx: &mut ViewContext<Self>,
6011    ) -> Result<()> {
6012        fn select_next_match_ranges(
6013            this: &mut Editor,
6014            range: Range<usize>,
6015            replace_newest: bool,
6016            auto_scroll: Option<Autoscroll>,
6017            cx: &mut ViewContext<Editor>,
6018        ) {
6019            this.unfold_ranges([range.clone()], false, true, cx);
6020            this.change_selections(auto_scroll, cx, |s| {
6021                if replace_newest {
6022                    s.delete(s.newest_anchor().id);
6023                }
6024                s.insert_range(range.clone());
6025            });
6026        }
6027
6028        let buffer = &display_map.buffer_snapshot;
6029        let mut selections = self.selections.all::<usize>(cx);
6030        if let Some(mut select_next_state) = self.select_next_state.take() {
6031            let query = &select_next_state.query;
6032            if !select_next_state.done {
6033                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6034                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6035                let mut next_selected_range = None;
6036
6037                let bytes_after_last_selection =
6038                    buffer.bytes_in_range(last_selection.end..buffer.len());
6039                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
6040                let query_matches = query
6041                    .stream_find_iter(bytes_after_last_selection)
6042                    .map(|result| (last_selection.end, result))
6043                    .chain(
6044                        query
6045                            .stream_find_iter(bytes_before_first_selection)
6046                            .map(|result| (0, result)),
6047                    );
6048
6049                for (start_offset, query_match) in query_matches {
6050                    let query_match = query_match.unwrap(); // can only fail due to I/O
6051                    let offset_range =
6052                        start_offset + query_match.start()..start_offset + query_match.end();
6053                    let display_range = offset_range.start.to_display_point(&display_map)
6054                        ..offset_range.end.to_display_point(&display_map);
6055
6056                    if !select_next_state.wordwise
6057                        || (!movement::is_inside_word(&display_map, display_range.start)
6058                            && !movement::is_inside_word(&display_map, display_range.end))
6059                    {
6060                        if selections
6061                            .iter()
6062                            .find(|selection| selection.equals(&offset_range))
6063                            .is_none()
6064                        {
6065                            next_selected_range = Some(offset_range);
6066                            break;
6067                        }
6068                    }
6069                }
6070
6071                if let Some(next_selected_range) = next_selected_range {
6072                    select_next_match_ranges(
6073                        self,
6074                        next_selected_range,
6075                        replace_newest,
6076                        autoscroll,
6077                        cx,
6078                    );
6079                } else {
6080                    select_next_state.done = true;
6081                }
6082            }
6083
6084            self.select_next_state = Some(select_next_state);
6085        } else if selections.len() == 1 {
6086            let selection = selections.last_mut().unwrap();
6087            if selection.start == selection.end {
6088                let word_range = movement::surrounding_word(
6089                    &display_map,
6090                    selection.start.to_display_point(&display_map),
6091                );
6092                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6093                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6094                selection.goal = SelectionGoal::None;
6095                selection.reversed = false;
6096
6097                let query = buffer
6098                    .text_for_range(selection.start..selection.end)
6099                    .collect::<String>();
6100
6101                let is_empty = query.is_empty();
6102                let select_state = SelectNextState {
6103                    query: AhoCorasick::new(&[query])?,
6104                    wordwise: true,
6105                    done: is_empty,
6106                };
6107                select_next_match_ranges(
6108                    self,
6109                    selection.start..selection.end,
6110                    replace_newest,
6111                    autoscroll,
6112                    cx,
6113                );
6114                self.select_next_state = Some(select_state);
6115            } else {
6116                let query = buffer
6117                    .text_for_range(selection.start..selection.end)
6118                    .collect::<String>();
6119                self.select_next_state = Some(SelectNextState {
6120                    query: AhoCorasick::new(&[query])?,
6121                    wordwise: false,
6122                    done: false,
6123                });
6124                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6125            }
6126        }
6127        Ok(())
6128    }
6129
6130    pub fn select_all_matches(
6131        &mut self,
6132        action: &SelectAllMatches,
6133        cx: &mut ViewContext<Self>,
6134    ) -> Result<()> {
6135        self.push_to_selection_history();
6136        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6137
6138        loop {
6139            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
6140
6141            if self
6142                .select_next_state
6143                .as_ref()
6144                .map(|selection_state| selection_state.done)
6145                .unwrap_or(true)
6146            {
6147                break;
6148            }
6149        }
6150
6151        Ok(())
6152    }
6153
6154    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6155        self.push_to_selection_history();
6156        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6157        self.select_next_match_internal(
6158            &display_map,
6159            action.replace_newest,
6160            Some(Autoscroll::newest()),
6161            cx,
6162        )?;
6163        Ok(())
6164    }
6165
6166    pub fn select_previous(
6167        &mut self,
6168        action: &SelectPrevious,
6169        cx: &mut ViewContext<Self>,
6170    ) -> Result<()> {
6171        self.push_to_selection_history();
6172        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6173        let buffer = &display_map.buffer_snapshot;
6174        let mut selections = self.selections.all::<usize>(cx);
6175        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6176            let query = &select_prev_state.query;
6177            if !select_prev_state.done {
6178                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6179                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6180                let mut next_selected_range = None;
6181                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6182                let bytes_before_last_selection =
6183                    buffer.reversed_bytes_in_range(0..last_selection.start);
6184                let bytes_after_first_selection =
6185                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6186                let query_matches = query
6187                    .stream_find_iter(bytes_before_last_selection)
6188                    .map(|result| (last_selection.start, result))
6189                    .chain(
6190                        query
6191                            .stream_find_iter(bytes_after_first_selection)
6192                            .map(|result| (buffer.len(), result)),
6193                    );
6194                for (end_offset, query_match) in query_matches {
6195                    let query_match = query_match.unwrap(); // can only fail due to I/O
6196                    let offset_range =
6197                        end_offset - query_match.end()..end_offset - query_match.start();
6198                    let display_range = offset_range.start.to_display_point(&display_map)
6199                        ..offset_range.end.to_display_point(&display_map);
6200
6201                    if !select_prev_state.wordwise
6202                        || (!movement::is_inside_word(&display_map, display_range.start)
6203                            && !movement::is_inside_word(&display_map, display_range.end))
6204                    {
6205                        next_selected_range = Some(offset_range);
6206                        break;
6207                    }
6208                }
6209
6210                if let Some(next_selected_range) = next_selected_range {
6211                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6212                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6213                        if action.replace_newest {
6214                            s.delete(s.newest_anchor().id);
6215                        }
6216                        s.insert_range(next_selected_range);
6217                    });
6218                } else {
6219                    select_prev_state.done = true;
6220                }
6221            }
6222
6223            self.select_prev_state = Some(select_prev_state);
6224        } else if selections.len() == 1 {
6225            let selection = selections.last_mut().unwrap();
6226            if selection.start == selection.end {
6227                let word_range = movement::surrounding_word(
6228                    &display_map,
6229                    selection.start.to_display_point(&display_map),
6230                );
6231                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6232                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6233                selection.goal = SelectionGoal::None;
6234                selection.reversed = false;
6235
6236                let query = buffer
6237                    .text_for_range(selection.start..selection.end)
6238                    .collect::<String>();
6239                let query = query.chars().rev().collect::<String>();
6240                let select_state = SelectNextState {
6241                    query: AhoCorasick::new(&[query])?,
6242                    wordwise: true,
6243                    done: false,
6244                };
6245                self.unfold_ranges([selection.start..selection.end], false, true, cx);
6246                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6247                    s.select(selections);
6248                });
6249                self.select_prev_state = Some(select_state);
6250            } else {
6251                let query = buffer
6252                    .text_for_range(selection.start..selection.end)
6253                    .collect::<String>();
6254                let query = query.chars().rev().collect::<String>();
6255                self.select_prev_state = Some(SelectNextState {
6256                    query: AhoCorasick::new(&[query])?,
6257                    wordwise: false,
6258                    done: false,
6259                });
6260                self.select_previous(action, cx)?;
6261            }
6262        }
6263        Ok(())
6264    }
6265
6266    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6267        self.transact(cx, |this, cx| {
6268            let mut selections = this.selections.all::<Point>(cx);
6269            let mut edits = Vec::new();
6270            let mut selection_edit_ranges = Vec::new();
6271            let mut last_toggled_row = None;
6272            let snapshot = this.buffer.read(cx).read(cx);
6273            let empty_str: Arc<str> = "".into();
6274            let mut suffixes_inserted = Vec::new();
6275
6276            fn comment_prefix_range(
6277                snapshot: &MultiBufferSnapshot,
6278                row: u32,
6279                comment_prefix: &str,
6280                comment_prefix_whitespace: &str,
6281            ) -> Range<Point> {
6282                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6283
6284                let mut line_bytes = snapshot
6285                    .bytes_in_range(start..snapshot.max_point())
6286                    .flatten()
6287                    .copied();
6288
6289                // If this line currently begins with the line comment prefix, then record
6290                // the range containing the prefix.
6291                if line_bytes
6292                    .by_ref()
6293                    .take(comment_prefix.len())
6294                    .eq(comment_prefix.bytes())
6295                {
6296                    // Include any whitespace that matches the comment prefix.
6297                    let matching_whitespace_len = line_bytes
6298                        .zip(comment_prefix_whitespace.bytes())
6299                        .take_while(|(a, b)| a == b)
6300                        .count() as u32;
6301                    let end = Point::new(
6302                        start.row,
6303                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6304                    );
6305                    start..end
6306                } else {
6307                    start..start
6308                }
6309            }
6310
6311            fn comment_suffix_range(
6312                snapshot: &MultiBufferSnapshot,
6313                row: u32,
6314                comment_suffix: &str,
6315                comment_suffix_has_leading_space: bool,
6316            ) -> Range<Point> {
6317                let end = Point::new(row, snapshot.line_len(row));
6318                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6319
6320                let mut line_end_bytes = snapshot
6321                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6322                    .flatten()
6323                    .copied();
6324
6325                let leading_space_len = if suffix_start_column > 0
6326                    && line_end_bytes.next() == Some(b' ')
6327                    && comment_suffix_has_leading_space
6328                {
6329                    1
6330                } else {
6331                    0
6332                };
6333
6334                // If this line currently begins with the line comment prefix, then record
6335                // the range containing the prefix.
6336                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6337                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6338                    start..end
6339                } else {
6340                    end..end
6341                }
6342            }
6343
6344            // TODO: Handle selections that cross excerpts
6345            for selection in &mut selections {
6346                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6347                let language = if let Some(language) =
6348                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6349                {
6350                    language
6351                } else {
6352                    continue;
6353                };
6354
6355                selection_edit_ranges.clear();
6356
6357                // If multiple selections contain a given row, avoid processing that
6358                // row more than once.
6359                let mut start_row = selection.start.row;
6360                if last_toggled_row == Some(start_row) {
6361                    start_row += 1;
6362                }
6363                let end_row =
6364                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6365                        selection.end.row - 1
6366                    } else {
6367                        selection.end.row
6368                    };
6369                last_toggled_row = Some(end_row);
6370
6371                if start_row > end_row {
6372                    continue;
6373                }
6374
6375                // If the language has line comments, toggle those.
6376                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6377                    // Split the comment prefix's trailing whitespace into a separate string,
6378                    // as that portion won't be used for detecting if a line is a comment.
6379                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6380                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6381                    let mut all_selection_lines_are_comments = true;
6382
6383                    for row in start_row..=end_row {
6384                        if snapshot.is_line_blank(row) && start_row < end_row {
6385                            continue;
6386                        }
6387
6388                        let prefix_range = comment_prefix_range(
6389                            snapshot.deref(),
6390                            row,
6391                            comment_prefix,
6392                            comment_prefix_whitespace,
6393                        );
6394                        if prefix_range.is_empty() {
6395                            all_selection_lines_are_comments = false;
6396                        }
6397                        selection_edit_ranges.push(prefix_range);
6398                    }
6399
6400                    if all_selection_lines_are_comments {
6401                        edits.extend(
6402                            selection_edit_ranges
6403                                .iter()
6404                                .cloned()
6405                                .map(|range| (range, empty_str.clone())),
6406                        );
6407                    } else {
6408                        let min_column = selection_edit_ranges
6409                            .iter()
6410                            .map(|r| r.start.column)
6411                            .min()
6412                            .unwrap_or(0);
6413                        edits.extend(selection_edit_ranges.iter().map(|range| {
6414                            let position = Point::new(range.start.row, min_column);
6415                            (position..position, full_comment_prefix.clone())
6416                        }));
6417                    }
6418                } else if let Some((full_comment_prefix, comment_suffix)) =
6419                    language.block_comment_delimiters()
6420                {
6421                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6422                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6423                    let prefix_range = comment_prefix_range(
6424                        snapshot.deref(),
6425                        start_row,
6426                        comment_prefix,
6427                        comment_prefix_whitespace,
6428                    );
6429                    let suffix_range = comment_suffix_range(
6430                        snapshot.deref(),
6431                        end_row,
6432                        comment_suffix.trim_start_matches(' '),
6433                        comment_suffix.starts_with(' '),
6434                    );
6435
6436                    if prefix_range.is_empty() || suffix_range.is_empty() {
6437                        edits.push((
6438                            prefix_range.start..prefix_range.start,
6439                            full_comment_prefix.clone(),
6440                        ));
6441                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6442                        suffixes_inserted.push((end_row, comment_suffix.len()));
6443                    } else {
6444                        edits.push((prefix_range, empty_str.clone()));
6445                        edits.push((suffix_range, empty_str.clone()));
6446                    }
6447                } else {
6448                    continue;
6449                }
6450            }
6451
6452            drop(snapshot);
6453            this.buffer.update(cx, |buffer, cx| {
6454                buffer.edit(edits, None, cx);
6455            });
6456
6457            // Adjust selections so that they end before any comment suffixes that
6458            // were inserted.
6459            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6460            let mut selections = this.selections.all::<Point>(cx);
6461            let snapshot = this.buffer.read(cx).read(cx);
6462            for selection in &mut selections {
6463                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6464                    match row.cmp(&selection.end.row) {
6465                        Ordering::Less => {
6466                            suffixes_inserted.next();
6467                            continue;
6468                        }
6469                        Ordering::Greater => break,
6470                        Ordering::Equal => {
6471                            if selection.end.column == snapshot.line_len(row) {
6472                                if selection.is_empty() {
6473                                    selection.start.column -= suffix_len as u32;
6474                                }
6475                                selection.end.column -= suffix_len as u32;
6476                            }
6477                            break;
6478                        }
6479                    }
6480                }
6481            }
6482
6483            drop(snapshot);
6484            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6485
6486            let selections = this.selections.all::<Point>(cx);
6487            let selections_on_single_row = selections.windows(2).all(|selections| {
6488                selections[0].start.row == selections[1].start.row
6489                    && selections[0].end.row == selections[1].end.row
6490                    && selections[0].start.row == selections[0].end.row
6491            });
6492            let selections_selecting = selections
6493                .iter()
6494                .any(|selection| selection.start != selection.end);
6495            let advance_downwards = action.advance_downwards
6496                && selections_on_single_row
6497                && !selections_selecting
6498                && this.mode != EditorMode::SingleLine;
6499
6500            if advance_downwards {
6501                let snapshot = this.buffer.read(cx).snapshot(cx);
6502
6503                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6504                    s.move_cursors_with(|display_snapshot, display_point, _| {
6505                        let mut point = display_point.to_point(display_snapshot);
6506                        point.row += 1;
6507                        point = snapshot.clip_point(point, Bias::Left);
6508                        let display_point = point.to_display_point(display_snapshot);
6509                        (display_point, SelectionGoal::Column(display_point.column()))
6510                    })
6511                });
6512            }
6513        });
6514    }
6515
6516    pub fn select_larger_syntax_node(
6517        &mut self,
6518        _: &SelectLargerSyntaxNode,
6519        cx: &mut ViewContext<Self>,
6520    ) {
6521        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6522        let buffer = self.buffer.read(cx).snapshot(cx);
6523        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6524
6525        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6526        let mut selected_larger_node = false;
6527        let new_selections = old_selections
6528            .iter()
6529            .map(|selection| {
6530                let old_range = selection.start..selection.end;
6531                let mut new_range = old_range.clone();
6532                while let Some(containing_range) =
6533                    buffer.range_for_syntax_ancestor(new_range.clone())
6534                {
6535                    new_range = containing_range;
6536                    if !display_map.intersects_fold(new_range.start)
6537                        && !display_map.intersects_fold(new_range.end)
6538                    {
6539                        break;
6540                    }
6541                }
6542
6543                selected_larger_node |= new_range != old_range;
6544                Selection {
6545                    id: selection.id,
6546                    start: new_range.start,
6547                    end: new_range.end,
6548                    goal: SelectionGoal::None,
6549                    reversed: selection.reversed,
6550                }
6551            })
6552            .collect::<Vec<_>>();
6553
6554        if selected_larger_node {
6555            stack.push(old_selections);
6556            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6557                s.select(new_selections);
6558            });
6559        }
6560        self.select_larger_syntax_node_stack = stack;
6561    }
6562
6563    pub fn select_smaller_syntax_node(
6564        &mut self,
6565        _: &SelectSmallerSyntaxNode,
6566        cx: &mut ViewContext<Self>,
6567    ) {
6568        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6569        if let Some(selections) = stack.pop() {
6570            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6571                s.select(selections.to_vec());
6572            });
6573        }
6574        self.select_larger_syntax_node_stack = stack;
6575    }
6576
6577    pub fn move_to_enclosing_bracket(
6578        &mut self,
6579        _: &MoveToEnclosingBracket,
6580        cx: &mut ViewContext<Self>,
6581    ) {
6582        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6583            s.move_offsets_with(|snapshot, selection| {
6584                let Some(enclosing_bracket_ranges) =
6585                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6586                else {
6587                    return;
6588                };
6589
6590                let mut best_length = usize::MAX;
6591                let mut best_inside = false;
6592                let mut best_in_bracket_range = false;
6593                let mut best_destination = None;
6594                for (open, close) in enclosing_bracket_ranges {
6595                    let close = close.to_inclusive();
6596                    let length = close.end() - open.start;
6597                    let inside = selection.start >= open.end && selection.end <= *close.start();
6598                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6599                        || close.contains(&selection.head());
6600
6601                    // If best is next to a bracket and current isn't, skip
6602                    if !in_bracket_range && best_in_bracket_range {
6603                        continue;
6604                    }
6605
6606                    // Prefer smaller lengths unless best is inside and current isn't
6607                    if length > best_length && (best_inside || !inside) {
6608                        continue;
6609                    }
6610
6611                    best_length = length;
6612                    best_inside = inside;
6613                    best_in_bracket_range = in_bracket_range;
6614                    best_destination = Some(
6615                        if close.contains(&selection.start) && close.contains(&selection.end) {
6616                            if inside {
6617                                open.end
6618                            } else {
6619                                open.start
6620                            }
6621                        } else {
6622                            if inside {
6623                                *close.start()
6624                            } else {
6625                                *close.end()
6626                            }
6627                        },
6628                    );
6629                }
6630
6631                if let Some(destination) = best_destination {
6632                    selection.collapse_to(destination, SelectionGoal::None);
6633                }
6634            })
6635        });
6636    }
6637
6638    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6639        self.end_selection(cx);
6640        self.selection_history.mode = SelectionHistoryMode::Undoing;
6641        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6642            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6643            self.select_next_state = entry.select_next_state;
6644            self.select_prev_state = entry.select_prev_state;
6645            self.add_selections_state = entry.add_selections_state;
6646            self.request_autoscroll(Autoscroll::newest(), cx);
6647        }
6648        self.selection_history.mode = SelectionHistoryMode::Normal;
6649    }
6650
6651    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6652        self.end_selection(cx);
6653        self.selection_history.mode = SelectionHistoryMode::Redoing;
6654        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6655            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6656            self.select_next_state = entry.select_next_state;
6657            self.select_prev_state = entry.select_prev_state;
6658            self.add_selections_state = entry.add_selections_state;
6659            self.request_autoscroll(Autoscroll::newest(), cx);
6660        }
6661        self.selection_history.mode = SelectionHistoryMode::Normal;
6662    }
6663
6664    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6665        self.go_to_diagnostic_impl(Direction::Next, cx)
6666    }
6667
6668    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6669        self.go_to_diagnostic_impl(Direction::Prev, cx)
6670    }
6671
6672    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6673        let buffer = self.buffer.read(cx).snapshot(cx);
6674        let selection = self.selections.newest::<usize>(cx);
6675
6676        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6677        if direction == Direction::Next {
6678            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6679                let (group_id, jump_to) = popover.activation_info();
6680                if self.activate_diagnostics(group_id, cx) {
6681                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6682                        let mut new_selection = s.newest_anchor().clone();
6683                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6684                        s.select_anchors(vec![new_selection.clone()]);
6685                    });
6686                }
6687                return;
6688            }
6689        }
6690
6691        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6692            active_diagnostics
6693                .primary_range
6694                .to_offset(&buffer)
6695                .to_inclusive()
6696        });
6697        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6698            if active_primary_range.contains(&selection.head()) {
6699                *active_primary_range.end()
6700            } else {
6701                selection.head()
6702            }
6703        } else {
6704            selection.head()
6705        };
6706
6707        loop {
6708            let mut diagnostics = if direction == Direction::Prev {
6709                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6710            } else {
6711                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6712            };
6713            let group = diagnostics.find_map(|entry| {
6714                if entry.diagnostic.is_primary
6715                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6716                    && !entry.range.is_empty()
6717                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6718                {
6719                    Some((entry.range, entry.diagnostic.group_id))
6720                } else {
6721                    None
6722                }
6723            });
6724
6725            if let Some((primary_range, group_id)) = group {
6726                if self.activate_diagnostics(group_id, cx) {
6727                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6728                        s.select(vec![Selection {
6729                            id: selection.id,
6730                            start: primary_range.start,
6731                            end: primary_range.start,
6732                            reversed: false,
6733                            goal: SelectionGoal::None,
6734                        }]);
6735                    });
6736                }
6737                break;
6738            } else {
6739                // Cycle around to the start of the buffer, potentially moving back to the start of
6740                // the currently active diagnostic.
6741                active_primary_range.take();
6742                if direction == Direction::Prev {
6743                    if search_start == buffer.len() {
6744                        break;
6745                    } else {
6746                        search_start = buffer.len();
6747                    }
6748                } else if search_start == 0 {
6749                    break;
6750                } else {
6751                    search_start = 0;
6752                }
6753            }
6754        }
6755    }
6756
6757    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6758        let snapshot = self
6759            .display_map
6760            .update(cx, |display_map, cx| display_map.snapshot(cx));
6761        let selection = self.selections.newest::<Point>(cx);
6762
6763        if !self.seek_in_direction(
6764            &snapshot,
6765            selection.head(),
6766            false,
6767            snapshot
6768                .buffer_snapshot
6769                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6770            cx,
6771        ) {
6772            let wrapped_point = Point::zero();
6773            self.seek_in_direction(
6774                &snapshot,
6775                wrapped_point,
6776                true,
6777                snapshot
6778                    .buffer_snapshot
6779                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6780                cx,
6781            );
6782        }
6783    }
6784
6785    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6786        let snapshot = self
6787            .display_map
6788            .update(cx, |display_map, cx| display_map.snapshot(cx));
6789        let selection = self.selections.newest::<Point>(cx);
6790
6791        if !self.seek_in_direction(
6792            &snapshot,
6793            selection.head(),
6794            false,
6795            snapshot
6796                .buffer_snapshot
6797                .git_diff_hunks_in_range_rev(0..selection.head().row),
6798            cx,
6799        ) {
6800            let wrapped_point = snapshot.buffer_snapshot.max_point();
6801            self.seek_in_direction(
6802                &snapshot,
6803                wrapped_point,
6804                true,
6805                snapshot
6806                    .buffer_snapshot
6807                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6808                cx,
6809            );
6810        }
6811    }
6812
6813    fn seek_in_direction(
6814        &mut self,
6815        snapshot: &DisplaySnapshot,
6816        initial_point: Point,
6817        is_wrapped: bool,
6818        hunks: impl Iterator<Item = DiffHunk<u32>>,
6819        cx: &mut ViewContext<Editor>,
6820    ) -> bool {
6821        let display_point = initial_point.to_display_point(snapshot);
6822        let mut hunks = hunks
6823            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6824            .skip_while(|hunk| {
6825                if is_wrapped {
6826                    false
6827                } else {
6828                    hunk.contains_display_row(display_point.row())
6829                }
6830            })
6831            .dedup();
6832
6833        if let Some(hunk) = hunks.next() {
6834            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6835                let row = hunk.start_display_row();
6836                let point = DisplayPoint::new(row, 0);
6837                s.select_display_ranges([point..point]);
6838            });
6839
6840            true
6841        } else {
6842            false
6843        }
6844    }
6845
6846    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6847        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6848    }
6849
6850    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6851        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6852    }
6853
6854    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6855        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6856    }
6857
6858    pub fn go_to_type_definition_split(
6859        &mut self,
6860        _: &GoToTypeDefinitionSplit,
6861        cx: &mut ViewContext<Self>,
6862    ) {
6863        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6864    }
6865
6866    fn go_to_definition_of_kind(
6867        &mut self,
6868        kind: GotoDefinitionKind,
6869        split: bool,
6870        cx: &mut ViewContext<Self>,
6871    ) {
6872        let Some(workspace) = self.workspace(cx) else {
6873            return;
6874        };
6875        let buffer = self.buffer.read(cx);
6876        let head = self.selections.newest::<usize>(cx).head();
6877        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6878            text_anchor
6879        } else {
6880            return;
6881        };
6882
6883        let project = workspace.read(cx).project().clone();
6884        let definitions = project.update(cx, |project, cx| match kind {
6885            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6886            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6887        });
6888
6889        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6890            let definitions = definitions.await?;
6891            editor.update(&mut cx, |editor, cx| {
6892                editor.navigate_to_definitions(
6893                    definitions
6894                        .into_iter()
6895                        .map(GoToDefinitionLink::Text)
6896                        .collect(),
6897                    split,
6898                    cx,
6899                );
6900            })?;
6901            Ok::<(), anyhow::Error>(())
6902        })
6903        .detach_and_log_err(cx);
6904    }
6905
6906    pub fn navigate_to_definitions(
6907        &mut self,
6908        mut definitions: Vec<GoToDefinitionLink>,
6909        split: bool,
6910        cx: &mut ViewContext<Editor>,
6911    ) {
6912        let Some(workspace) = self.workspace(cx) else {
6913            return;
6914        };
6915        let pane = workspace.read(cx).active_pane().clone();
6916        // If there is one definition, just open it directly
6917        if definitions.len() == 1 {
6918            let definition = definitions.pop().unwrap();
6919            let target_task = match definition {
6920                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
6921                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
6922                    self.compute_target_location(lsp_location, server_id, cx)
6923                }
6924            };
6925            cx.spawn(|editor, mut cx| async move {
6926                let target = target_task.await.context("target resolution task")?;
6927                if let Some(target) = target {
6928                    editor.update(&mut cx, |editor, cx| {
6929                        let range = target.range.to_offset(target.buffer.read(cx));
6930                        let range = editor.range_for_match(&range);
6931                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
6932                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6933                                s.select_ranges([range]);
6934                            });
6935                        } else {
6936                            cx.window_context().defer(move |cx| {
6937                                let target_editor: ViewHandle<Self> =
6938                                    workspace.update(cx, |workspace, cx| {
6939                                        if split {
6940                                            workspace.split_project_item(target.buffer.clone(), cx)
6941                                        } else {
6942                                            workspace.open_project_item(target.buffer.clone(), cx)
6943                                        }
6944                                    });
6945                                target_editor.update(cx, |target_editor, cx| {
6946                                    // When selecting a definition in a different buffer, disable the nav history
6947                                    // to avoid creating a history entry at the previous cursor location.
6948                                    pane.update(cx, |pane, _| pane.disable_history());
6949                                    target_editor.change_selections(
6950                                        Some(Autoscroll::fit()),
6951                                        cx,
6952                                        |s| {
6953                                            s.select_ranges([range]);
6954                                        },
6955                                    );
6956                                    pane.update(cx, |pane, _| pane.enable_history());
6957                                });
6958                            });
6959                        }
6960                    })
6961                } else {
6962                    Ok(())
6963                }
6964            })
6965            .detach_and_log_err(cx);
6966        } else if !definitions.is_empty() {
6967            let replica_id = self.replica_id(cx);
6968            cx.spawn(|editor, mut cx| async move {
6969                let (title, location_tasks) = editor
6970                    .update(&mut cx, |editor, cx| {
6971                        let title = definitions
6972                            .iter()
6973                            .find_map(|definition| match definition {
6974                                GoToDefinitionLink::Text(link) => {
6975                                    link.origin.as_ref().map(|origin| {
6976                                        let buffer = origin.buffer.read(cx);
6977                                        format!(
6978                                            "Definitions for {}",
6979                                            buffer
6980                                                .text_for_range(origin.range.clone())
6981                                                .collect::<String>()
6982                                        )
6983                                    })
6984                                }
6985                                GoToDefinitionLink::InlayHint(_, _) => None,
6986                            })
6987                            .unwrap_or("Definitions".to_string());
6988                        let location_tasks = definitions
6989                            .into_iter()
6990                            .map(|definition| match definition {
6991                                GoToDefinitionLink::Text(link) => {
6992                                    Task::Ready(Some(Ok(Some(link.target))))
6993                                }
6994                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
6995                                    editor.compute_target_location(lsp_location, server_id, cx)
6996                                }
6997                            })
6998                            .collect::<Vec<_>>();
6999                        (title, location_tasks)
7000                    })
7001                    .context("location tasks preparation")?;
7002
7003                let locations = futures::future::join_all(location_tasks)
7004                    .await
7005                    .into_iter()
7006                    .filter_map(|location| location.transpose())
7007                    .collect::<Result<_>>()
7008                    .context("location tasks")?;
7009                workspace.update(&mut cx, |workspace, cx| {
7010                    Self::open_locations_in_multibuffer(
7011                        workspace, locations, replica_id, title, split, cx,
7012                    )
7013                });
7014
7015                anyhow::Ok(())
7016            })
7017            .detach_and_log_err(cx);
7018        }
7019    }
7020
7021    fn compute_target_location(
7022        &self,
7023        lsp_location: lsp::Location,
7024        server_id: LanguageServerId,
7025        cx: &mut ViewContext<Editor>,
7026    ) -> Task<anyhow::Result<Option<Location>>> {
7027        let Some(project) = self.project.clone() else {
7028            return Task::Ready(Some(Ok(None)));
7029        };
7030
7031        cx.spawn(move |editor, mut cx| async move {
7032            let location_task = editor.update(&mut cx, |editor, cx| {
7033                project.update(cx, |project, cx| {
7034                    let language_server_name =
7035                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7036                            project
7037                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7038                                .map(|(_, lsp_adapter)| {
7039                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7040                                })
7041                        });
7042                    language_server_name.map(|language_server_name| {
7043                        project.open_local_buffer_via_lsp(
7044                            lsp_location.uri.clone(),
7045                            server_id,
7046                            language_server_name,
7047                            cx,
7048                        )
7049                    })
7050                })
7051            })?;
7052            let location = match location_task {
7053                Some(task) => Some({
7054                    let target_buffer_handle = task.await.context("open local buffer")?;
7055                    let range = {
7056                        target_buffer_handle.update(&mut cx, |target_buffer, _| {
7057                            let target_start = target_buffer.clip_point_utf16(
7058                                point_from_lsp(lsp_location.range.start),
7059                                Bias::Left,
7060                            );
7061                            let target_end = target_buffer.clip_point_utf16(
7062                                point_from_lsp(lsp_location.range.end),
7063                                Bias::Left,
7064                            );
7065                            target_buffer.anchor_after(target_start)
7066                                ..target_buffer.anchor_before(target_end)
7067                        })
7068                    };
7069                    Location {
7070                        buffer: target_buffer_handle,
7071                        range,
7072                    }
7073                }),
7074                None => None,
7075            };
7076            Ok(location)
7077        })
7078    }
7079
7080    pub fn find_all_references(
7081        workspace: &mut Workspace,
7082        _: &FindAllReferences,
7083        cx: &mut ViewContext<Workspace>,
7084    ) -> Option<Task<Result<()>>> {
7085        let active_item = workspace.active_item(cx)?;
7086        let editor_handle = active_item.act_as::<Self>(cx)?;
7087
7088        let editor = editor_handle.read(cx);
7089        let buffer = editor.buffer.read(cx);
7090        let head = editor.selections.newest::<usize>(cx).head();
7091        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7092        let replica_id = editor.replica_id(cx);
7093
7094        let project = workspace.project().clone();
7095        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7096        Some(cx.spawn_labeled(
7097            "Finding All References...",
7098            |workspace, mut cx| async move {
7099                let locations = references.await?;
7100                if locations.is_empty() {
7101                    return Ok(());
7102                }
7103
7104                workspace.update(&mut cx, |workspace, cx| {
7105                    let title = locations
7106                        .first()
7107                        .as_ref()
7108                        .map(|location| {
7109                            let buffer = location.buffer.read(cx);
7110                            format!(
7111                                "References to `{}`",
7112                                buffer
7113                                    .text_for_range(location.range.clone())
7114                                    .collect::<String>()
7115                            )
7116                        })
7117                        .unwrap();
7118                    Self::open_locations_in_multibuffer(
7119                        workspace, locations, replica_id, title, false, cx,
7120                    );
7121                })?;
7122
7123                Ok(())
7124            },
7125        ))
7126    }
7127
7128    /// Opens a multibuffer with the given project locations in it
7129    pub fn open_locations_in_multibuffer(
7130        workspace: &mut Workspace,
7131        mut locations: Vec<Location>,
7132        replica_id: ReplicaId,
7133        title: String,
7134        split: bool,
7135        cx: &mut ViewContext<Workspace>,
7136    ) {
7137        // If there are multiple definitions, open them in a multibuffer
7138        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7139        let mut locations = locations.into_iter().peekable();
7140        let mut ranges_to_highlight = Vec::new();
7141
7142        let excerpt_buffer = cx.add_model(|cx| {
7143            let mut multibuffer = MultiBuffer::new(replica_id);
7144            while let Some(location) = locations.next() {
7145                let buffer = location.buffer.read(cx);
7146                let mut ranges_for_buffer = Vec::new();
7147                let range = location.range.to_offset(buffer);
7148                ranges_for_buffer.push(range.clone());
7149
7150                while let Some(next_location) = locations.peek() {
7151                    if next_location.buffer == location.buffer {
7152                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7153                        locations.next();
7154                    } else {
7155                        break;
7156                    }
7157                }
7158
7159                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7160                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7161                    location.buffer.clone(),
7162                    ranges_for_buffer,
7163                    1,
7164                    cx,
7165                ))
7166            }
7167
7168            multibuffer.with_title(title)
7169        });
7170
7171        let editor = cx.add_view(|cx| {
7172            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7173        });
7174        editor.update(cx, |editor, cx| {
7175            editor.highlight_background::<Self>(
7176                ranges_to_highlight,
7177                |theme| theme.editor.highlighted_line_background,
7178                cx,
7179            );
7180        });
7181        if split {
7182            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7183        } else {
7184            workspace.add_item(Box::new(editor), cx);
7185        }
7186    }
7187
7188    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7189        use language::ToOffset as _;
7190
7191        let project = self.project.clone()?;
7192        let selection = self.selections.newest_anchor().clone();
7193        let (cursor_buffer, cursor_buffer_position) = self
7194            .buffer
7195            .read(cx)
7196            .text_anchor_for_position(selection.head(), cx)?;
7197        let (tail_buffer, _) = self
7198            .buffer
7199            .read(cx)
7200            .text_anchor_for_position(selection.tail(), cx)?;
7201        if tail_buffer != cursor_buffer {
7202            return None;
7203        }
7204
7205        let snapshot = cursor_buffer.read(cx).snapshot();
7206        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7207        let prepare_rename = project.update(cx, |project, cx| {
7208            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7209        });
7210
7211        Some(cx.spawn(|this, mut cx| async move {
7212            let rename_range = if let Some(range) = prepare_rename.await? {
7213                Some(range)
7214            } else {
7215                this.update(&mut cx, |this, cx| {
7216                    let buffer = this.buffer.read(cx).snapshot(cx);
7217                    let mut buffer_highlights = this
7218                        .document_highlights_for_position(selection.head(), &buffer)
7219                        .filter(|highlight| {
7220                            highlight.start.excerpt_id() == selection.head().excerpt_id()
7221                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
7222                        });
7223                    buffer_highlights
7224                        .next()
7225                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7226                })?
7227            };
7228            if let Some(rename_range) = rename_range {
7229                let rename_buffer_range = rename_range.to_offset(&snapshot);
7230                let cursor_offset_in_rename_range =
7231                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7232
7233                this.update(&mut cx, |this, cx| {
7234                    this.take_rename(false, cx);
7235                    let style = this.style(cx);
7236                    let buffer = this.buffer.read(cx).read(cx);
7237                    let cursor_offset = selection.head().to_offset(&buffer);
7238                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7239                    let rename_end = rename_start + rename_buffer_range.len();
7240                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7241                    let mut old_highlight_id = None;
7242                    let old_name: Arc<str> = buffer
7243                        .chunks(rename_start..rename_end, true)
7244                        .map(|chunk| {
7245                            if old_highlight_id.is_none() {
7246                                old_highlight_id = chunk.syntax_highlight_id;
7247                            }
7248                            chunk.text
7249                        })
7250                        .collect::<String>()
7251                        .into();
7252
7253                    drop(buffer);
7254
7255                    // Position the selection in the rename editor so that it matches the current selection.
7256                    this.show_local_selections = false;
7257                    let rename_editor = cx.add_view(|cx| {
7258                        let mut editor = Editor::single_line(None, cx);
7259                        if let Some(old_highlight_id) = old_highlight_id {
7260                            editor.override_text_style =
7261                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
7262                        }
7263                        editor.buffer.update(cx, |buffer, cx| {
7264                            buffer.edit([(0..0, old_name.clone())], None, cx)
7265                        });
7266                        editor.select_all(&SelectAll, cx);
7267                        editor
7268                    });
7269
7270                    let ranges = this
7271                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7272                        .into_iter()
7273                        .flat_map(|(_, ranges)| ranges.into_iter())
7274                        .chain(
7275                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7276                                .into_iter()
7277                                .flat_map(|(_, ranges)| ranges.into_iter()),
7278                        )
7279                        .collect();
7280
7281                    this.highlight_text::<Rename>(
7282                        ranges,
7283                        HighlightStyle {
7284                            fade_out: Some(style.rename_fade),
7285                            ..Default::default()
7286                        },
7287                        cx,
7288                    );
7289                    cx.focus(&rename_editor);
7290                    let block_id = this.insert_blocks(
7291                        [BlockProperties {
7292                            style: BlockStyle::Flex,
7293                            position: range.start.clone(),
7294                            height: 1,
7295                            render: Arc::new({
7296                                let editor = rename_editor.clone();
7297                                move |cx: &mut BlockContext| {
7298                                    ChildView::new(&editor, cx)
7299                                        .contained()
7300                                        .with_padding_left(cx.anchor_x)
7301                                        .into_any()
7302                                }
7303                            }),
7304                            disposition: BlockDisposition::Below,
7305                        }],
7306                        Some(Autoscroll::fit()),
7307                        cx,
7308                    )[0];
7309                    this.pending_rename = Some(RenameState {
7310                        range,
7311                        old_name,
7312                        editor: rename_editor,
7313                        block_id,
7314                    });
7315                })?;
7316            }
7317
7318            Ok(())
7319        }))
7320    }
7321
7322    pub fn confirm_rename(
7323        workspace: &mut Workspace,
7324        _: &ConfirmRename,
7325        cx: &mut ViewContext<Workspace>,
7326    ) -> Option<Task<Result<()>>> {
7327        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
7328
7329        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
7330            let rename = editor.take_rename(false, cx)?;
7331            let buffer = editor.buffer.read(cx);
7332            let (start_buffer, start) =
7333                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
7334            let (end_buffer, end) =
7335                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
7336            if start_buffer == end_buffer {
7337                let new_name = rename.editor.read(cx).text(cx);
7338                Some((start_buffer, start..end, rename.old_name, new_name))
7339            } else {
7340                None
7341            }
7342        })?;
7343
7344        let rename = workspace.project().clone().update(cx, |project, cx| {
7345            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7346        });
7347
7348        let editor = editor.downgrade();
7349        Some(cx.spawn(|workspace, mut cx| async move {
7350            let project_transaction = rename.await?;
7351            Self::open_project_transaction(
7352                &editor,
7353                workspace,
7354                project_transaction,
7355                format!("Rename: {}{}", old_name, new_name),
7356                cx.clone(),
7357            )
7358            .await?;
7359
7360            editor.update(&mut cx, |editor, cx| {
7361                editor.refresh_document_highlights(cx);
7362            })?;
7363            Ok(())
7364        }))
7365    }
7366
7367    fn take_rename(
7368        &mut self,
7369        moving_cursor: bool,
7370        cx: &mut ViewContext<Self>,
7371    ) -> Option<RenameState> {
7372        let rename = self.pending_rename.take()?;
7373        self.remove_blocks(
7374            [rename.block_id].into_iter().collect(),
7375            Some(Autoscroll::fit()),
7376            cx,
7377        );
7378        self.clear_highlights::<Rename>(cx);
7379        self.show_local_selections = true;
7380
7381        if moving_cursor {
7382            let rename_editor = rename.editor.read(cx);
7383            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7384
7385            // Update the selection to match the position of the selection inside
7386            // the rename editor.
7387            let snapshot = self.buffer.read(cx).read(cx);
7388            let rename_range = rename.range.to_offset(&snapshot);
7389            let cursor_in_editor = snapshot
7390                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7391                .min(rename_range.end);
7392            drop(snapshot);
7393
7394            self.change_selections(None, cx, |s| {
7395                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7396            });
7397        } else {
7398            self.refresh_document_highlights(cx);
7399        }
7400
7401        Some(rename)
7402    }
7403
7404    #[cfg(any(test, feature = "test-support"))]
7405    pub fn pending_rename(&self) -> Option<&RenameState> {
7406        self.pending_rename.as_ref()
7407    }
7408
7409    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7410        let project = match &self.project {
7411            Some(project) => project.clone(),
7412            None => return None,
7413        };
7414
7415        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7416    }
7417
7418    fn perform_format(
7419        &mut self,
7420        project: ModelHandle<Project>,
7421        trigger: FormatTrigger,
7422        cx: &mut ViewContext<Self>,
7423    ) -> Task<Result<()>> {
7424        let buffer = self.buffer().clone();
7425        let buffers = buffer.read(cx).all_buffers();
7426
7427        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
7428        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7429
7430        cx.spawn(|_, mut cx| async move {
7431            let transaction = futures::select_biased! {
7432                _ = timeout => {
7433                    log::warn!("timed out waiting for formatting");
7434                    None
7435                }
7436                transaction = format.log_err().fuse() => transaction,
7437            };
7438
7439            buffer.update(&mut cx, |buffer, cx| {
7440                if let Some(transaction) = transaction {
7441                    if !buffer.is_singleton() {
7442                        buffer.push_transaction(&transaction.0, cx);
7443                    }
7444                }
7445
7446                cx.notify();
7447            });
7448
7449            Ok(())
7450        })
7451    }
7452
7453    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7454        if let Some(project) = self.project.clone() {
7455            self.buffer.update(cx, |multi_buffer, cx| {
7456                project.update(cx, |project, cx| {
7457                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7458                });
7459            })
7460        }
7461    }
7462
7463    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7464        cx.show_character_palette();
7465    }
7466
7467    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7468        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7469            let buffer = self.buffer.read(cx).snapshot(cx);
7470            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7471            let is_valid = buffer
7472                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7473                .any(|entry| {
7474                    entry.diagnostic.is_primary
7475                        && !entry.range.is_empty()
7476                        && entry.range.start == primary_range_start
7477                        && entry.diagnostic.message == active_diagnostics.primary_message
7478                });
7479
7480            if is_valid != active_diagnostics.is_valid {
7481                active_diagnostics.is_valid = is_valid;
7482                let mut new_styles = HashMap::default();
7483                for (block_id, diagnostic) in &active_diagnostics.blocks {
7484                    new_styles.insert(
7485                        *block_id,
7486                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7487                    );
7488                }
7489                self.display_map
7490                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7491            }
7492        }
7493    }
7494
7495    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7496        self.dismiss_diagnostics(cx);
7497        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7498            let buffer = self.buffer.read(cx).snapshot(cx);
7499
7500            let mut primary_range = None;
7501            let mut primary_message = None;
7502            let mut group_end = Point::zero();
7503            let diagnostic_group = buffer
7504                .diagnostic_group::<Point>(group_id)
7505                .map(|entry| {
7506                    if entry.range.end > group_end {
7507                        group_end = entry.range.end;
7508                    }
7509                    if entry.diagnostic.is_primary {
7510                        primary_range = Some(entry.range.clone());
7511                        primary_message = Some(entry.diagnostic.message.clone());
7512                    }
7513                    entry
7514                })
7515                .collect::<Vec<_>>();
7516            let primary_range = primary_range?;
7517            let primary_message = primary_message?;
7518            let primary_range =
7519                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7520
7521            let blocks = display_map
7522                .insert_blocks(
7523                    diagnostic_group.iter().map(|entry| {
7524                        let diagnostic = entry.diagnostic.clone();
7525                        let message_height = diagnostic.message.lines().count() as u8;
7526                        BlockProperties {
7527                            style: BlockStyle::Fixed,
7528                            position: buffer.anchor_after(entry.range.start),
7529                            height: message_height,
7530                            render: diagnostic_block_renderer(diagnostic, true),
7531                            disposition: BlockDisposition::Below,
7532                        }
7533                    }),
7534                    cx,
7535                )
7536                .into_iter()
7537                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7538                .collect();
7539
7540            Some(ActiveDiagnosticGroup {
7541                primary_range,
7542                primary_message,
7543                blocks,
7544                is_valid: true,
7545            })
7546        });
7547        self.active_diagnostics.is_some()
7548    }
7549
7550    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7551        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7552            self.display_map.update(cx, |display_map, cx| {
7553                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7554            });
7555            cx.notify();
7556        }
7557    }
7558
7559    pub fn set_selections_from_remote(
7560        &mut self,
7561        selections: Vec<Selection<Anchor>>,
7562        pending_selection: Option<Selection<Anchor>>,
7563        cx: &mut ViewContext<Self>,
7564    ) {
7565        let old_cursor_position = self.selections.newest_anchor().head();
7566        self.selections.change_with(cx, |s| {
7567            s.select_anchors(selections);
7568            if let Some(pending_selection) = pending_selection {
7569                s.set_pending(pending_selection, SelectMode::Character);
7570            } else {
7571                s.clear_pending();
7572            }
7573        });
7574        self.selections_did_change(false, &old_cursor_position, cx);
7575    }
7576
7577    fn push_to_selection_history(&mut self) {
7578        self.selection_history.push(SelectionHistoryEntry {
7579            selections: self.selections.disjoint_anchors(),
7580            select_next_state: self.select_next_state.clone(),
7581            select_prev_state: self.select_prev_state.clone(),
7582            add_selections_state: self.add_selections_state.clone(),
7583        });
7584    }
7585
7586    pub fn transact(
7587        &mut self,
7588        cx: &mut ViewContext<Self>,
7589        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7590    ) -> Option<TransactionId> {
7591        self.start_transaction_at(Instant::now(), cx);
7592        update(self, cx);
7593        self.end_transaction_at(Instant::now(), cx)
7594    }
7595
7596    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7597        self.end_selection(cx);
7598        if let Some(tx_id) = self
7599            .buffer
7600            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7601        {
7602            self.selection_history
7603                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7604        }
7605    }
7606
7607    fn end_transaction_at(
7608        &mut self,
7609        now: Instant,
7610        cx: &mut ViewContext<Self>,
7611    ) -> Option<TransactionId> {
7612        if let Some(tx_id) = self
7613            .buffer
7614            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7615        {
7616            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7617                *end_selections = Some(self.selections.disjoint_anchors());
7618            } else {
7619                error!("unexpectedly ended a transaction that wasn't started by this editor");
7620            }
7621
7622            cx.emit(Event::Edited);
7623            Some(tx_id)
7624        } else {
7625            None
7626        }
7627    }
7628
7629    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7630        let mut fold_ranges = Vec::new();
7631
7632        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7633
7634        let selections = self.selections.all_adjusted(cx);
7635        for selection in selections {
7636            let range = selection.range().sorted();
7637            let buffer_start_row = range.start.row;
7638
7639            for row in (0..=range.end.row).rev() {
7640                let fold_range = display_map.foldable_range(row);
7641
7642                if let Some(fold_range) = fold_range {
7643                    if fold_range.end.row >= buffer_start_row {
7644                        fold_ranges.push(fold_range);
7645                        if row <= range.start.row {
7646                            break;
7647                        }
7648                    }
7649                }
7650            }
7651        }
7652
7653        self.fold_ranges(fold_ranges, true, cx);
7654    }
7655
7656    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7657        let buffer_row = fold_at.buffer_row;
7658        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7659
7660        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7661            let autoscroll = self
7662                .selections
7663                .all::<Point>(cx)
7664                .iter()
7665                .any(|selection| fold_range.overlaps(&selection.range()));
7666
7667            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7668        }
7669    }
7670
7671    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7672        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7673        let buffer = &display_map.buffer_snapshot;
7674        let selections = self.selections.all::<Point>(cx);
7675        let ranges = selections
7676            .iter()
7677            .map(|s| {
7678                let range = s.display_range(&display_map).sorted();
7679                let mut start = range.start.to_point(&display_map);
7680                let mut end = range.end.to_point(&display_map);
7681                start.column = 0;
7682                end.column = buffer.line_len(end.row);
7683                start..end
7684            })
7685            .collect::<Vec<_>>();
7686
7687        self.unfold_ranges(ranges, true, true, cx);
7688    }
7689
7690    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7691        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7692
7693        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7694            ..Point::new(
7695                unfold_at.buffer_row,
7696                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7697            );
7698
7699        let autoscroll = self
7700            .selections
7701            .all::<Point>(cx)
7702            .iter()
7703            .any(|selection| selection.range().overlaps(&intersection_range));
7704
7705        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7706    }
7707
7708    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7709        let selections = self.selections.all::<Point>(cx);
7710        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7711        let line_mode = self.selections.line_mode;
7712        let ranges = selections.into_iter().map(|s| {
7713            if line_mode {
7714                let start = Point::new(s.start.row, 0);
7715                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
7716                start..end
7717            } else {
7718                s.start..s.end
7719            }
7720        });
7721        self.fold_ranges(ranges, true, cx);
7722    }
7723
7724    pub fn fold_ranges<T: ToOffset + Clone>(
7725        &mut self,
7726        ranges: impl IntoIterator<Item = Range<T>>,
7727        auto_scroll: bool,
7728        cx: &mut ViewContext<Self>,
7729    ) {
7730        let mut ranges = ranges.into_iter().peekable();
7731        if ranges.peek().is_some() {
7732            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7733
7734            if auto_scroll {
7735                self.request_autoscroll(Autoscroll::fit(), cx);
7736            }
7737
7738            cx.notify();
7739        }
7740    }
7741
7742    pub fn unfold_ranges<T: ToOffset + Clone>(
7743        &mut self,
7744        ranges: impl IntoIterator<Item = Range<T>>,
7745        inclusive: bool,
7746        auto_scroll: bool,
7747        cx: &mut ViewContext<Self>,
7748    ) {
7749        let mut ranges = ranges.into_iter().peekable();
7750        if ranges.peek().is_some() {
7751            self.display_map
7752                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7753            if auto_scroll {
7754                self.request_autoscroll(Autoscroll::fit(), cx);
7755            }
7756
7757            cx.notify();
7758        }
7759    }
7760
7761    pub fn gutter_hover(
7762        &mut self,
7763        GutterHover { hovered }: &GutterHover,
7764        cx: &mut ViewContext<Self>,
7765    ) {
7766        self.gutter_hovered = *hovered;
7767        cx.notify();
7768    }
7769
7770    pub fn insert_blocks(
7771        &mut self,
7772        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7773        autoscroll: Option<Autoscroll>,
7774        cx: &mut ViewContext<Self>,
7775    ) -> Vec<BlockId> {
7776        let blocks = self
7777            .display_map
7778            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7779        if let Some(autoscroll) = autoscroll {
7780            self.request_autoscroll(autoscroll, cx);
7781        }
7782        blocks
7783    }
7784
7785    pub fn replace_blocks(
7786        &mut self,
7787        blocks: HashMap<BlockId, RenderBlock>,
7788        autoscroll: Option<Autoscroll>,
7789        cx: &mut ViewContext<Self>,
7790    ) {
7791        self.display_map
7792            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7793        if let Some(autoscroll) = autoscroll {
7794            self.request_autoscroll(autoscroll, cx);
7795        }
7796    }
7797
7798    pub fn remove_blocks(
7799        &mut self,
7800        block_ids: HashSet<BlockId>,
7801        autoscroll: Option<Autoscroll>,
7802        cx: &mut ViewContext<Self>,
7803    ) {
7804        self.display_map.update(cx, |display_map, cx| {
7805            display_map.remove_blocks(block_ids, cx)
7806        });
7807        if let Some(autoscroll) = autoscroll {
7808            self.request_autoscroll(autoscroll, cx);
7809        }
7810    }
7811
7812    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7813        self.display_map
7814            .update(cx, |map, cx| map.snapshot(cx))
7815            .longest_row()
7816    }
7817
7818    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7819        self.display_map
7820            .update(cx, |map, cx| map.snapshot(cx))
7821            .max_point()
7822    }
7823
7824    pub fn text(&self, cx: &AppContext) -> String {
7825        self.buffer.read(cx).read(cx).text()
7826    }
7827
7828    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7829        self.transact(cx, |this, cx| {
7830            this.buffer
7831                .read(cx)
7832                .as_singleton()
7833                .expect("you can only call set_text on editors for singleton buffers")
7834                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7835        });
7836    }
7837
7838    pub fn display_text(&self, cx: &mut AppContext) -> String {
7839        self.display_map
7840            .update(cx, |map, cx| map.snapshot(cx))
7841            .text()
7842    }
7843
7844    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7845        let mut wrap_guides = smallvec::smallvec![];
7846
7847        if self.show_wrap_guides == Some(false) {
7848            return wrap_guides;
7849        }
7850
7851        let settings = self.buffer.read(cx).settings_at(0, cx);
7852        if settings.show_wrap_guides {
7853            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7854                wrap_guides.push((soft_wrap as usize, true));
7855            }
7856            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7857        }
7858
7859        wrap_guides
7860    }
7861
7862    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7863        let settings = self.buffer.read(cx).settings_at(0, cx);
7864        let mode = self
7865            .soft_wrap_mode_override
7866            .unwrap_or_else(|| settings.soft_wrap);
7867        match mode {
7868            language_settings::SoftWrap::None => SoftWrap::None,
7869            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7870            language_settings::SoftWrap::PreferredLineLength => {
7871                SoftWrap::Column(settings.preferred_line_length)
7872            }
7873        }
7874    }
7875
7876    pub fn set_soft_wrap_mode(
7877        &mut self,
7878        mode: language_settings::SoftWrap,
7879        cx: &mut ViewContext<Self>,
7880    ) {
7881        self.soft_wrap_mode_override = Some(mode);
7882        cx.notify();
7883    }
7884
7885    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7886        self.display_map
7887            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7888    }
7889
7890    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7891        if self.soft_wrap_mode_override.is_some() {
7892            self.soft_wrap_mode_override.take();
7893        } else {
7894            let soft_wrap = match self.soft_wrap_mode(cx) {
7895                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7896                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7897            };
7898            self.soft_wrap_mode_override = Some(soft_wrap);
7899        }
7900        cx.notify();
7901    }
7902
7903    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7904        self.show_gutter = show_gutter;
7905        cx.notify();
7906    }
7907
7908    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7909        self.show_wrap_guides = Some(show_gutter);
7910        cx.notify();
7911    }
7912
7913    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7914        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7915            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7916                cx.reveal_path(&file.abs_path(cx));
7917            }
7918        }
7919    }
7920
7921    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7922        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7923            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7924                if let Some(path) = file.abs_path(cx).to_str() {
7925                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7926                }
7927            }
7928        }
7929    }
7930
7931    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7932        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7933            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7934                if let Some(path) = file.path().to_str() {
7935                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7936                }
7937            }
7938        }
7939    }
7940
7941    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7942        self.highlighted_rows = rows;
7943    }
7944
7945    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7946        self.highlighted_rows.clone()
7947    }
7948
7949    pub fn highlight_background<T: 'static>(
7950        &mut self,
7951        ranges: Vec<Range<Anchor>>,
7952        color_fetcher: fn(&Theme) -> Color,
7953        cx: &mut ViewContext<Self>,
7954    ) {
7955        self.background_highlights
7956            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7957        cx.notify();
7958    }
7959
7960    pub fn highlight_inlay_background<T: 'static>(
7961        &mut self,
7962        ranges: Vec<InlayHighlight>,
7963        color_fetcher: fn(&Theme) -> Color,
7964        cx: &mut ViewContext<Self>,
7965    ) {
7966        // TODO: no actual highlights happen for inlays currently, find a way to do that
7967        self.inlay_background_highlights
7968            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
7969        cx.notify();
7970    }
7971
7972    pub fn clear_background_highlights<T: 'static>(
7973        &mut self,
7974        cx: &mut ViewContext<Self>,
7975    ) -> Option<BackgroundHighlight> {
7976        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
7977        let inlay_highlights = self
7978            .inlay_background_highlights
7979            .remove(&Some(TypeId::of::<T>()));
7980        if text_highlights.is_some() || inlay_highlights.is_some() {
7981            cx.notify();
7982        }
7983        text_highlights
7984    }
7985
7986    #[cfg(feature = "test-support")]
7987    pub fn all_text_background_highlights(
7988        &mut self,
7989        cx: &mut ViewContext<Self>,
7990    ) -> Vec<(Range<DisplayPoint>, Color)> {
7991        let snapshot = self.snapshot(cx);
7992        let buffer = &snapshot.buffer_snapshot;
7993        let start = buffer.anchor_before(0);
7994        let end = buffer.anchor_after(buffer.len());
7995        let theme = theme::current(cx);
7996        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7997    }
7998
7999    fn document_highlights_for_position<'a>(
8000        &'a self,
8001        position: Anchor,
8002        buffer: &'a MultiBufferSnapshot,
8003    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8004        let read_highlights = self
8005            .background_highlights
8006            .get(&TypeId::of::<DocumentHighlightRead>())
8007            .map(|h| &h.1);
8008        let write_highlights = self
8009            .background_highlights
8010            .get(&TypeId::of::<DocumentHighlightWrite>())
8011            .map(|h| &h.1);
8012        let left_position = position.bias_left(buffer);
8013        let right_position = position.bias_right(buffer);
8014        read_highlights
8015            .into_iter()
8016            .chain(write_highlights)
8017            .flat_map(move |ranges| {
8018                let start_ix = match ranges.binary_search_by(|probe| {
8019                    let cmp = probe.end.cmp(&left_position, buffer);
8020                    if cmp.is_ge() {
8021                        Ordering::Greater
8022                    } else {
8023                        Ordering::Less
8024                    }
8025                }) {
8026                    Ok(i) | Err(i) => i,
8027                };
8028
8029                let right_position = right_position.clone();
8030                ranges[start_ix..]
8031                    .iter()
8032                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8033            })
8034    }
8035
8036    pub fn background_highlights_in_range(
8037        &self,
8038        search_range: Range<Anchor>,
8039        display_snapshot: &DisplaySnapshot,
8040        theme: &Theme,
8041    ) -> Vec<(Range<DisplayPoint>, Color)> {
8042        let mut results = Vec::new();
8043        for (color_fetcher, ranges) in self.background_highlights.values() {
8044            let color = color_fetcher(theme);
8045            let start_ix = match ranges.binary_search_by(|probe| {
8046                let cmp = probe
8047                    .end
8048                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8049                if cmp.is_gt() {
8050                    Ordering::Greater
8051                } else {
8052                    Ordering::Less
8053                }
8054            }) {
8055                Ok(i) | Err(i) => i,
8056            };
8057            for range in &ranges[start_ix..] {
8058                if range
8059                    .start
8060                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8061                    .is_ge()
8062                {
8063                    break;
8064                }
8065
8066                let start = range.start.to_display_point(&display_snapshot);
8067                let end = range.end.to_display_point(&display_snapshot);
8068                results.push((start..end, color))
8069            }
8070        }
8071        results
8072    }
8073
8074    pub fn background_highlight_row_ranges<T: 'static>(
8075        &self,
8076        search_range: Range<Anchor>,
8077        display_snapshot: &DisplaySnapshot,
8078        count: usize,
8079    ) -> Vec<RangeInclusive<DisplayPoint>> {
8080        let mut results = Vec::new();
8081        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8082            return vec![];
8083        };
8084
8085        let start_ix = match ranges.binary_search_by(|probe| {
8086            let cmp = probe
8087                .end
8088                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8089            if cmp.is_gt() {
8090                Ordering::Greater
8091            } else {
8092                Ordering::Less
8093            }
8094        }) {
8095            Ok(i) | Err(i) => i,
8096        };
8097        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8098            if let (Some(start_display), Some(end_display)) = (start, end) {
8099                results.push(
8100                    start_display.to_display_point(display_snapshot)
8101                        ..=end_display.to_display_point(display_snapshot),
8102                );
8103            }
8104        };
8105        let mut start_row: Option<Point> = None;
8106        let mut end_row: Option<Point> = None;
8107        if ranges.len() > count {
8108            return Vec::new();
8109        }
8110        for range in &ranges[start_ix..] {
8111            if range
8112                .start
8113                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8114                .is_ge()
8115            {
8116                break;
8117            }
8118            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8119            if let Some(current_row) = &end_row {
8120                if end.row == current_row.row {
8121                    continue;
8122                }
8123            }
8124            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8125            if start_row.is_none() {
8126                assert_eq!(end_row, None);
8127                start_row = Some(start);
8128                end_row = Some(end);
8129                continue;
8130            }
8131            if let Some(current_end) = end_row.as_mut() {
8132                if start.row > current_end.row + 1 {
8133                    push_region(start_row, end_row);
8134                    start_row = Some(start);
8135                    end_row = Some(end);
8136                } else {
8137                    // Merge two hunks.
8138                    *current_end = end;
8139                }
8140            } else {
8141                unreachable!();
8142            }
8143        }
8144        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8145        push_region(start_row, end_row);
8146        results
8147    }
8148
8149    pub fn highlight_text<T: 'static>(
8150        &mut self,
8151        ranges: Vec<Range<Anchor>>,
8152        style: HighlightStyle,
8153        cx: &mut ViewContext<Self>,
8154    ) {
8155        self.display_map.update(cx, |map, _| {
8156            map.highlight_text(TypeId::of::<T>(), ranges, style)
8157        });
8158        cx.notify();
8159    }
8160
8161    pub fn highlight_inlays<T: 'static>(
8162        &mut self,
8163        highlights: Vec<InlayHighlight>,
8164        style: HighlightStyle,
8165        cx: &mut ViewContext<Self>,
8166    ) {
8167        self.display_map.update(cx, |map, _| {
8168            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8169        });
8170        cx.notify();
8171    }
8172
8173    pub fn text_highlights<'a, T: 'static>(
8174        &'a self,
8175        cx: &'a AppContext,
8176    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8177        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8178    }
8179
8180    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8181        let cleared = self
8182            .display_map
8183            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8184        if cleared {
8185            cx.notify();
8186        }
8187    }
8188
8189    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
8190        self.blink_manager.read(cx).visible() && self.focused
8191    }
8192
8193    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
8194        cx.notify();
8195    }
8196
8197    fn on_buffer_event(
8198        &mut self,
8199        multibuffer: ModelHandle<MultiBuffer>,
8200        event: &multi_buffer::Event,
8201        cx: &mut ViewContext<Self>,
8202    ) {
8203        match event {
8204            multi_buffer::Event::Edited {
8205                sigleton_buffer_edited,
8206            } => {
8207                self.refresh_active_diagnostics(cx);
8208                self.refresh_code_actions(cx);
8209                if self.has_active_copilot_suggestion(cx) {
8210                    self.update_visible_copilot_suggestion(cx);
8211                }
8212                cx.emit(Event::BufferEdited);
8213
8214                if *sigleton_buffer_edited {
8215                    if let Some(project) = &self.project {
8216                        let project = project.read(cx);
8217                        let languages_affected = multibuffer
8218                            .read(cx)
8219                            .all_buffers()
8220                            .into_iter()
8221                            .filter_map(|buffer| {
8222                                let buffer = buffer.read(cx);
8223                                let language = buffer.language()?;
8224                                if project.is_local()
8225                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8226                                {
8227                                    None
8228                                } else {
8229                                    Some(language)
8230                                }
8231                            })
8232                            .cloned()
8233                            .collect::<HashSet<_>>();
8234                        if !languages_affected.is_empty() {
8235                            self.refresh_inlay_hints(
8236                                InlayHintRefreshReason::BufferEdited(languages_affected),
8237                                cx,
8238                            );
8239                        }
8240                    }
8241                }
8242            }
8243            multi_buffer::Event::ExcerptsAdded {
8244                buffer,
8245                predecessor,
8246                excerpts,
8247            } => {
8248                cx.emit(Event::ExcerptsAdded {
8249                    buffer: buffer.clone(),
8250                    predecessor: *predecessor,
8251                    excerpts: excerpts.clone(),
8252                });
8253                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8254            }
8255            multi_buffer::Event::ExcerptsRemoved { ids } => {
8256                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8257                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
8258            }
8259            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
8260            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
8261            multi_buffer::Event::Saved => cx.emit(Event::Saved),
8262            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
8263            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
8264            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
8265            multi_buffer::Event::Closed => cx.emit(Event::Closed),
8266            multi_buffer::Event::DiagnosticsUpdated => {
8267                self.refresh_active_diagnostics(cx);
8268            }
8269            _ => {}
8270        };
8271    }
8272
8273    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
8274        cx.notify();
8275    }
8276
8277    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8278        self.refresh_copilot_suggestions(true, cx);
8279        self.refresh_inlay_hints(
8280            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8281                self.selections.newest_anchor().head(),
8282                &self.buffer.read(cx).snapshot(cx),
8283                cx,
8284            )),
8285            cx,
8286        );
8287    }
8288
8289    pub fn set_searchable(&mut self, searchable: bool) {
8290        self.searchable = searchable;
8291    }
8292
8293    pub fn searchable(&self) -> bool {
8294        self.searchable
8295    }
8296
8297    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
8298        let active_item = workspace.active_item(cx);
8299        let editor_handle = if let Some(editor) = active_item
8300            .as_ref()
8301            .and_then(|item| item.act_as::<Self>(cx))
8302        {
8303            editor
8304        } else {
8305            cx.propagate_action();
8306            return;
8307        };
8308
8309        let editor = editor_handle.read(cx);
8310        let buffer = editor.buffer.read(cx);
8311        if buffer.is_singleton() {
8312            cx.propagate_action();
8313            return;
8314        }
8315
8316        let mut new_selections_by_buffer = HashMap::default();
8317        for selection in editor.selections.all::<usize>(cx) {
8318            for (buffer, mut range, _) in
8319                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8320            {
8321                if selection.reversed {
8322                    mem::swap(&mut range.start, &mut range.end);
8323                }
8324                new_selections_by_buffer
8325                    .entry(buffer)
8326                    .or_insert(Vec::new())
8327                    .push(range)
8328            }
8329        }
8330
8331        editor_handle.update(cx, |editor, cx| {
8332            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
8333        });
8334        let pane = workspace.active_pane().clone();
8335        pane.update(cx, |pane, _| pane.disable_history());
8336
8337        // We defer the pane interaction because we ourselves are a workspace item
8338        // and activating a new item causes the pane to call a method on us reentrantly,
8339        // which panics if we're on the stack.
8340        cx.defer(move |workspace, cx| {
8341            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8342                let editor = workspace.open_project_item::<Self>(buffer, cx);
8343                editor.update(cx, |editor, cx| {
8344                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8345                        s.select_ranges(ranges);
8346                    });
8347                });
8348            }
8349
8350            pane.update(cx, |pane, _| pane.enable_history());
8351        });
8352    }
8353
8354    fn jump(
8355        workspace: &mut Workspace,
8356        path: ProjectPath,
8357        position: Point,
8358        anchor: language::Anchor,
8359        cx: &mut ViewContext<Workspace>,
8360    ) {
8361        let editor = workspace.open_path(path, None, true, cx);
8362        cx.spawn(|_, mut cx| async move {
8363            let editor = editor
8364                .await?
8365                .downcast::<Editor>()
8366                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8367                .downgrade();
8368            editor.update(&mut cx, |editor, cx| {
8369                let buffer = editor
8370                    .buffer()
8371                    .read(cx)
8372                    .as_singleton()
8373                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8374                let buffer = buffer.read(cx);
8375                let cursor = if buffer.can_resolve(&anchor) {
8376                    language::ToPoint::to_point(&anchor, buffer)
8377                } else {
8378                    buffer.clip_point(position, Bias::Left)
8379                };
8380
8381                let nav_history = editor.nav_history.take();
8382                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8383                    s.select_ranges([cursor..cursor]);
8384                });
8385                editor.nav_history = nav_history;
8386
8387                anyhow::Ok(())
8388            })??;
8389
8390            anyhow::Ok(())
8391        })
8392        .detach_and_log_err(cx);
8393    }
8394
8395    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8396        let snapshot = self.buffer.read(cx).read(cx);
8397        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8398        Some(
8399            ranges
8400                .iter()
8401                .map(move |range| {
8402                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8403                })
8404                .collect(),
8405        )
8406    }
8407
8408    fn selection_replacement_ranges(
8409        &self,
8410        range: Range<OffsetUtf16>,
8411        cx: &AppContext,
8412    ) -> Vec<Range<OffsetUtf16>> {
8413        let selections = self.selections.all::<OffsetUtf16>(cx);
8414        let newest_selection = selections
8415            .iter()
8416            .max_by_key(|selection| selection.id)
8417            .unwrap();
8418        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8419        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8420        let snapshot = self.buffer.read(cx).read(cx);
8421        selections
8422            .into_iter()
8423            .map(|mut selection| {
8424                selection.start.0 =
8425                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8426                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8427                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8428                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8429            })
8430            .collect()
8431    }
8432
8433    fn report_copilot_event(
8434        &self,
8435        suggestion_id: Option<String>,
8436        suggestion_accepted: bool,
8437        cx: &AppContext,
8438    ) {
8439        let Some(project) = &self.project else { return };
8440
8441        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8442        let file_extension = self
8443            .buffer
8444            .read(cx)
8445            .as_singleton()
8446            .and_then(|b| b.read(cx).file())
8447            .and_then(|file| Path::new(file.file_name(cx)).extension())
8448            .and_then(|e| e.to_str())
8449            .map(|a| a.to_string());
8450
8451        let telemetry = project.read(cx).client().telemetry().clone();
8452        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8453
8454        let event = ClickhouseEvent::Copilot {
8455            suggestion_id,
8456            suggestion_accepted,
8457            file_extension,
8458        };
8459        telemetry.report_clickhouse_event(event, telemetry_settings);
8460    }
8461
8462    fn report_editor_event(
8463        &self,
8464        operation: &'static str,
8465        file_extension: Option<String>,
8466        cx: &AppContext,
8467    ) {
8468        let Some(project) = &self.project else { return };
8469
8470        // If None, we are in a file without an extension
8471        let file = self
8472            .buffer
8473            .read(cx)
8474            .as_singleton()
8475            .and_then(|b| b.read(cx).file());
8476        let file_extension = file_extension.or(file
8477            .as_ref()
8478            .and_then(|file| Path::new(file.file_name(cx)).extension())
8479            .and_then(|e| e.to_str())
8480            .map(|a| a.to_string()));
8481
8482        let vim_mode = cx
8483            .global::<SettingsStore>()
8484            .raw_user_settings()
8485            .get("vim_mode")
8486            == Some(&serde_json::Value::Bool(true));
8487        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8488        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8489        let copilot_enabled_for_language = self
8490            .buffer
8491            .read(cx)
8492            .settings_at(0, cx)
8493            .show_copilot_suggestions;
8494
8495        let telemetry = project.read(cx).client().telemetry().clone();
8496        let event = ClickhouseEvent::Editor {
8497            file_extension,
8498            vim_mode,
8499            operation,
8500            copilot_enabled,
8501            copilot_enabled_for_language,
8502        };
8503        telemetry.report_clickhouse_event(event, telemetry_settings)
8504    }
8505
8506    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8507    /// with each line being an array of {text, highlight} objects.
8508    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8509        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8510            return;
8511        };
8512
8513        #[derive(Serialize)]
8514        struct Chunk<'a> {
8515            text: String,
8516            highlight: Option<&'a str>,
8517        }
8518
8519        let snapshot = buffer.read(cx).snapshot();
8520        let range = self
8521            .selected_text_range(cx)
8522            .and_then(|selected_range| {
8523                if selected_range.is_empty() {
8524                    None
8525                } else {
8526                    Some(selected_range)
8527                }
8528            })
8529            .unwrap_or_else(|| 0..snapshot.len());
8530
8531        let chunks = snapshot.chunks(range, true);
8532        let mut lines = Vec::new();
8533        let mut line: VecDeque<Chunk> = VecDeque::new();
8534
8535        let theme = &theme::current(cx).editor.syntax;
8536
8537        for chunk in chunks {
8538            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8539            let mut chunk_lines = chunk.text.split("\n").peekable();
8540            while let Some(text) = chunk_lines.next() {
8541                let mut merged_with_last_token = false;
8542                if let Some(last_token) = line.back_mut() {
8543                    if last_token.highlight == highlight {
8544                        last_token.text.push_str(text);
8545                        merged_with_last_token = true;
8546                    }
8547                }
8548
8549                if !merged_with_last_token {
8550                    line.push_back(Chunk {
8551                        text: text.into(),
8552                        highlight,
8553                    });
8554                }
8555
8556                if chunk_lines.peek().is_some() {
8557                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8558                        line.pop_front();
8559                    }
8560                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8561                        line.pop_back();
8562                    }
8563
8564                    lines.push(mem::take(&mut line));
8565                }
8566            }
8567        }
8568
8569        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8570            return;
8571        };
8572        cx.write_to_clipboard(ClipboardItem::new(lines));
8573    }
8574
8575    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8576        &self.inlay_hint_cache
8577    }
8578
8579    pub fn replay_insert_event(
8580        &mut self,
8581        text: &str,
8582        relative_utf16_range: Option<Range<isize>>,
8583        cx: &mut ViewContext<Self>,
8584    ) {
8585        if !self.input_enabled {
8586            cx.emit(Event::InputIgnored { text: text.into() });
8587            return;
8588        }
8589        if let Some(relative_utf16_range) = relative_utf16_range {
8590            let selections = self.selections.all::<OffsetUtf16>(cx);
8591            self.change_selections(None, cx, |s| {
8592                let new_ranges = selections.into_iter().map(|range| {
8593                    let start = OffsetUtf16(
8594                        range
8595                            .head()
8596                            .0
8597                            .saturating_add_signed(relative_utf16_range.start),
8598                    );
8599                    let end = OffsetUtf16(
8600                        range
8601                            .head()
8602                            .0
8603                            .saturating_add_signed(relative_utf16_range.end),
8604                    );
8605                    start..end
8606                });
8607                s.select_ranges(new_ranges);
8608            });
8609        }
8610
8611        self.handle_input(text, cx);
8612    }
8613
8614    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
8615        let Some(project) = self.project.as_ref() else {
8616            return false;
8617        };
8618        let project = project.read(cx);
8619
8620        let mut supports = false;
8621        self.buffer().read(cx).for_each_buffer(|buffer| {
8622            if !supports {
8623                supports = project
8624                    .language_servers_for_buffer(buffer.read(cx), cx)
8625                    .any(
8626                        |(_, server)| match server.capabilities().inlay_hint_provider {
8627                            Some(lsp::OneOf::Left(enabled)) => enabled,
8628                            Some(lsp::OneOf::Right(_)) => true,
8629                            None => false,
8630                        },
8631                    )
8632            }
8633        });
8634        supports
8635    }
8636}
8637
8638pub trait CollaborationHub {
8639    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
8640    fn user_participant_indices<'a>(
8641        &self,
8642        cx: &'a AppContext,
8643    ) -> &'a HashMap<u64, ParticipantIndex>;
8644}
8645
8646impl CollaborationHub for ModelHandle<Project> {
8647    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
8648        self.read(cx).collaborators()
8649    }
8650
8651    fn user_participant_indices<'a>(
8652        &self,
8653        cx: &'a AppContext,
8654    ) -> &'a HashMap<u64, ParticipantIndex> {
8655        self.read(cx).user_store().read(cx).participant_indices()
8656    }
8657}
8658
8659fn inlay_hint_settings(
8660    location: Anchor,
8661    snapshot: &MultiBufferSnapshot,
8662    cx: &mut ViewContext<'_, '_, Editor>,
8663) -> InlayHintSettings {
8664    let file = snapshot.file_at(location);
8665    let language = snapshot.language_at(location);
8666    let settings = all_language_settings(file, cx);
8667    settings
8668        .language(language.map(|l| l.name()).as_deref())
8669        .inlay_hints
8670}
8671
8672fn consume_contiguous_rows(
8673    contiguous_row_selections: &mut Vec<Selection<Point>>,
8674    selection: &Selection<Point>,
8675    display_map: &DisplaySnapshot,
8676    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8677) -> (u32, u32) {
8678    contiguous_row_selections.push(selection.clone());
8679    let start_row = selection.start.row;
8680    let mut end_row = ending_row(selection, display_map);
8681
8682    while let Some(next_selection) = selections.peek() {
8683        if next_selection.start.row <= end_row {
8684            end_row = ending_row(next_selection, display_map);
8685            contiguous_row_selections.push(selections.next().unwrap().clone());
8686        } else {
8687            break;
8688        }
8689    }
8690    (start_row, end_row)
8691}
8692
8693fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8694    if next_selection.end.column > 0 || next_selection.is_empty() {
8695        display_map.next_line_boundary(next_selection.end).0.row + 1
8696    } else {
8697        next_selection.end.row
8698    }
8699}
8700
8701impl EditorSnapshot {
8702    pub fn remote_selections_in_range<'a>(
8703        &'a self,
8704        range: &'a Range<Anchor>,
8705        collaboration_hub: &dyn CollaborationHub,
8706        cx: &'a AppContext,
8707    ) -> impl 'a + Iterator<Item = RemoteSelection> {
8708        let participant_indices = collaboration_hub.user_participant_indices(cx);
8709        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
8710        let collaborators_by_replica_id = collaborators_by_peer_id
8711            .iter()
8712            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
8713            .collect::<HashMap<_, _>>();
8714        self.buffer_snapshot
8715            .remote_selections_in_range(range)
8716            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
8717                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
8718                let participant_index = participant_indices.get(&collaborator.user_id).copied();
8719                Some(RemoteSelection {
8720                    replica_id,
8721                    selection,
8722                    cursor_shape,
8723                    line_mode,
8724                    participant_index,
8725                    peer_id: collaborator.peer_id,
8726                })
8727            })
8728    }
8729
8730    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8731        self.display_snapshot.buffer_snapshot.language_at(position)
8732    }
8733
8734    pub fn is_focused(&self) -> bool {
8735        self.is_focused
8736    }
8737
8738    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8739        self.placeholder_text.as_ref()
8740    }
8741
8742    pub fn scroll_position(&self) -> Vector2F {
8743        self.scroll_anchor.scroll_position(&self.display_snapshot)
8744    }
8745}
8746
8747impl Deref for EditorSnapshot {
8748    type Target = DisplaySnapshot;
8749
8750    fn deref(&self) -> &Self::Target {
8751        &self.display_snapshot
8752    }
8753}
8754
8755#[derive(Clone, Debug, PartialEq, Eq)]
8756pub enum Event {
8757    InputIgnored {
8758        text: Arc<str>,
8759    },
8760    InputHandled {
8761        utf16_range_to_replace: Option<Range<isize>>,
8762        text: Arc<str>,
8763    },
8764    ExcerptsAdded {
8765        buffer: ModelHandle<Buffer>,
8766        predecessor: ExcerptId,
8767        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8768    },
8769    ExcerptsRemoved {
8770        ids: Vec<ExcerptId>,
8771    },
8772    BufferEdited,
8773    Edited,
8774    Reparsed,
8775    Focused,
8776    Blurred,
8777    DirtyChanged,
8778    Saved,
8779    TitleChanged,
8780    DiffBaseChanged,
8781    SelectionsChanged {
8782        local: bool,
8783    },
8784    ScrollPositionChanged {
8785        local: bool,
8786        autoscroll: bool,
8787    },
8788    Closed,
8789}
8790
8791pub struct EditorFocused(pub ViewHandle<Editor>);
8792pub struct EditorBlurred(pub ViewHandle<Editor>);
8793pub struct EditorReleased(pub WeakViewHandle<Editor>);
8794
8795impl Entity for Editor {
8796    type Event = Event;
8797
8798    fn release(&mut self, cx: &mut AppContext) {
8799        cx.emit_global(EditorReleased(self.handle.clone()));
8800    }
8801}
8802
8803impl View for Editor {
8804    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8805        let style = self.style(cx);
8806        let font_changed = self.display_map.update(cx, |map, cx| {
8807            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8808            map.set_font(style.text.font_id, style.text.font_size, cx)
8809        });
8810
8811        if font_changed {
8812            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8813                hide_hover(editor, cx);
8814                hide_link_definition(editor, cx);
8815            });
8816        }
8817
8818        Stack::new()
8819            .with_child(EditorElement::new(style.clone()))
8820            .with_child(ChildView::new(&self.mouse_context_menu, cx))
8821            .into_any()
8822    }
8823
8824    fn ui_name() -> &'static str {
8825        "Editor"
8826    }
8827
8828    fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
8829        if cx.is_self_focused() {
8830            let focused_event = EditorFocused(cx.handle());
8831            cx.emit(Event::Focused);
8832            cx.emit_global(focused_event);
8833        }
8834        if let Some(rename) = self.pending_rename.as_ref() {
8835            cx.focus(&rename.editor);
8836        } else if cx.is_self_focused() || !focused.is::<Editor>() {
8837            if !self.focused {
8838                self.blink_manager.update(cx, BlinkManager::enable);
8839            }
8840            self.focused = true;
8841            self.buffer.update(cx, |buffer, cx| {
8842                buffer.finalize_last_transaction(cx);
8843                if self.leader_peer_id.is_none() {
8844                    buffer.set_active_selections(
8845                        &self.selections.disjoint_anchors(),
8846                        self.selections.line_mode,
8847                        self.cursor_shape,
8848                        cx,
8849                    );
8850                }
8851            });
8852        }
8853    }
8854
8855    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8856        let blurred_event = EditorBlurred(cx.handle());
8857        cx.emit_global(blurred_event);
8858        self.focused = false;
8859        self.blink_manager.update(cx, BlinkManager::disable);
8860        self.buffer
8861            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8862        self.hide_context_menu(cx);
8863        hide_hover(self, cx);
8864        cx.emit(Event::Blurred);
8865        cx.notify();
8866    }
8867
8868    fn modifiers_changed(
8869        &mut self,
8870        event: &gpui::platform::ModifiersChangedEvent,
8871        cx: &mut ViewContext<Self>,
8872    ) -> bool {
8873        let pending_selection = self.has_pending_selection();
8874
8875        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
8876            if event.cmd && !pending_selection {
8877                let point = point.clone();
8878                let snapshot = self.snapshot(cx);
8879                let kind = point.definition_kind(event.shift);
8880
8881                show_link_definition(kind, self, point, snapshot, cx);
8882                return false;
8883            }
8884        }
8885
8886        {
8887            if self.link_go_to_definition_state.symbol_range.is_some()
8888                || !self.link_go_to_definition_state.definitions.is_empty()
8889            {
8890                self.link_go_to_definition_state.symbol_range.take();
8891                self.link_go_to_definition_state.definitions.clear();
8892                cx.notify();
8893            }
8894
8895            self.link_go_to_definition_state.task = None;
8896
8897            self.clear_highlights::<LinkGoToDefinitionState>(cx);
8898        }
8899
8900        false
8901    }
8902
8903    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8904        Self::reset_to_default_keymap_context(keymap);
8905        let mode = match self.mode {
8906            EditorMode::SingleLine => "single_line",
8907            EditorMode::AutoHeight { .. } => "auto_height",
8908            EditorMode::Full => "full",
8909        };
8910        keymap.add_key("mode", mode);
8911        if self.pending_rename.is_some() {
8912            keymap.add_identifier("renaming");
8913        }
8914        if self.context_menu_visible() {
8915            match self.context_menu.as_ref() {
8916                Some(ContextMenu::Completions(_)) => {
8917                    keymap.add_identifier("menu");
8918                    keymap.add_identifier("showing_completions")
8919                }
8920                Some(ContextMenu::CodeActions(_)) => {
8921                    keymap.add_identifier("menu");
8922                    keymap.add_identifier("showing_code_actions")
8923                }
8924                None => {}
8925            }
8926        }
8927
8928        for layer in self.keymap_context_layers.values() {
8929            keymap.extend(layer);
8930        }
8931
8932        if let Some(extension) = self
8933            .buffer
8934            .read(cx)
8935            .as_singleton()
8936            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8937        {
8938            keymap.add_key("extension", extension.to_string());
8939        }
8940    }
8941
8942    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8943        Some(
8944            self.buffer
8945                .read(cx)
8946                .read(cx)
8947                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8948                .collect(),
8949        )
8950    }
8951
8952    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8953        // Prevent the IME menu from appearing when holding down an alphabetic key
8954        // while input is disabled.
8955        if !self.input_enabled {
8956            return None;
8957        }
8958
8959        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8960        Some(range.start.0..range.end.0)
8961    }
8962
8963    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8964        let snapshot = self.buffer.read(cx).read(cx);
8965        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8966        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8967    }
8968
8969    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8970        self.clear_highlights::<InputComposition>(cx);
8971        self.ime_transaction.take();
8972    }
8973
8974    fn replace_text_in_range(
8975        &mut self,
8976        range_utf16: Option<Range<usize>>,
8977        text: &str,
8978        cx: &mut ViewContext<Self>,
8979    ) {
8980        if !self.input_enabled {
8981            cx.emit(Event::InputIgnored { text: text.into() });
8982            return;
8983        }
8984
8985        self.transact(cx, |this, cx| {
8986            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8987                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8988                Some(this.selection_replacement_ranges(range_utf16, cx))
8989            } else {
8990                this.marked_text_ranges(cx)
8991            };
8992
8993            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
8994                let newest_selection_id = this.selections.newest_anchor().id;
8995                this.selections
8996                    .all::<OffsetUtf16>(cx)
8997                    .iter()
8998                    .zip(ranges_to_replace.iter())
8999                    .find_map(|(selection, range)| {
9000                        if selection.id == newest_selection_id {
9001                            Some(
9002                                (range.start.0 as isize - selection.head().0 as isize)
9003                                    ..(range.end.0 as isize - selection.head().0 as isize),
9004                            )
9005                        } else {
9006                            None
9007                        }
9008                    })
9009            });
9010
9011            cx.emit(Event::InputHandled {
9012                utf16_range_to_replace: range_to_replace,
9013                text: text.into(),
9014            });
9015
9016            if let Some(new_selected_ranges) = new_selected_ranges {
9017                this.change_selections(None, cx, |selections| {
9018                    selections.select_ranges(new_selected_ranges)
9019                });
9020            }
9021
9022            this.handle_input(text, cx);
9023        });
9024
9025        if let Some(transaction) = self.ime_transaction {
9026            self.buffer.update(cx, |buffer, cx| {
9027                buffer.group_until_transaction(transaction, cx);
9028            });
9029        }
9030
9031        self.unmark_text(cx);
9032    }
9033
9034    fn replace_and_mark_text_in_range(
9035        &mut self,
9036        range_utf16: Option<Range<usize>>,
9037        text: &str,
9038        new_selected_range_utf16: Option<Range<usize>>,
9039        cx: &mut ViewContext<Self>,
9040    ) {
9041        if !self.input_enabled {
9042            cx.emit(Event::InputIgnored { text: text.into() });
9043            return;
9044        }
9045
9046        let transaction = self.transact(cx, |this, cx| {
9047            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9048                let snapshot = this.buffer.read(cx).read(cx);
9049                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9050                    for marked_range in &mut marked_ranges {
9051                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9052                        marked_range.start.0 += relative_range_utf16.start;
9053                        marked_range.start =
9054                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9055                        marked_range.end =
9056                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9057                    }
9058                }
9059                Some(marked_ranges)
9060            } else if let Some(range_utf16) = range_utf16 {
9061                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9062                Some(this.selection_replacement_ranges(range_utf16, cx))
9063            } else {
9064                None
9065            };
9066
9067            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9068                let newest_selection_id = this.selections.newest_anchor().id;
9069                this.selections
9070                    .all::<OffsetUtf16>(cx)
9071                    .iter()
9072                    .zip(ranges_to_replace.iter())
9073                    .find_map(|(selection, range)| {
9074                        if selection.id == newest_selection_id {
9075                            Some(
9076                                (range.start.0 as isize - selection.head().0 as isize)
9077                                    ..(range.end.0 as isize - selection.head().0 as isize),
9078                            )
9079                        } else {
9080                            None
9081                        }
9082                    })
9083            });
9084
9085            cx.emit(Event::InputHandled {
9086                utf16_range_to_replace: range_to_replace,
9087                text: text.into(),
9088            });
9089
9090            if let Some(ranges) = ranges_to_replace {
9091                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9092            }
9093
9094            let marked_ranges = {
9095                let snapshot = this.buffer.read(cx).read(cx);
9096                this.selections
9097                    .disjoint_anchors()
9098                    .iter()
9099                    .map(|selection| {
9100                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9101                    })
9102                    .collect::<Vec<_>>()
9103            };
9104
9105            if text.is_empty() {
9106                this.unmark_text(cx);
9107            } else {
9108                this.highlight_text::<InputComposition>(
9109                    marked_ranges.clone(),
9110                    this.style(cx).composition_mark,
9111                    cx,
9112                );
9113            }
9114
9115            this.handle_input(text, cx);
9116
9117            if let Some(new_selected_range) = new_selected_range_utf16 {
9118                let snapshot = this.buffer.read(cx).read(cx);
9119                let new_selected_ranges = marked_ranges
9120                    .into_iter()
9121                    .map(|marked_range| {
9122                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9123                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9124                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9125                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9126                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9127                    })
9128                    .collect::<Vec<_>>();
9129
9130                drop(snapshot);
9131                this.change_selections(None, cx, |selections| {
9132                    selections.select_ranges(new_selected_ranges)
9133                });
9134            }
9135        });
9136
9137        self.ime_transaction = self.ime_transaction.or(transaction);
9138        if let Some(transaction) = self.ime_transaction {
9139            self.buffer.update(cx, |buffer, cx| {
9140                buffer.group_until_transaction(transaction, cx);
9141            });
9142        }
9143
9144        if self.text_highlights::<InputComposition>(cx).is_none() {
9145            self.ime_transaction.take();
9146        }
9147    }
9148}
9149
9150fn build_style(
9151    settings: &ThemeSettings,
9152    get_field_editor_theme: Option<&GetFieldEditorTheme>,
9153    override_text_style: Option<&OverrideTextStyle>,
9154    cx: &AppContext,
9155) -> EditorStyle {
9156    let font_cache = cx.font_cache();
9157    let line_height_scalar = settings.line_height();
9158    let theme_id = settings.theme.meta.id;
9159    let mut theme = settings.theme.editor.clone();
9160    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
9161        let field_editor_theme = get_field_editor_theme(&settings.theme);
9162        theme.text_color = field_editor_theme.text.color;
9163        theme.selection = field_editor_theme.selection;
9164        theme.background = field_editor_theme
9165            .container
9166            .background_color
9167            .unwrap_or_default();
9168        EditorStyle {
9169            text: field_editor_theme.text,
9170            placeholder_text: field_editor_theme.placeholder_text,
9171            line_height_scalar,
9172            theme,
9173            theme_id,
9174        }
9175    } else {
9176        let font_family_id = settings.buffer_font_family;
9177        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
9178        let font_properties = Default::default();
9179        let font_id = font_cache
9180            .select_font(font_family_id, &font_properties)
9181            .unwrap();
9182        let font_size = settings.buffer_font_size(cx);
9183        EditorStyle {
9184            text: TextStyle {
9185                color: settings.theme.editor.text_color,
9186                font_family_name,
9187                font_family_id,
9188                font_id,
9189                font_size,
9190                font_properties,
9191                underline: Default::default(),
9192                soft_wrap: false,
9193            },
9194            placeholder_text: None,
9195            line_height_scalar,
9196            theme,
9197            theme_id,
9198        }
9199    };
9200
9201    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
9202        if let Some(highlighted) = style
9203            .text
9204            .clone()
9205            .highlight(highlight_style, font_cache)
9206            .log_err()
9207        {
9208            style.text = highlighted;
9209        }
9210    }
9211
9212    style
9213}
9214
9215trait SelectionExt {
9216    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9217    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9218    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9219    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9220        -> Range<u32>;
9221}
9222
9223impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9224    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9225        let start = self.start.to_point(buffer);
9226        let end = self.end.to_point(buffer);
9227        if self.reversed {
9228            end..start
9229        } else {
9230            start..end
9231        }
9232    }
9233
9234    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9235        let start = self.start.to_offset(buffer);
9236        let end = self.end.to_offset(buffer);
9237        if self.reversed {
9238            end..start
9239        } else {
9240            start..end
9241        }
9242    }
9243
9244    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9245        let start = self
9246            .start
9247            .to_point(&map.buffer_snapshot)
9248            .to_display_point(map);
9249        let end = self
9250            .end
9251            .to_point(&map.buffer_snapshot)
9252            .to_display_point(map);
9253        if self.reversed {
9254            end..start
9255        } else {
9256            start..end
9257        }
9258    }
9259
9260    fn spanned_rows(
9261        &self,
9262        include_end_if_at_line_start: bool,
9263        map: &DisplaySnapshot,
9264    ) -> Range<u32> {
9265        let start = self.start.to_point(&map.buffer_snapshot);
9266        let mut end = self.end.to_point(&map.buffer_snapshot);
9267        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9268            end.row -= 1;
9269        }
9270
9271        let buffer_start = map.prev_line_boundary(start).0;
9272        let buffer_end = map.next_line_boundary(end).0;
9273        buffer_start.row..buffer_end.row + 1
9274    }
9275}
9276
9277impl<T: InvalidationRegion> InvalidationStack<T> {
9278    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9279    where
9280        S: Clone + ToOffset,
9281    {
9282        while let Some(region) = self.last() {
9283            let all_selections_inside_invalidation_ranges =
9284                if selections.len() == region.ranges().len() {
9285                    selections
9286                        .iter()
9287                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9288                        .all(|(selection, invalidation_range)| {
9289                            let head = selection.head().to_offset(buffer);
9290                            invalidation_range.start <= head && invalidation_range.end >= head
9291                        })
9292                } else {
9293                    false
9294                };
9295
9296            if all_selections_inside_invalidation_ranges {
9297                break;
9298            } else {
9299                self.pop();
9300            }
9301        }
9302    }
9303}
9304
9305impl<T> Default for InvalidationStack<T> {
9306    fn default() -> Self {
9307        Self(Default::default())
9308    }
9309}
9310
9311impl<T> Deref for InvalidationStack<T> {
9312    type Target = Vec<T>;
9313
9314    fn deref(&self) -> &Self::Target {
9315        &self.0
9316    }
9317}
9318
9319impl<T> DerefMut for InvalidationStack<T> {
9320    fn deref_mut(&mut self) -> &mut Self::Target {
9321        &mut self.0
9322    }
9323}
9324
9325impl InvalidationRegion for SnippetState {
9326    fn ranges(&self) -> &[Range<Anchor>] {
9327        &self.ranges[self.active_index]
9328    }
9329}
9330
9331impl Deref for EditorStyle {
9332    type Target = theme::Editor;
9333
9334    fn deref(&self) -> &Self::Target {
9335        &self.theme
9336    }
9337}
9338
9339pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
9340    let mut highlighted_lines = Vec::new();
9341
9342    for (index, line) in diagnostic.message.lines().enumerate() {
9343        let line = match &diagnostic.source {
9344            Some(source) if index == 0 => {
9345                let source_highlight = Vec::from_iter(0..source.len());
9346                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
9347            }
9348
9349            _ => highlight_diagnostic_message(Vec::new(), line),
9350        };
9351        highlighted_lines.push(line);
9352    }
9353    let message = diagnostic.message;
9354    Arc::new(move |cx: &mut BlockContext| {
9355        let message = message.clone();
9356        let settings = settings::get::<ThemeSettings>(cx);
9357        let tooltip_style = settings.theme.tooltip.clone();
9358        let theme = &settings.theme.editor;
9359        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
9360        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
9361        let anchor_x = cx.anchor_x;
9362        enum BlockContextToolip {}
9363        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
9364            Flex::column()
9365                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
9366                    Label::new(
9367                        line.clone(),
9368                        style.message.clone().with_font_size(font_size),
9369                    )
9370                    .with_highlights(highlights.clone())
9371                    .contained()
9372                    .with_margin_left(anchor_x)
9373                }))
9374                .aligned()
9375                .left()
9376                .into_any()
9377        })
9378        .with_cursor_style(CursorStyle::PointingHand)
9379        .on_click(MouseButton::Left, move |_, _, cx| {
9380            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
9381        })
9382        // We really need to rethink this ID system...
9383        .with_tooltip::<BlockContextToolip>(
9384            cx.block_id,
9385            "Copy diagnostic message",
9386            None,
9387            tooltip_style,
9388            cx,
9389        )
9390        .into_any()
9391    })
9392}
9393
9394pub fn highlight_diagnostic_message(
9395    initial_highlights: Vec<usize>,
9396    message: &str,
9397) -> (String, Vec<usize>) {
9398    let mut message_without_backticks = String::new();
9399    let mut prev_offset = 0;
9400    let mut inside_block = false;
9401    let mut highlights = initial_highlights;
9402    for (match_ix, (offset, _)) in message
9403        .match_indices('`')
9404        .chain([(message.len(), "")])
9405        .enumerate()
9406    {
9407        message_without_backticks.push_str(&message[prev_offset..offset]);
9408        if inside_block {
9409            highlights.extend(prev_offset - match_ix..offset - match_ix);
9410        }
9411
9412        inside_block = !inside_block;
9413        prev_offset = offset + 1;
9414    }
9415
9416    (message_without_backticks, highlights)
9417}
9418
9419pub fn diagnostic_style(
9420    severity: DiagnosticSeverity,
9421    valid: bool,
9422    theme: &theme::Editor,
9423) -> DiagnosticStyle {
9424    match (severity, valid) {
9425        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
9426        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
9427        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
9428        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
9429        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
9430        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
9431        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
9432        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
9433        _ => theme.invalid_hint_diagnostic.clone(),
9434    }
9435}
9436
9437pub fn combine_syntax_and_fuzzy_match_highlights(
9438    text: &str,
9439    default_style: HighlightStyle,
9440    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
9441    match_indices: &[usize],
9442) -> Vec<(Range<usize>, HighlightStyle)> {
9443    let mut result = Vec::new();
9444    let mut match_indices = match_indices.iter().copied().peekable();
9445
9446    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
9447    {
9448        syntax_highlight.weight = None;
9449
9450        // Add highlights for any fuzzy match characters before the next
9451        // syntax highlight range.
9452        while let Some(&match_index) = match_indices.peek() {
9453            if match_index >= range.start {
9454                break;
9455            }
9456            match_indices.next();
9457            let end_index = char_ix_after(match_index, text);
9458            let mut match_style = default_style;
9459            match_style.weight = Some(fonts::Weight::BOLD);
9460            result.push((match_index..end_index, match_style));
9461        }
9462
9463        if range.start == usize::MAX {
9464            break;
9465        }
9466
9467        // Add highlights for any fuzzy match characters within the
9468        // syntax highlight range.
9469        let mut offset = range.start;
9470        while let Some(&match_index) = match_indices.peek() {
9471            if match_index >= range.end {
9472                break;
9473            }
9474
9475            match_indices.next();
9476            if match_index > offset {
9477                result.push((offset..match_index, syntax_highlight));
9478            }
9479
9480            let mut end_index = char_ix_after(match_index, text);
9481            while let Some(&next_match_index) = match_indices.peek() {
9482                if next_match_index == end_index && next_match_index < range.end {
9483                    end_index = char_ix_after(next_match_index, text);
9484                    match_indices.next();
9485                } else {
9486                    break;
9487                }
9488            }
9489
9490            let mut match_style = syntax_highlight;
9491            match_style.weight = Some(fonts::Weight::BOLD);
9492            result.push((match_index..end_index, match_style));
9493            offset = end_index;
9494        }
9495
9496        if offset < range.end {
9497            result.push((offset..range.end, syntax_highlight));
9498        }
9499    }
9500
9501    fn char_ix_after(ix: usize, text: &str) -> usize {
9502        ix + text[ix..].chars().next().unwrap().len_utf8()
9503    }
9504
9505    result
9506}
9507
9508pub fn styled_runs_for_code_label<'a>(
9509    label: &'a CodeLabel,
9510    syntax_theme: &'a theme::SyntaxTheme,
9511) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9512    let fade_out = HighlightStyle {
9513        fade_out: Some(0.35),
9514        ..Default::default()
9515    };
9516
9517    let mut prev_end = label.filter_range.end;
9518    label
9519        .runs
9520        .iter()
9521        .enumerate()
9522        .flat_map(move |(ix, (range, highlight_id))| {
9523            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9524                style
9525            } else {
9526                return Default::default();
9527            };
9528            let mut muted_style = style;
9529            muted_style.highlight(fade_out);
9530
9531            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9532            if range.start >= label.filter_range.end {
9533                if range.start > prev_end {
9534                    runs.push((prev_end..range.start, fade_out));
9535                }
9536                runs.push((range.clone(), muted_style));
9537            } else if range.end <= label.filter_range.end {
9538                runs.push((range.clone(), style));
9539            } else {
9540                runs.push((range.start..label.filter_range.end, style));
9541                runs.push((label.filter_range.end..range.end, muted_style));
9542            }
9543            prev_end = cmp::max(prev_end, range.end);
9544
9545            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9546                runs.push((prev_end..label.text.len(), fade_out));
9547            }
9548
9549            runs
9550        })
9551}
9552
9553pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9554    let mut index = 0;
9555    let mut codepoints = text.char_indices().peekable();
9556
9557    std::iter::from_fn(move || {
9558        let start_index = index;
9559        while let Some((new_index, codepoint)) = codepoints.next() {
9560            index = new_index + codepoint.len_utf8();
9561            let current_upper = codepoint.is_uppercase();
9562            let next_upper = codepoints
9563                .peek()
9564                .map(|(_, c)| c.is_uppercase())
9565                .unwrap_or(false);
9566
9567            if !current_upper && next_upper {
9568                return Some(&text[start_index..index]);
9569            }
9570        }
9571
9572        index = text.len();
9573        if start_index < text.len() {
9574            return Some(&text[start_index..]);
9575        }
9576        None
9577    })
9578    .flat_map(|word| word.split_inclusive('_'))
9579    .flat_map(|word| word.split_inclusive('-'))
9580}
9581
9582trait RangeToAnchorExt {
9583    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9584}
9585
9586impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9587    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9588        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9589    }
9590}