editor.rs

   1mod blink_manager;
   2pub mod display_map;
   3mod element;
   4
   5mod git;
   6mod highlight_matching_bracket;
   7mod hover_popover;
   8pub mod items;
   9mod link_go_to_definition;
  10mod mouse_context_menu;
  11pub mod movement;
  12mod multi_buffer;
  13mod persistence;
  14pub mod scroll;
  15pub mod selections_collection;
  16
  17#[cfg(test)]
  18mod editor_tests;
  19#[cfg(any(test, feature = "test-support"))]
  20pub mod test;
  21
  22use aho_corasick::AhoCorasick;
  23use anyhow::{anyhow, Result};
  24use blink_manager::BlinkManager;
  25use clock::ReplicaId;
  26use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  27use copilot::Copilot;
  28pub use display_map::DisplayPoint;
  29use display_map::*;
  30pub use element::*;
  31use futures::FutureExt;
  32use fuzzy::{StringMatch, StringMatchCandidate};
  33use gpui::{
  34    actions,
  35    color::Color,
  36    elements::*,
  37    executor,
  38    fonts::{self, HighlightStyle, TextStyle},
  39    geometry::vector::Vector2F,
  40    impl_actions,
  41    keymap_matcher::KeymapContext,
  42    platform::{CursorStyle, MouseButton},
  43    serde_json::{self, json},
  44    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  45    ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
  46};
  47use highlight_matching_bracket::refresh_matching_bracket_highlights;
  48use hover_popover::{hide_hover, HoverState};
  49pub use items::MAX_TAB_TITLE_LEN;
  50use itertools::Itertools;
  51pub use language::{char_kind, CharKind};
  52use language::{
  53    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  54    Diagnostic, DiagnosticSeverity, IndentKind, IndentSize, Language, OffsetRangeExt, OffsetUtf16,
  55    Point, Selection, SelectionGoal, TransactionId,
  56};
  57use link_go_to_definition::{
  58    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  59};
  60pub use multi_buffer::{
  61    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  62    ToPoint,
  63};
  64use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  65use ordered_float::OrderedFloat;
  66use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  67use scroll::{
  68    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  69};
  70use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  71use serde::{Deserialize, Serialize};
  72use settings::Settings;
  73use smallvec::SmallVec;
  74use snippet::Snippet;
  75use std::{
  76    any::TypeId,
  77    borrow::Cow,
  78    cmp::{self, Ordering, Reverse},
  79    mem,
  80    num::NonZeroU32,
  81    ops::{Deref, DerefMut, Range},
  82    path::Path,
  83    sync::Arc,
  84    time::{Duration, Instant},
  85};
  86pub use sum_tree::Bias;
  87use theme::{DiagnosticStyle, Theme};
  88use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  89use workspace::{ItemNavHistory, ViewId, Workspace};
  90
  91use crate::git::diff_hunk_to_display;
  92
  93const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  94const MAX_LINE_LEN: usize = 1024;
  95const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  96const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  97const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  98
  99pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 100
 101#[derive(Clone, Deserialize, PartialEq, Default)]
 102pub struct SelectNext {
 103    #[serde(default)]
 104    pub replace_newest: bool,
 105}
 106
 107#[derive(Clone, Deserialize, PartialEq)]
 108pub struct SelectToBeginningOfLine {
 109    #[serde(default)]
 110    stop_at_soft_wraps: bool,
 111}
 112
 113#[derive(Clone, Default, Deserialize, PartialEq)]
 114pub struct MovePageUp {
 115    #[serde(default)]
 116    center_cursor: bool,
 117}
 118
 119#[derive(Clone, Default, Deserialize, PartialEq)]
 120pub struct MovePageDown {
 121    #[serde(default)]
 122    center_cursor: bool,
 123}
 124
 125#[derive(Clone, Deserialize, PartialEq)]
 126pub struct SelectToEndOfLine {
 127    #[serde(default)]
 128    stop_at_soft_wraps: bool,
 129}
 130
 131#[derive(Clone, Deserialize, PartialEq)]
 132pub struct ToggleCodeActions {
 133    #[serde(default)]
 134    pub deployed_from_indicator: bool,
 135}
 136
 137#[derive(Clone, Default, Deserialize, PartialEq)]
 138pub struct ConfirmCompletion {
 139    #[serde(default)]
 140    pub item_ix: Option<usize>,
 141}
 142
 143#[derive(Clone, Default, Deserialize, PartialEq)]
 144pub struct ConfirmCodeAction {
 145    #[serde(default)]
 146    pub item_ix: Option<usize>,
 147}
 148
 149#[derive(Clone, Default, Deserialize, PartialEq)]
 150pub struct ToggleComments {
 151    #[serde(default)]
 152    pub advance_downwards: bool,
 153}
 154
 155#[derive(Clone, Default, Deserialize, PartialEq)]
 156pub struct FoldAt {
 157    pub buffer_row: u32,
 158}
 159
 160#[derive(Clone, Default, Deserialize, PartialEq)]
 161pub struct UnfoldAt {
 162    pub buffer_row: u32,
 163}
 164
 165#[derive(Clone, Default, Deserialize, PartialEq)]
 166pub struct GutterHover {
 167    pub hovered: bool,
 168}
 169
 170actions!(
 171    editor,
 172    [
 173        Cancel,
 174        Backspace,
 175        Delete,
 176        Newline,
 177        NewlineAbove,
 178        NewlineBelow,
 179        GoToDiagnostic,
 180        GoToPrevDiagnostic,
 181        GoToHunk,
 182        GoToPrevHunk,
 183        Indent,
 184        Outdent,
 185        DeleteLine,
 186        DeleteToPreviousWordStart,
 187        DeleteToPreviousSubwordStart,
 188        DeleteToNextWordEnd,
 189        DeleteToNextSubwordEnd,
 190        DeleteToBeginningOfLine,
 191        DeleteToEndOfLine,
 192        CutToEndOfLine,
 193        DuplicateLine,
 194        MoveLineUp,
 195        MoveLineDown,
 196        Transpose,
 197        Cut,
 198        Copy,
 199        Paste,
 200        Undo,
 201        Redo,
 202        MoveUp,
 203        PageUp,
 204        MoveDown,
 205        PageDown,
 206        MoveLeft,
 207        MoveRight,
 208        MoveToPreviousWordStart,
 209        MoveToPreviousSubwordStart,
 210        MoveToNextWordEnd,
 211        MoveToNextSubwordEnd,
 212        MoveToBeginningOfLine,
 213        MoveToEndOfLine,
 214        MoveToBeginning,
 215        MoveToEnd,
 216        SelectUp,
 217        SelectDown,
 218        SelectLeft,
 219        SelectRight,
 220        SelectToPreviousWordStart,
 221        SelectToPreviousSubwordStart,
 222        SelectToNextWordEnd,
 223        SelectToNextSubwordEnd,
 224        SelectToBeginning,
 225        SelectToEnd,
 226        SelectAll,
 227        SelectLine,
 228        SplitSelectionIntoLines,
 229        AddSelectionAbove,
 230        AddSelectionBelow,
 231        Tab,
 232        TabPrev,
 233        ShowCharacterPalette,
 234        SelectLargerSyntaxNode,
 235        SelectSmallerSyntaxNode,
 236        GoToDefinition,
 237        GoToTypeDefinition,
 238        MoveToEnclosingBracket,
 239        UndoSelection,
 240        RedoSelection,
 241        FindAllReferences,
 242        Rename,
 243        ConfirmRename,
 244        Fold,
 245        UnfoldLines,
 246        FoldSelectedRanges,
 247        ShowCompletions,
 248        OpenExcerpts,
 249        RestartLanguageServer,
 250        Hover,
 251        Format,
 252        ToggleSoftWrap,
 253        RevealInFinder,
 254        CopyPath,
 255        CopyRelativePath,
 256        CopyHighlightJson
 257    ]
 258);
 259
 260impl_actions!(
 261    editor,
 262    [
 263        SelectNext,
 264        SelectToBeginningOfLine,
 265        SelectToEndOfLine,
 266        ToggleCodeActions,
 267        MovePageUp,
 268        MovePageDown,
 269        ConfirmCompletion,
 270        ConfirmCodeAction,
 271        ToggleComments,
 272        FoldAt,
 273        UnfoldAt,
 274        GutterHover
 275    ]
 276);
 277
 278enum DocumentHighlightRead {}
 279enum DocumentHighlightWrite {}
 280enum InputComposition {}
 281
 282#[derive(Copy, Clone, PartialEq, Eq)]
 283pub enum Direction {
 284    Prev,
 285    Next,
 286}
 287
 288pub fn init(cx: &mut AppContext) {
 289    cx.add_action(Editor::new_file);
 290    cx.add_action(Editor::cancel);
 291    cx.add_action(Editor::newline);
 292    cx.add_action(Editor::newline_above);
 293    cx.add_action(Editor::newline_below);
 294    cx.add_action(Editor::backspace);
 295    cx.add_action(Editor::delete);
 296    cx.add_action(Editor::tab);
 297    cx.add_action(Editor::tab_prev);
 298    cx.add_action(Editor::indent);
 299    cx.add_action(Editor::outdent);
 300    cx.add_action(Editor::delete_line);
 301    cx.add_action(Editor::delete_to_previous_word_start);
 302    cx.add_action(Editor::delete_to_previous_subword_start);
 303    cx.add_action(Editor::delete_to_next_word_end);
 304    cx.add_action(Editor::delete_to_next_subword_end);
 305    cx.add_action(Editor::delete_to_beginning_of_line);
 306    cx.add_action(Editor::delete_to_end_of_line);
 307    cx.add_action(Editor::cut_to_end_of_line);
 308    cx.add_action(Editor::duplicate_line);
 309    cx.add_action(Editor::move_line_up);
 310    cx.add_action(Editor::move_line_down);
 311    cx.add_action(Editor::transpose);
 312    cx.add_action(Editor::cut);
 313    cx.add_action(Editor::copy);
 314    cx.add_action(Editor::paste);
 315    cx.add_action(Editor::undo);
 316    cx.add_action(Editor::redo);
 317    cx.add_action(Editor::move_up);
 318    cx.add_action(Editor::move_page_up);
 319    cx.add_action(Editor::move_down);
 320    cx.add_action(Editor::move_page_down);
 321    cx.add_action(Editor::next_screen);
 322    cx.add_action(Editor::move_left);
 323    cx.add_action(Editor::move_right);
 324    cx.add_action(Editor::move_to_previous_word_start);
 325    cx.add_action(Editor::move_to_previous_subword_start);
 326    cx.add_action(Editor::move_to_next_word_end);
 327    cx.add_action(Editor::move_to_next_subword_end);
 328    cx.add_action(Editor::move_to_beginning_of_line);
 329    cx.add_action(Editor::move_to_end_of_line);
 330    cx.add_action(Editor::move_to_beginning);
 331    cx.add_action(Editor::move_to_end);
 332    cx.add_action(Editor::select_up);
 333    cx.add_action(Editor::select_down);
 334    cx.add_action(Editor::select_left);
 335    cx.add_action(Editor::select_right);
 336    cx.add_action(Editor::select_to_previous_word_start);
 337    cx.add_action(Editor::select_to_previous_subword_start);
 338    cx.add_action(Editor::select_to_next_word_end);
 339    cx.add_action(Editor::select_to_next_subword_end);
 340    cx.add_action(Editor::select_to_beginning_of_line);
 341    cx.add_action(Editor::select_to_end_of_line);
 342    cx.add_action(Editor::select_to_beginning);
 343    cx.add_action(Editor::select_to_end);
 344    cx.add_action(Editor::select_all);
 345    cx.add_action(Editor::select_line);
 346    cx.add_action(Editor::split_selection_into_lines);
 347    cx.add_action(Editor::add_selection_above);
 348    cx.add_action(Editor::add_selection_below);
 349    cx.add_action(Editor::select_next);
 350    cx.add_action(Editor::toggle_comments);
 351    cx.add_action(Editor::select_larger_syntax_node);
 352    cx.add_action(Editor::select_smaller_syntax_node);
 353    cx.add_action(Editor::move_to_enclosing_bracket);
 354    cx.add_action(Editor::undo_selection);
 355    cx.add_action(Editor::redo_selection);
 356    cx.add_action(Editor::go_to_diagnostic);
 357    cx.add_action(Editor::go_to_prev_diagnostic);
 358    cx.add_action(Editor::go_to_hunk);
 359    cx.add_action(Editor::go_to_prev_hunk);
 360    cx.add_action(Editor::go_to_definition);
 361    cx.add_action(Editor::go_to_type_definition);
 362    cx.add_action(Editor::fold);
 363    cx.add_action(Editor::fold_at);
 364    cx.add_action(Editor::unfold_lines);
 365    cx.add_action(Editor::unfold_at);
 366    cx.add_action(Editor::gutter_hover);
 367    cx.add_action(Editor::fold_selected_ranges);
 368    cx.add_action(Editor::show_completions);
 369    cx.add_action(Editor::toggle_code_actions);
 370    cx.add_action(Editor::open_excerpts);
 371    cx.add_action(Editor::toggle_soft_wrap);
 372    cx.add_action(Editor::reveal_in_finder);
 373    cx.add_action(Editor::copy_path);
 374    cx.add_action(Editor::copy_relative_path);
 375    cx.add_action(Editor::copy_highlight_json);
 376    cx.add_async_action(Editor::format);
 377    cx.add_action(Editor::restart_language_server);
 378    cx.add_action(Editor::show_character_palette);
 379    cx.add_async_action(Editor::confirm_completion);
 380    cx.add_async_action(Editor::confirm_code_action);
 381    cx.add_async_action(Editor::rename);
 382    cx.add_async_action(Editor::confirm_rename);
 383    cx.add_async_action(Editor::find_all_references);
 384    cx.add_action(Editor::next_copilot_suggestion);
 385    cx.add_action(Editor::previous_copilot_suggestion);
 386    cx.add_action(Editor::copilot_suggest);
 387
 388    hover_popover::init(cx);
 389    scroll::actions::init(cx);
 390
 391    workspace::register_project_item::<Editor>(cx);
 392    workspace::register_followable_item::<Editor>(cx);
 393    workspace::register_deserializable_item::<Editor>(cx);
 394}
 395
 396trait InvalidationRegion {
 397    fn ranges(&self) -> &[Range<Anchor>];
 398}
 399
 400#[derive(Clone, Debug, PartialEq)]
 401pub enum SelectPhase {
 402    Begin {
 403        position: DisplayPoint,
 404        add: bool,
 405        click_count: usize,
 406    },
 407    BeginColumnar {
 408        position: DisplayPoint,
 409        goal_column: u32,
 410    },
 411    Extend {
 412        position: DisplayPoint,
 413        click_count: usize,
 414    },
 415    Update {
 416        position: DisplayPoint,
 417        goal_column: u32,
 418        scroll_position: Vector2F,
 419    },
 420    End,
 421}
 422
 423#[derive(Clone, Debug)]
 424pub enum SelectMode {
 425    Character,
 426    Word(Range<Anchor>),
 427    Line(Range<Anchor>),
 428    All,
 429}
 430
 431#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 432pub enum EditorMode {
 433    SingleLine,
 434    AutoHeight { max_lines: usize },
 435    Full,
 436}
 437
 438#[derive(Clone)]
 439pub enum SoftWrap {
 440    None,
 441    EditorWidth,
 442    Column(u32),
 443}
 444
 445#[derive(Clone)]
 446pub struct EditorStyle {
 447    pub text: TextStyle,
 448    pub placeholder_text: Option<TextStyle>,
 449    pub theme: theme::Editor,
 450    pub theme_id: usize,
 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        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
2929            self.clear_copilot_suggestions(cx);
2930            return None;
2931        }
2932
2933        let (buffer, buffer_position) =
2934            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
2935        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
2936            if debounce {
2937                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
2938            }
2939
2940            let completions = copilot
2941                .update(&mut cx, |copilot, cx| {
2942                    copilot.completions(&buffer, buffer_position, cx)
2943                })
2944                .await
2945                .log_err()
2946                .into_iter()
2947                .flatten()
2948                .collect_vec();
2949
2950            this.update(&mut cx, |this, cx| {
2951                if !completions.is_empty() {
2952                    this.copilot_state.cycled = false;
2953                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
2954                    this.copilot_state.completions.clear();
2955                    this.copilot_state.active_completion_index = 0;
2956                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
2957                    for completion in completions {
2958                        this.copilot_state.push_completion(completion);
2959                    }
2960                    this.update_visible_copilot_suggestion(cx);
2961                }
2962            })
2963            .log_err()?;
2964            Some(())
2965        });
2966
2967        Some(())
2968    }
2969
2970    fn cycle_copilot_suggestions(
2971        &mut self,
2972        direction: Direction,
2973        cx: &mut ViewContext<Self>,
2974    ) -> Option<()> {
2975        let copilot = Copilot::global(cx)?;
2976        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
2977            return None;
2978        }
2979
2980        if self.copilot_state.cycled {
2981            self.copilot_state.cycle_completions(direction);
2982            self.update_visible_copilot_suggestion(cx);
2983        } else {
2984            let cursor = self.selections.newest_anchor().head();
2985            let (buffer, buffer_position) =
2986                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
2987            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
2988                let completions = copilot
2989                    .update(&mut cx, |copilot, cx| {
2990                        copilot.completions_cycling(&buffer, buffer_position, cx)
2991                    })
2992                    .await;
2993
2994                this.update(&mut cx, |this, cx| {
2995                    this.copilot_state.cycled = true;
2996                    for completion in completions.log_err().into_iter().flatten() {
2997                        this.copilot_state.push_completion(completion);
2998                    }
2999                    this.copilot_state.cycle_completions(direction);
3000                    this.update_visible_copilot_suggestion(cx);
3001                })
3002                .log_err()?;
3003
3004                Some(())
3005            });
3006        }
3007
3008        Some(())
3009    }
3010
3011    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3012        if !self.has_active_copilot_suggestion(cx) {
3013            self.refresh_copilot_suggestions(false, cx);
3014            return;
3015        }
3016
3017        self.update_visible_copilot_suggestion(cx);
3018    }
3019
3020    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3021        if self.has_active_copilot_suggestion(cx) {
3022            self.cycle_copilot_suggestions(Direction::Next, cx);
3023        } else {
3024            self.refresh_copilot_suggestions(false, cx);
3025        }
3026    }
3027
3028    fn previous_copilot_suggestion(
3029        &mut self,
3030        _: &copilot::PreviousSuggestion,
3031        cx: &mut ViewContext<Self>,
3032    ) {
3033        if self.has_active_copilot_suggestion(cx) {
3034            self.cycle_copilot_suggestions(Direction::Prev, cx);
3035        } else {
3036            self.refresh_copilot_suggestions(false, cx);
3037        }
3038    }
3039
3040    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3041        if let Some(suggestion) = self
3042            .display_map
3043            .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx))
3044        {
3045            if let Some((copilot, completion)) =
3046                Copilot::global(cx).zip(self.copilot_state.active_completion())
3047            {
3048                copilot
3049                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3050                    .detach_and_log_err(cx);
3051            }
3052            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3053            cx.notify();
3054            true
3055        } else {
3056            false
3057        }
3058    }
3059
3060    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3061        if self.has_active_copilot_suggestion(cx) {
3062            if let Some(copilot) = Copilot::global(cx) {
3063                copilot
3064                    .update(cx, |copilot, cx| {
3065                        copilot.discard_completions(&self.copilot_state.completions, cx)
3066                    })
3067                    .detach_and_log_err(cx);
3068            }
3069
3070            self.display_map
3071                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
3072            cx.notify();
3073            true
3074        } else {
3075            false
3076        }
3077    }
3078
3079    fn is_copilot_enabled_at(
3080        &self,
3081        location: Anchor,
3082        snapshot: &MultiBufferSnapshot,
3083        cx: &mut ViewContext<Self>,
3084    ) -> bool {
3085        let settings = cx.global::<Settings>();
3086
3087        let language_name = snapshot
3088            .language_at(location)
3089            .map(|language| language.name());
3090        if !settings.show_copilot_suggestions(language_name.as_deref()) {
3091            return false;
3092        }
3093
3094        let file = snapshot.file_at(location);
3095        if let Some(file) = file {
3096            let path = file.path();
3097            if settings
3098                .copilot
3099                .disabled_globs
3100                .iter()
3101                .any(|glob| glob.matches_path(path))
3102            {
3103                return false;
3104            }
3105        }
3106
3107        true
3108    }
3109
3110    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3111        self.display_map.read(cx).has_suggestion()
3112    }
3113
3114    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3115        let snapshot = self.buffer.read(cx).snapshot(cx);
3116        let selection = self.selections.newest_anchor();
3117        let cursor = selection.head();
3118
3119        if self.context_menu.is_some()
3120            || !self.completion_tasks.is_empty()
3121            || selection.start != selection.end
3122        {
3123            self.discard_copilot_suggestion(cx);
3124        } else if let Some(text) = self
3125            .copilot_state
3126            .text_for_active_completion(cursor, &snapshot)
3127        {
3128            self.display_map.update(cx, move |map, cx| {
3129                map.replace_suggestion(
3130                    Some(Suggestion {
3131                        position: cursor,
3132                        text: text.trim_end().into(),
3133                    }),
3134                    cx,
3135                )
3136            });
3137            cx.notify();
3138        } else {
3139            self.discard_copilot_suggestion(cx);
3140        }
3141    }
3142
3143    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3144        self.copilot_state = Default::default();
3145        self.discard_copilot_suggestion(cx);
3146    }
3147
3148    pub fn render_code_actions_indicator(
3149        &self,
3150        style: &EditorStyle,
3151        active: bool,
3152        cx: &mut ViewContext<Self>,
3153    ) -> Option<AnyElement<Self>> {
3154        if self.available_code_actions.is_some() {
3155            enum CodeActions {}
3156            Some(
3157                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3158                    Svg::new("icons/bolt_8.svg")
3159                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3160                })
3161                .with_cursor_style(CursorStyle::PointingHand)
3162                .with_padding(Padding::uniform(3.))
3163                .on_down(MouseButton::Left, |_, _, cx| {
3164                    cx.dispatch_action(ToggleCodeActions {
3165                        deployed_from_indicator: true,
3166                    });
3167                })
3168                .into_any(),
3169            )
3170        } else {
3171            None
3172        }
3173    }
3174
3175    pub fn render_fold_indicators(
3176        &self,
3177        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3178        style: &EditorStyle,
3179        gutter_hovered: bool,
3180        line_height: f32,
3181        gutter_margin: f32,
3182        cx: &mut ViewContext<Self>,
3183    ) -> Vec<Option<AnyElement<Self>>> {
3184        enum FoldIndicators {}
3185
3186        let style = style.folds.clone();
3187
3188        fold_data
3189            .iter()
3190            .enumerate()
3191            .map(|(ix, fold_data)| {
3192                fold_data
3193                    .map(|(fold_status, buffer_row, active)| {
3194                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3195                            MouseEventHandler::<FoldIndicators, _>::new(
3196                                ix as usize,
3197                                cx,
3198                                |mouse_state, _| {
3199                                    Svg::new(match fold_status {
3200                                        FoldStatus::Folded => style.folded_icon.clone(),
3201                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3202                                    })
3203                                    .with_color(
3204                                        style
3205                                            .indicator
3206                                            .style_for(
3207                                                mouse_state,
3208                                                fold_status == FoldStatus::Folded,
3209                                            )
3210                                            .color,
3211                                    )
3212                                    .constrained()
3213                                    .with_width(gutter_margin * style.icon_margin_scale)
3214                                    .aligned()
3215                                    .constrained()
3216                                    .with_height(line_height)
3217                                    .with_width(gutter_margin)
3218                                    .aligned()
3219                                },
3220                            )
3221                            .with_cursor_style(CursorStyle::PointingHand)
3222                            .with_padding(Padding::uniform(3.))
3223                            .on_click(MouseButton::Left, {
3224                                move |_, _, cx| {
3225                                    cx.dispatch_any_action(match fold_status {
3226                                        FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
3227                                        FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
3228                                    });
3229                                }
3230                            })
3231                            .into_any()
3232                        })
3233                    })
3234                    .flatten()
3235            })
3236            .collect()
3237    }
3238
3239    pub fn context_menu_visible(&self) -> bool {
3240        self.context_menu
3241            .as_ref()
3242            .map_or(false, |menu| menu.visible())
3243    }
3244
3245    pub fn render_context_menu(
3246        &self,
3247        cursor_position: DisplayPoint,
3248        style: EditorStyle,
3249        cx: &mut ViewContext<Editor>,
3250    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3251        self.context_menu
3252            .as_ref()
3253            .map(|menu| menu.render(cursor_position, style, cx))
3254    }
3255
3256    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3257        if !matches!(menu, ContextMenu::Completions(_)) {
3258            self.completion_tasks.clear();
3259        }
3260        self.context_menu = Some(menu);
3261        self.discard_copilot_suggestion(cx);
3262        cx.notify();
3263    }
3264
3265    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3266        cx.notify();
3267        self.completion_tasks.clear();
3268        let context_menu = self.context_menu.take();
3269        if context_menu.is_some() {
3270            self.update_visible_copilot_suggestion(cx);
3271        }
3272        context_menu
3273    }
3274
3275    pub fn insert_snippet(
3276        &mut self,
3277        insertion_ranges: &[Range<usize>],
3278        snippet: Snippet,
3279        cx: &mut ViewContext<Self>,
3280    ) -> Result<()> {
3281        let tabstops = self.buffer.update(cx, |buffer, cx| {
3282            let snippet_text: Arc<str> = snippet.text.clone().into();
3283            buffer.edit(
3284                insertion_ranges
3285                    .iter()
3286                    .cloned()
3287                    .map(|range| (range, snippet_text.clone())),
3288                Some(AutoindentMode::EachLine),
3289                cx,
3290            );
3291
3292            let snapshot = &*buffer.read(cx);
3293            let snippet = &snippet;
3294            snippet
3295                .tabstops
3296                .iter()
3297                .map(|tabstop| {
3298                    let mut tabstop_ranges = tabstop
3299                        .iter()
3300                        .flat_map(|tabstop_range| {
3301                            let mut delta = 0_isize;
3302                            insertion_ranges.iter().map(move |insertion_range| {
3303                                let insertion_start = insertion_range.start as isize + delta;
3304                                delta +=
3305                                    snippet.text.len() as isize - insertion_range.len() as isize;
3306
3307                                let start = snapshot.anchor_before(
3308                                    (insertion_start + tabstop_range.start) as usize,
3309                                );
3310                                let end = snapshot
3311                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3312                                start..end
3313                            })
3314                        })
3315                        .collect::<Vec<_>>();
3316                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3317                    tabstop_ranges
3318                })
3319                .collect::<Vec<_>>()
3320        });
3321
3322        if let Some(tabstop) = tabstops.first() {
3323            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3324                s.select_ranges(tabstop.iter().cloned());
3325            });
3326            self.snippet_stack.push(SnippetState {
3327                active_index: 0,
3328                ranges: tabstops,
3329            });
3330        }
3331
3332        Ok(())
3333    }
3334
3335    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3336        self.move_to_snippet_tabstop(Bias::Right, cx)
3337    }
3338
3339    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3340        self.move_to_snippet_tabstop(Bias::Left, cx)
3341    }
3342
3343    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3344        if let Some(mut snippet) = self.snippet_stack.pop() {
3345            match bias {
3346                Bias::Left => {
3347                    if snippet.active_index > 0 {
3348                        snippet.active_index -= 1;
3349                    } else {
3350                        self.snippet_stack.push(snippet);
3351                        return false;
3352                    }
3353                }
3354                Bias::Right => {
3355                    if snippet.active_index + 1 < snippet.ranges.len() {
3356                        snippet.active_index += 1;
3357                    } else {
3358                        self.snippet_stack.push(snippet);
3359                        return false;
3360                    }
3361                }
3362            }
3363            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3364                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3365                    s.select_anchor_ranges(current_ranges.iter().cloned())
3366                });
3367                // If snippet state is not at the last tabstop, push it back on the stack
3368                if snippet.active_index + 1 < snippet.ranges.len() {
3369                    self.snippet_stack.push(snippet);
3370                }
3371                return true;
3372            }
3373        }
3374
3375        false
3376    }
3377
3378    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3379        self.transact(cx, |this, cx| {
3380            this.select_all(&SelectAll, cx);
3381            this.insert("", cx);
3382        });
3383    }
3384
3385    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3386        self.transact(cx, |this, cx| {
3387            this.select_autoclose_pair(cx);
3388            let mut selections = this.selections.all::<Point>(cx);
3389            if !this.selections.line_mode {
3390                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3391                for selection in &mut selections {
3392                    if selection.is_empty() {
3393                        let old_head = selection.head();
3394                        let mut new_head =
3395                            movement::left(&display_map, old_head.to_display_point(&display_map))
3396                                .to_point(&display_map);
3397                        if let Some((buffer, line_buffer_range)) = display_map
3398                            .buffer_snapshot
3399                            .buffer_line_for_row(old_head.row)
3400                        {
3401                            let indent_size =
3402                                buffer.indent_size_for_line(line_buffer_range.start.row);
3403                            let language_name = buffer
3404                                .language_at(line_buffer_range.start)
3405                                .map(|language| language.name());
3406                            let indent_len = match indent_size.kind {
3407                                IndentKind::Space => {
3408                                    cx.global::<Settings>().tab_size(language_name.as_deref())
3409                                }
3410                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3411                            };
3412                            if old_head.column <= indent_size.len && old_head.column > 0 {
3413                                let indent_len = indent_len.get();
3414                                new_head = cmp::min(
3415                                    new_head,
3416                                    Point::new(
3417                                        old_head.row,
3418                                        ((old_head.column - 1) / indent_len) * indent_len,
3419                                    ),
3420                                );
3421                            }
3422                        }
3423
3424                        selection.set_head(new_head, SelectionGoal::None);
3425                    }
3426                }
3427            }
3428
3429            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3430            this.insert("", cx);
3431            this.refresh_copilot_suggestions(true, cx);
3432        });
3433    }
3434
3435    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3436        self.transact(cx, |this, cx| {
3437            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3438                let line_mode = s.line_mode;
3439                s.move_with(|map, selection| {
3440                    if selection.is_empty() && !line_mode {
3441                        let cursor = movement::right(map, selection.head());
3442                        selection.set_head(cursor, SelectionGoal::None);
3443                    }
3444                })
3445            });
3446            this.insert("", cx);
3447            this.refresh_copilot_suggestions(true, cx);
3448        });
3449    }
3450
3451    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3452        if self.move_to_prev_snippet_tabstop(cx) {
3453            return;
3454        }
3455
3456        self.outdent(&Outdent, cx);
3457    }
3458
3459    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3460        if self.move_to_next_snippet_tabstop(cx) {
3461            return;
3462        }
3463
3464        let mut selections = self.selections.all_adjusted(cx);
3465        let buffer = self.buffer.read(cx);
3466        let snapshot = buffer.snapshot(cx);
3467        let rows_iter = selections.iter().map(|s| s.head().row);
3468        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3469
3470        let mut edits = Vec::new();
3471        let mut prev_edited_row = 0;
3472        let mut row_delta = 0;
3473        for selection in &mut selections {
3474            if selection.start.row != prev_edited_row {
3475                row_delta = 0;
3476            }
3477            prev_edited_row = selection.end.row;
3478
3479            // If the selection is non-empty, then increase the indentation of the selected lines.
3480            if !selection.is_empty() {
3481                row_delta =
3482                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3483                continue;
3484            }
3485
3486            // If the selection is empty and the cursor is in the leading whitespace before the
3487            // suggested indentation, then auto-indent the line.
3488            let cursor = selection.head();
3489            let current_indent = snapshot.indent_size_for_line(cursor.row);
3490            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3491                if cursor.column < suggested_indent.len
3492                    && cursor.column <= current_indent.len
3493                    && current_indent.len <= suggested_indent.len
3494                {
3495                    selection.start = Point::new(cursor.row, suggested_indent.len);
3496                    selection.end = selection.start;
3497                    if row_delta == 0 {
3498                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3499                            cursor.row,
3500                            current_indent,
3501                            suggested_indent,
3502                        ));
3503                        row_delta = suggested_indent.len - current_indent.len;
3504                    }
3505                    continue;
3506                }
3507            }
3508
3509            // Accept copilot suggestion if there is only one selection and the cursor is not
3510            // in the leading whitespace.
3511            if self.selections.count() == 1
3512                && cursor.column >= current_indent.len
3513                && self.has_active_copilot_suggestion(cx)
3514            {
3515                self.accept_copilot_suggestion(cx);
3516                return;
3517            }
3518
3519            // Otherwise, insert a hard or soft tab.
3520            let settings = cx.global::<Settings>();
3521            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3522            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3523                IndentSize::tab()
3524            } else {
3525                let tab_size = settings.tab_size(language_name.as_deref()).get();
3526                let char_column = snapshot
3527                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3528                    .flat_map(str::chars)
3529                    .count()
3530                    + row_delta as usize;
3531                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3532                IndentSize::spaces(chars_to_next_tab_stop)
3533            };
3534            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3535            selection.end = selection.start;
3536            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3537            row_delta += tab_size.len;
3538        }
3539
3540        self.transact(cx, |this, cx| {
3541            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3542            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3543            this.refresh_copilot_suggestions(true, cx);
3544        });
3545    }
3546
3547    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3548        let mut selections = self.selections.all::<Point>(cx);
3549        let mut prev_edited_row = 0;
3550        let mut row_delta = 0;
3551        let mut edits = Vec::new();
3552        let buffer = self.buffer.read(cx);
3553        let snapshot = buffer.snapshot(cx);
3554        for selection in &mut selections {
3555            if selection.start.row != prev_edited_row {
3556                row_delta = 0;
3557            }
3558            prev_edited_row = selection.end.row;
3559
3560            row_delta =
3561                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3562        }
3563
3564        self.transact(cx, |this, cx| {
3565            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3566            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3567        });
3568    }
3569
3570    fn indent_selection(
3571        buffer: &MultiBuffer,
3572        snapshot: &MultiBufferSnapshot,
3573        selection: &mut Selection<Point>,
3574        edits: &mut Vec<(Range<Point>, String)>,
3575        delta_for_start_row: u32,
3576        cx: &AppContext,
3577    ) -> u32 {
3578        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3579        let settings = cx.global::<Settings>();
3580        let tab_size = settings.tab_size(language_name.as_deref()).get();
3581        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3582            IndentKind::Tab
3583        } else {
3584            IndentKind::Space
3585        };
3586        let mut start_row = selection.start.row;
3587        let mut end_row = selection.end.row + 1;
3588
3589        // If a selection ends at the beginning of a line, don't indent
3590        // that last line.
3591        if selection.end.column == 0 {
3592            end_row -= 1;
3593        }
3594
3595        // Avoid re-indenting a row that has already been indented by a
3596        // previous selection, but still update this selection's column
3597        // to reflect that indentation.
3598        if delta_for_start_row > 0 {
3599            start_row += 1;
3600            selection.start.column += delta_for_start_row;
3601            if selection.end.row == selection.start.row {
3602                selection.end.column += delta_for_start_row;
3603            }
3604        }
3605
3606        let mut delta_for_end_row = 0;
3607        for row in start_row..end_row {
3608            let current_indent = snapshot.indent_size_for_line(row);
3609            let indent_delta = match (current_indent.kind, indent_kind) {
3610                (IndentKind::Space, IndentKind::Space) => {
3611                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3612                    IndentSize::spaces(columns_to_next_tab_stop)
3613                }
3614                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3615                (_, IndentKind::Tab) => IndentSize::tab(),
3616            };
3617
3618            let row_start = Point::new(row, 0);
3619            edits.push((
3620                row_start..row_start,
3621                indent_delta.chars().collect::<String>(),
3622            ));
3623
3624            // Update this selection's endpoints to reflect the indentation.
3625            if row == selection.start.row {
3626                selection.start.column += indent_delta.len;
3627            }
3628            if row == selection.end.row {
3629                selection.end.column += indent_delta.len;
3630                delta_for_end_row = indent_delta.len;
3631            }
3632        }
3633
3634        if selection.start.row == selection.end.row {
3635            delta_for_start_row + delta_for_end_row
3636        } else {
3637            delta_for_end_row
3638        }
3639    }
3640
3641    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3642        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3643        let selections = self.selections.all::<Point>(cx);
3644        let mut deletion_ranges = Vec::new();
3645        let mut last_outdent = None;
3646        {
3647            let buffer = self.buffer.read(cx);
3648            let snapshot = buffer.snapshot(cx);
3649            for selection in &selections {
3650                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3651                let tab_size = cx
3652                    .global::<Settings>()
3653                    .tab_size(language_name.as_deref())
3654                    .get();
3655                let mut rows = selection.spanned_rows(false, &display_map);
3656
3657                // Avoid re-outdenting a row that has already been outdented by a
3658                // previous selection.
3659                if let Some(last_row) = last_outdent {
3660                    if last_row == rows.start {
3661                        rows.start += 1;
3662                    }
3663                }
3664
3665                for row in rows {
3666                    let indent_size = snapshot.indent_size_for_line(row);
3667                    if indent_size.len > 0 {
3668                        let deletion_len = match indent_size.kind {
3669                            IndentKind::Space => {
3670                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3671                                if columns_to_prev_tab_stop == 0 {
3672                                    tab_size
3673                                } else {
3674                                    columns_to_prev_tab_stop
3675                                }
3676                            }
3677                            IndentKind::Tab => 1,
3678                        };
3679                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3680                        last_outdent = Some(row);
3681                    }
3682                }
3683            }
3684        }
3685
3686        self.transact(cx, |this, cx| {
3687            this.buffer.update(cx, |buffer, cx| {
3688                let empty_str: Arc<str> = "".into();
3689                buffer.edit(
3690                    deletion_ranges
3691                        .into_iter()
3692                        .map(|range| (range, empty_str.clone())),
3693                    None,
3694                    cx,
3695                );
3696            });
3697            let selections = this.selections.all::<usize>(cx);
3698            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3699        });
3700    }
3701
3702    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3703        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3704        let selections = self.selections.all::<Point>(cx);
3705
3706        let mut new_cursors = Vec::new();
3707        let mut edit_ranges = Vec::new();
3708        let mut selections = selections.iter().peekable();
3709        while let Some(selection) = selections.next() {
3710            let mut rows = selection.spanned_rows(false, &display_map);
3711            let goal_display_column = selection.head().to_display_point(&display_map).column();
3712
3713            // Accumulate contiguous regions of rows that we want to delete.
3714            while let Some(next_selection) = selections.peek() {
3715                let next_rows = next_selection.spanned_rows(false, &display_map);
3716                if next_rows.start <= rows.end {
3717                    rows.end = next_rows.end;
3718                    selections.next().unwrap();
3719                } else {
3720                    break;
3721                }
3722            }
3723
3724            let buffer = &display_map.buffer_snapshot;
3725            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3726            let edit_end;
3727            let cursor_buffer_row;
3728            if buffer.max_point().row >= rows.end {
3729                // If there's a line after the range, delete the \n from the end of the row range
3730                // and position the cursor on the next line.
3731                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3732                cursor_buffer_row = rows.end;
3733            } else {
3734                // If there isn't a line after the range, delete the \n from the line before the
3735                // start of the row range and position the cursor there.
3736                edit_start = edit_start.saturating_sub(1);
3737                edit_end = buffer.len();
3738                cursor_buffer_row = rows.start.saturating_sub(1);
3739            }
3740
3741            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3742            *cursor.column_mut() =
3743                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3744
3745            new_cursors.push((
3746                selection.id,
3747                buffer.anchor_after(cursor.to_point(&display_map)),
3748            ));
3749            edit_ranges.push(edit_start..edit_end);
3750        }
3751
3752        self.transact(cx, |this, cx| {
3753            let buffer = this.buffer.update(cx, |buffer, cx| {
3754                let empty_str: Arc<str> = "".into();
3755                buffer.edit(
3756                    edit_ranges
3757                        .into_iter()
3758                        .map(|range| (range, empty_str.clone())),
3759                    None,
3760                    cx,
3761                );
3762                buffer.snapshot(cx)
3763            });
3764            let new_selections = new_cursors
3765                .into_iter()
3766                .map(|(id, cursor)| {
3767                    let cursor = cursor.to_point(&buffer);
3768                    Selection {
3769                        id,
3770                        start: cursor,
3771                        end: cursor,
3772                        reversed: false,
3773                        goal: SelectionGoal::None,
3774                    }
3775                })
3776                .collect();
3777
3778            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3779                s.select(new_selections);
3780            });
3781        });
3782    }
3783
3784    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3785        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3786        let buffer = &display_map.buffer_snapshot;
3787        let selections = self.selections.all::<Point>(cx);
3788
3789        let mut edits = Vec::new();
3790        let mut selections_iter = selections.iter().peekable();
3791        while let Some(selection) = selections_iter.next() {
3792            // Avoid duplicating the same lines twice.
3793            let mut rows = selection.spanned_rows(false, &display_map);
3794
3795            while let Some(next_selection) = selections_iter.peek() {
3796                let next_rows = next_selection.spanned_rows(false, &display_map);
3797                if next_rows.start < rows.end {
3798                    rows.end = next_rows.end;
3799                    selections_iter.next().unwrap();
3800                } else {
3801                    break;
3802                }
3803            }
3804
3805            // Copy the text from the selected row region and splice it at the start of the region.
3806            let start = Point::new(rows.start, 0);
3807            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3808            let text = buffer
3809                .text_for_range(start..end)
3810                .chain(Some("\n"))
3811                .collect::<String>();
3812            edits.push((start..start, text));
3813        }
3814
3815        self.transact(cx, |this, cx| {
3816            this.buffer.update(cx, |buffer, cx| {
3817                buffer.edit(edits, None, cx);
3818            });
3819
3820            this.request_autoscroll(Autoscroll::fit(), cx);
3821        });
3822    }
3823
3824    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3825        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3826        let buffer = self.buffer.read(cx).snapshot(cx);
3827
3828        let mut edits = Vec::new();
3829        let mut unfold_ranges = Vec::new();
3830        let mut refold_ranges = Vec::new();
3831
3832        let selections = self.selections.all::<Point>(cx);
3833        let mut selections = selections.iter().peekable();
3834        let mut contiguous_row_selections = Vec::new();
3835        let mut new_selections = Vec::new();
3836
3837        while let Some(selection) = selections.next() {
3838            // Find all the selections that span a contiguous row range
3839            let (start_row, end_row) = consume_contiguous_rows(
3840                &mut contiguous_row_selections,
3841                selection,
3842                &display_map,
3843                &mut selections,
3844            );
3845
3846            // Move the text spanned by the row range to be before the line preceding the row range
3847            if start_row > 0 {
3848                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3849                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3850                let insertion_point = display_map
3851                    .prev_line_boundary(Point::new(start_row - 1, 0))
3852                    .0;
3853
3854                // Don't move lines across excerpts
3855                if buffer
3856                    .excerpt_boundaries_in_range((
3857                        Bound::Excluded(insertion_point),
3858                        Bound::Included(range_to_move.end),
3859                    ))
3860                    .next()
3861                    .is_none()
3862                {
3863                    let text = buffer
3864                        .text_for_range(range_to_move.clone())
3865                        .flat_map(|s| s.chars())
3866                        .skip(1)
3867                        .chain(['\n'])
3868                        .collect::<String>();
3869
3870                    edits.push((
3871                        buffer.anchor_after(range_to_move.start)
3872                            ..buffer.anchor_before(range_to_move.end),
3873                        String::new(),
3874                    ));
3875                    let insertion_anchor = buffer.anchor_after(insertion_point);
3876                    edits.push((insertion_anchor..insertion_anchor, text));
3877
3878                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3879
3880                    // Move selections up
3881                    new_selections.extend(contiguous_row_selections.drain(..).map(
3882                        |mut selection| {
3883                            selection.start.row -= row_delta;
3884                            selection.end.row -= row_delta;
3885                            selection
3886                        },
3887                    ));
3888
3889                    // Move folds up
3890                    unfold_ranges.push(range_to_move.clone());
3891                    for fold in display_map.folds_in_range(
3892                        buffer.anchor_before(range_to_move.start)
3893                            ..buffer.anchor_after(range_to_move.end),
3894                    ) {
3895                        let mut start = fold.start.to_point(&buffer);
3896                        let mut end = fold.end.to_point(&buffer);
3897                        start.row -= row_delta;
3898                        end.row -= row_delta;
3899                        refold_ranges.push(start..end);
3900                    }
3901                }
3902            }
3903
3904            // If we didn't move line(s), preserve the existing selections
3905            new_selections.append(&mut contiguous_row_selections);
3906        }
3907
3908        self.transact(cx, |this, cx| {
3909            this.unfold_ranges(unfold_ranges, true, true, cx);
3910            this.buffer.update(cx, |buffer, cx| {
3911                for (range, text) in edits {
3912                    buffer.edit([(range, text)], None, cx);
3913                }
3914            });
3915            this.fold_ranges(refold_ranges, true, cx);
3916            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3917                s.select(new_selections);
3918            })
3919        });
3920    }
3921
3922    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3923        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3924        let buffer = self.buffer.read(cx).snapshot(cx);
3925
3926        let mut edits = Vec::new();
3927        let mut unfold_ranges = Vec::new();
3928        let mut refold_ranges = Vec::new();
3929
3930        let selections = self.selections.all::<Point>(cx);
3931        let mut selections = selections.iter().peekable();
3932        let mut contiguous_row_selections = Vec::new();
3933        let mut new_selections = Vec::new();
3934
3935        while let Some(selection) = selections.next() {
3936            // Find all the selections that span a contiguous row range
3937            let (start_row, end_row) = consume_contiguous_rows(
3938                &mut contiguous_row_selections,
3939                selection,
3940                &display_map,
3941                &mut selections,
3942            );
3943
3944            // Move the text spanned by the row range to be after the last line of the row range
3945            if end_row <= buffer.max_point().row {
3946                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3947                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3948
3949                // Don't move lines across excerpt boundaries
3950                if buffer
3951                    .excerpt_boundaries_in_range((
3952                        Bound::Excluded(range_to_move.start),
3953                        Bound::Included(insertion_point),
3954                    ))
3955                    .next()
3956                    .is_none()
3957                {
3958                    let mut text = String::from("\n");
3959                    text.extend(buffer.text_for_range(range_to_move.clone()));
3960                    text.pop(); // Drop trailing newline
3961                    edits.push((
3962                        buffer.anchor_after(range_to_move.start)
3963                            ..buffer.anchor_before(range_to_move.end),
3964                        String::new(),
3965                    ));
3966                    let insertion_anchor = buffer.anchor_after(insertion_point);
3967                    edits.push((insertion_anchor..insertion_anchor, text));
3968
3969                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3970
3971                    // Move selections down
3972                    new_selections.extend(contiguous_row_selections.drain(..).map(
3973                        |mut selection| {
3974                            selection.start.row += row_delta;
3975                            selection.end.row += row_delta;
3976                            selection
3977                        },
3978                    ));
3979
3980                    // Move folds down
3981                    unfold_ranges.push(range_to_move.clone());
3982                    for fold in display_map.folds_in_range(
3983                        buffer.anchor_before(range_to_move.start)
3984                            ..buffer.anchor_after(range_to_move.end),
3985                    ) {
3986                        let mut start = fold.start.to_point(&buffer);
3987                        let mut end = fold.end.to_point(&buffer);
3988                        start.row += row_delta;
3989                        end.row += row_delta;
3990                        refold_ranges.push(start..end);
3991                    }
3992                }
3993            }
3994
3995            // If we didn't move line(s), preserve the existing selections
3996            new_selections.append(&mut contiguous_row_selections);
3997        }
3998
3999        self.transact(cx, |this, cx| {
4000            this.unfold_ranges(unfold_ranges, true, true, cx);
4001            this.buffer.update(cx, |buffer, cx| {
4002                for (range, text) in edits {
4003                    buffer.edit([(range, text)], None, cx);
4004                }
4005            });
4006            this.fold_ranges(refold_ranges, true, cx);
4007            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4008        });
4009    }
4010
4011    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4012        self.transact(cx, |this, cx| {
4013            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4014                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4015                let line_mode = s.line_mode;
4016                s.move_with(|display_map, selection| {
4017                    if !selection.is_empty() || line_mode {
4018                        return;
4019                    }
4020
4021                    let mut head = selection.head();
4022                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4023                    if head.column() == display_map.line_len(head.row()) {
4024                        transpose_offset = display_map
4025                            .buffer_snapshot
4026                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4027                    }
4028
4029                    if transpose_offset == 0 {
4030                        return;
4031                    }
4032
4033                    *head.column_mut() += 1;
4034                    head = display_map.clip_point(head, Bias::Right);
4035                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4036
4037                    let transpose_start = display_map
4038                        .buffer_snapshot
4039                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4040                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4041                        let transpose_end = display_map
4042                            .buffer_snapshot
4043                            .clip_offset(transpose_offset + 1, Bias::Right);
4044                        if let Some(ch) =
4045                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4046                        {
4047                            edits.push((transpose_start..transpose_offset, String::new()));
4048                            edits.push((transpose_end..transpose_end, ch.to_string()));
4049                        }
4050                    }
4051                });
4052                edits
4053            });
4054            this.buffer
4055                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4056            let selections = this.selections.all::<usize>(cx);
4057            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4058                s.select(selections);
4059            });
4060        });
4061    }
4062
4063    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4064        let mut text = String::new();
4065        let buffer = self.buffer.read(cx).snapshot(cx);
4066        let mut selections = self.selections.all::<Point>(cx);
4067        let mut clipboard_selections = Vec::with_capacity(selections.len());
4068        {
4069            let max_point = buffer.max_point();
4070            for selection in &mut selections {
4071                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4072                if is_entire_line {
4073                    selection.start = Point::new(selection.start.row, 0);
4074                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4075                    selection.goal = SelectionGoal::None;
4076                }
4077                let mut len = 0;
4078                for chunk in buffer.text_for_range(selection.start..selection.end) {
4079                    text.push_str(chunk);
4080                    len += chunk.len();
4081                }
4082                clipboard_selections.push(ClipboardSelection {
4083                    len,
4084                    is_entire_line,
4085                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4086                });
4087            }
4088        }
4089
4090        self.transact(cx, |this, cx| {
4091            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4092                s.select(selections);
4093            });
4094            this.insert("", cx);
4095            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4096        });
4097    }
4098
4099    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4100        let selections = self.selections.all::<Point>(cx);
4101        let buffer = self.buffer.read(cx).read(cx);
4102        let mut text = String::new();
4103
4104        let mut clipboard_selections = Vec::with_capacity(selections.len());
4105        {
4106            let max_point = buffer.max_point();
4107            for selection in selections.iter() {
4108                let mut start = selection.start;
4109                let mut end = selection.end;
4110                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4111                if is_entire_line {
4112                    start = Point::new(start.row, 0);
4113                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4114                }
4115                let mut len = 0;
4116                for chunk in buffer.text_for_range(start..end) {
4117                    text.push_str(chunk);
4118                    len += chunk.len();
4119                }
4120                clipboard_selections.push(ClipboardSelection {
4121                    len,
4122                    is_entire_line,
4123                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4124                });
4125            }
4126        }
4127
4128        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4129    }
4130
4131    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4132        self.transact(cx, |this, cx| {
4133            if let Some(item) = cx.read_from_clipboard() {
4134                let mut clipboard_text = Cow::Borrowed(item.text());
4135                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4136                    let old_selections = this.selections.all::<usize>(cx);
4137                    let all_selections_were_entire_line =
4138                        clipboard_selections.iter().all(|s| s.is_entire_line);
4139                    let first_selection_indent_column =
4140                        clipboard_selections.first().map(|s| s.first_line_indent);
4141                    if clipboard_selections.len() != old_selections.len() {
4142                        let mut newline_separated_text = String::new();
4143                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4144                        let mut ix = 0;
4145                        while let Some(clipboard_selection) = clipboard_selections.next() {
4146                            newline_separated_text
4147                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4148                            ix += clipboard_selection.len;
4149                            if clipboard_selections.peek().is_some() {
4150                                newline_separated_text.push('\n');
4151                            }
4152                        }
4153                        clipboard_text = Cow::Owned(newline_separated_text);
4154                    }
4155
4156                    this.buffer.update(cx, |buffer, cx| {
4157                        let snapshot = buffer.read(cx);
4158                        let mut start_offset = 0;
4159                        let mut edits = Vec::new();
4160                        let mut original_indent_columns = Vec::new();
4161                        let line_mode = this.selections.line_mode;
4162                        for (ix, selection) in old_selections.iter().enumerate() {
4163                            let to_insert;
4164                            let entire_line;
4165                            let original_indent_column;
4166                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4167                                let end_offset = start_offset + clipboard_selection.len;
4168                                to_insert = &clipboard_text[start_offset..end_offset];
4169                                entire_line = clipboard_selection.is_entire_line;
4170                                start_offset = end_offset;
4171                                original_indent_column =
4172                                    Some(clipboard_selection.first_line_indent);
4173                            } else {
4174                                to_insert = clipboard_text.as_str();
4175                                entire_line = all_selections_were_entire_line;
4176                                original_indent_column = first_selection_indent_column
4177                            }
4178
4179                            // If the corresponding selection was empty when this slice of the
4180                            // clipboard text was written, then the entire line containing the
4181                            // selection was copied. If this selection is also currently empty,
4182                            // then paste the line before the current line of the buffer.
4183                            let range = if selection.is_empty() && !line_mode && entire_line {
4184                                let column = selection.start.to_point(&snapshot).column as usize;
4185                                let line_start = selection.start - column;
4186                                line_start..line_start
4187                            } else {
4188                                selection.range()
4189                            };
4190
4191                            edits.push((range, to_insert));
4192                            original_indent_columns.extend(original_indent_column);
4193                        }
4194                        drop(snapshot);
4195
4196                        buffer.edit(
4197                            edits,
4198                            Some(AutoindentMode::Block {
4199                                original_indent_columns,
4200                            }),
4201                            cx,
4202                        );
4203                    });
4204
4205                    let selections = this.selections.all::<usize>(cx);
4206                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4207                } else {
4208                    this.insert(&clipboard_text, cx);
4209                }
4210            }
4211        });
4212    }
4213
4214    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4215        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4216            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4217                self.change_selections(None, cx, |s| {
4218                    s.select_anchors(selections.to_vec());
4219                });
4220            }
4221            self.request_autoscroll(Autoscroll::fit(), cx);
4222            self.unmark_text(cx);
4223            self.refresh_copilot_suggestions(true, cx);
4224            cx.emit(Event::Edited);
4225        }
4226    }
4227
4228    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4229        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4230            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4231            {
4232                self.change_selections(None, cx, |s| {
4233                    s.select_anchors(selections.to_vec());
4234                });
4235            }
4236            self.request_autoscroll(Autoscroll::fit(), cx);
4237            self.unmark_text(cx);
4238            self.refresh_copilot_suggestions(true, cx);
4239            cx.emit(Event::Edited);
4240        }
4241    }
4242
4243    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4244        self.buffer
4245            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4246    }
4247
4248    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4249        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4250            let line_mode = s.line_mode;
4251            s.move_with(|map, selection| {
4252                let cursor = if selection.is_empty() && !line_mode {
4253                    movement::left(map, selection.start)
4254                } else {
4255                    selection.start
4256                };
4257                selection.collapse_to(cursor, SelectionGoal::None);
4258            });
4259        })
4260    }
4261
4262    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4263        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4264            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4265        })
4266    }
4267
4268    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4269        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4270            let line_mode = s.line_mode;
4271            s.move_with(|map, selection| {
4272                let cursor = if selection.is_empty() && !line_mode {
4273                    movement::right(map, selection.end)
4274                } else {
4275                    selection.end
4276                };
4277                selection.collapse_to(cursor, SelectionGoal::None)
4278            });
4279        })
4280    }
4281
4282    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4283        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4284            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4285        })
4286    }
4287
4288    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4289        if self.take_rename(true, cx).is_some() {
4290            return;
4291        }
4292
4293        if let Some(context_menu) = self.context_menu.as_mut() {
4294            if context_menu.select_prev(cx) {
4295                return;
4296            }
4297        }
4298
4299        if matches!(self.mode, EditorMode::SingleLine) {
4300            cx.propagate_action();
4301            return;
4302        }
4303
4304        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4305            let line_mode = s.line_mode;
4306            s.move_with(|map, selection| {
4307                if !selection.is_empty() && !line_mode {
4308                    selection.goal = SelectionGoal::None;
4309                }
4310                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4311                selection.collapse_to(cursor, goal);
4312            });
4313        })
4314    }
4315
4316    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4317        if self.take_rename(true, cx).is_some() {
4318            return;
4319        }
4320
4321        if self
4322            .context_menu
4323            .as_mut()
4324            .map(|menu| menu.select_first(cx))
4325            .unwrap_or(false)
4326        {
4327            return;
4328        }
4329
4330        if matches!(self.mode, EditorMode::SingleLine) {
4331            cx.propagate_action();
4332            return;
4333        }
4334
4335        let row_count = if let Some(row_count) = self.visible_line_count() {
4336            row_count as u32 - 1
4337        } else {
4338            return;
4339        };
4340
4341        let autoscroll = if action.center_cursor {
4342            Autoscroll::center()
4343        } else {
4344            Autoscroll::fit()
4345        };
4346
4347        self.change_selections(Some(autoscroll), cx, |s| {
4348            let line_mode = s.line_mode;
4349            s.move_with(|map, selection| {
4350                if !selection.is_empty() && !line_mode {
4351                    selection.goal = SelectionGoal::None;
4352                }
4353                let (cursor, goal) =
4354                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4355                selection.collapse_to(cursor, goal);
4356            });
4357        });
4358    }
4359
4360    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4361        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4362            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4363        })
4364    }
4365
4366    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4367        self.take_rename(true, cx);
4368
4369        if let Some(context_menu) = self.context_menu.as_mut() {
4370            if context_menu.select_next(cx) {
4371                return;
4372            }
4373        }
4374
4375        if self.mode == EditorMode::SingleLine {
4376            cx.propagate_action();
4377            return;
4378        }
4379
4380        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4381            let line_mode = s.line_mode;
4382            s.move_with(|map, selection| {
4383                if !selection.is_empty() && !line_mode {
4384                    selection.goal = SelectionGoal::None;
4385                }
4386                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4387                selection.collapse_to(cursor, goal);
4388            });
4389        });
4390    }
4391
4392    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4393        if self.take_rename(true, cx).is_some() {
4394            return;
4395        }
4396
4397        if self
4398            .context_menu
4399            .as_mut()
4400            .map(|menu| menu.select_last(cx))
4401            .unwrap_or(false)
4402        {
4403            return;
4404        }
4405
4406        if matches!(self.mode, EditorMode::SingleLine) {
4407            cx.propagate_action();
4408            return;
4409        }
4410
4411        let row_count = if let Some(row_count) = self.visible_line_count() {
4412            row_count as u32 - 1
4413        } else {
4414            return;
4415        };
4416
4417        let autoscroll = if action.center_cursor {
4418            Autoscroll::center()
4419        } else {
4420            Autoscroll::fit()
4421        };
4422
4423        self.change_selections(Some(autoscroll), cx, |s| {
4424            let line_mode = s.line_mode;
4425            s.move_with(|map, selection| {
4426                if !selection.is_empty() && !line_mode {
4427                    selection.goal = SelectionGoal::None;
4428                }
4429                let (cursor, goal) =
4430                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4431                selection.collapse_to(cursor, goal);
4432            });
4433        });
4434    }
4435
4436    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4437        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4438            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4439        });
4440    }
4441
4442    pub fn move_to_previous_word_start(
4443        &mut self,
4444        _: &MoveToPreviousWordStart,
4445        cx: &mut ViewContext<Self>,
4446    ) {
4447        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4448            s.move_cursors_with(|map, head, _| {
4449                (
4450                    movement::previous_word_start(map, head),
4451                    SelectionGoal::None,
4452                )
4453            });
4454        })
4455    }
4456
4457    pub fn move_to_previous_subword_start(
4458        &mut self,
4459        _: &MoveToPreviousSubwordStart,
4460        cx: &mut ViewContext<Self>,
4461    ) {
4462        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4463            s.move_cursors_with(|map, head, _| {
4464                (
4465                    movement::previous_subword_start(map, head),
4466                    SelectionGoal::None,
4467                )
4468            });
4469        })
4470    }
4471
4472    pub fn select_to_previous_word_start(
4473        &mut self,
4474        _: &SelectToPreviousWordStart,
4475        cx: &mut ViewContext<Self>,
4476    ) {
4477        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4478            s.move_heads_with(|map, head, _| {
4479                (
4480                    movement::previous_word_start(map, head),
4481                    SelectionGoal::None,
4482                )
4483            });
4484        })
4485    }
4486
4487    pub fn select_to_previous_subword_start(
4488        &mut self,
4489        _: &SelectToPreviousSubwordStart,
4490        cx: &mut ViewContext<Self>,
4491    ) {
4492        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4493            s.move_heads_with(|map, head, _| {
4494                (
4495                    movement::previous_subword_start(map, head),
4496                    SelectionGoal::None,
4497                )
4498            });
4499        })
4500    }
4501
4502    pub fn delete_to_previous_word_start(
4503        &mut self,
4504        _: &DeleteToPreviousWordStart,
4505        cx: &mut ViewContext<Self>,
4506    ) {
4507        self.transact(cx, |this, cx| {
4508            this.select_autoclose_pair(cx);
4509            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4510                let line_mode = s.line_mode;
4511                s.move_with(|map, selection| {
4512                    if selection.is_empty() && !line_mode {
4513                        let cursor = movement::previous_word_start(map, selection.head());
4514                        selection.set_head(cursor, SelectionGoal::None);
4515                    }
4516                });
4517            });
4518            this.insert("", cx);
4519        });
4520    }
4521
4522    pub fn delete_to_previous_subword_start(
4523        &mut self,
4524        _: &DeleteToPreviousSubwordStart,
4525        cx: &mut ViewContext<Self>,
4526    ) {
4527        self.transact(cx, |this, cx| {
4528            this.select_autoclose_pair(cx);
4529            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4530                let line_mode = s.line_mode;
4531                s.move_with(|map, selection| {
4532                    if selection.is_empty() && !line_mode {
4533                        let cursor = movement::previous_subword_start(map, selection.head());
4534                        selection.set_head(cursor, SelectionGoal::None);
4535                    }
4536                });
4537            });
4538            this.insert("", cx);
4539        });
4540    }
4541
4542    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4543        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4544            s.move_cursors_with(|map, head, _| {
4545                (movement::next_word_end(map, head), SelectionGoal::None)
4546            });
4547        })
4548    }
4549
4550    pub fn move_to_next_subword_end(
4551        &mut self,
4552        _: &MoveToNextSubwordEnd,
4553        cx: &mut ViewContext<Self>,
4554    ) {
4555        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4556            s.move_cursors_with(|map, head, _| {
4557                (movement::next_subword_end(map, head), SelectionGoal::None)
4558            });
4559        })
4560    }
4561
4562    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4563        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4564            s.move_heads_with(|map, head, _| {
4565                (movement::next_word_end(map, head), SelectionGoal::None)
4566            });
4567        })
4568    }
4569
4570    pub fn select_to_next_subword_end(
4571        &mut self,
4572        _: &SelectToNextSubwordEnd,
4573        cx: &mut ViewContext<Self>,
4574    ) {
4575        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4576            s.move_heads_with(|map, head, _| {
4577                (movement::next_subword_end(map, head), SelectionGoal::None)
4578            });
4579        })
4580    }
4581
4582    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4583        self.transact(cx, |this, cx| {
4584            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4585                let line_mode = s.line_mode;
4586                s.move_with(|map, selection| {
4587                    if selection.is_empty() && !line_mode {
4588                        let cursor = movement::next_word_end(map, selection.head());
4589                        selection.set_head(cursor, SelectionGoal::None);
4590                    }
4591                });
4592            });
4593            this.insert("", cx);
4594        });
4595    }
4596
4597    pub fn delete_to_next_subword_end(
4598        &mut self,
4599        _: &DeleteToNextSubwordEnd,
4600        cx: &mut ViewContext<Self>,
4601    ) {
4602        self.transact(cx, |this, cx| {
4603            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4604                s.move_with(|map, selection| {
4605                    if selection.is_empty() {
4606                        let cursor = movement::next_subword_end(map, selection.head());
4607                        selection.set_head(cursor, SelectionGoal::None);
4608                    }
4609                });
4610            });
4611            this.insert("", cx);
4612        });
4613    }
4614
4615    pub fn move_to_beginning_of_line(
4616        &mut self,
4617        _: &MoveToBeginningOfLine,
4618        cx: &mut ViewContext<Self>,
4619    ) {
4620        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4621            s.move_cursors_with(|map, head, _| {
4622                (
4623                    movement::indented_line_beginning(map, head, true),
4624                    SelectionGoal::None,
4625                )
4626            });
4627        })
4628    }
4629
4630    pub fn select_to_beginning_of_line(
4631        &mut self,
4632        action: &SelectToBeginningOfLine,
4633        cx: &mut ViewContext<Self>,
4634    ) {
4635        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4636            s.move_heads_with(|map, head, _| {
4637                (
4638                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4639                    SelectionGoal::None,
4640                )
4641            });
4642        });
4643    }
4644
4645    pub fn delete_to_beginning_of_line(
4646        &mut self,
4647        _: &DeleteToBeginningOfLine,
4648        cx: &mut ViewContext<Self>,
4649    ) {
4650        self.transact(cx, |this, cx| {
4651            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4652                s.move_with(|_, selection| {
4653                    selection.reversed = true;
4654                });
4655            });
4656
4657            this.select_to_beginning_of_line(
4658                &SelectToBeginningOfLine {
4659                    stop_at_soft_wraps: false,
4660                },
4661                cx,
4662            );
4663            this.backspace(&Backspace, cx);
4664        });
4665    }
4666
4667    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4668        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4669            s.move_cursors_with(|map, head, _| {
4670                (movement::line_end(map, head, true), SelectionGoal::None)
4671            });
4672        })
4673    }
4674
4675    pub fn select_to_end_of_line(
4676        &mut self,
4677        action: &SelectToEndOfLine,
4678        cx: &mut ViewContext<Self>,
4679    ) {
4680        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4681            s.move_heads_with(|map, head, _| {
4682                (
4683                    movement::line_end(map, head, action.stop_at_soft_wraps),
4684                    SelectionGoal::None,
4685                )
4686            });
4687        })
4688    }
4689
4690    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4691        self.transact(cx, |this, cx| {
4692            this.select_to_end_of_line(
4693                &SelectToEndOfLine {
4694                    stop_at_soft_wraps: false,
4695                },
4696                cx,
4697            );
4698            this.delete(&Delete, cx);
4699        });
4700    }
4701
4702    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4703        self.transact(cx, |this, cx| {
4704            this.select_to_end_of_line(
4705                &SelectToEndOfLine {
4706                    stop_at_soft_wraps: false,
4707                },
4708                cx,
4709            );
4710            this.cut(&Cut, cx);
4711        });
4712    }
4713
4714    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4715        if matches!(self.mode, EditorMode::SingleLine) {
4716            cx.propagate_action();
4717            return;
4718        }
4719
4720        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4721            s.select_ranges(vec![0..0]);
4722        });
4723    }
4724
4725    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4726        let mut selection = self.selections.last::<Point>(cx);
4727        selection.set_head(Point::zero(), SelectionGoal::None);
4728
4729        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4730            s.select(vec![selection]);
4731        });
4732    }
4733
4734    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4735        if matches!(self.mode, EditorMode::SingleLine) {
4736            cx.propagate_action();
4737            return;
4738        }
4739
4740        let cursor = self.buffer.read(cx).read(cx).len();
4741        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4742            s.select_ranges(vec![cursor..cursor])
4743        });
4744    }
4745
4746    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4747        self.nav_history = nav_history;
4748    }
4749
4750    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4751        self.nav_history.as_ref()
4752    }
4753
4754    fn push_to_nav_history(
4755        &self,
4756        cursor_anchor: Anchor,
4757        new_position: Option<Point>,
4758        cx: &mut ViewContext<Self>,
4759    ) {
4760        if let Some(nav_history) = &self.nav_history {
4761            let buffer = self.buffer.read(cx).read(cx);
4762            let cursor_position = cursor_anchor.to_point(&buffer);
4763            let scroll_state = self.scroll_manager.anchor();
4764            let scroll_top_row = scroll_state.top_row(&buffer);
4765            drop(buffer);
4766
4767            if let Some(new_position) = new_position {
4768                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4769                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4770                    return;
4771                }
4772            }
4773
4774            nav_history.push(
4775                Some(NavigationData {
4776                    cursor_anchor,
4777                    cursor_position,
4778                    scroll_anchor: scroll_state,
4779                    scroll_top_row,
4780                }),
4781                cx,
4782            );
4783        }
4784    }
4785
4786    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4787        let buffer = self.buffer.read(cx).snapshot(cx);
4788        let mut selection = self.selections.first::<usize>(cx);
4789        selection.set_head(buffer.len(), SelectionGoal::None);
4790        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4791            s.select(vec![selection]);
4792        });
4793    }
4794
4795    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4796        let end = self.buffer.read(cx).read(cx).len();
4797        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4798            s.select_ranges(vec![0..end]);
4799        });
4800    }
4801
4802    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4803        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4804        let mut selections = self.selections.all::<Point>(cx);
4805        let max_point = display_map.buffer_snapshot.max_point();
4806        for selection in &mut selections {
4807            let rows = selection.spanned_rows(true, &display_map);
4808            selection.start = Point::new(rows.start, 0);
4809            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4810            selection.reversed = false;
4811        }
4812        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4813            s.select(selections);
4814        });
4815    }
4816
4817    pub fn split_selection_into_lines(
4818        &mut self,
4819        _: &SplitSelectionIntoLines,
4820        cx: &mut ViewContext<Self>,
4821    ) {
4822        let mut to_unfold = Vec::new();
4823        let mut new_selection_ranges = Vec::new();
4824        {
4825            let selections = self.selections.all::<Point>(cx);
4826            let buffer = self.buffer.read(cx).read(cx);
4827            for selection in selections {
4828                for row in selection.start.row..selection.end.row {
4829                    let cursor = Point::new(row, buffer.line_len(row));
4830                    new_selection_ranges.push(cursor..cursor);
4831                }
4832                new_selection_ranges.push(selection.end..selection.end);
4833                to_unfold.push(selection.start..selection.end);
4834            }
4835        }
4836        self.unfold_ranges(to_unfold, true, true, cx);
4837        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4838            s.select_ranges(new_selection_ranges);
4839        });
4840    }
4841
4842    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4843        self.add_selection(true, cx);
4844    }
4845
4846    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4847        self.add_selection(false, cx);
4848    }
4849
4850    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4851        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4852        let mut selections = self.selections.all::<Point>(cx);
4853        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4854            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4855            let range = oldest_selection.display_range(&display_map).sorted();
4856            let columns = cmp::min(range.start.column(), range.end.column())
4857                ..cmp::max(range.start.column(), range.end.column());
4858
4859            selections.clear();
4860            let mut stack = Vec::new();
4861            for row in range.start.row()..=range.end.row() {
4862                if let Some(selection) = self.selections.build_columnar_selection(
4863                    &display_map,
4864                    row,
4865                    &columns,
4866                    oldest_selection.reversed,
4867                ) {
4868                    stack.push(selection.id);
4869                    selections.push(selection);
4870                }
4871            }
4872
4873            if above {
4874                stack.reverse();
4875            }
4876
4877            AddSelectionsState { above, stack }
4878        });
4879
4880        let last_added_selection = *state.stack.last().unwrap();
4881        let mut new_selections = Vec::new();
4882        if above == state.above {
4883            let end_row = if above {
4884                0
4885            } else {
4886                display_map.max_point().row()
4887            };
4888
4889            'outer: for selection in selections {
4890                if selection.id == last_added_selection {
4891                    let range = selection.display_range(&display_map).sorted();
4892                    debug_assert_eq!(range.start.row(), range.end.row());
4893                    let mut row = range.start.row();
4894                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4895                    {
4896                        start..end
4897                    } else {
4898                        cmp::min(range.start.column(), range.end.column())
4899                            ..cmp::max(range.start.column(), range.end.column())
4900                    };
4901
4902                    while row != end_row {
4903                        if above {
4904                            row -= 1;
4905                        } else {
4906                            row += 1;
4907                        }
4908
4909                        if let Some(new_selection) = self.selections.build_columnar_selection(
4910                            &display_map,
4911                            row,
4912                            &columns,
4913                            selection.reversed,
4914                        ) {
4915                            state.stack.push(new_selection.id);
4916                            if above {
4917                                new_selections.push(new_selection);
4918                                new_selections.push(selection);
4919                            } else {
4920                                new_selections.push(selection);
4921                                new_selections.push(new_selection);
4922                            }
4923
4924                            continue 'outer;
4925                        }
4926                    }
4927                }
4928
4929                new_selections.push(selection);
4930            }
4931        } else {
4932            new_selections = selections;
4933            new_selections.retain(|s| s.id != last_added_selection);
4934            state.stack.pop();
4935        }
4936
4937        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4938            s.select(new_selections);
4939        });
4940        if state.stack.len() > 1 {
4941            self.add_selections_state = Some(state);
4942        }
4943    }
4944
4945    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4946        self.push_to_selection_history();
4947        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4948        let buffer = &display_map.buffer_snapshot;
4949        let mut selections = self.selections.all::<usize>(cx);
4950        if let Some(mut select_next_state) = self.select_next_state.take() {
4951            let query = &select_next_state.query;
4952            if !select_next_state.done {
4953                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4954                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4955                let mut next_selected_range = None;
4956
4957                let bytes_after_last_selection =
4958                    buffer.bytes_in_range(last_selection.end..buffer.len());
4959                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4960                let query_matches = query
4961                    .stream_find_iter(bytes_after_last_selection)
4962                    .map(|result| (last_selection.end, result))
4963                    .chain(
4964                        query
4965                            .stream_find_iter(bytes_before_first_selection)
4966                            .map(|result| (0, result)),
4967                    );
4968                for (start_offset, query_match) in query_matches {
4969                    let query_match = query_match.unwrap(); // can only fail due to I/O
4970                    let offset_range =
4971                        start_offset + query_match.start()..start_offset + query_match.end();
4972                    let display_range = offset_range.start.to_display_point(&display_map)
4973                        ..offset_range.end.to_display_point(&display_map);
4974
4975                    if !select_next_state.wordwise
4976                        || (!movement::is_inside_word(&display_map, display_range.start)
4977                            && !movement::is_inside_word(&display_map, display_range.end))
4978                    {
4979                        next_selected_range = Some(offset_range);
4980                        break;
4981                    }
4982                }
4983
4984                if let Some(next_selected_range) = next_selected_range {
4985                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
4986                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4987                        if action.replace_newest {
4988                            s.delete(s.newest_anchor().id);
4989                        }
4990                        s.insert_range(next_selected_range);
4991                    });
4992                } else {
4993                    select_next_state.done = true;
4994                }
4995            }
4996
4997            self.select_next_state = Some(select_next_state);
4998        } else if selections.len() == 1 {
4999            let selection = selections.last_mut().unwrap();
5000            if selection.start == selection.end {
5001                let word_range = movement::surrounding_word(
5002                    &display_map,
5003                    selection.start.to_display_point(&display_map),
5004                );
5005                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5006                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5007                selection.goal = SelectionGoal::None;
5008                selection.reversed = false;
5009
5010                let query = buffer
5011                    .text_for_range(selection.start..selection.end)
5012                    .collect::<String>();
5013                let select_state = SelectNextState {
5014                    query: AhoCorasick::new_auto_configured(&[query]),
5015                    wordwise: true,
5016                    done: false,
5017                };
5018                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5019                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5020                    s.select(selections);
5021                });
5022                self.select_next_state = Some(select_state);
5023            } else {
5024                let query = buffer
5025                    .text_for_range(selection.start..selection.end)
5026                    .collect::<String>();
5027                self.select_next_state = Some(SelectNextState {
5028                    query: AhoCorasick::new_auto_configured(&[query]),
5029                    wordwise: false,
5030                    done: false,
5031                });
5032                self.select_next(action, cx);
5033            }
5034        }
5035    }
5036
5037    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5038        self.transact(cx, |this, cx| {
5039            let mut selections = this.selections.all::<Point>(cx);
5040            let mut edits = Vec::new();
5041            let mut selection_edit_ranges = Vec::new();
5042            let mut last_toggled_row = None;
5043            let snapshot = this.buffer.read(cx).read(cx);
5044            let empty_str: Arc<str> = "".into();
5045            let mut suffixes_inserted = Vec::new();
5046
5047            fn comment_prefix_range(
5048                snapshot: &MultiBufferSnapshot,
5049                row: u32,
5050                comment_prefix: &str,
5051                comment_prefix_whitespace: &str,
5052            ) -> Range<Point> {
5053                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5054
5055                let mut line_bytes = snapshot
5056                    .bytes_in_range(start..snapshot.max_point())
5057                    .flatten()
5058                    .copied();
5059
5060                // If this line currently begins with the line comment prefix, then record
5061                // the range containing the prefix.
5062                if line_bytes
5063                    .by_ref()
5064                    .take(comment_prefix.len())
5065                    .eq(comment_prefix.bytes())
5066                {
5067                    // Include any whitespace that matches the comment prefix.
5068                    let matching_whitespace_len = line_bytes
5069                        .zip(comment_prefix_whitespace.bytes())
5070                        .take_while(|(a, b)| a == b)
5071                        .count() as u32;
5072                    let end = Point::new(
5073                        start.row,
5074                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5075                    );
5076                    start..end
5077                } else {
5078                    start..start
5079                }
5080            }
5081
5082            fn comment_suffix_range(
5083                snapshot: &MultiBufferSnapshot,
5084                row: u32,
5085                comment_suffix: &str,
5086                comment_suffix_has_leading_space: bool,
5087            ) -> Range<Point> {
5088                let end = Point::new(row, snapshot.line_len(row));
5089                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5090
5091                let mut line_end_bytes = snapshot
5092                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5093                    .flatten()
5094                    .copied();
5095
5096                let leading_space_len = if suffix_start_column > 0
5097                    && line_end_bytes.next() == Some(b' ')
5098                    && comment_suffix_has_leading_space
5099                {
5100                    1
5101                } else {
5102                    0
5103                };
5104
5105                // If this line currently begins with the line comment prefix, then record
5106                // the range containing the prefix.
5107                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5108                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5109                    start..end
5110                } else {
5111                    end..end
5112                }
5113            }
5114
5115            // TODO: Handle selections that cross excerpts
5116            for selection in &mut selections {
5117                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5118                let language = if let Some(language) =
5119                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5120                {
5121                    language
5122                } else {
5123                    continue;
5124                };
5125
5126                selection_edit_ranges.clear();
5127
5128                // If multiple selections contain a given row, avoid processing that
5129                // row more than once.
5130                let mut start_row = selection.start.row;
5131                if last_toggled_row == Some(start_row) {
5132                    start_row += 1;
5133                }
5134                let end_row =
5135                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5136                        selection.end.row - 1
5137                    } else {
5138                        selection.end.row
5139                    };
5140                last_toggled_row = Some(end_row);
5141
5142                if start_row > end_row {
5143                    continue;
5144                }
5145
5146                // If the language has line comments, toggle those.
5147                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5148                    // Split the comment prefix's trailing whitespace into a separate string,
5149                    // as that portion won't be used for detecting if a line is a comment.
5150                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5151                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5152                    let mut all_selection_lines_are_comments = true;
5153
5154                    for row in start_row..=end_row {
5155                        if snapshot.is_line_blank(row) {
5156                            continue;
5157                        }
5158
5159                        let prefix_range = comment_prefix_range(
5160                            snapshot.deref(),
5161                            row,
5162                            comment_prefix,
5163                            comment_prefix_whitespace,
5164                        );
5165                        if prefix_range.is_empty() {
5166                            all_selection_lines_are_comments = false;
5167                        }
5168                        selection_edit_ranges.push(prefix_range);
5169                    }
5170
5171                    if all_selection_lines_are_comments {
5172                        edits.extend(
5173                            selection_edit_ranges
5174                                .iter()
5175                                .cloned()
5176                                .map(|range| (range, empty_str.clone())),
5177                        );
5178                    } else {
5179                        let min_column = selection_edit_ranges
5180                            .iter()
5181                            .map(|r| r.start.column)
5182                            .min()
5183                            .unwrap_or(0);
5184                        edits.extend(selection_edit_ranges.iter().map(|range| {
5185                            let position = Point::new(range.start.row, min_column);
5186                            (position..position, full_comment_prefix.clone())
5187                        }));
5188                    }
5189                } else if let Some((full_comment_prefix, comment_suffix)) =
5190                    language.block_comment_delimiters()
5191                {
5192                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5193                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5194                    let prefix_range = comment_prefix_range(
5195                        snapshot.deref(),
5196                        start_row,
5197                        comment_prefix,
5198                        comment_prefix_whitespace,
5199                    );
5200                    let suffix_range = comment_suffix_range(
5201                        snapshot.deref(),
5202                        end_row,
5203                        comment_suffix.trim_start_matches(' '),
5204                        comment_suffix.starts_with(' '),
5205                    );
5206
5207                    if prefix_range.is_empty() || suffix_range.is_empty() {
5208                        edits.push((
5209                            prefix_range.start..prefix_range.start,
5210                            full_comment_prefix.clone(),
5211                        ));
5212                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5213                        suffixes_inserted.push((end_row, comment_suffix.len()));
5214                    } else {
5215                        edits.push((prefix_range, empty_str.clone()));
5216                        edits.push((suffix_range, empty_str.clone()));
5217                    }
5218                } else {
5219                    continue;
5220                }
5221            }
5222
5223            drop(snapshot);
5224            this.buffer.update(cx, |buffer, cx| {
5225                buffer.edit(edits, None, cx);
5226            });
5227
5228            // Adjust selections so that they end before any comment suffixes that
5229            // were inserted.
5230            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5231            let mut selections = this.selections.all::<Point>(cx);
5232            let snapshot = this.buffer.read(cx).read(cx);
5233            for selection in &mut selections {
5234                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5235                    match row.cmp(&selection.end.row) {
5236                        Ordering::Less => {
5237                            suffixes_inserted.next();
5238                            continue;
5239                        }
5240                        Ordering::Greater => break,
5241                        Ordering::Equal => {
5242                            if selection.end.column == snapshot.line_len(row) {
5243                                if selection.is_empty() {
5244                                    selection.start.column -= suffix_len as u32;
5245                                }
5246                                selection.end.column -= suffix_len as u32;
5247                            }
5248                            break;
5249                        }
5250                    }
5251                }
5252            }
5253
5254            drop(snapshot);
5255            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5256
5257            let selections = this.selections.all::<Point>(cx);
5258            let selections_on_single_row = selections.windows(2).all(|selections| {
5259                selections[0].start.row == selections[1].start.row
5260                    && selections[0].end.row == selections[1].end.row
5261                    && selections[0].start.row == selections[0].end.row
5262            });
5263            let selections_selecting = selections
5264                .iter()
5265                .any(|selection| selection.start != selection.end);
5266            let advance_downwards = action.advance_downwards
5267                && selections_on_single_row
5268                && !selections_selecting
5269                && this.mode != EditorMode::SingleLine;
5270
5271            if advance_downwards {
5272                let snapshot = this.buffer.read(cx).snapshot(cx);
5273
5274                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5275                    s.move_cursors_with(|display_snapshot, display_point, _| {
5276                        let mut point = display_point.to_point(display_snapshot);
5277                        point.row += 1;
5278                        point = snapshot.clip_point(point, Bias::Left);
5279                        let display_point = point.to_display_point(display_snapshot);
5280                        (display_point, SelectionGoal::Column(display_point.column()))
5281                    })
5282                });
5283            }
5284        });
5285    }
5286
5287    pub fn select_larger_syntax_node(
5288        &mut self,
5289        _: &SelectLargerSyntaxNode,
5290        cx: &mut ViewContext<Self>,
5291    ) {
5292        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5293        let buffer = self.buffer.read(cx).snapshot(cx);
5294        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5295
5296        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5297        let mut selected_larger_node = false;
5298        let new_selections = old_selections
5299            .iter()
5300            .map(|selection| {
5301                let old_range = selection.start..selection.end;
5302                let mut new_range = old_range.clone();
5303                while let Some(containing_range) =
5304                    buffer.range_for_syntax_ancestor(new_range.clone())
5305                {
5306                    new_range = containing_range;
5307                    if !display_map.intersects_fold(new_range.start)
5308                        && !display_map.intersects_fold(new_range.end)
5309                    {
5310                        break;
5311                    }
5312                }
5313
5314                selected_larger_node |= new_range != old_range;
5315                Selection {
5316                    id: selection.id,
5317                    start: new_range.start,
5318                    end: new_range.end,
5319                    goal: SelectionGoal::None,
5320                    reversed: selection.reversed,
5321                }
5322            })
5323            .collect::<Vec<_>>();
5324
5325        if selected_larger_node {
5326            stack.push(old_selections);
5327            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5328                s.select(new_selections);
5329            });
5330        }
5331        self.select_larger_syntax_node_stack = stack;
5332    }
5333
5334    pub fn select_smaller_syntax_node(
5335        &mut self,
5336        _: &SelectSmallerSyntaxNode,
5337        cx: &mut ViewContext<Self>,
5338    ) {
5339        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5340        if let Some(selections) = stack.pop() {
5341            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5342                s.select(selections.to_vec());
5343            });
5344        }
5345        self.select_larger_syntax_node_stack = stack;
5346    }
5347
5348    pub fn move_to_enclosing_bracket(
5349        &mut self,
5350        _: &MoveToEnclosingBracket,
5351        cx: &mut ViewContext<Self>,
5352    ) {
5353        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5354            s.move_offsets_with(|snapshot, selection| {
5355                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5356                    return;
5357                };
5358
5359                let mut best_length = usize::MAX;
5360                let mut best_inside = false;
5361                let mut best_in_bracket_range = false;
5362                let mut best_destination = None;
5363                for (open, close) in enclosing_bracket_ranges {
5364                    let close = close.to_inclusive();
5365                    let length = close.end() - open.start;
5366                    let inside = selection.start >= open.end && selection.end <= *close.start();
5367                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5368
5369                    // If best is next to a bracket and current isn't, skip
5370                    if !in_bracket_range && best_in_bracket_range {
5371                        continue;
5372                    }
5373
5374                    // Prefer smaller lengths unless best is inside and current isn't
5375                    if length > best_length && (best_inside || !inside) {
5376                        continue;
5377                    }
5378
5379                    best_length = length;
5380                    best_inside = inside;
5381                    best_in_bracket_range = in_bracket_range;
5382                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5383                        if inside {
5384                            open.end
5385                        } else {
5386                            open.start
5387                        }
5388                    } else {
5389                        if inside {
5390                            *close.start()
5391                        } else {
5392                            *close.end()
5393                        }
5394                    });
5395                }
5396
5397                if let Some(destination) = best_destination {
5398                    selection.collapse_to(destination, SelectionGoal::None);
5399                }
5400            })
5401        });
5402    }
5403
5404    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5405        self.end_selection(cx);
5406        self.selection_history.mode = SelectionHistoryMode::Undoing;
5407        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5408            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5409            self.select_next_state = entry.select_next_state;
5410            self.add_selections_state = entry.add_selections_state;
5411            self.request_autoscroll(Autoscroll::newest(), cx);
5412        }
5413        self.selection_history.mode = SelectionHistoryMode::Normal;
5414    }
5415
5416    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5417        self.end_selection(cx);
5418        self.selection_history.mode = SelectionHistoryMode::Redoing;
5419        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5420            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5421            self.select_next_state = entry.select_next_state;
5422            self.add_selections_state = entry.add_selections_state;
5423            self.request_autoscroll(Autoscroll::newest(), cx);
5424        }
5425        self.selection_history.mode = SelectionHistoryMode::Normal;
5426    }
5427
5428    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5429        self.go_to_diagnostic_impl(Direction::Next, cx)
5430    }
5431
5432    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5433        self.go_to_diagnostic_impl(Direction::Prev, cx)
5434    }
5435
5436    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5437        let buffer = self.buffer.read(cx).snapshot(cx);
5438        let selection = self.selections.newest::<usize>(cx);
5439
5440        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5441        if direction == Direction::Next {
5442            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5443                let (group_id, jump_to) = popover.activation_info();
5444                if self.activate_diagnostics(group_id, cx) {
5445                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5446                        let mut new_selection = s.newest_anchor().clone();
5447                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5448                        s.select_anchors(vec![new_selection.clone()]);
5449                    });
5450                }
5451                return;
5452            }
5453        }
5454
5455        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5456            active_diagnostics
5457                .primary_range
5458                .to_offset(&buffer)
5459                .to_inclusive()
5460        });
5461        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5462            if active_primary_range.contains(&selection.head()) {
5463                *active_primary_range.end()
5464            } else {
5465                selection.head()
5466            }
5467        } else {
5468            selection.head()
5469        };
5470
5471        loop {
5472            let mut diagnostics = if direction == Direction::Prev {
5473                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5474            } else {
5475                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5476            };
5477            let group = diagnostics.find_map(|entry| {
5478                if entry.diagnostic.is_primary
5479                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5480                    && !entry.range.is_empty()
5481                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5482                {
5483                    Some((entry.range, entry.diagnostic.group_id))
5484                } else {
5485                    None
5486                }
5487            });
5488
5489            if let Some((primary_range, group_id)) = group {
5490                if self.activate_diagnostics(group_id, cx) {
5491                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5492                        s.select(vec![Selection {
5493                            id: selection.id,
5494                            start: primary_range.start,
5495                            end: primary_range.start,
5496                            reversed: false,
5497                            goal: SelectionGoal::None,
5498                        }]);
5499                    });
5500                }
5501                break;
5502            } else {
5503                // Cycle around to the start of the buffer, potentially moving back to the start of
5504                // the currently active diagnostic.
5505                active_primary_range.take();
5506                if direction == Direction::Prev {
5507                    if search_start == buffer.len() {
5508                        break;
5509                    } else {
5510                        search_start = buffer.len();
5511                    }
5512                } else if search_start == 0 {
5513                    break;
5514                } else {
5515                    search_start = 0;
5516                }
5517            }
5518        }
5519    }
5520
5521    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5522        self.go_to_hunk_impl(Direction::Next, cx)
5523    }
5524
5525    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5526        self.go_to_hunk_impl(Direction::Prev, cx)
5527    }
5528
5529    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5530        let snapshot = self
5531            .display_map
5532            .update(cx, |display_map, cx| display_map.snapshot(cx));
5533        let selection = self.selections.newest::<Point>(cx);
5534
5535        fn seek_in_direction(
5536            this: &mut Editor,
5537            snapshot: &DisplaySnapshot,
5538            initial_point: Point,
5539            is_wrapped: bool,
5540            direction: Direction,
5541            cx: &mut ViewContext<Editor>,
5542        ) -> bool {
5543            let hunks = if direction == Direction::Next {
5544                snapshot
5545                    .buffer_snapshot
5546                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
5547            } else {
5548                snapshot
5549                    .buffer_snapshot
5550                    .git_diff_hunks_in_range(0..initial_point.row, true)
5551            };
5552
5553            let display_point = initial_point.to_display_point(snapshot);
5554            let mut hunks = hunks
5555                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5556                .skip_while(|hunk| {
5557                    if is_wrapped {
5558                        false
5559                    } else {
5560                        hunk.contains_display_row(display_point.row())
5561                    }
5562                })
5563                .dedup();
5564
5565            if let Some(hunk) = hunks.next() {
5566                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5567                    let row = hunk.start_display_row();
5568                    let point = DisplayPoint::new(row, 0);
5569                    s.select_display_ranges([point..point]);
5570                });
5571
5572                true
5573            } else {
5574                false
5575            }
5576        }
5577
5578        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5579            let wrapped_point = match direction {
5580                Direction::Next => Point::zero(),
5581                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5582            };
5583            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5584        }
5585    }
5586
5587    pub fn go_to_definition(
5588        workspace: &mut Workspace,
5589        _: &GoToDefinition,
5590        cx: &mut ViewContext<Workspace>,
5591    ) {
5592        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5593    }
5594
5595    pub fn go_to_type_definition(
5596        workspace: &mut Workspace,
5597        _: &GoToTypeDefinition,
5598        cx: &mut ViewContext<Workspace>,
5599    ) {
5600        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5601    }
5602
5603    fn go_to_definition_of_kind(
5604        kind: GotoDefinitionKind,
5605        workspace: &mut Workspace,
5606        cx: &mut ViewContext<Workspace>,
5607    ) {
5608        let active_item = workspace.active_item(cx);
5609        let editor_handle = if let Some(editor) = active_item
5610            .as_ref()
5611            .and_then(|item| item.act_as::<Self>(cx))
5612        {
5613            editor
5614        } else {
5615            return;
5616        };
5617
5618        let editor = editor_handle.read(cx);
5619        let buffer = editor.buffer.read(cx);
5620        let head = editor.selections.newest::<usize>(cx).head();
5621        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5622            text_anchor
5623        } else {
5624            return;
5625        };
5626
5627        let project = workspace.project().clone();
5628        let definitions = project.update(cx, |project, cx| match kind {
5629            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5630            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5631        });
5632
5633        cx.spawn_labeled("Fetching Definition...", |workspace, mut cx| async move {
5634            let definitions = definitions.await?;
5635            workspace.update(&mut cx, |workspace, cx| {
5636                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5637            })?;
5638
5639            Ok::<(), anyhow::Error>(())
5640        })
5641        .detach_and_log_err(cx);
5642    }
5643
5644    pub fn navigate_to_definitions(
5645        workspace: &mut Workspace,
5646        editor_handle: ViewHandle<Editor>,
5647        definitions: Vec<LocationLink>,
5648        cx: &mut ViewContext<Workspace>,
5649    ) {
5650        let pane = workspace.active_pane().clone();
5651        // If there is one definition, just open it directly
5652        if let [definition] = definitions.as_slice() {
5653            let range = definition
5654                .target
5655                .range
5656                .to_offset(definition.target.buffer.read(cx));
5657
5658            let target_editor_handle =
5659                workspace.open_project_item(definition.target.buffer.clone(), cx);
5660            target_editor_handle.update(cx, |target_editor, cx| {
5661                // When selecting a definition in a different buffer, disable the nav history
5662                // to avoid creating a history entry at the previous cursor location.
5663                if editor_handle != target_editor_handle {
5664                    pane.update(cx, |pane, _| pane.disable_history());
5665                }
5666                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5667                    s.select_ranges([range]);
5668                });
5669
5670                pane.update(cx, |pane, _| pane.enable_history());
5671            });
5672        } else if !definitions.is_empty() {
5673            let replica_id = editor_handle.read(cx).replica_id(cx);
5674            let title = definitions
5675                .iter()
5676                .find(|definition| definition.origin.is_some())
5677                .and_then(|definition| {
5678                    definition.origin.as_ref().map(|origin| {
5679                        let buffer = origin.buffer.read(cx);
5680                        format!(
5681                            "Definitions for {}",
5682                            buffer
5683                                .text_for_range(origin.range.clone())
5684                                .collect::<String>()
5685                        )
5686                    })
5687                })
5688                .unwrap_or("Definitions".to_owned());
5689            let locations = definitions
5690                .into_iter()
5691                .map(|definition| definition.target)
5692                .collect();
5693            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5694        }
5695    }
5696
5697    pub fn find_all_references(
5698        workspace: &mut Workspace,
5699        _: &FindAllReferences,
5700        cx: &mut ViewContext<Workspace>,
5701    ) -> Option<Task<Result<()>>> {
5702        let active_item = workspace.active_item(cx)?;
5703        let editor_handle = active_item.act_as::<Self>(cx)?;
5704
5705        let editor = editor_handle.read(cx);
5706        let buffer = editor.buffer.read(cx);
5707        let head = editor.selections.newest::<usize>(cx).head();
5708        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5709        let replica_id = editor.replica_id(cx);
5710
5711        let project = workspace.project().clone();
5712        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5713        Some(cx.spawn_labeled(
5714            "Finding All References...",
5715            |workspace, mut cx| async move {
5716                let locations = references.await?;
5717                if locations.is_empty() {
5718                    return Ok(());
5719                }
5720
5721                workspace.update(&mut cx, |workspace, cx| {
5722                    let title = locations
5723                        .first()
5724                        .as_ref()
5725                        .map(|location| {
5726                            let buffer = location.buffer.read(cx);
5727                            format!(
5728                                "References to `{}`",
5729                                buffer
5730                                    .text_for_range(location.range.clone())
5731                                    .collect::<String>()
5732                            )
5733                        })
5734                        .unwrap();
5735                    Self::open_locations_in_multibuffer(
5736                        workspace, locations, replica_id, title, cx,
5737                    );
5738                })?;
5739
5740                Ok(())
5741            },
5742        ))
5743    }
5744
5745    /// Opens a multibuffer with the given project locations in it
5746    pub fn open_locations_in_multibuffer(
5747        workspace: &mut Workspace,
5748        mut locations: Vec<Location>,
5749        replica_id: ReplicaId,
5750        title: String,
5751        cx: &mut ViewContext<Workspace>,
5752    ) {
5753        // If there are multiple definitions, open them in a multibuffer
5754        locations.sort_by_key(|location| location.buffer.id());
5755        let mut locations = locations.into_iter().peekable();
5756        let mut ranges_to_highlight = Vec::new();
5757
5758        let excerpt_buffer = cx.add_model(|cx| {
5759            let mut multibuffer = MultiBuffer::new(replica_id);
5760            while let Some(location) = locations.next() {
5761                let buffer = location.buffer.read(cx);
5762                let mut ranges_for_buffer = Vec::new();
5763                let range = location.range.to_offset(buffer);
5764                ranges_for_buffer.push(range.clone());
5765
5766                while let Some(next_location) = locations.peek() {
5767                    if next_location.buffer == location.buffer {
5768                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5769                        locations.next();
5770                    } else {
5771                        break;
5772                    }
5773                }
5774
5775                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5776                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5777                    location.buffer.clone(),
5778                    ranges_for_buffer,
5779                    1,
5780                    cx,
5781                ))
5782            }
5783
5784            multibuffer.with_title(title)
5785        });
5786
5787        let editor = cx.add_view(|cx| {
5788            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5789        });
5790        editor.update(cx, |editor, cx| {
5791            editor.highlight_background::<Self>(
5792                ranges_to_highlight,
5793                |theme| theme.editor.highlighted_line_background,
5794                cx,
5795            );
5796        });
5797        workspace.add_item(Box::new(editor), cx);
5798    }
5799
5800    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5801        use language::ToOffset as _;
5802
5803        let project = self.project.clone()?;
5804        let selection = self.selections.newest_anchor().clone();
5805        let (cursor_buffer, cursor_buffer_position) = self
5806            .buffer
5807            .read(cx)
5808            .text_anchor_for_position(selection.head(), cx)?;
5809        let (tail_buffer, _) = self
5810            .buffer
5811            .read(cx)
5812            .text_anchor_for_position(selection.tail(), cx)?;
5813        if tail_buffer != cursor_buffer {
5814            return None;
5815        }
5816
5817        let snapshot = cursor_buffer.read(cx).snapshot();
5818        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5819        let prepare_rename = project.update(cx, |project, cx| {
5820            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5821        });
5822
5823        Some(cx.spawn(|this, mut cx| async move {
5824            let rename_range = if let Some(range) = prepare_rename.await? {
5825                Some(range)
5826            } else {
5827                this.read_with(&cx, |this, cx| {
5828                    let buffer = this.buffer.read(cx).snapshot(cx);
5829                    let mut buffer_highlights = this
5830                        .document_highlights_for_position(selection.head(), &buffer)
5831                        .filter(|highlight| {
5832                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5833                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5834                        });
5835                    buffer_highlights
5836                        .next()
5837                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5838                })?
5839            };
5840            if let Some(rename_range) = rename_range {
5841                let rename_buffer_range = rename_range.to_offset(&snapshot);
5842                let cursor_offset_in_rename_range =
5843                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5844
5845                this.update(&mut cx, |this, cx| {
5846                    this.take_rename(false, cx);
5847                    let style = this.style(cx);
5848                    let buffer = this.buffer.read(cx).read(cx);
5849                    let cursor_offset = selection.head().to_offset(&buffer);
5850                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5851                    let rename_end = rename_start + rename_buffer_range.len();
5852                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5853                    let mut old_highlight_id = None;
5854                    let old_name: Arc<str> = buffer
5855                        .chunks(rename_start..rename_end, true)
5856                        .map(|chunk| {
5857                            if old_highlight_id.is_none() {
5858                                old_highlight_id = chunk.syntax_highlight_id;
5859                            }
5860                            chunk.text
5861                        })
5862                        .collect::<String>()
5863                        .into();
5864
5865                    drop(buffer);
5866
5867                    // Position the selection in the rename editor so that it matches the current selection.
5868                    this.show_local_selections = false;
5869                    let rename_editor = cx.add_view(|cx| {
5870                        let mut editor = Editor::single_line(None, cx);
5871                        if let Some(old_highlight_id) = old_highlight_id {
5872                            editor.override_text_style =
5873                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5874                        }
5875                        editor.buffer.update(cx, |buffer, cx| {
5876                            buffer.edit([(0..0, old_name.clone())], None, cx)
5877                        });
5878                        editor.select_all(&SelectAll, cx);
5879                        editor
5880                    });
5881
5882                    let ranges = this
5883                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5884                        .into_iter()
5885                        .flat_map(|(_, ranges)| ranges)
5886                        .chain(
5887                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5888                                .into_iter()
5889                                .flat_map(|(_, ranges)| ranges),
5890                        )
5891                        .collect();
5892
5893                    this.highlight_text::<Rename>(
5894                        ranges,
5895                        HighlightStyle {
5896                            fade_out: Some(style.rename_fade),
5897                            ..Default::default()
5898                        },
5899                        cx,
5900                    );
5901                    cx.focus(&rename_editor);
5902                    let block_id = this.insert_blocks(
5903                        [BlockProperties {
5904                            style: BlockStyle::Flex,
5905                            position: range.start.clone(),
5906                            height: 1,
5907                            render: Arc::new({
5908                                let editor = rename_editor.clone();
5909                                move |cx: &mut BlockContext| {
5910                                    ChildView::new(&editor, cx)
5911                                        .contained()
5912                                        .with_padding_left(cx.anchor_x)
5913                                        .into_any()
5914                                }
5915                            }),
5916                            disposition: BlockDisposition::Below,
5917                        }],
5918                        cx,
5919                    )[0];
5920                    this.pending_rename = Some(RenameState {
5921                        range,
5922                        old_name,
5923                        editor: rename_editor,
5924                        block_id,
5925                    });
5926                })?;
5927            }
5928
5929            Ok(())
5930        }))
5931    }
5932
5933    pub fn confirm_rename(
5934        workspace: &mut Workspace,
5935        _: &ConfirmRename,
5936        cx: &mut ViewContext<Workspace>,
5937    ) -> Option<Task<Result<()>>> {
5938        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5939
5940        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5941            let rename = editor.take_rename(false, cx)?;
5942            let buffer = editor.buffer.read(cx);
5943            let (start_buffer, start) =
5944                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5945            let (end_buffer, end) =
5946                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5947            if start_buffer == end_buffer {
5948                let new_name = rename.editor.read(cx).text(cx);
5949                Some((start_buffer, start..end, rename.old_name, new_name))
5950            } else {
5951                None
5952            }
5953        })?;
5954
5955        let rename = workspace.project().clone().update(cx, |project, cx| {
5956            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5957        });
5958
5959        let editor = editor.downgrade();
5960        Some(cx.spawn(|workspace, mut cx| async move {
5961            let project_transaction = rename.await?;
5962            Self::open_project_transaction(
5963                &editor,
5964                workspace,
5965                project_transaction,
5966                format!("Rename: {}{}", old_name, new_name),
5967                cx.clone(),
5968            )
5969            .await?;
5970
5971            editor.update(&mut cx, |editor, cx| {
5972                editor.refresh_document_highlights(cx);
5973            })?;
5974            Ok(())
5975        }))
5976    }
5977
5978    fn take_rename(
5979        &mut self,
5980        moving_cursor: bool,
5981        cx: &mut ViewContext<Self>,
5982    ) -> Option<RenameState> {
5983        let rename = self.pending_rename.take()?;
5984        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5985        self.clear_text_highlights::<Rename>(cx);
5986        self.show_local_selections = true;
5987
5988        if moving_cursor {
5989            let rename_editor = rename.editor.read(cx);
5990            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5991
5992            // Update the selection to match the position of the selection inside
5993            // the rename editor.
5994            let snapshot = self.buffer.read(cx).read(cx);
5995            let rename_range = rename.range.to_offset(&snapshot);
5996            let cursor_in_editor = snapshot
5997                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5998                .min(rename_range.end);
5999            drop(snapshot);
6000
6001            self.change_selections(None, cx, |s| {
6002                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6003            });
6004        } else {
6005            self.refresh_document_highlights(cx);
6006        }
6007
6008        Some(rename)
6009    }
6010
6011    #[cfg(any(test, feature = "test-support"))]
6012    pub fn pending_rename(&self) -> Option<&RenameState> {
6013        self.pending_rename.as_ref()
6014    }
6015
6016    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6017        let project = match &self.project {
6018            Some(project) => project.clone(),
6019            None => return None,
6020        };
6021
6022        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6023    }
6024
6025    fn perform_format(
6026        &mut self,
6027        project: ModelHandle<Project>,
6028        trigger: FormatTrigger,
6029        cx: &mut ViewContext<Self>,
6030    ) -> Task<Result<()>> {
6031        let buffer = self.buffer().clone();
6032        let buffers = buffer.read(cx).all_buffers();
6033
6034        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6035        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6036
6037        cx.spawn(|_, mut cx| async move {
6038            let transaction = futures::select_biased! {
6039                _ = timeout => {
6040                    log::warn!("timed out waiting for formatting");
6041                    None
6042                }
6043                transaction = format.log_err().fuse() => transaction,
6044            };
6045
6046            buffer.update(&mut cx, |buffer, cx| {
6047                if let Some(transaction) = transaction {
6048                    if !buffer.is_singleton() {
6049                        buffer.push_transaction(&transaction.0);
6050                    }
6051                }
6052
6053                cx.notify();
6054            });
6055
6056            Ok(())
6057        })
6058    }
6059
6060    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6061        if let Some(project) = self.project.clone() {
6062            self.buffer.update(cx, |multi_buffer, cx| {
6063                project.update(cx, |project, cx| {
6064                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6065                });
6066            })
6067        }
6068    }
6069
6070    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6071        cx.show_character_palette();
6072    }
6073
6074    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6075        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6076            let buffer = self.buffer.read(cx).snapshot(cx);
6077            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6078            let is_valid = buffer
6079                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6080                .any(|entry| {
6081                    entry.diagnostic.is_primary
6082                        && !entry.range.is_empty()
6083                        && entry.range.start == primary_range_start
6084                        && entry.diagnostic.message == active_diagnostics.primary_message
6085                });
6086
6087            if is_valid != active_diagnostics.is_valid {
6088                active_diagnostics.is_valid = is_valid;
6089                let mut new_styles = HashMap::default();
6090                for (block_id, diagnostic) in &active_diagnostics.blocks {
6091                    new_styles.insert(
6092                        *block_id,
6093                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6094                    );
6095                }
6096                self.display_map
6097                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6098            }
6099        }
6100    }
6101
6102    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6103        self.dismiss_diagnostics(cx);
6104        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6105            let buffer = self.buffer.read(cx).snapshot(cx);
6106
6107            let mut primary_range = None;
6108            let mut primary_message = None;
6109            let mut group_end = Point::zero();
6110            let diagnostic_group = buffer
6111                .diagnostic_group::<Point>(group_id)
6112                .map(|entry| {
6113                    if entry.range.end > group_end {
6114                        group_end = entry.range.end;
6115                    }
6116                    if entry.diagnostic.is_primary {
6117                        primary_range = Some(entry.range.clone());
6118                        primary_message = Some(entry.diagnostic.message.clone());
6119                    }
6120                    entry
6121                })
6122                .collect::<Vec<_>>();
6123            let primary_range = primary_range?;
6124            let primary_message = primary_message?;
6125            let primary_range =
6126                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6127
6128            let blocks = display_map
6129                .insert_blocks(
6130                    diagnostic_group.iter().map(|entry| {
6131                        let diagnostic = entry.diagnostic.clone();
6132                        let message_height = diagnostic.message.lines().count() as u8;
6133                        BlockProperties {
6134                            style: BlockStyle::Fixed,
6135                            position: buffer.anchor_after(entry.range.start),
6136                            height: message_height,
6137                            render: diagnostic_block_renderer(diagnostic, true),
6138                            disposition: BlockDisposition::Below,
6139                        }
6140                    }),
6141                    cx,
6142                )
6143                .into_iter()
6144                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6145                .collect();
6146
6147            Some(ActiveDiagnosticGroup {
6148                primary_range,
6149                primary_message,
6150                blocks,
6151                is_valid: true,
6152            })
6153        });
6154        self.active_diagnostics.is_some()
6155    }
6156
6157    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6158        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6159            self.display_map.update(cx, |display_map, cx| {
6160                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6161            });
6162            cx.notify();
6163        }
6164    }
6165
6166    pub fn set_selections_from_remote(
6167        &mut self,
6168        selections: Vec<Selection<Anchor>>,
6169        pending_selection: Option<Selection<Anchor>>,
6170        cx: &mut ViewContext<Self>,
6171    ) {
6172        let old_cursor_position = self.selections.newest_anchor().head();
6173        self.selections.change_with(cx, |s| {
6174            s.select_anchors(selections);
6175            if let Some(pending_selection) = pending_selection {
6176                s.set_pending(pending_selection, SelectMode::Character);
6177            } else {
6178                s.clear_pending();
6179            }
6180        });
6181        self.selections_did_change(false, &old_cursor_position, cx);
6182    }
6183
6184    fn push_to_selection_history(&mut self) {
6185        self.selection_history.push(SelectionHistoryEntry {
6186            selections: self.selections.disjoint_anchors(),
6187            select_next_state: self.select_next_state.clone(),
6188            add_selections_state: self.add_selections_state.clone(),
6189        });
6190    }
6191
6192    pub fn transact(
6193        &mut self,
6194        cx: &mut ViewContext<Self>,
6195        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6196    ) -> Option<TransactionId> {
6197        self.start_transaction_at(Instant::now(), cx);
6198        update(self, cx);
6199        self.end_transaction_at(Instant::now(), cx)
6200    }
6201
6202    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6203        self.end_selection(cx);
6204        if let Some(tx_id) = self
6205            .buffer
6206            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6207        {
6208            self.selection_history
6209                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6210        }
6211    }
6212
6213    fn end_transaction_at(
6214        &mut self,
6215        now: Instant,
6216        cx: &mut ViewContext<Self>,
6217    ) -> Option<TransactionId> {
6218        if let Some(tx_id) = self
6219            .buffer
6220            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6221        {
6222            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6223                *end_selections = Some(self.selections.disjoint_anchors());
6224            } else {
6225                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6226            }
6227
6228            cx.emit(Event::Edited);
6229            Some(tx_id)
6230        } else {
6231            None
6232        }
6233    }
6234
6235    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6236        let mut fold_ranges = Vec::new();
6237
6238        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6239
6240        let selections = self.selections.all::<Point>(cx);
6241        for selection in selections {
6242            let range = selection.range().sorted();
6243            let buffer_start_row = range.start.row;
6244
6245            for row in (0..=range.end.row).rev() {
6246                let fold_range = display_map.foldable_range(row);
6247
6248                if let Some(fold_range) = fold_range {
6249                    if fold_range.end.row >= buffer_start_row {
6250                        fold_ranges.push(fold_range);
6251                        if row <= range.start.row {
6252                            break;
6253                        }
6254                    }
6255                }
6256            }
6257        }
6258
6259        self.fold_ranges(fold_ranges, true, cx);
6260    }
6261
6262    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6263        let buffer_row = fold_at.buffer_row;
6264        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6265
6266        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6267            let autoscroll = self
6268                .selections
6269                .all::<Point>(cx)
6270                .iter()
6271                .any(|selection| fold_range.overlaps(&selection.range()));
6272
6273            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6274        }
6275    }
6276
6277    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6278        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6279        let buffer = &display_map.buffer_snapshot;
6280        let selections = self.selections.all::<Point>(cx);
6281        let ranges = selections
6282            .iter()
6283            .map(|s| {
6284                let range = s.display_range(&display_map).sorted();
6285                let mut start = range.start.to_point(&display_map);
6286                let mut end = range.end.to_point(&display_map);
6287                start.column = 0;
6288                end.column = buffer.line_len(end.row);
6289                start..end
6290            })
6291            .collect::<Vec<_>>();
6292
6293        self.unfold_ranges(ranges, true, true, cx);
6294    }
6295
6296    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6298
6299        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6300            ..Point::new(
6301                unfold_at.buffer_row,
6302                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6303            );
6304
6305        let autoscroll = self
6306            .selections
6307            .all::<Point>(cx)
6308            .iter()
6309            .any(|selection| selection.range().overlaps(&intersection_range));
6310
6311        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6312    }
6313
6314    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6315        let selections = self.selections.all::<Point>(cx);
6316        let ranges = selections.into_iter().map(|s| s.start..s.end);
6317        self.fold_ranges(ranges, true, cx);
6318    }
6319
6320    pub fn fold_ranges<T: ToOffset + Clone>(
6321        &mut self,
6322        ranges: impl IntoIterator<Item = Range<T>>,
6323        auto_scroll: bool,
6324        cx: &mut ViewContext<Self>,
6325    ) {
6326        let mut ranges = ranges.into_iter().peekable();
6327        if ranges.peek().is_some() {
6328            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6329
6330            if auto_scroll {
6331                self.request_autoscroll(Autoscroll::fit(), cx);
6332            }
6333
6334            cx.notify();
6335        }
6336    }
6337
6338    pub fn unfold_ranges<T: ToOffset + Clone>(
6339        &mut self,
6340        ranges: impl IntoIterator<Item = Range<T>>,
6341        inclusive: bool,
6342        auto_scroll: bool,
6343        cx: &mut ViewContext<Self>,
6344    ) {
6345        let mut ranges = ranges.into_iter().peekable();
6346        if ranges.peek().is_some() {
6347            self.display_map
6348                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6349            if auto_scroll {
6350                self.request_autoscroll(Autoscroll::fit(), cx);
6351            }
6352
6353            cx.notify();
6354        }
6355    }
6356
6357    pub fn gutter_hover(
6358        &mut self,
6359        GutterHover { hovered }: &GutterHover,
6360        cx: &mut ViewContext<Self>,
6361    ) {
6362        self.gutter_hovered = *hovered;
6363        cx.notify();
6364    }
6365
6366    pub fn insert_blocks(
6367        &mut self,
6368        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6369        cx: &mut ViewContext<Self>,
6370    ) -> Vec<BlockId> {
6371        let blocks = self
6372            .display_map
6373            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6374        self.request_autoscroll(Autoscroll::fit(), cx);
6375        blocks
6376    }
6377
6378    pub fn replace_blocks(
6379        &mut self,
6380        blocks: HashMap<BlockId, RenderBlock>,
6381        cx: &mut ViewContext<Self>,
6382    ) {
6383        self.display_map
6384            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6385        self.request_autoscroll(Autoscroll::fit(), cx);
6386    }
6387
6388    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6389        self.display_map.update(cx, |display_map, cx| {
6390            display_map.remove_blocks(block_ids, cx)
6391        });
6392    }
6393
6394    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6395        self.display_map
6396            .update(cx, |map, cx| map.snapshot(cx))
6397            .longest_row()
6398    }
6399
6400    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6401        self.display_map
6402            .update(cx, |map, cx| map.snapshot(cx))
6403            .max_point()
6404    }
6405
6406    pub fn text(&self, cx: &AppContext) -> String {
6407        self.buffer.read(cx).read(cx).text()
6408    }
6409
6410    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6411        self.transact(cx, |this, cx| {
6412            this.buffer
6413                .read(cx)
6414                .as_singleton()
6415                .expect("you can only call set_text on editors for singleton buffers")
6416                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6417        });
6418    }
6419
6420    pub fn display_text(&self, cx: &mut AppContext) -> String {
6421        self.display_map
6422            .update(cx, |map, cx| map.snapshot(cx))
6423            .text()
6424    }
6425
6426    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6427        let language_name = self
6428            .buffer
6429            .read(cx)
6430            .as_singleton()
6431            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6432            .map(|l| l.name());
6433
6434        let settings = cx.global::<Settings>();
6435        let mode = self
6436            .soft_wrap_mode_override
6437            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6438        match mode {
6439            settings::SoftWrap::None => SoftWrap::None,
6440            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6441            settings::SoftWrap::PreferredLineLength => {
6442                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6443            }
6444        }
6445    }
6446
6447    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6448        self.soft_wrap_mode_override = Some(mode);
6449        cx.notify();
6450    }
6451
6452    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6453        self.display_map
6454            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6455    }
6456
6457    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6458        if self.soft_wrap_mode_override.is_some() {
6459            self.soft_wrap_mode_override.take();
6460        } else {
6461            let soft_wrap = match self.soft_wrap_mode(cx) {
6462                SoftWrap::None => settings::SoftWrap::EditorWidth,
6463                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
6464            };
6465            self.soft_wrap_mode_override = Some(soft_wrap);
6466        }
6467        cx.notify();
6468    }
6469
6470    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6471        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6472            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6473                cx.reveal_path(&file.abs_path(cx));
6474            }
6475        }
6476    }
6477
6478    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6479        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6480            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6481                if let Some(path) = file.abs_path(cx).to_str() {
6482                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6483                }
6484            }
6485        }
6486    }
6487
6488    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6489        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6490            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6491                if let Some(path) = file.path().to_str() {
6492                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6493                }
6494            }
6495        }
6496    }
6497
6498    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6499        self.highlighted_rows = rows;
6500    }
6501
6502    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6503        self.highlighted_rows.clone()
6504    }
6505
6506    pub fn highlight_background<T: 'static>(
6507        &mut self,
6508        ranges: Vec<Range<Anchor>>,
6509        color_fetcher: fn(&Theme) -> Color,
6510        cx: &mut ViewContext<Self>,
6511    ) {
6512        self.background_highlights
6513            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6514        cx.notify();
6515    }
6516
6517    #[allow(clippy::type_complexity)]
6518    pub fn clear_background_highlights<T: 'static>(
6519        &mut self,
6520        cx: &mut ViewContext<Self>,
6521    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6522        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6523        if highlights.is_some() {
6524            cx.notify();
6525        }
6526        highlights
6527    }
6528
6529    #[cfg(feature = "test-support")]
6530    pub fn all_background_highlights(
6531        &mut self,
6532        cx: &mut ViewContext<Self>,
6533    ) -> Vec<(Range<DisplayPoint>, Color)> {
6534        let snapshot = self.snapshot(cx);
6535        let buffer = &snapshot.buffer_snapshot;
6536        let start = buffer.anchor_before(0);
6537        let end = buffer.anchor_after(buffer.len());
6538        let theme = cx.global::<Settings>().theme.as_ref();
6539        self.background_highlights_in_range(start..end, &snapshot, theme)
6540    }
6541
6542    fn document_highlights_for_position<'a>(
6543        &'a self,
6544        position: Anchor,
6545        buffer: &'a MultiBufferSnapshot,
6546    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6547        let read_highlights = self
6548            .background_highlights
6549            .get(&TypeId::of::<DocumentHighlightRead>())
6550            .map(|h| &h.1);
6551        let write_highlights = self
6552            .background_highlights
6553            .get(&TypeId::of::<DocumentHighlightWrite>())
6554            .map(|h| &h.1);
6555        let left_position = position.bias_left(buffer);
6556        let right_position = position.bias_right(buffer);
6557        read_highlights
6558            .into_iter()
6559            .chain(write_highlights)
6560            .flat_map(move |ranges| {
6561                let start_ix = match ranges.binary_search_by(|probe| {
6562                    let cmp = probe.end.cmp(&left_position, buffer);
6563                    if cmp.is_ge() {
6564                        Ordering::Greater
6565                    } else {
6566                        Ordering::Less
6567                    }
6568                }) {
6569                    Ok(i) | Err(i) => i,
6570                };
6571
6572                let right_position = right_position.clone();
6573                ranges[start_ix..]
6574                    .iter()
6575                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6576            })
6577    }
6578
6579    pub fn background_highlights_in_range(
6580        &self,
6581        search_range: Range<Anchor>,
6582        display_snapshot: &DisplaySnapshot,
6583        theme: &Theme,
6584    ) -> Vec<(Range<DisplayPoint>, Color)> {
6585        let mut results = Vec::new();
6586        let buffer = &display_snapshot.buffer_snapshot;
6587        for (color_fetcher, ranges) in self.background_highlights.values() {
6588            let color = color_fetcher(theme);
6589            let start_ix = match ranges.binary_search_by(|probe| {
6590                let cmp = probe.end.cmp(&search_range.start, buffer);
6591                if cmp.is_gt() {
6592                    Ordering::Greater
6593                } else {
6594                    Ordering::Less
6595                }
6596            }) {
6597                Ok(i) | Err(i) => i,
6598            };
6599            for range in &ranges[start_ix..] {
6600                if range.start.cmp(&search_range.end, buffer).is_ge() {
6601                    break;
6602                }
6603                let start = range
6604                    .start
6605                    .to_point(buffer)
6606                    .to_display_point(display_snapshot);
6607                let end = range
6608                    .end
6609                    .to_point(buffer)
6610                    .to_display_point(display_snapshot);
6611                results.push((start..end, color))
6612            }
6613        }
6614        results
6615    }
6616
6617    pub fn highlight_text<T: 'static>(
6618        &mut self,
6619        ranges: Vec<Range<Anchor>>,
6620        style: HighlightStyle,
6621        cx: &mut ViewContext<Self>,
6622    ) {
6623        self.display_map.update(cx, |map, _| {
6624            map.highlight_text(TypeId::of::<T>(), ranges, style)
6625        });
6626        cx.notify();
6627    }
6628
6629    pub fn text_highlights<'a, T: 'static>(
6630        &'a self,
6631        cx: &'a AppContext,
6632    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6633        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6634    }
6635
6636    pub fn clear_text_highlights<T: 'static>(
6637        &mut self,
6638        cx: &mut ViewContext<Self>,
6639    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6640        let highlights = self
6641            .display_map
6642            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6643        if highlights.is_some() {
6644            cx.notify();
6645        }
6646        highlights
6647    }
6648
6649    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6650        self.blink_manager.read(cx).visible() && self.focused
6651    }
6652
6653    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6654        cx.notify();
6655    }
6656
6657    fn on_buffer_event(
6658        &mut self,
6659        _: ModelHandle<MultiBuffer>,
6660        event: &multi_buffer::Event,
6661        cx: &mut ViewContext<Self>,
6662    ) {
6663        match event {
6664            multi_buffer::Event::Edited => {
6665                self.refresh_active_diagnostics(cx);
6666                self.refresh_code_actions(cx);
6667                if self.has_active_copilot_suggestion(cx) {
6668                    self.update_visible_copilot_suggestion(cx);
6669                }
6670                cx.emit(Event::BufferEdited);
6671            }
6672            multi_buffer::Event::ExcerptsAdded {
6673                buffer,
6674                predecessor,
6675                excerpts,
6676            } => cx.emit(Event::ExcerptsAdded {
6677                buffer: buffer.clone(),
6678                predecessor: *predecessor,
6679                excerpts: excerpts.clone(),
6680            }),
6681            multi_buffer::Event::ExcerptsRemoved { ids } => {
6682                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6683            }
6684            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6685            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6686            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6687            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6688            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6689            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6690            multi_buffer::Event::DiagnosticsUpdated => {
6691                self.refresh_active_diagnostics(cx);
6692            }
6693            multi_buffer::Event::LanguageChanged => {}
6694        }
6695    }
6696
6697    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6698        cx.notify();
6699    }
6700
6701    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6702        self.refresh_copilot_suggestions(true, cx);
6703    }
6704
6705    pub fn set_searchable(&mut self, searchable: bool) {
6706        self.searchable = searchable;
6707    }
6708
6709    pub fn searchable(&self) -> bool {
6710        self.searchable
6711    }
6712
6713    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6714        let active_item = workspace.active_item(cx);
6715        let editor_handle = if let Some(editor) = active_item
6716            .as_ref()
6717            .and_then(|item| item.act_as::<Self>(cx))
6718        {
6719            editor
6720        } else {
6721            cx.propagate_action();
6722            return;
6723        };
6724
6725        let editor = editor_handle.read(cx);
6726        let buffer = editor.buffer.read(cx);
6727        if buffer.is_singleton() {
6728            cx.propagate_action();
6729            return;
6730        }
6731
6732        let mut new_selections_by_buffer = HashMap::default();
6733        for selection in editor.selections.all::<usize>(cx) {
6734            for (buffer, mut range) in
6735                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6736            {
6737                if selection.reversed {
6738                    mem::swap(&mut range.start, &mut range.end);
6739                }
6740                new_selections_by_buffer
6741                    .entry(buffer)
6742                    .or_insert(Vec::new())
6743                    .push(range)
6744            }
6745        }
6746
6747        editor_handle.update(cx, |editor, cx| {
6748            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6749        });
6750        let pane = workspace.active_pane().clone();
6751        pane.update(cx, |pane, _| pane.disable_history());
6752
6753        // We defer the pane interaction because we ourselves are a workspace item
6754        // and activating a new item causes the pane to call a method on us reentrantly,
6755        // which panics if we're on the stack.
6756        cx.defer(move |workspace, cx| {
6757            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6758                let editor = workspace.open_project_item::<Self>(buffer, cx);
6759                editor.update(cx, |editor, cx| {
6760                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6761                        s.select_ranges(ranges);
6762                    });
6763                });
6764            }
6765
6766            pane.update(cx, |pane, _| pane.enable_history());
6767        });
6768    }
6769
6770    fn jump(
6771        workspace: &mut Workspace,
6772        path: ProjectPath,
6773        position: Point,
6774        anchor: language::Anchor,
6775        cx: &mut ViewContext<Workspace>,
6776    ) {
6777        let editor = workspace.open_path(path, None, true, cx);
6778        cx.spawn(|_, mut cx| async move {
6779            let editor = editor
6780                .await?
6781                .downcast::<Editor>()
6782                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6783                .downgrade();
6784            editor.update(&mut cx, |editor, cx| {
6785                let buffer = editor
6786                    .buffer()
6787                    .read(cx)
6788                    .as_singleton()
6789                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6790                let buffer = buffer.read(cx);
6791                let cursor = if buffer.can_resolve(&anchor) {
6792                    language::ToPoint::to_point(&anchor, buffer)
6793                } else {
6794                    buffer.clip_point(position, Bias::Left)
6795                };
6796
6797                let nav_history = editor.nav_history.take();
6798                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6799                    s.select_ranges([cursor..cursor]);
6800                });
6801                editor.nav_history = nav_history;
6802
6803                anyhow::Ok(())
6804            })??;
6805
6806            anyhow::Ok(())
6807        })
6808        .detach_and_log_err(cx);
6809    }
6810
6811    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6812        let snapshot = self.buffer.read(cx).read(cx);
6813        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6814        Some(
6815            ranges
6816                .iter()
6817                .map(move |range| {
6818                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6819                })
6820                .collect(),
6821        )
6822    }
6823
6824    fn selection_replacement_ranges(
6825        &self,
6826        range: Range<OffsetUtf16>,
6827        cx: &AppContext,
6828    ) -> Vec<Range<OffsetUtf16>> {
6829        let selections = self.selections.all::<OffsetUtf16>(cx);
6830        let newest_selection = selections
6831            .iter()
6832            .max_by_key(|selection| selection.id)
6833            .unwrap();
6834        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6835        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6836        let snapshot = self.buffer.read(cx).read(cx);
6837        selections
6838            .into_iter()
6839            .map(|mut selection| {
6840                selection.start.0 =
6841                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6842                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6843                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6844                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6845            })
6846            .collect()
6847    }
6848
6849    fn report_event(&self, name: &str, cx: &AppContext) {
6850        if let Some((project, file)) = self.project.as_ref().zip(
6851            self.buffer
6852                .read(cx)
6853                .as_singleton()
6854                .and_then(|b| b.read(cx).file()),
6855        ) {
6856            let settings = cx.global::<Settings>();
6857
6858            let extension = Path::new(file.file_name(cx))
6859                .extension()
6860                .and_then(|e| e.to_str());
6861            project.read(cx).client().report_event(
6862                name,
6863                json!({ "File Extension": extension, "Vim Mode": settings.vim_mode  }),
6864                settings.telemetry(),
6865            );
6866        }
6867    }
6868
6869    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6870    /// with each line being an array of {text, highlight} objects.
6871    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6872        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6873            return;
6874        };
6875
6876        #[derive(Serialize)]
6877        struct Chunk<'a> {
6878            text: String,
6879            highlight: Option<&'a str>,
6880        }
6881
6882        let snapshot = buffer.read(cx).snapshot();
6883        let range = self
6884            .selected_text_range(cx)
6885            .and_then(|selected_range| {
6886                if selected_range.is_empty() {
6887                    None
6888                } else {
6889                    Some(selected_range)
6890                }
6891            })
6892            .unwrap_or_else(|| 0..snapshot.len());
6893
6894        let chunks = snapshot.chunks(range, true);
6895        let mut lines = Vec::new();
6896        let mut line: VecDeque<Chunk> = VecDeque::new();
6897
6898        let theme = &cx.global::<Settings>().theme.editor.syntax;
6899
6900        for chunk in chunks {
6901            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
6902            let mut chunk_lines = chunk.text.split("\n").peekable();
6903            while let Some(text) = chunk_lines.next() {
6904                let mut merged_with_last_token = false;
6905                if let Some(last_token) = line.back_mut() {
6906                    if last_token.highlight == highlight {
6907                        last_token.text.push_str(text);
6908                        merged_with_last_token = true;
6909                    }
6910                }
6911
6912                if !merged_with_last_token {
6913                    line.push_back(Chunk {
6914                        text: text.into(),
6915                        highlight,
6916                    });
6917                }
6918
6919                if chunk_lines.peek().is_some() {
6920                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
6921                        line.pop_front();
6922                    }
6923                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
6924                        line.pop_back();
6925                    }
6926
6927                    lines.push(mem::take(&mut line));
6928                }
6929            }
6930        }
6931
6932        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
6933        cx.write_to_clipboard(ClipboardItem::new(lines));
6934    }
6935}
6936
6937fn consume_contiguous_rows(
6938    contiguous_row_selections: &mut Vec<Selection<Point>>,
6939    selection: &Selection<Point>,
6940    display_map: &DisplaySnapshot,
6941    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
6942) -> (u32, u32) {
6943    contiguous_row_selections.push(selection.clone());
6944    let start_row = selection.start.row;
6945    let mut end_row = ending_row(selection, display_map);
6946
6947    while let Some(next_selection) = selections.peek() {
6948        if next_selection.start.row <= end_row {
6949            end_row = ending_row(next_selection, display_map);
6950            contiguous_row_selections.push(selections.next().unwrap().clone());
6951        } else {
6952            break;
6953        }
6954    }
6955    (start_row, end_row)
6956}
6957
6958fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
6959    if next_selection.end.column > 0 || next_selection.is_empty() {
6960        display_map.next_line_boundary(next_selection.end).0.row + 1
6961    } else {
6962        next_selection.end.row
6963    }
6964}
6965
6966impl EditorSnapshot {
6967    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6968        self.display_snapshot.buffer_snapshot.language_at(position)
6969    }
6970
6971    pub fn is_focused(&self) -> bool {
6972        self.is_focused
6973    }
6974
6975    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6976        self.placeholder_text.as_ref()
6977    }
6978
6979    pub fn scroll_position(&self) -> Vector2F {
6980        self.scroll_anchor.scroll_position(&self.display_snapshot)
6981    }
6982}
6983
6984impl Deref for EditorSnapshot {
6985    type Target = DisplaySnapshot;
6986
6987    fn deref(&self) -> &Self::Target {
6988        &self.display_snapshot
6989    }
6990}
6991
6992#[derive(Clone, Debug, PartialEq, Eq)]
6993pub enum Event {
6994    InputIgnored {
6995        text: Arc<str>,
6996    },
6997    ExcerptsAdded {
6998        buffer: ModelHandle<Buffer>,
6999        predecessor: ExcerptId,
7000        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7001    },
7002    ExcerptsRemoved {
7003        ids: Vec<ExcerptId>,
7004    },
7005    BufferEdited,
7006    Edited,
7007    Reparsed,
7008    Blurred,
7009    DirtyChanged,
7010    Saved,
7011    TitleChanged,
7012    SelectionsChanged {
7013        local: bool,
7014    },
7015    ScrollPositionChanged {
7016        local: bool,
7017    },
7018    Closed,
7019}
7020
7021pub struct EditorFocused(pub ViewHandle<Editor>);
7022pub struct EditorBlurred(pub ViewHandle<Editor>);
7023pub struct EditorReleased(pub WeakViewHandle<Editor>);
7024
7025impl Entity for Editor {
7026    type Event = Event;
7027
7028    fn release(&mut self, cx: &mut AppContext) {
7029        cx.emit_global(EditorReleased(self.handle.clone()));
7030    }
7031}
7032
7033impl View for Editor {
7034    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7035        let style = self.style(cx);
7036        let font_changed = self.display_map.update(cx, |map, cx| {
7037            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7038            map.set_font(style.text.font_id, style.text.font_size, cx)
7039        });
7040
7041        if font_changed {
7042            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7043                hide_hover(editor, cx);
7044                hide_link_definition(editor, cx);
7045            });
7046        }
7047
7048        Stack::new()
7049            .with_child(EditorElement::new(style.clone()))
7050            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7051            .into_any()
7052    }
7053
7054    fn ui_name() -> &'static str {
7055        "Editor"
7056    }
7057
7058    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7059        if cx.is_self_focused() {
7060            let focused_event = EditorFocused(cx.handle());
7061            cx.emit_global(focused_event);
7062        }
7063        if let Some(rename) = self.pending_rename.as_ref() {
7064            cx.focus(&rename.editor);
7065        } else {
7066            if !self.focused {
7067                self.blink_manager.update(cx, BlinkManager::enable);
7068            }
7069            self.focused = true;
7070            self.buffer.update(cx, |buffer, cx| {
7071                buffer.finalize_last_transaction(cx);
7072                if self.leader_replica_id.is_none() {
7073                    buffer.set_active_selections(
7074                        &self.selections.disjoint_anchors(),
7075                        self.selections.line_mode,
7076                        self.cursor_shape,
7077                        cx,
7078                    );
7079                }
7080            });
7081        }
7082    }
7083
7084    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7085        let blurred_event = EditorBlurred(cx.handle());
7086        cx.emit_global(blurred_event);
7087        self.focused = false;
7088        self.blink_manager.update(cx, BlinkManager::disable);
7089        self.buffer
7090            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7091        self.hide_context_menu(cx);
7092        hide_hover(self, cx);
7093        cx.emit(Event::Blurred);
7094        cx.notify();
7095    }
7096
7097    fn modifiers_changed(
7098        &mut self,
7099        event: &gpui::platform::ModifiersChangedEvent,
7100        cx: &mut ViewContext<Self>,
7101    ) -> bool {
7102        let pending_selection = self.has_pending_selection();
7103
7104        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7105            if event.cmd && !pending_selection {
7106                let snapshot = self.snapshot(cx);
7107                let kind = if event.shift {
7108                    LinkDefinitionKind::Type
7109                } else {
7110                    LinkDefinitionKind::Symbol
7111                };
7112
7113                show_link_definition(kind, self, point, snapshot, cx);
7114                return false;
7115            }
7116        }
7117
7118        {
7119            if self.link_go_to_definition_state.symbol_range.is_some()
7120                || !self.link_go_to_definition_state.definitions.is_empty()
7121            {
7122                self.link_go_to_definition_state.symbol_range.take();
7123                self.link_go_to_definition_state.definitions.clear();
7124                cx.notify();
7125            }
7126
7127            self.link_go_to_definition_state.task = None;
7128
7129            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7130        }
7131
7132        false
7133    }
7134
7135    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
7136        let mut context = Self::default_keymap_context();
7137        let mode = match self.mode {
7138            EditorMode::SingleLine => "single_line",
7139            EditorMode::AutoHeight { .. } => "auto_height",
7140            EditorMode::Full => "full",
7141        };
7142        context.add_key("mode", mode);
7143        if self.pending_rename.is_some() {
7144            context.add_identifier("renaming");
7145        }
7146        match self.context_menu.as_ref() {
7147            Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
7148            Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
7149            None => {}
7150        }
7151
7152        for layer in self.keymap_context_layers.values() {
7153            context.extend(layer);
7154        }
7155
7156        context
7157    }
7158
7159    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7160        Some(
7161            self.buffer
7162                .read(cx)
7163                .read(cx)
7164                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7165                .collect(),
7166        )
7167    }
7168
7169    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7170        // Prevent the IME menu from appearing when holding down an alphabetic key
7171        // while input is disabled.
7172        if !self.input_enabled {
7173            return None;
7174        }
7175
7176        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7177        Some(range.start.0..range.end.0)
7178    }
7179
7180    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7181        let snapshot = self.buffer.read(cx).read(cx);
7182        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7183        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7184    }
7185
7186    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7187        self.clear_text_highlights::<InputComposition>(cx);
7188        self.ime_transaction.take();
7189    }
7190
7191    fn replace_text_in_range(
7192        &mut self,
7193        range_utf16: Option<Range<usize>>,
7194        text: &str,
7195        cx: &mut ViewContext<Self>,
7196    ) {
7197        self.transact(cx, |this, cx| {
7198            if this.input_enabled {
7199                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7200                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7201                    Some(this.selection_replacement_ranges(range_utf16, cx))
7202                } else {
7203                    this.marked_text_ranges(cx)
7204                };
7205
7206                if let Some(new_selected_ranges) = new_selected_ranges {
7207                    this.change_selections(None, cx, |selections| {
7208                        selections.select_ranges(new_selected_ranges)
7209                    });
7210                }
7211            }
7212
7213            this.handle_input(text, cx);
7214        });
7215
7216        if !self.input_enabled {
7217            return;
7218        }
7219
7220        if let Some(transaction) = self.ime_transaction {
7221            self.buffer.update(cx, |buffer, cx| {
7222                buffer.group_until_transaction(transaction, cx);
7223            });
7224        }
7225
7226        self.unmark_text(cx);
7227    }
7228
7229    fn replace_and_mark_text_in_range(
7230        &mut self,
7231        range_utf16: Option<Range<usize>>,
7232        text: &str,
7233        new_selected_range_utf16: Option<Range<usize>>,
7234        cx: &mut ViewContext<Self>,
7235    ) {
7236        if !self.input_enabled {
7237            return;
7238        }
7239
7240        let transaction = self.transact(cx, |this, cx| {
7241            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7242                let snapshot = this.buffer.read(cx).read(cx);
7243                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7244                    for marked_range in &mut marked_ranges {
7245                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7246                        marked_range.start.0 += relative_range_utf16.start;
7247                        marked_range.start =
7248                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7249                        marked_range.end =
7250                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7251                    }
7252                }
7253                Some(marked_ranges)
7254            } else if let Some(range_utf16) = range_utf16 {
7255                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7256                Some(this.selection_replacement_ranges(range_utf16, cx))
7257            } else {
7258                None
7259            };
7260
7261            if let Some(ranges) = ranges_to_replace {
7262                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7263            }
7264
7265            let marked_ranges = {
7266                let snapshot = this.buffer.read(cx).read(cx);
7267                this.selections
7268                    .disjoint_anchors()
7269                    .iter()
7270                    .map(|selection| {
7271                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7272                    })
7273                    .collect::<Vec<_>>()
7274            };
7275
7276            if text.is_empty() {
7277                this.unmark_text(cx);
7278            } else {
7279                this.highlight_text::<InputComposition>(
7280                    marked_ranges.clone(),
7281                    this.style(cx).composition_mark,
7282                    cx,
7283                );
7284            }
7285
7286            this.handle_input(text, cx);
7287
7288            if let Some(new_selected_range) = new_selected_range_utf16 {
7289                let snapshot = this.buffer.read(cx).read(cx);
7290                let new_selected_ranges = marked_ranges
7291                    .into_iter()
7292                    .map(|marked_range| {
7293                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7294                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7295                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7296                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7297                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7298                    })
7299                    .collect::<Vec<_>>();
7300
7301                drop(snapshot);
7302                this.change_selections(None, cx, |selections| {
7303                    selections.select_ranges(new_selected_ranges)
7304                });
7305            }
7306        });
7307
7308        self.ime_transaction = self.ime_transaction.or(transaction);
7309        if let Some(transaction) = self.ime_transaction {
7310            self.buffer.update(cx, |buffer, cx| {
7311                buffer.group_until_transaction(transaction, cx);
7312            });
7313        }
7314
7315        if self.text_highlights::<InputComposition>(cx).is_none() {
7316            self.ime_transaction.take();
7317        }
7318    }
7319}
7320
7321fn build_style(
7322    settings: &Settings,
7323    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7324    override_text_style: Option<&OverrideTextStyle>,
7325    cx: &AppContext,
7326) -> EditorStyle {
7327    let font_cache = cx.font_cache();
7328
7329    let theme_id = settings.theme.meta.id;
7330    let mut theme = settings.theme.editor.clone();
7331    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7332        let field_editor_theme = get_field_editor_theme(&settings.theme);
7333        theme.text_color = field_editor_theme.text.color;
7334        theme.selection = field_editor_theme.selection;
7335        theme.background = field_editor_theme
7336            .container
7337            .background_color
7338            .unwrap_or_default();
7339        EditorStyle {
7340            text: field_editor_theme.text,
7341            placeholder_text: field_editor_theme.placeholder_text,
7342            theme,
7343            theme_id,
7344        }
7345    } else {
7346        let font_family_id = settings.buffer_font_family;
7347        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7348        let font_properties = Default::default();
7349        let font_id = font_cache
7350            .select_font(font_family_id, &font_properties)
7351            .unwrap();
7352        let font_size = settings.buffer_font_size;
7353        EditorStyle {
7354            text: TextStyle {
7355                color: settings.theme.editor.text_color,
7356                font_family_name,
7357                font_family_id,
7358                font_id,
7359                font_size,
7360                font_properties,
7361                underline: Default::default(),
7362            },
7363            placeholder_text: None,
7364            theme,
7365            theme_id,
7366        }
7367    };
7368
7369    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7370        if let Some(highlighted) = style
7371            .text
7372            .clone()
7373            .highlight(highlight_style, font_cache)
7374            .log_err()
7375        {
7376            style.text = highlighted;
7377        }
7378    }
7379
7380    style
7381}
7382
7383trait SelectionExt {
7384    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7385    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7386    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7387    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7388        -> Range<u32>;
7389}
7390
7391impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7392    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7393        let start = self.start.to_point(buffer);
7394        let end = self.end.to_point(buffer);
7395        if self.reversed {
7396            end..start
7397        } else {
7398            start..end
7399        }
7400    }
7401
7402    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7403        let start = self.start.to_offset(buffer);
7404        let end = self.end.to_offset(buffer);
7405        if self.reversed {
7406            end..start
7407        } else {
7408            start..end
7409        }
7410    }
7411
7412    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7413        let start = self
7414            .start
7415            .to_point(&map.buffer_snapshot)
7416            .to_display_point(map);
7417        let end = self
7418            .end
7419            .to_point(&map.buffer_snapshot)
7420            .to_display_point(map);
7421        if self.reversed {
7422            end..start
7423        } else {
7424            start..end
7425        }
7426    }
7427
7428    fn spanned_rows(
7429        &self,
7430        include_end_if_at_line_start: bool,
7431        map: &DisplaySnapshot,
7432    ) -> Range<u32> {
7433        let start = self.start.to_point(&map.buffer_snapshot);
7434        let mut end = self.end.to_point(&map.buffer_snapshot);
7435        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7436            end.row -= 1;
7437        }
7438
7439        let buffer_start = map.prev_line_boundary(start).0;
7440        let buffer_end = map.next_line_boundary(end).0;
7441        buffer_start.row..buffer_end.row + 1
7442    }
7443}
7444
7445impl<T: InvalidationRegion> InvalidationStack<T> {
7446    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7447    where
7448        S: Clone + ToOffset,
7449    {
7450        while let Some(region) = self.last() {
7451            let all_selections_inside_invalidation_ranges =
7452                if selections.len() == region.ranges().len() {
7453                    selections
7454                        .iter()
7455                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7456                        .all(|(selection, invalidation_range)| {
7457                            let head = selection.head().to_offset(buffer);
7458                            invalidation_range.start <= head && invalidation_range.end >= head
7459                        })
7460                } else {
7461                    false
7462                };
7463
7464            if all_selections_inside_invalidation_ranges {
7465                break;
7466            } else {
7467                self.pop();
7468            }
7469        }
7470    }
7471}
7472
7473impl<T> Default for InvalidationStack<T> {
7474    fn default() -> Self {
7475        Self(Default::default())
7476    }
7477}
7478
7479impl<T> Deref for InvalidationStack<T> {
7480    type Target = Vec<T>;
7481
7482    fn deref(&self) -> &Self::Target {
7483        &self.0
7484    }
7485}
7486
7487impl<T> DerefMut for InvalidationStack<T> {
7488    fn deref_mut(&mut self) -> &mut Self::Target {
7489        &mut self.0
7490    }
7491}
7492
7493impl InvalidationRegion for SnippetState {
7494    fn ranges(&self) -> &[Range<Anchor>] {
7495        &self.ranges[self.active_index]
7496    }
7497}
7498
7499impl Deref for EditorStyle {
7500    type Target = theme::Editor;
7501
7502    fn deref(&self) -> &Self::Target {
7503        &self.theme
7504    }
7505}
7506
7507pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7508    let mut highlighted_lines = Vec::new();
7509    for line in diagnostic.message.lines() {
7510        highlighted_lines.push(highlight_diagnostic_message(line));
7511    }
7512
7513    Arc::new(move |cx: &mut BlockContext| {
7514        let settings = cx.global::<Settings>();
7515        let theme = &settings.theme.editor;
7516        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7517        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7518        Flex::column()
7519            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7520                Label::new(
7521                    line.clone(),
7522                    style.message.clone().with_font_size(font_size),
7523                )
7524                .with_highlights(highlights.clone())
7525                .contained()
7526                .with_margin_left(cx.anchor_x)
7527            }))
7528            .aligned()
7529            .left()
7530            .into_any()
7531    })
7532}
7533
7534pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
7535    let mut message_without_backticks = String::new();
7536    let mut prev_offset = 0;
7537    let mut inside_block = false;
7538    let mut highlights = Vec::new();
7539    for (match_ix, (offset, _)) in message
7540        .match_indices('`')
7541        .chain([(message.len(), "")])
7542        .enumerate()
7543    {
7544        message_without_backticks.push_str(&message[prev_offset..offset]);
7545        if inside_block {
7546            highlights.extend(prev_offset - match_ix..offset - match_ix);
7547        }
7548
7549        inside_block = !inside_block;
7550        prev_offset = offset + 1;
7551    }
7552
7553    (message_without_backticks, highlights)
7554}
7555
7556pub fn diagnostic_style(
7557    severity: DiagnosticSeverity,
7558    valid: bool,
7559    theme: &theme::Editor,
7560) -> DiagnosticStyle {
7561    match (severity, valid) {
7562        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7563        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7564        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7565        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7566        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7567        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7568        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7569        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7570        _ => theme.invalid_hint_diagnostic.clone(),
7571    }
7572}
7573
7574pub fn combine_syntax_and_fuzzy_match_highlights(
7575    text: &str,
7576    default_style: HighlightStyle,
7577    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7578    match_indices: &[usize],
7579) -> Vec<(Range<usize>, HighlightStyle)> {
7580    let mut result = Vec::new();
7581    let mut match_indices = match_indices.iter().copied().peekable();
7582
7583    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7584    {
7585        syntax_highlight.weight = None;
7586
7587        // Add highlights for any fuzzy match characters before the next
7588        // syntax highlight range.
7589        while let Some(&match_index) = match_indices.peek() {
7590            if match_index >= range.start {
7591                break;
7592            }
7593            match_indices.next();
7594            let end_index = char_ix_after(match_index, text);
7595            let mut match_style = default_style;
7596            match_style.weight = Some(fonts::Weight::BOLD);
7597            result.push((match_index..end_index, match_style));
7598        }
7599
7600        if range.start == usize::MAX {
7601            break;
7602        }
7603
7604        // Add highlights for any fuzzy match characters within the
7605        // syntax highlight range.
7606        let mut offset = range.start;
7607        while let Some(&match_index) = match_indices.peek() {
7608            if match_index >= range.end {
7609                break;
7610            }
7611
7612            match_indices.next();
7613            if match_index > offset {
7614                result.push((offset..match_index, syntax_highlight));
7615            }
7616
7617            let mut end_index = char_ix_after(match_index, text);
7618            while let Some(&next_match_index) = match_indices.peek() {
7619                if next_match_index == end_index && next_match_index < range.end {
7620                    end_index = char_ix_after(next_match_index, text);
7621                    match_indices.next();
7622                } else {
7623                    break;
7624                }
7625            }
7626
7627            let mut match_style = syntax_highlight;
7628            match_style.weight = Some(fonts::Weight::BOLD);
7629            result.push((match_index..end_index, match_style));
7630            offset = end_index;
7631        }
7632
7633        if offset < range.end {
7634            result.push((offset..range.end, syntax_highlight));
7635        }
7636    }
7637
7638    fn char_ix_after(ix: usize, text: &str) -> usize {
7639        ix + text[ix..].chars().next().unwrap().len_utf8()
7640    }
7641
7642    result
7643}
7644
7645pub fn styled_runs_for_code_label<'a>(
7646    label: &'a CodeLabel,
7647    syntax_theme: &'a theme::SyntaxTheme,
7648) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7649    let fade_out = HighlightStyle {
7650        fade_out: Some(0.35),
7651        ..Default::default()
7652    };
7653
7654    let mut prev_end = label.filter_range.end;
7655    label
7656        .runs
7657        .iter()
7658        .enumerate()
7659        .flat_map(move |(ix, (range, highlight_id))| {
7660            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7661                style
7662            } else {
7663                return Default::default();
7664            };
7665            let mut muted_style = style;
7666            muted_style.highlight(fade_out);
7667
7668            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7669            if range.start >= label.filter_range.end {
7670                if range.start > prev_end {
7671                    runs.push((prev_end..range.start, fade_out));
7672                }
7673                runs.push((range.clone(), muted_style));
7674            } else if range.end <= label.filter_range.end {
7675                runs.push((range.clone(), style));
7676            } else {
7677                runs.push((range.start..label.filter_range.end, style));
7678                runs.push((label.filter_range.end..range.end, muted_style));
7679            }
7680            prev_end = cmp::max(prev_end, range.end);
7681
7682            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7683                runs.push((prev_end..label.text.len(), fade_out));
7684            }
7685
7686            runs
7687        })
7688}
7689
7690pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7691    let mut index = 0;
7692    let mut codepoints = text.char_indices().peekable();
7693
7694    std::iter::from_fn(move || {
7695        let start_index = index;
7696        while let Some((new_index, codepoint)) = codepoints.next() {
7697            index = new_index + codepoint.len_utf8();
7698            let current_upper = codepoint.is_uppercase();
7699            let next_upper = codepoints
7700                .peek()
7701                .map(|(_, c)| c.is_uppercase())
7702                .unwrap_or(false);
7703
7704            if !current_upper && next_upper {
7705                return Some(&text[start_index..index]);
7706            }
7707        }
7708
7709        index = text.len();
7710        if start_index < text.len() {
7711            return Some(&text[start_index..]);
7712        }
7713        None
7714    })
7715    .flat_map(|word| word.split_inclusive('_'))
7716}
7717
7718trait RangeToAnchorExt {
7719    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7720}
7721
7722impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7723    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7724        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7725    }
7726}