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