editor.rs

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