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