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