editor.rs

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