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