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