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