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