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