editor.rs

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