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