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