editor.rs

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