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