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