editor.rs

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