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