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