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