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