editor.rs

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