editor.rs

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