editor.rs

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