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