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