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