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