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