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