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