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