editor.rs

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