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