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