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