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