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