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) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
6247                    return;
6248                };
6249
6250                let mut best_length = usize::MAX;
6251                let mut best_inside = false;
6252                let mut best_in_bracket_range = false;
6253                let mut best_destination = None;
6254                for (open, close) in enclosing_bracket_ranges {
6255                    let close = close.to_inclusive();
6256                    let length = close.end() - open.start;
6257                    let inside = selection.start >= open.end && selection.end <= *close.start();
6258                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
6259
6260                    // If best is next to a bracket and current isn't, skip
6261                    if !in_bracket_range && best_in_bracket_range {
6262                        continue;
6263                    }
6264
6265                    // Prefer smaller lengths unless best is inside and current isn't
6266                    if length > best_length && (best_inside || !inside) {
6267                        continue;
6268                    }
6269
6270                    best_length = length;
6271                    best_inside = inside;
6272                    best_in_bracket_range = in_bracket_range;
6273                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
6274                        if inside {
6275                            open.end
6276                        } else {
6277                            open.start
6278                        }
6279                    } else {
6280                        if inside {
6281                            *close.start()
6282                        } else {
6283                            *close.end()
6284                        }
6285                    });
6286                }
6287
6288                if let Some(destination) = best_destination {
6289                    selection.collapse_to(destination, SelectionGoal::None);
6290                }
6291            })
6292        });
6293    }
6294
6295    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6296        self.end_selection(cx);
6297        self.selection_history.mode = SelectionHistoryMode::Undoing;
6298        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6299            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6300            self.select_next_state = entry.select_next_state;
6301            self.select_prev_state = entry.select_prev_state;
6302            self.add_selections_state = entry.add_selections_state;
6303            self.request_autoscroll(Autoscroll::newest(), cx);
6304        }
6305        self.selection_history.mode = SelectionHistoryMode::Normal;
6306    }
6307
6308    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6309        self.end_selection(cx);
6310        self.selection_history.mode = SelectionHistoryMode::Redoing;
6311        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6312            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6313            self.select_next_state = entry.select_next_state;
6314            self.select_prev_state = entry.select_prev_state;
6315            self.add_selections_state = entry.add_selections_state;
6316            self.request_autoscroll(Autoscroll::newest(), cx);
6317        }
6318        self.selection_history.mode = SelectionHistoryMode::Normal;
6319    }
6320
6321    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6322        self.go_to_diagnostic_impl(Direction::Next, cx)
6323    }
6324
6325    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6326        self.go_to_diagnostic_impl(Direction::Prev, cx)
6327    }
6328
6329    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6330        let buffer = self.buffer.read(cx).snapshot(cx);
6331        let selection = self.selections.newest::<usize>(cx);
6332
6333        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6334        if direction == Direction::Next {
6335            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6336                let (group_id, jump_to) = popover.activation_info();
6337                if self.activate_diagnostics(group_id, cx) {
6338                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6339                        let mut new_selection = s.newest_anchor().clone();
6340                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6341                        s.select_anchors(vec![new_selection.clone()]);
6342                    });
6343                }
6344                return;
6345            }
6346        }
6347
6348        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6349            active_diagnostics
6350                .primary_range
6351                .to_offset(&buffer)
6352                .to_inclusive()
6353        });
6354        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6355            if active_primary_range.contains(&selection.head()) {
6356                *active_primary_range.end()
6357            } else {
6358                selection.head()
6359            }
6360        } else {
6361            selection.head()
6362        };
6363
6364        loop {
6365            let mut diagnostics = if direction == Direction::Prev {
6366                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6367            } else {
6368                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6369            };
6370            let group = diagnostics.find_map(|entry| {
6371                if entry.diagnostic.is_primary
6372                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6373                    && !entry.range.is_empty()
6374                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6375                {
6376                    Some((entry.range, entry.diagnostic.group_id))
6377                } else {
6378                    None
6379                }
6380            });
6381
6382            if let Some((primary_range, group_id)) = group {
6383                if self.activate_diagnostics(group_id, cx) {
6384                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6385                        s.select(vec![Selection {
6386                            id: selection.id,
6387                            start: primary_range.start,
6388                            end: primary_range.start,
6389                            reversed: false,
6390                            goal: SelectionGoal::None,
6391                        }]);
6392                    });
6393                }
6394                break;
6395            } else {
6396                // Cycle around to the start of the buffer, potentially moving back to the start of
6397                // the currently active diagnostic.
6398                active_primary_range.take();
6399                if direction == Direction::Prev {
6400                    if search_start == buffer.len() {
6401                        break;
6402                    } else {
6403                        search_start = buffer.len();
6404                    }
6405                } else if search_start == 0 {
6406                    break;
6407                } else {
6408                    search_start = 0;
6409                }
6410            }
6411        }
6412    }
6413
6414    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6415        let snapshot = self
6416            .display_map
6417            .update(cx, |display_map, cx| display_map.snapshot(cx));
6418        let selection = self.selections.newest::<Point>(cx);
6419
6420        if !self.seek_in_direction(
6421            &snapshot,
6422            selection.head(),
6423            false,
6424            snapshot
6425                .buffer_snapshot
6426                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6427            cx,
6428        ) {
6429            let wrapped_point = Point::zero();
6430            self.seek_in_direction(
6431                &snapshot,
6432                wrapped_point,
6433                true,
6434                snapshot
6435                    .buffer_snapshot
6436                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6437                cx,
6438            );
6439        }
6440    }
6441
6442    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6443        let snapshot = self
6444            .display_map
6445            .update(cx, |display_map, cx| display_map.snapshot(cx));
6446        let selection = self.selections.newest::<Point>(cx);
6447
6448        if !self.seek_in_direction(
6449            &snapshot,
6450            selection.head(),
6451            false,
6452            snapshot
6453                .buffer_snapshot
6454                .git_diff_hunks_in_range_rev(0..selection.head().row),
6455            cx,
6456        ) {
6457            let wrapped_point = snapshot.buffer_snapshot.max_point();
6458            self.seek_in_direction(
6459                &snapshot,
6460                wrapped_point,
6461                true,
6462                snapshot
6463                    .buffer_snapshot
6464                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6465                cx,
6466            );
6467        }
6468    }
6469
6470    fn seek_in_direction(
6471        &mut self,
6472        snapshot: &DisplaySnapshot,
6473        initial_point: Point,
6474        is_wrapped: bool,
6475        hunks: impl Iterator<Item = DiffHunk<u32>>,
6476        cx: &mut ViewContext<Editor>,
6477    ) -> bool {
6478        let display_point = initial_point.to_display_point(snapshot);
6479        let mut hunks = hunks
6480            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6481            .skip_while(|hunk| {
6482                if is_wrapped {
6483                    false
6484                } else {
6485                    hunk.contains_display_row(display_point.row())
6486                }
6487            })
6488            .dedup();
6489
6490        if let Some(hunk) = hunks.next() {
6491            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6492                let row = hunk.start_display_row();
6493                let point = DisplayPoint::new(row, 0);
6494                s.select_display_ranges([point..point]);
6495            });
6496
6497            true
6498        } else {
6499            false
6500        }
6501    }
6502
6503    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6504        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6505    }
6506
6507    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6508        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6509    }
6510
6511    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6512        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6513    }
6514
6515    pub fn go_to_type_definition_split(
6516        &mut self,
6517        _: &GoToTypeDefinitionSplit,
6518        cx: &mut ViewContext<Self>,
6519    ) {
6520        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6521    }
6522
6523    fn go_to_definition_of_kind(
6524        &mut self,
6525        kind: GotoDefinitionKind,
6526        split: bool,
6527        cx: &mut ViewContext<Self>,
6528    ) {
6529        let Some(workspace) = self.workspace(cx) else { return };
6530        let buffer = self.buffer.read(cx);
6531        let head = self.selections.newest::<usize>(cx).head();
6532        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6533            text_anchor
6534        } else {
6535            return;
6536        };
6537
6538        let project = workspace.read(cx).project().clone();
6539        let definitions = project.update(cx, |project, cx| match kind {
6540            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6541            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6542        });
6543
6544        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6545            let definitions = definitions.await?;
6546            editor.update(&mut cx, |editor, cx| {
6547                editor.navigate_to_definitions(definitions, split, cx);
6548            })?;
6549            Ok::<(), anyhow::Error>(())
6550        })
6551        .detach_and_log_err(cx);
6552    }
6553
6554    pub fn navigate_to_definitions(
6555        &mut self,
6556        mut definitions: Vec<LocationLink>,
6557        split: bool,
6558        cx: &mut ViewContext<Editor>,
6559    ) {
6560        let Some(workspace) = self.workspace(cx) else { return };
6561        let pane = workspace.read(cx).active_pane().clone();
6562        // If there is one definition, just open it directly
6563        if definitions.len() == 1 {
6564            let definition = definitions.pop().unwrap();
6565            let range = definition
6566                .target
6567                .range
6568                .to_offset(definition.target.buffer.read(cx));
6569
6570            let range = self.range_for_match(&range);
6571            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6572                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6573                    s.select_ranges([range]);
6574                });
6575            } else {
6576                cx.window_context().defer(move |cx| {
6577                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6578                        if split {
6579                            workspace.split_project_item(definition.target.buffer.clone(), cx)
6580                        } else {
6581                            workspace.open_project_item(definition.target.buffer.clone(), cx)
6582                        }
6583                    });
6584                    target_editor.update(cx, |target_editor, cx| {
6585                        // When selecting a definition in a different buffer, disable the nav history
6586                        // to avoid creating a history entry at the previous cursor location.
6587                        pane.update(cx, |pane, _| pane.disable_history());
6588                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6589                            s.select_ranges([range]);
6590                        });
6591                        pane.update(cx, |pane, _| pane.enable_history());
6592                    });
6593                });
6594            }
6595        } else if !definitions.is_empty() {
6596            let replica_id = self.replica_id(cx);
6597            cx.window_context().defer(move |cx| {
6598                let title = definitions
6599                    .iter()
6600                    .find(|definition| definition.origin.is_some())
6601                    .and_then(|definition| {
6602                        definition.origin.as_ref().map(|origin| {
6603                            let buffer = origin.buffer.read(cx);
6604                            format!(
6605                                "Definitions for {}",
6606                                buffer
6607                                    .text_for_range(origin.range.clone())
6608                                    .collect::<String>()
6609                            )
6610                        })
6611                    })
6612                    .unwrap_or("Definitions".to_owned());
6613                let locations = definitions
6614                    .into_iter()
6615                    .map(|definition| definition.target)
6616                    .collect();
6617                workspace.update(cx, |workspace, cx| {
6618                    Self::open_locations_in_multibuffer(
6619                        workspace, locations, replica_id, title, split, cx,
6620                    )
6621                });
6622            });
6623        }
6624    }
6625
6626    pub fn find_all_references(
6627        workspace: &mut Workspace,
6628        _: &FindAllReferences,
6629        cx: &mut ViewContext<Workspace>,
6630    ) -> Option<Task<Result<()>>> {
6631        let active_item = workspace.active_item(cx)?;
6632        let editor_handle = active_item.act_as::<Self>(cx)?;
6633
6634        let editor = editor_handle.read(cx);
6635        let buffer = editor.buffer.read(cx);
6636        let head = editor.selections.newest::<usize>(cx).head();
6637        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6638        let replica_id = editor.replica_id(cx);
6639
6640        let project = workspace.project().clone();
6641        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6642        Some(cx.spawn_labeled(
6643            "Finding All References...",
6644            |workspace, mut cx| async move {
6645                let locations = references.await?;
6646                if locations.is_empty() {
6647                    return Ok(());
6648                }
6649
6650                workspace.update(&mut cx, |workspace, cx| {
6651                    let title = locations
6652                        .first()
6653                        .as_ref()
6654                        .map(|location| {
6655                            let buffer = location.buffer.read(cx);
6656                            format!(
6657                                "References to `{}`",
6658                                buffer
6659                                    .text_for_range(location.range.clone())
6660                                    .collect::<String>()
6661                            )
6662                        })
6663                        .unwrap();
6664                    Self::open_locations_in_multibuffer(
6665                        workspace, locations, replica_id, title, false, cx,
6666                    );
6667                })?;
6668
6669                Ok(())
6670            },
6671        ))
6672    }
6673
6674    /// Opens a multibuffer with the given project locations in it
6675    pub fn open_locations_in_multibuffer(
6676        workspace: &mut Workspace,
6677        mut locations: Vec<Location>,
6678        replica_id: ReplicaId,
6679        title: String,
6680        split: bool,
6681        cx: &mut ViewContext<Workspace>,
6682    ) {
6683        // If there are multiple definitions, open them in a multibuffer
6684        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6685        let mut locations = locations.into_iter().peekable();
6686        let mut ranges_to_highlight = Vec::new();
6687
6688        let excerpt_buffer = cx.add_model(|cx| {
6689            let mut multibuffer = MultiBuffer::new(replica_id);
6690            while let Some(location) = locations.next() {
6691                let buffer = location.buffer.read(cx);
6692                let mut ranges_for_buffer = Vec::new();
6693                let range = location.range.to_offset(buffer);
6694                ranges_for_buffer.push(range.clone());
6695
6696                while let Some(next_location) = locations.peek() {
6697                    if next_location.buffer == location.buffer {
6698                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6699                        locations.next();
6700                    } else {
6701                        break;
6702                    }
6703                }
6704
6705                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6706                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6707                    location.buffer.clone(),
6708                    ranges_for_buffer,
6709                    1,
6710                    cx,
6711                ))
6712            }
6713
6714            multibuffer.with_title(title)
6715        });
6716
6717        let editor = cx.add_view(|cx| {
6718            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6719        });
6720        editor.update(cx, |editor, cx| {
6721            editor.highlight_background::<Self>(
6722                ranges_to_highlight,
6723                |theme| theme.editor.highlighted_line_background,
6724                cx,
6725            );
6726        });
6727        if split {
6728            workspace.split_item(Box::new(editor), cx);
6729        } else {
6730            workspace.add_item(Box::new(editor), cx);
6731        }
6732    }
6733
6734    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6735        use language::ToOffset as _;
6736
6737        let project = self.project.clone()?;
6738        let selection = self.selections.newest_anchor().clone();
6739        let (cursor_buffer, cursor_buffer_position) = self
6740            .buffer
6741            .read(cx)
6742            .text_anchor_for_position(selection.head(), cx)?;
6743        let (tail_buffer, _) = self
6744            .buffer
6745            .read(cx)
6746            .text_anchor_for_position(selection.tail(), cx)?;
6747        if tail_buffer != cursor_buffer {
6748            return None;
6749        }
6750
6751        let snapshot = cursor_buffer.read(cx).snapshot();
6752        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6753        let prepare_rename = project.update(cx, |project, cx| {
6754            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6755        });
6756
6757        Some(cx.spawn(|this, mut cx| async move {
6758            let rename_range = if let Some(range) = prepare_rename.await? {
6759                Some(range)
6760            } else {
6761                this.update(&mut cx, |this, cx| {
6762                    let buffer = this.buffer.read(cx).snapshot(cx);
6763                    let display_snapshot = this
6764                        .display_map
6765                        .update(cx, |display_map, cx| display_map.snapshot(cx));
6766                    let mut buffer_highlights = this
6767                        .document_highlights_for_position(
6768                            selection.head(),
6769                            &buffer,
6770                            &display_snapshot,
6771                        )
6772                        .filter_map(|highlight| highlight.as_text_range())
6773                        .filter(|highlight| {
6774                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6775                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6776                        });
6777                    buffer_highlights
6778                        .next()
6779                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6780                })?
6781            };
6782            if let Some(rename_range) = rename_range {
6783                let rename_buffer_range = rename_range.to_offset(&snapshot);
6784                let cursor_offset_in_rename_range =
6785                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6786
6787                this.update(&mut cx, |this, cx| {
6788                    this.take_rename(false, cx);
6789                    let style = this.style(cx);
6790                    let buffer = this.buffer.read(cx).read(cx);
6791                    let cursor_offset = selection.head().to_offset(&buffer);
6792                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6793                    let rename_end = rename_start + rename_buffer_range.len();
6794                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6795                    let mut old_highlight_id = None;
6796                    let old_name: Arc<str> = buffer
6797                        .chunks(rename_start..rename_end, true)
6798                        .map(|chunk| {
6799                            if old_highlight_id.is_none() {
6800                                old_highlight_id = chunk.syntax_highlight_id;
6801                            }
6802                            chunk.text
6803                        })
6804                        .collect::<String>()
6805                        .into();
6806
6807                    drop(buffer);
6808
6809                    // Position the selection in the rename editor so that it matches the current selection.
6810                    this.show_local_selections = false;
6811                    let rename_editor = cx.add_view(|cx| {
6812                        let mut editor = Editor::single_line(None, cx);
6813                        if let Some(old_highlight_id) = old_highlight_id {
6814                            editor.override_text_style =
6815                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6816                        }
6817                        editor.buffer.update(cx, |buffer, cx| {
6818                            buffer.edit([(0..0, old_name.clone())], None, cx)
6819                        });
6820                        editor.select_all(&SelectAll, cx);
6821                        editor
6822                    });
6823
6824                    let ranges = this
6825                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6826                        .into_iter()
6827                        .flat_map(|(_, ranges)| {
6828                            ranges.into_iter().filter_map(|range| range.as_text_range())
6829                        })
6830                        .chain(
6831                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6832                                .into_iter()
6833                                .flat_map(|(_, ranges)| {
6834                                    ranges.into_iter().filter_map(|range| range.as_text_range())
6835                                }),
6836                        )
6837                        .collect();
6838
6839                    this.highlight_text::<Rename>(
6840                        ranges,
6841                        HighlightStyle {
6842                            fade_out: Some(style.rename_fade),
6843                            ..Default::default()
6844                        },
6845                        cx,
6846                    );
6847                    cx.focus(&rename_editor);
6848                    let block_id = this.insert_blocks(
6849                        [BlockProperties {
6850                            style: BlockStyle::Flex,
6851                            position: range.start.clone(),
6852                            height: 1,
6853                            render: Arc::new({
6854                                let editor = rename_editor.clone();
6855                                move |cx: &mut BlockContext| {
6856                                    ChildView::new(&editor, cx)
6857                                        .contained()
6858                                        .with_padding_left(cx.anchor_x)
6859                                        .into_any()
6860                                }
6861                            }),
6862                            disposition: BlockDisposition::Below,
6863                        }],
6864                        Some(Autoscroll::fit()),
6865                        cx,
6866                    )[0];
6867                    this.pending_rename = Some(RenameState {
6868                        range,
6869                        old_name,
6870                        editor: rename_editor,
6871                        block_id,
6872                    });
6873                })?;
6874            }
6875
6876            Ok(())
6877        }))
6878    }
6879
6880    pub fn confirm_rename(
6881        workspace: &mut Workspace,
6882        _: &ConfirmRename,
6883        cx: &mut ViewContext<Workspace>,
6884    ) -> Option<Task<Result<()>>> {
6885        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6886
6887        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6888            let rename = editor.take_rename(false, cx)?;
6889            let buffer = editor.buffer.read(cx);
6890            let (start_buffer, start) =
6891                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6892            let (end_buffer, end) =
6893                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6894            if start_buffer == end_buffer {
6895                let new_name = rename.editor.read(cx).text(cx);
6896                Some((start_buffer, start..end, rename.old_name, new_name))
6897            } else {
6898                None
6899            }
6900        })?;
6901
6902        let rename = workspace.project().clone().update(cx, |project, cx| {
6903            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6904        });
6905
6906        let editor = editor.downgrade();
6907        Some(cx.spawn(|workspace, mut cx| async move {
6908            let project_transaction = rename.await?;
6909            Self::open_project_transaction(
6910                &editor,
6911                workspace,
6912                project_transaction,
6913                format!("Rename: {}{}", old_name, new_name),
6914                cx.clone(),
6915            )
6916            .await?;
6917
6918            editor.update(&mut cx, |editor, cx| {
6919                editor.refresh_document_highlights(cx);
6920            })?;
6921            Ok(())
6922        }))
6923    }
6924
6925    fn take_rename(
6926        &mut self,
6927        moving_cursor: bool,
6928        cx: &mut ViewContext<Self>,
6929    ) -> Option<RenameState> {
6930        let rename = self.pending_rename.take()?;
6931        self.remove_blocks(
6932            [rename.block_id].into_iter().collect(),
6933            Some(Autoscroll::fit()),
6934            cx,
6935        );
6936        self.clear_text_highlights::<Rename>(cx);
6937        self.show_local_selections = true;
6938
6939        if moving_cursor {
6940            let rename_editor = rename.editor.read(cx);
6941            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6942
6943            // Update the selection to match the position of the selection inside
6944            // the rename editor.
6945            let snapshot = self.buffer.read(cx).read(cx);
6946            let rename_range = rename.range.to_offset(&snapshot);
6947            let cursor_in_editor = snapshot
6948                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6949                .min(rename_range.end);
6950            drop(snapshot);
6951
6952            self.change_selections(None, cx, |s| {
6953                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6954            });
6955        } else {
6956            self.refresh_document_highlights(cx);
6957        }
6958
6959        Some(rename)
6960    }
6961
6962    #[cfg(any(test, feature = "test-support"))]
6963    pub fn pending_rename(&self) -> Option<&RenameState> {
6964        self.pending_rename.as_ref()
6965    }
6966
6967    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6968        let project = match &self.project {
6969            Some(project) => project.clone(),
6970            None => return None,
6971        };
6972
6973        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6974    }
6975
6976    fn perform_format(
6977        &mut self,
6978        project: ModelHandle<Project>,
6979        trigger: FormatTrigger,
6980        cx: &mut ViewContext<Self>,
6981    ) -> Task<Result<()>> {
6982        let buffer = self.buffer().clone();
6983        let buffers = buffer.read(cx).all_buffers();
6984
6985        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6986        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6987
6988        cx.spawn(|_, mut cx| async move {
6989            let transaction = futures::select_biased! {
6990                _ = timeout => {
6991                    log::warn!("timed out waiting for formatting");
6992                    None
6993                }
6994                transaction = format.log_err().fuse() => transaction,
6995            };
6996
6997            buffer.update(&mut cx, |buffer, cx| {
6998                if let Some(transaction) = transaction {
6999                    if !buffer.is_singleton() {
7000                        buffer.push_transaction(&transaction.0, cx);
7001                    }
7002                }
7003
7004                cx.notify();
7005            });
7006
7007            Ok(())
7008        })
7009    }
7010
7011    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7012        if let Some(project) = self.project.clone() {
7013            self.buffer.update(cx, |multi_buffer, cx| {
7014                project.update(cx, |project, cx| {
7015                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7016                });
7017            })
7018        }
7019    }
7020
7021    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7022        cx.show_character_palette();
7023    }
7024
7025    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7026        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7027            let buffer = self.buffer.read(cx).snapshot(cx);
7028            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7029            let is_valid = buffer
7030                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7031                .any(|entry| {
7032                    entry.diagnostic.is_primary
7033                        && !entry.range.is_empty()
7034                        && entry.range.start == primary_range_start
7035                        && entry.diagnostic.message == active_diagnostics.primary_message
7036                });
7037
7038            if is_valid != active_diagnostics.is_valid {
7039                active_diagnostics.is_valid = is_valid;
7040                let mut new_styles = HashMap::default();
7041                for (block_id, diagnostic) in &active_diagnostics.blocks {
7042                    new_styles.insert(
7043                        *block_id,
7044                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7045                    );
7046                }
7047                self.display_map
7048                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7049            }
7050        }
7051    }
7052
7053    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7054        self.dismiss_diagnostics(cx);
7055        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7056            let buffer = self.buffer.read(cx).snapshot(cx);
7057
7058            let mut primary_range = None;
7059            let mut primary_message = None;
7060            let mut group_end = Point::zero();
7061            let diagnostic_group = buffer
7062                .diagnostic_group::<Point>(group_id)
7063                .map(|entry| {
7064                    if entry.range.end > group_end {
7065                        group_end = entry.range.end;
7066                    }
7067                    if entry.diagnostic.is_primary {
7068                        primary_range = Some(entry.range.clone());
7069                        primary_message = Some(entry.diagnostic.message.clone());
7070                    }
7071                    entry
7072                })
7073                .collect::<Vec<_>>();
7074            let primary_range = primary_range?;
7075            let primary_message = primary_message?;
7076            let primary_range =
7077                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7078
7079            let blocks = display_map
7080                .insert_blocks(
7081                    diagnostic_group.iter().map(|entry| {
7082                        let diagnostic = entry.diagnostic.clone();
7083                        let message_height = diagnostic.message.lines().count() as u8;
7084                        BlockProperties {
7085                            style: BlockStyle::Fixed,
7086                            position: buffer.anchor_after(entry.range.start),
7087                            height: message_height,
7088                            render: diagnostic_block_renderer(diagnostic, true),
7089                            disposition: BlockDisposition::Below,
7090                        }
7091                    }),
7092                    cx,
7093                )
7094                .into_iter()
7095                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7096                .collect();
7097
7098            Some(ActiveDiagnosticGroup {
7099                primary_range,
7100                primary_message,
7101                blocks,
7102                is_valid: true,
7103            })
7104        });
7105        self.active_diagnostics.is_some()
7106    }
7107
7108    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7109        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7110            self.display_map.update(cx, |display_map, cx| {
7111                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7112            });
7113            cx.notify();
7114        }
7115    }
7116
7117    pub fn set_selections_from_remote(
7118        &mut self,
7119        selections: Vec<Selection<Anchor>>,
7120        pending_selection: Option<Selection<Anchor>>,
7121        cx: &mut ViewContext<Self>,
7122    ) {
7123        let old_cursor_position = self.selections.newest_anchor().head();
7124        self.selections.change_with(cx, |s| {
7125            s.select_anchors(selections);
7126            if let Some(pending_selection) = pending_selection {
7127                s.set_pending(pending_selection, SelectMode::Character);
7128            } else {
7129                s.clear_pending();
7130            }
7131        });
7132        self.selections_did_change(false, &old_cursor_position, cx);
7133    }
7134
7135    fn push_to_selection_history(&mut self) {
7136        self.selection_history.push(SelectionHistoryEntry {
7137            selections: self.selections.disjoint_anchors(),
7138            select_next_state: self.select_next_state.clone(),
7139            select_prev_state: self.select_prev_state.clone(),
7140            add_selections_state: self.add_selections_state.clone(),
7141        });
7142    }
7143
7144    pub fn transact(
7145        &mut self,
7146        cx: &mut ViewContext<Self>,
7147        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7148    ) -> Option<TransactionId> {
7149        self.start_transaction_at(Instant::now(), cx);
7150        update(self, cx);
7151        self.end_transaction_at(Instant::now(), cx)
7152    }
7153
7154    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7155        self.end_selection(cx);
7156        if let Some(tx_id) = self
7157            .buffer
7158            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7159        {
7160            self.selection_history
7161                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7162        }
7163    }
7164
7165    fn end_transaction_at(
7166        &mut self,
7167        now: Instant,
7168        cx: &mut ViewContext<Self>,
7169    ) -> Option<TransactionId> {
7170        if let Some(tx_id) = self
7171            .buffer
7172            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7173        {
7174            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7175                *end_selections = Some(self.selections.disjoint_anchors());
7176            } else {
7177                error!("unexpectedly ended a transaction that wasn't started by this editor");
7178            }
7179
7180            cx.emit(Event::Edited);
7181            Some(tx_id)
7182        } else {
7183            None
7184        }
7185    }
7186
7187    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7188        let mut fold_ranges = Vec::new();
7189
7190        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7191
7192        let selections = self.selections.all::<Point>(cx);
7193        for selection in selections {
7194            let range = selection.range().sorted();
7195            let buffer_start_row = range.start.row;
7196
7197            for row in (0..=range.end.row).rev() {
7198                let fold_range = display_map.foldable_range(row);
7199
7200                if let Some(fold_range) = fold_range {
7201                    if fold_range.end.row >= buffer_start_row {
7202                        fold_ranges.push(fold_range);
7203                        if row <= range.start.row {
7204                            break;
7205                        }
7206                    }
7207                }
7208            }
7209        }
7210
7211        self.fold_ranges(fold_ranges, true, cx);
7212    }
7213
7214    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7215        let buffer_row = fold_at.buffer_row;
7216        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7217
7218        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7219            let autoscroll = self
7220                .selections
7221                .all::<Point>(cx)
7222                .iter()
7223                .any(|selection| fold_range.overlaps(&selection.range()));
7224
7225            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7226        }
7227    }
7228
7229    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7230        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7231        let buffer = &display_map.buffer_snapshot;
7232        let selections = self.selections.all::<Point>(cx);
7233        let ranges = selections
7234            .iter()
7235            .map(|s| {
7236                let range = s.display_range(&display_map).sorted();
7237                let mut start = range.start.to_point(&display_map);
7238                let mut end = range.end.to_point(&display_map);
7239                start.column = 0;
7240                end.column = buffer.line_len(end.row);
7241                start..end
7242            })
7243            .collect::<Vec<_>>();
7244
7245        self.unfold_ranges(ranges, true, true, cx);
7246    }
7247
7248    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7249        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7250
7251        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7252            ..Point::new(
7253                unfold_at.buffer_row,
7254                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7255            );
7256
7257        let autoscroll = self
7258            .selections
7259            .all::<Point>(cx)
7260            .iter()
7261            .any(|selection| selection.range().overlaps(&intersection_range));
7262
7263        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7264    }
7265
7266    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7267        let selections = self.selections.all::<Point>(cx);
7268        let ranges = selections.into_iter().map(|s| s.start..s.end);
7269        self.fold_ranges(ranges, true, cx);
7270    }
7271
7272    pub fn fold_ranges<T: ToOffset + Clone>(
7273        &mut self,
7274        ranges: impl IntoIterator<Item = Range<T>>,
7275        auto_scroll: bool,
7276        cx: &mut ViewContext<Self>,
7277    ) {
7278        let mut ranges = ranges.into_iter().peekable();
7279        if ranges.peek().is_some() {
7280            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7281
7282            if auto_scroll {
7283                self.request_autoscroll(Autoscroll::fit(), cx);
7284            }
7285
7286            cx.notify();
7287        }
7288    }
7289
7290    pub fn unfold_ranges<T: ToOffset + Clone>(
7291        &mut self,
7292        ranges: impl IntoIterator<Item = Range<T>>,
7293        inclusive: bool,
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
7300                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7301            if auto_scroll {
7302                self.request_autoscroll(Autoscroll::fit(), cx);
7303            }
7304
7305            cx.notify();
7306        }
7307    }
7308
7309    pub fn gutter_hover(
7310        &mut self,
7311        GutterHover { hovered }: &GutterHover,
7312        cx: &mut ViewContext<Self>,
7313    ) {
7314        self.gutter_hovered = *hovered;
7315        cx.notify();
7316    }
7317
7318    pub fn insert_blocks(
7319        &mut self,
7320        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7321        autoscroll: Option<Autoscroll>,
7322        cx: &mut ViewContext<Self>,
7323    ) -> Vec<BlockId> {
7324        let blocks = self
7325            .display_map
7326            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7327        if let Some(autoscroll) = autoscroll {
7328            self.request_autoscroll(autoscroll, cx);
7329        }
7330        blocks
7331    }
7332
7333    pub fn replace_blocks(
7334        &mut self,
7335        blocks: HashMap<BlockId, RenderBlock>,
7336        autoscroll: Option<Autoscroll>,
7337        cx: &mut ViewContext<Self>,
7338    ) {
7339        self.display_map
7340            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7341        if let Some(autoscroll) = autoscroll {
7342            self.request_autoscroll(autoscroll, cx);
7343        }
7344    }
7345
7346    pub fn remove_blocks(
7347        &mut self,
7348        block_ids: HashSet<BlockId>,
7349        autoscroll: Option<Autoscroll>,
7350        cx: &mut ViewContext<Self>,
7351    ) {
7352        self.display_map.update(cx, |display_map, cx| {
7353            display_map.remove_blocks(block_ids, cx)
7354        });
7355        if let Some(autoscroll) = autoscroll {
7356            self.request_autoscroll(autoscroll, cx);
7357        }
7358    }
7359
7360    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7361        self.display_map
7362            .update(cx, |map, cx| map.snapshot(cx))
7363            .longest_row()
7364    }
7365
7366    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7367        self.display_map
7368            .update(cx, |map, cx| map.snapshot(cx))
7369            .max_point()
7370    }
7371
7372    pub fn text(&self, cx: &AppContext) -> String {
7373        self.buffer.read(cx).read(cx).text()
7374    }
7375
7376    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7377        self.transact(cx, |this, cx| {
7378            this.buffer
7379                .read(cx)
7380                .as_singleton()
7381                .expect("you can only call set_text on editors for singleton buffers")
7382                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7383        });
7384    }
7385
7386    pub fn display_text(&self, cx: &mut AppContext) -> String {
7387        self.display_map
7388            .update(cx, |map, cx| map.snapshot(cx))
7389            .text()
7390    }
7391
7392    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7393        let mut wrap_guides = smallvec::smallvec![];
7394
7395        if self.show_wrap_guides == Some(false) {
7396            return wrap_guides;
7397        }
7398
7399        let settings = self.buffer.read(cx).settings_at(0, cx);
7400        if settings.show_wrap_guides {
7401            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7402                wrap_guides.push((soft_wrap as usize, true));
7403            }
7404            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7405        }
7406
7407        wrap_guides
7408    }
7409
7410    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7411        let settings = self.buffer.read(cx).settings_at(0, cx);
7412        let mode = self
7413            .soft_wrap_mode_override
7414            .unwrap_or_else(|| settings.soft_wrap);
7415        match mode {
7416            language_settings::SoftWrap::None => SoftWrap::None,
7417            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7418            language_settings::SoftWrap::PreferredLineLength => {
7419                SoftWrap::Column(settings.preferred_line_length)
7420            }
7421        }
7422    }
7423
7424    pub fn set_soft_wrap_mode(
7425        &mut self,
7426        mode: language_settings::SoftWrap,
7427        cx: &mut ViewContext<Self>,
7428    ) {
7429        self.soft_wrap_mode_override = Some(mode);
7430        cx.notify();
7431    }
7432
7433    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7434        self.display_map
7435            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7436    }
7437
7438    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7439        if self.soft_wrap_mode_override.is_some() {
7440            self.soft_wrap_mode_override.take();
7441        } else {
7442            let soft_wrap = match self.soft_wrap_mode(cx) {
7443                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7444                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7445            };
7446            self.soft_wrap_mode_override = Some(soft_wrap);
7447        }
7448        cx.notify();
7449    }
7450
7451    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7452        self.show_gutter = show_gutter;
7453        cx.notify();
7454    }
7455
7456    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7457        self.show_wrap_guides = Some(show_gutter);
7458        cx.notify();
7459    }
7460
7461    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7462        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7463            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7464                cx.reveal_path(&file.abs_path(cx));
7465            }
7466        }
7467    }
7468
7469    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7470        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7471            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7472                if let Some(path) = file.abs_path(cx).to_str() {
7473                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7474                }
7475            }
7476        }
7477    }
7478
7479    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7480        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7481            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7482                if let Some(path) = file.path().to_str() {
7483                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7484                }
7485            }
7486        }
7487    }
7488
7489    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7490        self.highlighted_rows = rows;
7491    }
7492
7493    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7494        self.highlighted_rows.clone()
7495    }
7496
7497    pub fn highlight_background<T: 'static>(
7498        &mut self,
7499        ranges: Vec<Range<Anchor>>,
7500        color_fetcher: fn(&Theme) -> Color,
7501        cx: &mut ViewContext<Self>,
7502    ) {
7503        self.background_highlights.insert(
7504            TypeId::of::<T>(),
7505            (
7506                color_fetcher,
7507                ranges.into_iter().map(DocumentRange::Text).collect(),
7508            ),
7509        );
7510        cx.notify();
7511    }
7512
7513    pub fn highlight_inlay_background<T: 'static>(
7514        &mut self,
7515        ranges: Vec<InlayRange>,
7516        color_fetcher: fn(&Theme) -> Color,
7517        cx: &mut ViewContext<Self>,
7518    ) {
7519        self.background_highlights.insert(
7520            TypeId::of::<T>(),
7521            (
7522                color_fetcher,
7523                ranges.into_iter().map(DocumentRange::Inlay).collect(),
7524            ),
7525        );
7526        cx.notify();
7527    }
7528
7529    pub fn clear_background_highlights<T: 'static>(
7530        &mut self,
7531        cx: &mut ViewContext<Self>,
7532    ) -> Option<BackgroundHighlight> {
7533        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7534        if highlights.is_some() {
7535            cx.notify();
7536        }
7537        highlights
7538    }
7539
7540    #[cfg(feature = "test-support")]
7541    pub fn all_background_highlights(
7542        &mut self,
7543        cx: &mut ViewContext<Self>,
7544    ) -> Vec<(Range<DisplayPoint>, Color)> {
7545        let snapshot = self.snapshot(cx);
7546        let buffer = &snapshot.buffer_snapshot;
7547        let start = buffer.anchor_before(0);
7548        let end = buffer.anchor_after(buffer.len());
7549        let theme = theme::current(cx);
7550        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7551    }
7552
7553    fn document_highlights_for_position<'a>(
7554        &'a self,
7555        position: Anchor,
7556        buffer: &'a MultiBufferSnapshot,
7557        display_snapshot: &'a DisplaySnapshot,
7558    ) -> impl 'a + Iterator<Item = &DocumentRange> {
7559        let read_highlights = self
7560            .background_highlights
7561            .get(&TypeId::of::<DocumentHighlightRead>())
7562            .map(|h| &h.1);
7563        let write_highlights = self
7564            .background_highlights
7565            .get(&TypeId::of::<DocumentHighlightWrite>())
7566            .map(|h| &h.1);
7567        let left_position = display_snapshot.anchor_to_inlay_offset(position.bias_left(buffer));
7568        let right_position = display_snapshot.anchor_to_inlay_offset(position.bias_right(buffer));
7569        read_highlights
7570            .into_iter()
7571            .chain(write_highlights)
7572            .flat_map(move |ranges| {
7573                let start_ix = match ranges.binary_search_by(|probe| {
7574                    let cmp = document_to_inlay_range(probe, display_snapshot)
7575                        .end
7576                        .cmp(&left_position);
7577                    if cmp.is_ge() {
7578                        Ordering::Greater
7579                    } else {
7580                        Ordering::Less
7581                    }
7582                }) {
7583                    Ok(i) | Err(i) => i,
7584                };
7585
7586                let right_position = right_position.clone();
7587                ranges[start_ix..].iter().take_while(move |range| {
7588                    document_to_inlay_range(range, display_snapshot)
7589                        .start
7590                        .cmp(&right_position)
7591                        .is_le()
7592                })
7593            })
7594    }
7595
7596    pub fn background_highlights_in_range(
7597        &self,
7598        search_range: Range<Anchor>,
7599        display_snapshot: &DisplaySnapshot,
7600        theme: &Theme,
7601    ) -> Vec<(Range<DisplayPoint>, Color)> {
7602        let search_range = display_snapshot.anchor_to_inlay_offset(search_range.start)
7603            ..display_snapshot.anchor_to_inlay_offset(search_range.end);
7604        let mut results = Vec::new();
7605        for (color_fetcher, ranges) in self.background_highlights.values() {
7606            let color = color_fetcher(theme);
7607            let start_ix = match ranges.binary_search_by(|probe| {
7608                let cmp = document_to_inlay_range(probe, display_snapshot)
7609                    .end
7610                    .cmp(&search_range.start);
7611                if cmp.is_gt() {
7612                    Ordering::Greater
7613                } else {
7614                    Ordering::Less
7615                }
7616            }) {
7617                Ok(i) | Err(i) => i,
7618            };
7619            for range in &ranges[start_ix..] {
7620                let range = document_to_inlay_range(range, display_snapshot);
7621                if range.start.cmp(&search_range.end).is_ge() {
7622                    break;
7623                }
7624
7625                let start = display_snapshot.inlay_offset_to_display_point(range.start, Bias::Left);
7626                let end = display_snapshot.inlay_offset_to_display_point(range.end, Bias::Right);
7627                results.push((start..end, color))
7628            }
7629        }
7630        results
7631    }
7632
7633    pub fn background_highlight_row_ranges<T: 'static>(
7634        &self,
7635        search_range: Range<Anchor>,
7636        display_snapshot: &DisplaySnapshot,
7637        count: usize,
7638    ) -> Vec<RangeInclusive<DisplayPoint>> {
7639        let search_range = display_snapshot.anchor_to_inlay_offset(search_range.start)
7640            ..display_snapshot.anchor_to_inlay_offset(search_range.end);
7641        let mut results = Vec::new();
7642        let Some((_, ranges)) = self.background_highlights
7643            .get(&TypeId::of::<T>()) else {
7644                return vec![];
7645            };
7646
7647        let start_ix = match ranges.binary_search_by(|probe| {
7648            let cmp = document_to_inlay_range(probe, display_snapshot)
7649                .end
7650                .cmp(&search_range.start);
7651            if cmp.is_gt() {
7652                Ordering::Greater
7653            } else {
7654                Ordering::Less
7655            }
7656        }) {
7657            Ok(i) | Err(i) => i,
7658        };
7659        let mut push_region = |start: Option<Point>, end: Option<Point>| {
7660            if let (Some(start_display), Some(end_display)) = (start, end) {
7661                results.push(
7662                    start_display.to_display_point(display_snapshot)
7663                        ..=end_display.to_display_point(display_snapshot),
7664                );
7665            }
7666        };
7667        let mut start_row: Option<Point> = None;
7668        let mut end_row: Option<Point> = None;
7669        if ranges.len() > count {
7670            return Vec::new();
7671        }
7672        for range in &ranges[start_ix..] {
7673            let range = document_to_inlay_range(range, display_snapshot);
7674            if range.start.cmp(&search_range.end).is_ge() {
7675                break;
7676            }
7677            let end = display_snapshot
7678                .inlay_offset_to_display_point(range.end, Bias::Right)
7679                .to_point(display_snapshot);
7680            if let Some(current_row) = &end_row {
7681                if end.row == current_row.row {
7682                    continue;
7683                }
7684            }
7685            let start = display_snapshot
7686                .inlay_offset_to_display_point(range.start, Bias::Left)
7687                .to_point(display_snapshot);
7688
7689            if start_row.is_none() {
7690                assert_eq!(end_row, None);
7691                start_row = Some(start);
7692                end_row = Some(end);
7693                continue;
7694            }
7695            if let Some(current_end) = end_row.as_mut() {
7696                if start.row > current_end.row + 1 {
7697                    push_region(start_row, end_row);
7698                    start_row = Some(start);
7699                    end_row = Some(end);
7700                } else {
7701                    // Merge two hunks.
7702                    *current_end = end;
7703                }
7704            } else {
7705                unreachable!();
7706            }
7707        }
7708        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
7709        push_region(start_row, end_row);
7710        results
7711    }
7712
7713    pub fn highlight_text<T: 'static>(
7714        &mut self,
7715        ranges: Vec<Range<Anchor>>,
7716        style: HighlightStyle,
7717        cx: &mut ViewContext<Self>,
7718    ) {
7719        self.display_map.update(cx, |map, _| {
7720            map.highlight_text(TypeId::of::<T>(), ranges, style)
7721        });
7722        cx.notify();
7723    }
7724
7725    pub fn highlight_inlays<T: 'static>(
7726        &mut self,
7727        ranges: Vec<InlayRange>,
7728        style: HighlightStyle,
7729        cx: &mut ViewContext<Self>,
7730    ) {
7731        self.display_map.update(cx, |map, _| {
7732            map.highlight_inlays(TypeId::of::<T>(), ranges, style)
7733        });
7734        cx.notify();
7735    }
7736
7737    pub fn text_highlights<'a, T: 'static>(
7738        &'a self,
7739        cx: &'a AppContext,
7740    ) -> Option<(HighlightStyle, &'a [DocumentRange])> {
7741        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7742    }
7743
7744    pub fn clear_text_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
7745        let text_highlights = self
7746            .display_map
7747            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7748        if text_highlights.is_some() {
7749            cx.notify();
7750        }
7751    }
7752
7753    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7754        self.blink_manager.read(cx).visible() && self.focused
7755    }
7756
7757    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7758        cx.notify();
7759    }
7760
7761    fn on_buffer_event(
7762        &mut self,
7763        multibuffer: ModelHandle<MultiBuffer>,
7764        event: &multi_buffer::Event,
7765        cx: &mut ViewContext<Self>,
7766    ) {
7767        match event {
7768            multi_buffer::Event::Edited => {
7769                self.refresh_active_diagnostics(cx);
7770                self.refresh_code_actions(cx);
7771                if self.has_active_copilot_suggestion(cx) {
7772                    self.update_visible_copilot_suggestion(cx);
7773                }
7774                cx.emit(Event::BufferEdited);
7775
7776                if let Some(project) = &self.project {
7777                    let project = project.read(cx);
7778                    let languages_affected = multibuffer
7779                        .read(cx)
7780                        .all_buffers()
7781                        .into_iter()
7782                        .filter_map(|buffer| {
7783                            let buffer = buffer.read(cx);
7784                            let language = buffer.language()?;
7785                            if project.is_local()
7786                                && project.language_servers_for_buffer(buffer, cx).count() == 0
7787                            {
7788                                None
7789                            } else {
7790                                Some(language)
7791                            }
7792                        })
7793                        .cloned()
7794                        .collect::<HashSet<_>>();
7795                    if !languages_affected.is_empty() {
7796                        self.refresh_inlay_hints(
7797                            InlayHintRefreshReason::BufferEdited(languages_affected),
7798                            cx,
7799                        );
7800                    }
7801                }
7802            }
7803            multi_buffer::Event::ExcerptsAdded {
7804                buffer,
7805                predecessor,
7806                excerpts,
7807            } => cx.emit(Event::ExcerptsAdded {
7808                buffer: buffer.clone(),
7809                predecessor: *predecessor,
7810                excerpts: excerpts.clone(),
7811            }),
7812            multi_buffer::Event::ExcerptsRemoved { ids } => {
7813                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7814            }
7815            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7816            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7817            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7818            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7819            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7820            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7821            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7822            multi_buffer::Event::DiagnosticsUpdated => {
7823                self.refresh_active_diagnostics(cx);
7824            }
7825            _ => {}
7826        };
7827    }
7828
7829    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7830        cx.notify();
7831    }
7832
7833    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7834        self.refresh_copilot_suggestions(true, cx);
7835        self.refresh_inlay_hints(
7836            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
7837                self.selections.newest_anchor().head(),
7838                &self.buffer.read(cx).snapshot(cx),
7839                cx,
7840            )),
7841            cx,
7842        );
7843    }
7844
7845    pub fn set_searchable(&mut self, searchable: bool) {
7846        self.searchable = searchable;
7847    }
7848
7849    pub fn searchable(&self) -> bool {
7850        self.searchable
7851    }
7852
7853    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7854        let active_item = workspace.active_item(cx);
7855        let editor_handle = if let Some(editor) = active_item
7856            .as_ref()
7857            .and_then(|item| item.act_as::<Self>(cx))
7858        {
7859            editor
7860        } else {
7861            cx.propagate_action();
7862            return;
7863        };
7864
7865        let editor = editor_handle.read(cx);
7866        let buffer = editor.buffer.read(cx);
7867        if buffer.is_singleton() {
7868            cx.propagate_action();
7869            return;
7870        }
7871
7872        let mut new_selections_by_buffer = HashMap::default();
7873        for selection in editor.selections.all::<usize>(cx) {
7874            for (buffer, mut range, _) in
7875                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7876            {
7877                if selection.reversed {
7878                    mem::swap(&mut range.start, &mut range.end);
7879                }
7880                new_selections_by_buffer
7881                    .entry(buffer)
7882                    .or_insert(Vec::new())
7883                    .push(range)
7884            }
7885        }
7886
7887        editor_handle.update(cx, |editor, cx| {
7888            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7889        });
7890        let pane = workspace.active_pane().clone();
7891        pane.update(cx, |pane, _| pane.disable_history());
7892
7893        // We defer the pane interaction because we ourselves are a workspace item
7894        // and activating a new item causes the pane to call a method on us reentrantly,
7895        // which panics if we're on the stack.
7896        cx.defer(move |workspace, cx| {
7897            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7898                let editor = workspace.open_project_item::<Self>(buffer, cx);
7899                editor.update(cx, |editor, cx| {
7900                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7901                        s.select_ranges(ranges);
7902                    });
7903                });
7904            }
7905
7906            pane.update(cx, |pane, _| pane.enable_history());
7907        });
7908    }
7909
7910    fn jump(
7911        workspace: &mut Workspace,
7912        path: ProjectPath,
7913        position: Point,
7914        anchor: language::Anchor,
7915        cx: &mut ViewContext<Workspace>,
7916    ) {
7917        let editor = workspace.open_path(path, None, true, cx);
7918        cx.spawn(|_, mut cx| async move {
7919            let editor = editor
7920                .await?
7921                .downcast::<Editor>()
7922                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7923                .downgrade();
7924            editor.update(&mut cx, |editor, cx| {
7925                let buffer = editor
7926                    .buffer()
7927                    .read(cx)
7928                    .as_singleton()
7929                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7930                let buffer = buffer.read(cx);
7931                let cursor = if buffer.can_resolve(&anchor) {
7932                    language::ToPoint::to_point(&anchor, buffer)
7933                } else {
7934                    buffer.clip_point(position, Bias::Left)
7935                };
7936
7937                let nav_history = editor.nav_history.take();
7938                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7939                    s.select_ranges([cursor..cursor]);
7940                });
7941                editor.nav_history = nav_history;
7942
7943                anyhow::Ok(())
7944            })??;
7945
7946            anyhow::Ok(())
7947        })
7948        .detach_and_log_err(cx);
7949    }
7950
7951    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7952        let snapshot = self.buffer.read(cx).read(cx);
7953        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7954        Some(
7955            ranges
7956                .iter()
7957                .filter_map(|range| range.as_text_range())
7958                .map(move |range| {
7959                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7960                })
7961                .collect(),
7962        )
7963    }
7964
7965    fn selection_replacement_ranges(
7966        &self,
7967        range: Range<OffsetUtf16>,
7968        cx: &AppContext,
7969    ) -> Vec<Range<OffsetUtf16>> {
7970        let selections = self.selections.all::<OffsetUtf16>(cx);
7971        let newest_selection = selections
7972            .iter()
7973            .max_by_key(|selection| selection.id)
7974            .unwrap();
7975        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7976        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7977        let snapshot = self.buffer.read(cx).read(cx);
7978        selections
7979            .into_iter()
7980            .map(|mut selection| {
7981                selection.start.0 =
7982                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7983                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7984                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7985                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7986            })
7987            .collect()
7988    }
7989
7990    fn report_copilot_event(
7991        &self,
7992        suggestion_id: Option<String>,
7993        suggestion_accepted: bool,
7994        cx: &AppContext,
7995    ) {
7996        let Some(project) = &self.project else {
7997            return
7998        };
7999
8000        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8001        let file_extension = self
8002            .buffer
8003            .read(cx)
8004            .as_singleton()
8005            .and_then(|b| b.read(cx).file())
8006            .and_then(|file| Path::new(file.file_name(cx)).extension())
8007            .and_then(|e| e.to_str())
8008            .map(|a| a.to_string());
8009
8010        let telemetry = project.read(cx).client().telemetry().clone();
8011        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8012
8013        let event = ClickhouseEvent::Copilot {
8014            suggestion_id,
8015            suggestion_accepted,
8016            file_extension,
8017        };
8018        telemetry.report_clickhouse_event(event, telemetry_settings);
8019    }
8020
8021    fn report_editor_event(
8022        &self,
8023        operation: &'static str,
8024        file_extension: Option<String>,
8025        cx: &AppContext,
8026    ) {
8027        let Some(project) = &self.project else {
8028            return
8029        };
8030
8031        // If None, we are in a file without an extension
8032        let file = self
8033            .buffer
8034            .read(cx)
8035            .as_singleton()
8036            .and_then(|b| b.read(cx).file());
8037        let file_extension = file_extension.or(file
8038            .as_ref()
8039            .and_then(|file| Path::new(file.file_name(cx)).extension())
8040            .and_then(|e| e.to_str())
8041            .map(|a| a.to_string()));
8042
8043        let vim_mode = cx
8044            .global::<SettingsStore>()
8045            .raw_user_settings()
8046            .get("vim_mode")
8047            == Some(&serde_json::Value::Bool(true));
8048        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8049        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8050        let copilot_enabled_for_language = self
8051            .buffer
8052            .read(cx)
8053            .settings_at(0, cx)
8054            .show_copilot_suggestions;
8055
8056        let telemetry = project.read(cx).client().telemetry().clone();
8057        let event = ClickhouseEvent::Editor {
8058            file_extension,
8059            vim_mode,
8060            operation,
8061            copilot_enabled,
8062            copilot_enabled_for_language,
8063        };
8064        telemetry.report_clickhouse_event(event, telemetry_settings)
8065    }
8066
8067    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8068    /// with each line being an array of {text, highlight} objects.
8069    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8070        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8071            return;
8072        };
8073
8074        #[derive(Serialize)]
8075        struct Chunk<'a> {
8076            text: String,
8077            highlight: Option<&'a str>,
8078        }
8079
8080        let snapshot = buffer.read(cx).snapshot();
8081        let range = self
8082            .selected_text_range(cx)
8083            .and_then(|selected_range| {
8084                if selected_range.is_empty() {
8085                    None
8086                } else {
8087                    Some(selected_range)
8088                }
8089            })
8090            .unwrap_or_else(|| 0..snapshot.len());
8091
8092        let chunks = snapshot.chunks(range, true);
8093        let mut lines = Vec::new();
8094        let mut line: VecDeque<Chunk> = VecDeque::new();
8095
8096        let theme = &theme::current(cx).editor.syntax;
8097
8098        for chunk in chunks {
8099            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8100            let mut chunk_lines = chunk.text.split("\n").peekable();
8101            while let Some(text) = chunk_lines.next() {
8102                let mut merged_with_last_token = false;
8103                if let Some(last_token) = line.back_mut() {
8104                    if last_token.highlight == highlight {
8105                        last_token.text.push_str(text);
8106                        merged_with_last_token = true;
8107                    }
8108                }
8109
8110                if !merged_with_last_token {
8111                    line.push_back(Chunk {
8112                        text: text.into(),
8113                        highlight,
8114                    });
8115                }
8116
8117                if chunk_lines.peek().is_some() {
8118                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8119                        line.pop_front();
8120                    }
8121                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8122                        line.pop_back();
8123                    }
8124
8125                    lines.push(mem::take(&mut line));
8126                }
8127            }
8128        }
8129
8130        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
8131        cx.write_to_clipboard(ClipboardItem::new(lines));
8132    }
8133
8134    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8135        &self.inlay_hint_cache
8136    }
8137}
8138
8139fn document_to_inlay_range(
8140    range: &DocumentRange,
8141    snapshot: &DisplaySnapshot,
8142) -> Range<InlayOffset> {
8143    match range {
8144        DocumentRange::Text(text_range) => {
8145            snapshot.anchor_to_inlay_offset(text_range.start)
8146                ..snapshot.anchor_to_inlay_offset(text_range.end)
8147        }
8148        DocumentRange::Inlay(inlay_range) => inlay_range.highlight_start..inlay_range.highlight_end,
8149    }
8150}
8151
8152fn inlay_hint_settings(
8153    location: Anchor,
8154    snapshot: &MultiBufferSnapshot,
8155    cx: &mut ViewContext<'_, '_, Editor>,
8156) -> InlayHintSettings {
8157    let file = snapshot.file_at(location);
8158    let language = snapshot.language_at(location);
8159    let settings = all_language_settings(file, cx);
8160    settings
8161        .language(language.map(|l| l.name()).as_deref())
8162        .inlay_hints
8163}
8164
8165fn consume_contiguous_rows(
8166    contiguous_row_selections: &mut Vec<Selection<Point>>,
8167    selection: &Selection<Point>,
8168    display_map: &DisplaySnapshot,
8169    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8170) -> (u32, u32) {
8171    contiguous_row_selections.push(selection.clone());
8172    let start_row = selection.start.row;
8173    let mut end_row = ending_row(selection, display_map);
8174
8175    while let Some(next_selection) = selections.peek() {
8176        if next_selection.start.row <= end_row {
8177            end_row = ending_row(next_selection, display_map);
8178            contiguous_row_selections.push(selections.next().unwrap().clone());
8179        } else {
8180            break;
8181        }
8182    }
8183    (start_row, end_row)
8184}
8185
8186fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8187    if next_selection.end.column > 0 || next_selection.is_empty() {
8188        display_map.next_line_boundary(next_selection.end).0.row + 1
8189    } else {
8190        next_selection.end.row
8191    }
8192}
8193
8194impl EditorSnapshot {
8195    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8196        self.display_snapshot.buffer_snapshot.language_at(position)
8197    }
8198
8199    pub fn is_focused(&self) -> bool {
8200        self.is_focused
8201    }
8202
8203    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8204        self.placeholder_text.as_ref()
8205    }
8206
8207    pub fn scroll_position(&self) -> Vector2F {
8208        self.scroll_anchor.scroll_position(&self.display_snapshot)
8209    }
8210}
8211
8212impl Deref for EditorSnapshot {
8213    type Target = DisplaySnapshot;
8214
8215    fn deref(&self) -> &Self::Target {
8216        &self.display_snapshot
8217    }
8218}
8219
8220#[derive(Clone, Debug, PartialEq, Eq)]
8221pub enum Event {
8222    InputIgnored {
8223        text: Arc<str>,
8224    },
8225    ExcerptsAdded {
8226        buffer: ModelHandle<Buffer>,
8227        predecessor: ExcerptId,
8228        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8229    },
8230    ExcerptsRemoved {
8231        ids: Vec<ExcerptId>,
8232    },
8233    BufferEdited,
8234    Edited,
8235    Reparsed,
8236    Focused,
8237    Blurred,
8238    DirtyChanged,
8239    Saved,
8240    TitleChanged,
8241    DiffBaseChanged,
8242    SelectionsChanged {
8243        local: bool,
8244    },
8245    ScrollPositionChanged {
8246        local: bool,
8247        autoscroll: bool,
8248    },
8249    Closed,
8250}
8251
8252pub struct EditorFocused(pub ViewHandle<Editor>);
8253pub struct EditorBlurred(pub ViewHandle<Editor>);
8254pub struct EditorReleased(pub WeakViewHandle<Editor>);
8255
8256impl Entity for Editor {
8257    type Event = Event;
8258
8259    fn release(&mut self, cx: &mut AppContext) {
8260        cx.emit_global(EditorReleased(self.handle.clone()));
8261    }
8262}
8263
8264impl View for Editor {
8265    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8266        let style = self.style(cx);
8267        let font_changed = self.display_map.update(cx, |map, cx| {
8268            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8269            map.set_font(style.text.font_id, style.text.font_size, cx)
8270        });
8271
8272        if font_changed {
8273            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8274                hide_hover(editor, cx);
8275                hide_link_definition(editor, cx);
8276            });
8277        }
8278
8279        Stack::new()
8280            .with_child(EditorElement::new(style.clone()))
8281            .with_child(ChildView::new(&self.mouse_context_menu, cx))
8282            .into_any()
8283    }
8284
8285    fn ui_name() -> &'static str {
8286        "Editor"
8287    }
8288
8289    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8290        if cx.is_self_focused() {
8291            let focused_event = EditorFocused(cx.handle());
8292            cx.emit(Event::Focused);
8293            cx.emit_global(focused_event);
8294        }
8295        if let Some(rename) = self.pending_rename.as_ref() {
8296            cx.focus(&rename.editor);
8297        } else {
8298            if !self.focused {
8299                self.blink_manager.update(cx, BlinkManager::enable);
8300            }
8301            self.focused = true;
8302            self.buffer.update(cx, |buffer, cx| {
8303                buffer.finalize_last_transaction(cx);
8304                if self.leader_replica_id.is_none() {
8305                    buffer.set_active_selections(
8306                        &self.selections.disjoint_anchors(),
8307                        self.selections.line_mode,
8308                        self.cursor_shape,
8309                        cx,
8310                    );
8311                }
8312            });
8313        }
8314    }
8315
8316    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8317        let blurred_event = EditorBlurred(cx.handle());
8318        cx.emit_global(blurred_event);
8319        self.focused = false;
8320        self.blink_manager.update(cx, BlinkManager::disable);
8321        self.buffer
8322            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8323        self.hide_context_menu(cx);
8324        hide_hover(self, cx);
8325        cx.emit(Event::Blurred);
8326        cx.notify();
8327    }
8328
8329    fn modifiers_changed(
8330        &mut self,
8331        event: &gpui::platform::ModifiersChangedEvent,
8332        cx: &mut ViewContext<Self>,
8333    ) -> bool {
8334        let pending_selection = self.has_pending_selection();
8335
8336        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
8337            if event.cmd && !pending_selection {
8338                let point = point.clone();
8339                let snapshot = self.snapshot(cx);
8340                let kind = point.definition_kind(event.shift);
8341
8342                show_link_definition(kind, self, point, snapshot, cx);
8343                return false;
8344            }
8345        }
8346
8347        {
8348            if self.link_go_to_definition_state.symbol_range.is_some()
8349                || !self.link_go_to_definition_state.definitions.is_empty()
8350            {
8351                self.link_go_to_definition_state.symbol_range.take();
8352                self.link_go_to_definition_state.definitions.clear();
8353                cx.notify();
8354            }
8355
8356            self.link_go_to_definition_state.task = None;
8357
8358            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8359        }
8360
8361        false
8362    }
8363
8364    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8365        Self::reset_to_default_keymap_context(keymap);
8366        let mode = match self.mode {
8367            EditorMode::SingleLine => "single_line",
8368            EditorMode::AutoHeight { .. } => "auto_height",
8369            EditorMode::Full => "full",
8370        };
8371        keymap.add_key("mode", mode);
8372        if self.pending_rename.is_some() {
8373            keymap.add_identifier("renaming");
8374        }
8375        match self.context_menu.as_ref() {
8376            Some(ContextMenu::Completions(_)) => {
8377                keymap.add_identifier("menu");
8378                keymap.add_identifier("showing_completions")
8379            }
8380            Some(ContextMenu::CodeActions(_)) => {
8381                keymap.add_identifier("menu");
8382                keymap.add_identifier("showing_code_actions")
8383            }
8384            None => {}
8385        }
8386        for layer in self.keymap_context_layers.values() {
8387            keymap.extend(layer);
8388        }
8389
8390        if let Some(extension) = self
8391            .buffer
8392            .read(cx)
8393            .as_singleton()
8394            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8395        {
8396            keymap.add_key("extension", extension.to_string());
8397        }
8398    }
8399
8400    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8401        Some(
8402            self.buffer
8403                .read(cx)
8404                .read(cx)
8405                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8406                .collect(),
8407        )
8408    }
8409
8410    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8411        // Prevent the IME menu from appearing when holding down an alphabetic key
8412        // while input is disabled.
8413        if !self.input_enabled {
8414            return None;
8415        }
8416
8417        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8418        Some(range.start.0..range.end.0)
8419    }
8420
8421    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8422        let snapshot = self.buffer.read(cx).read(cx);
8423        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8424        let range = range.as_text_range()?;
8425        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8426    }
8427
8428    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8429        self.clear_text_highlights::<InputComposition>(cx);
8430        self.ime_transaction.take();
8431    }
8432
8433    fn replace_text_in_range(
8434        &mut self,
8435        range_utf16: Option<Range<usize>>,
8436        text: &str,
8437        cx: &mut ViewContext<Self>,
8438    ) {
8439        self.transact(cx, |this, cx| {
8440            if this.input_enabled {
8441                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8442                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8443                    Some(this.selection_replacement_ranges(range_utf16, cx))
8444                } else {
8445                    this.marked_text_ranges(cx)
8446                };
8447
8448                if let Some(new_selected_ranges) = new_selected_ranges {
8449                    this.change_selections(None, cx, |selections| {
8450                        selections.select_ranges(new_selected_ranges)
8451                    });
8452                }
8453            }
8454
8455            this.handle_input(text, cx);
8456        });
8457
8458        if !self.input_enabled {
8459            return;
8460        }
8461
8462        if let Some(transaction) = self.ime_transaction {
8463            self.buffer.update(cx, |buffer, cx| {
8464                buffer.group_until_transaction(transaction, cx);
8465            });
8466        }
8467
8468        self.unmark_text(cx);
8469    }
8470
8471    fn replace_and_mark_text_in_range(
8472        &mut self,
8473        range_utf16: Option<Range<usize>>,
8474        text: &str,
8475        new_selected_range_utf16: Option<Range<usize>>,
8476        cx: &mut ViewContext<Self>,
8477    ) {
8478        if !self.input_enabled {
8479            return;
8480        }
8481
8482        let transaction = self.transact(cx, |this, cx| {
8483            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8484                let snapshot = this.buffer.read(cx).read(cx);
8485                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8486                    for marked_range in &mut marked_ranges {
8487                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8488                        marked_range.start.0 += relative_range_utf16.start;
8489                        marked_range.start =
8490                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8491                        marked_range.end =
8492                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8493                    }
8494                }
8495                Some(marked_ranges)
8496            } else if let Some(range_utf16) = range_utf16 {
8497                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8498                Some(this.selection_replacement_ranges(range_utf16, cx))
8499            } else {
8500                None
8501            };
8502
8503            if let Some(ranges) = ranges_to_replace {
8504                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8505            }
8506
8507            let marked_ranges = {
8508                let snapshot = this.buffer.read(cx).read(cx);
8509                this.selections
8510                    .disjoint_anchors()
8511                    .iter()
8512                    .map(|selection| {
8513                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8514                    })
8515                    .collect::<Vec<_>>()
8516            };
8517
8518            if text.is_empty() {
8519                this.unmark_text(cx);
8520            } else {
8521                this.highlight_text::<InputComposition>(
8522                    marked_ranges.clone(),
8523                    this.style(cx).composition_mark,
8524                    cx,
8525                );
8526            }
8527
8528            this.handle_input(text, cx);
8529
8530            if let Some(new_selected_range) = new_selected_range_utf16 {
8531                let snapshot = this.buffer.read(cx).read(cx);
8532                let new_selected_ranges = marked_ranges
8533                    .into_iter()
8534                    .map(|marked_range| {
8535                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8536                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8537                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8538                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8539                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8540                    })
8541                    .collect::<Vec<_>>();
8542
8543                drop(snapshot);
8544                this.change_selections(None, cx, |selections| {
8545                    selections.select_ranges(new_selected_ranges)
8546                });
8547            }
8548        });
8549
8550        self.ime_transaction = self.ime_transaction.or(transaction);
8551        if let Some(transaction) = self.ime_transaction {
8552            self.buffer.update(cx, |buffer, cx| {
8553                buffer.group_until_transaction(transaction, cx);
8554            });
8555        }
8556
8557        if self.text_highlights::<InputComposition>(cx).is_none() {
8558            self.ime_transaction.take();
8559        }
8560    }
8561}
8562
8563fn build_style(
8564    settings: &ThemeSettings,
8565    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8566    override_text_style: Option<&OverrideTextStyle>,
8567    cx: &AppContext,
8568) -> EditorStyle {
8569    let font_cache = cx.font_cache();
8570    let line_height_scalar = settings.line_height();
8571    let theme_id = settings.theme.meta.id;
8572    let mut theme = settings.theme.editor.clone();
8573    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8574        let field_editor_theme = get_field_editor_theme(&settings.theme);
8575        theme.text_color = field_editor_theme.text.color;
8576        theme.selection = field_editor_theme.selection;
8577        theme.background = field_editor_theme
8578            .container
8579            .background_color
8580            .unwrap_or_default();
8581        EditorStyle {
8582            text: field_editor_theme.text,
8583            placeholder_text: field_editor_theme.placeholder_text,
8584            line_height_scalar,
8585            theme,
8586            theme_id,
8587        }
8588    } else {
8589        let font_family_id = settings.buffer_font_family;
8590        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8591        let font_properties = Default::default();
8592        let font_id = font_cache
8593            .select_font(font_family_id, &font_properties)
8594            .unwrap();
8595        let font_size = settings.buffer_font_size(cx);
8596        EditorStyle {
8597            text: TextStyle {
8598                color: settings.theme.editor.text_color,
8599                font_family_name,
8600                font_family_id,
8601                font_id,
8602                font_size,
8603                font_properties,
8604                underline: Default::default(),
8605                soft_wrap: false,
8606            },
8607            placeholder_text: None,
8608            line_height_scalar,
8609            theme,
8610            theme_id,
8611        }
8612    };
8613
8614    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8615        if let Some(highlighted) = style
8616            .text
8617            .clone()
8618            .highlight(highlight_style, font_cache)
8619            .log_err()
8620        {
8621            style.text = highlighted;
8622        }
8623    }
8624
8625    style
8626}
8627
8628trait SelectionExt {
8629    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8630    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8631    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8632    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8633        -> Range<u32>;
8634}
8635
8636impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8637    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8638        let start = self.start.to_point(buffer);
8639        let end = self.end.to_point(buffer);
8640        if self.reversed {
8641            end..start
8642        } else {
8643            start..end
8644        }
8645    }
8646
8647    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8648        let start = self.start.to_offset(buffer);
8649        let end = self.end.to_offset(buffer);
8650        if self.reversed {
8651            end..start
8652        } else {
8653            start..end
8654        }
8655    }
8656
8657    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8658        let start = self
8659            .start
8660            .to_point(&map.buffer_snapshot)
8661            .to_display_point(map);
8662        let end = self
8663            .end
8664            .to_point(&map.buffer_snapshot)
8665            .to_display_point(map);
8666        if self.reversed {
8667            end..start
8668        } else {
8669            start..end
8670        }
8671    }
8672
8673    fn spanned_rows(
8674        &self,
8675        include_end_if_at_line_start: bool,
8676        map: &DisplaySnapshot,
8677    ) -> Range<u32> {
8678        let start = self.start.to_point(&map.buffer_snapshot);
8679        let mut end = self.end.to_point(&map.buffer_snapshot);
8680        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8681            end.row -= 1;
8682        }
8683
8684        let buffer_start = map.prev_line_boundary(start).0;
8685        let buffer_end = map.next_line_boundary(end).0;
8686        buffer_start.row..buffer_end.row + 1
8687    }
8688}
8689
8690impl<T: InvalidationRegion> InvalidationStack<T> {
8691    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8692    where
8693        S: Clone + ToOffset,
8694    {
8695        while let Some(region) = self.last() {
8696            let all_selections_inside_invalidation_ranges =
8697                if selections.len() == region.ranges().len() {
8698                    selections
8699                        .iter()
8700                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8701                        .all(|(selection, invalidation_range)| {
8702                            let head = selection.head().to_offset(buffer);
8703                            invalidation_range.start <= head && invalidation_range.end >= head
8704                        })
8705                } else {
8706                    false
8707                };
8708
8709            if all_selections_inside_invalidation_ranges {
8710                break;
8711            } else {
8712                self.pop();
8713            }
8714        }
8715    }
8716}
8717
8718impl<T> Default for InvalidationStack<T> {
8719    fn default() -> Self {
8720        Self(Default::default())
8721    }
8722}
8723
8724impl<T> Deref for InvalidationStack<T> {
8725    type Target = Vec<T>;
8726
8727    fn deref(&self) -> &Self::Target {
8728        &self.0
8729    }
8730}
8731
8732impl<T> DerefMut for InvalidationStack<T> {
8733    fn deref_mut(&mut self) -> &mut Self::Target {
8734        &mut self.0
8735    }
8736}
8737
8738impl InvalidationRegion for SnippetState {
8739    fn ranges(&self) -> &[Range<Anchor>] {
8740        &self.ranges[self.active_index]
8741    }
8742}
8743
8744impl Deref for EditorStyle {
8745    type Target = theme::Editor;
8746
8747    fn deref(&self) -> &Self::Target {
8748        &self.theme
8749    }
8750}
8751
8752pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8753    let mut highlighted_lines = Vec::new();
8754
8755    for (index, line) in diagnostic.message.lines().enumerate() {
8756        let line = match &diagnostic.source {
8757            Some(source) if index == 0 => {
8758                let source_highlight = Vec::from_iter(0..source.len());
8759                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8760            }
8761
8762            _ => highlight_diagnostic_message(Vec::new(), line),
8763        };
8764        highlighted_lines.push(line);
8765    }
8766    let message = diagnostic.message;
8767    Arc::new(move |cx: &mut BlockContext| {
8768        let message = message.clone();
8769        let settings = settings::get::<ThemeSettings>(cx);
8770        let tooltip_style = settings.theme.tooltip.clone();
8771        let theme = &settings.theme.editor;
8772        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8773        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8774        let anchor_x = cx.anchor_x;
8775        enum BlockContextToolip {}
8776        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
8777            Flex::column()
8778                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8779                    Label::new(
8780                        line.clone(),
8781                        style.message.clone().with_font_size(font_size),
8782                    )
8783                    .with_highlights(highlights.clone())
8784                    .contained()
8785                    .with_margin_left(anchor_x)
8786                }))
8787                .aligned()
8788                .left()
8789                .into_any()
8790        })
8791        .with_cursor_style(CursorStyle::PointingHand)
8792        .on_click(MouseButton::Left, move |_, _, cx| {
8793            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8794        })
8795        // We really need to rethink this ID system...
8796        .with_tooltip::<BlockContextToolip>(
8797            cx.block_id,
8798            "Copy diagnostic message",
8799            None,
8800            tooltip_style,
8801            cx,
8802        )
8803        .into_any()
8804    })
8805}
8806
8807pub fn highlight_diagnostic_message(
8808    initial_highlights: Vec<usize>,
8809    message: &str,
8810) -> (String, Vec<usize>) {
8811    let mut message_without_backticks = String::new();
8812    let mut prev_offset = 0;
8813    let mut inside_block = false;
8814    let mut highlights = initial_highlights;
8815    for (match_ix, (offset, _)) in message
8816        .match_indices('`')
8817        .chain([(message.len(), "")])
8818        .enumerate()
8819    {
8820        message_without_backticks.push_str(&message[prev_offset..offset]);
8821        if inside_block {
8822            highlights.extend(prev_offset - match_ix..offset - match_ix);
8823        }
8824
8825        inside_block = !inside_block;
8826        prev_offset = offset + 1;
8827    }
8828
8829    (message_without_backticks, highlights)
8830}
8831
8832pub fn diagnostic_style(
8833    severity: DiagnosticSeverity,
8834    valid: bool,
8835    theme: &theme::Editor,
8836) -> DiagnosticStyle {
8837    match (severity, valid) {
8838        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8839        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8840        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8841        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8842        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8843        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8844        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8845        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8846        _ => theme.invalid_hint_diagnostic.clone(),
8847    }
8848}
8849
8850pub fn combine_syntax_and_fuzzy_match_highlights(
8851    text: &str,
8852    default_style: HighlightStyle,
8853    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8854    match_indices: &[usize],
8855) -> Vec<(Range<usize>, HighlightStyle)> {
8856    let mut result = Vec::new();
8857    let mut match_indices = match_indices.iter().copied().peekable();
8858
8859    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8860    {
8861        syntax_highlight.weight = None;
8862
8863        // Add highlights for any fuzzy match characters before the next
8864        // syntax highlight range.
8865        while let Some(&match_index) = match_indices.peek() {
8866            if match_index >= range.start {
8867                break;
8868            }
8869            match_indices.next();
8870            let end_index = char_ix_after(match_index, text);
8871            let mut match_style = default_style;
8872            match_style.weight = Some(fonts::Weight::BOLD);
8873            result.push((match_index..end_index, match_style));
8874        }
8875
8876        if range.start == usize::MAX {
8877            break;
8878        }
8879
8880        // Add highlights for any fuzzy match characters within the
8881        // syntax highlight range.
8882        let mut offset = range.start;
8883        while let Some(&match_index) = match_indices.peek() {
8884            if match_index >= range.end {
8885                break;
8886            }
8887
8888            match_indices.next();
8889            if match_index > offset {
8890                result.push((offset..match_index, syntax_highlight));
8891            }
8892
8893            let mut end_index = char_ix_after(match_index, text);
8894            while let Some(&next_match_index) = match_indices.peek() {
8895                if next_match_index == end_index && next_match_index < range.end {
8896                    end_index = char_ix_after(next_match_index, text);
8897                    match_indices.next();
8898                } else {
8899                    break;
8900                }
8901            }
8902
8903            let mut match_style = syntax_highlight;
8904            match_style.weight = Some(fonts::Weight::BOLD);
8905            result.push((match_index..end_index, match_style));
8906            offset = end_index;
8907        }
8908
8909        if offset < range.end {
8910            result.push((offset..range.end, syntax_highlight));
8911        }
8912    }
8913
8914    fn char_ix_after(ix: usize, text: &str) -> usize {
8915        ix + text[ix..].chars().next().unwrap().len_utf8()
8916    }
8917
8918    result
8919}
8920
8921pub fn styled_runs_for_code_label<'a>(
8922    label: &'a CodeLabel,
8923    syntax_theme: &'a theme::SyntaxTheme,
8924) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8925    let fade_out = HighlightStyle {
8926        fade_out: Some(0.35),
8927        ..Default::default()
8928    };
8929
8930    let mut prev_end = label.filter_range.end;
8931    label
8932        .runs
8933        .iter()
8934        .enumerate()
8935        .flat_map(move |(ix, (range, highlight_id))| {
8936            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8937                style
8938            } else {
8939                return Default::default();
8940            };
8941            let mut muted_style = style;
8942            muted_style.highlight(fade_out);
8943
8944            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8945            if range.start >= label.filter_range.end {
8946                if range.start > prev_end {
8947                    runs.push((prev_end..range.start, fade_out));
8948                }
8949                runs.push((range.clone(), muted_style));
8950            } else if range.end <= label.filter_range.end {
8951                runs.push((range.clone(), style));
8952            } else {
8953                runs.push((range.start..label.filter_range.end, style));
8954                runs.push((label.filter_range.end..range.end, muted_style));
8955            }
8956            prev_end = cmp::max(prev_end, range.end);
8957
8958            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8959                runs.push((prev_end..label.text.len(), fade_out));
8960            }
8961
8962            runs
8963        })
8964}
8965
8966pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8967    let mut index = 0;
8968    let mut codepoints = text.char_indices().peekable();
8969
8970    std::iter::from_fn(move || {
8971        let start_index = index;
8972        while let Some((new_index, codepoint)) = codepoints.next() {
8973            index = new_index + codepoint.len_utf8();
8974            let current_upper = codepoint.is_uppercase();
8975            let next_upper = codepoints
8976                .peek()
8977                .map(|(_, c)| c.is_uppercase())
8978                .unwrap_or(false);
8979
8980            if !current_upper && next_upper {
8981                return Some(&text[start_index..index]);
8982            }
8983        }
8984
8985        index = text.len();
8986        if start_index < text.len() {
8987            return Some(&text[start_index..]);
8988        }
8989        None
8990    })
8991    .flat_map(|word| word.split_inclusive('_'))
8992}
8993
8994trait RangeToAnchorExt {
8995    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8996}
8997
8998impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8999    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9000        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9001    }
9002}