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 ::git::diff::DiffHunk;
  24use aho_corasick::AhoCorasick;
  25use anyhow::{anyhow, Result};
  26use blink_manager::BlinkManager;
  27use client::{ClickhouseEvent, TelemetrySettings};
  28use clock::ReplicaId;
  29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  30use copilot::Copilot;
  31pub use display_map::DisplayPoint;
  32use display_map::*;
  33pub use editor_settings::EditorSettings;
  34pub use element::*;
  35use futures::FutureExt;
  36use fuzzy::{StringMatch, StringMatchCandidate};
  37use gpui::{
  38    actions,
  39    color::Color,
  40    elements::*,
  41    executor,
  42    fonts::{self, HighlightStyle, TextStyle},
  43    geometry::vector::Vector2F,
  44    impl_actions,
  45    keymap_matcher::KeymapContext,
  46    platform::{CursorStyle, MouseButton},
  47    serde_json::{self, json},
  48    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  49    ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
  50};
  51use highlight_matching_bracket::refresh_matching_bracket_highlights;
  52use hover_popover::{hide_hover, HoverState};
  53pub use items::MAX_TAB_TITLE_LEN;
  54use itertools::Itertools;
  55pub use language::{char_kind, CharKind};
  56use language::{
  57    language_settings::{self, all_language_settings},
  58    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  59    Diagnostic, DiagnosticSeverity, File, IndentKind, IndentSize, Language, OffsetRangeExt,
  60    OffsetUtf16, Point, Selection, SelectionGoal, TransactionId,
  61};
  62use link_go_to_definition::{
  63    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  64};
  65pub use multi_buffer::{
  66    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  67    ToPoint,
  68};
  69use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  70use ordered_float::OrderedFloat;
  71use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  72use scroll::{
  73    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  74};
  75use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  76use serde::{Deserialize, Serialize};
  77use settings::SettingsStore;
  78use smallvec::SmallVec;
  79use snippet::Snippet;
  80use std::{
  81    any::TypeId,
  82    borrow::Cow,
  83    cmp::{self, Ordering, Reverse},
  84    mem,
  85    num::NonZeroU32,
  86    ops::{Deref, DerefMut, Range},
  87    path::Path,
  88    sync::Arc,
  89    time::{Duration, Instant},
  90};
  91pub use sum_tree::Bias;
  92use theme::{DiagnosticStyle, Theme, ThemeSettings};
  93use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  94use workspace::{ItemNavHistory, ViewId, Workspace};
  95
  96use crate::git::diff_hunk_to_display;
  97
  98const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  99const MAX_LINE_LEN: usize = 1024;
 100const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 101const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 102const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 103
 104pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 105
 106#[derive(Clone, Deserialize, PartialEq, Default)]
 107pub struct SelectNext {
 108    #[serde(default)]
 109    pub replace_newest: bool,
 110}
 111
 112#[derive(Clone, Deserialize, PartialEq)]
 113pub struct SelectToBeginningOfLine {
 114    #[serde(default)]
 115    stop_at_soft_wraps: bool,
 116}
 117
 118#[derive(Clone, Default, Deserialize, PartialEq)]
 119pub struct MovePageUp {
 120    #[serde(default)]
 121    center_cursor: bool,
 122}
 123
 124#[derive(Clone, Default, Deserialize, PartialEq)]
 125pub struct MovePageDown {
 126    #[serde(default)]
 127    center_cursor: bool,
 128}
 129
 130#[derive(Clone, Deserialize, PartialEq)]
 131pub struct SelectToEndOfLine {
 132    #[serde(default)]
 133    stop_at_soft_wraps: bool,
 134}
 135
 136#[derive(Clone, Deserialize, PartialEq)]
 137pub struct ToggleCodeActions {
 138    #[serde(default)]
 139    pub deployed_from_indicator: bool,
 140}
 141
 142#[derive(Clone, Default, Deserialize, PartialEq)]
 143pub struct ConfirmCompletion {
 144    #[serde(default)]
 145    pub item_ix: Option<usize>,
 146}
 147
 148#[derive(Clone, Default, Deserialize, PartialEq)]
 149pub struct ConfirmCodeAction {
 150    #[serde(default)]
 151    pub item_ix: Option<usize>,
 152}
 153
 154#[derive(Clone, Default, Deserialize, PartialEq)]
 155pub struct ToggleComments {
 156    #[serde(default)]
 157    pub advance_downwards: bool,
 158}
 159
 160#[derive(Clone, Default, Deserialize, PartialEq)]
 161pub struct FoldAt {
 162    pub buffer_row: u32,
 163}
 164
 165#[derive(Clone, Default, Deserialize, PartialEq)]
 166pub struct UnfoldAt {
 167    pub buffer_row: u32,
 168}
 169
 170#[derive(Clone, Default, Deserialize, PartialEq)]
 171pub struct GutterHover {
 172    pub hovered: bool,
 173}
 174
 175actions!(
 176    editor,
 177    [
 178        Cancel,
 179        Backspace,
 180        Delete,
 181        Newline,
 182        NewlineAbove,
 183        NewlineBelow,
 184        GoToDiagnostic,
 185        GoToPrevDiagnostic,
 186        GoToHunk,
 187        GoToPrevHunk,
 188        Indent,
 189        Outdent,
 190        DeleteLine,
 191        DeleteToPreviousWordStart,
 192        DeleteToPreviousSubwordStart,
 193        DeleteToNextWordEnd,
 194        DeleteToNextSubwordEnd,
 195        DeleteToBeginningOfLine,
 196        DeleteToEndOfLine,
 197        CutToEndOfLine,
 198        DuplicateLine,
 199        MoveLineUp,
 200        MoveLineDown,
 201        Transpose,
 202        Cut,
 203        Copy,
 204        Paste,
 205        Undo,
 206        Redo,
 207        MoveUp,
 208        PageUp,
 209        MoveDown,
 210        PageDown,
 211        MoveLeft,
 212        MoveRight,
 213        MoveToPreviousWordStart,
 214        MoveToPreviousSubwordStart,
 215        MoveToNextWordEnd,
 216        MoveToNextSubwordEnd,
 217        MoveToBeginningOfLine,
 218        MoveToEndOfLine,
 219        MoveToStartOfParagraph,
 220        MoveToEndOfParagraph,
 221        MoveToBeginning,
 222        MoveToEnd,
 223        SelectUp,
 224        SelectDown,
 225        SelectLeft,
 226        SelectRight,
 227        SelectToPreviousWordStart,
 228        SelectToPreviousSubwordStart,
 229        SelectToNextWordEnd,
 230        SelectToNextSubwordEnd,
 231        SelectToStartOfParagraph,
 232        SelectToEndOfParagraph,
 233        SelectToBeginning,
 234        SelectToEnd,
 235        SelectAll,
 236        SelectLine,
 237        SplitSelectionIntoLines,
 238        AddSelectionAbove,
 239        AddSelectionBelow,
 240        Tab,
 241        TabPrev,
 242        ShowCharacterPalette,
 243        SelectLargerSyntaxNode,
 244        SelectSmallerSyntaxNode,
 245        GoToDefinition,
 246        GoToTypeDefinition,
 247        MoveToEnclosingBracket,
 248        UndoSelection,
 249        RedoSelection,
 250        FindAllReferences,
 251        Rename,
 252        ConfirmRename,
 253        Fold,
 254        UnfoldLines,
 255        FoldSelectedRanges,
 256        ShowCompletions,
 257        OpenExcerpts,
 258        RestartLanguageServer,
 259        Hover,
 260        Format,
 261        ToggleSoftWrap,
 262        RevealInFinder,
 263        CopyPath,
 264        CopyRelativePath,
 265        CopyHighlightJson
 266    ]
 267);
 268
 269impl_actions!(
 270    editor,
 271    [
 272        SelectNext,
 273        SelectToBeginningOfLine,
 274        SelectToEndOfLine,
 275        ToggleCodeActions,
 276        MovePageUp,
 277        MovePageDown,
 278        ConfirmCompletion,
 279        ConfirmCodeAction,
 280        ToggleComments,
 281        FoldAt,
 282        UnfoldAt,
 283        GutterHover
 284    ]
 285);
 286
 287enum DocumentHighlightRead {}
 288enum DocumentHighlightWrite {}
 289enum InputComposition {}
 290
 291#[derive(Copy, Clone, PartialEq, Eq)]
 292pub enum Direction {
 293    Prev,
 294    Next,
 295}
 296
 297pub fn init_settings(cx: &mut AppContext) {
 298    settings::register::<EditorSettings>(cx);
 299}
 300
 301pub fn init(cx: &mut AppContext) {
 302    init_settings(cx);
 303    cx.add_action(Editor::new_file);
 304    cx.add_action(Editor::cancel);
 305    cx.add_action(Editor::newline);
 306    cx.add_action(Editor::newline_above);
 307    cx.add_action(Editor::newline_below);
 308    cx.add_action(Editor::backspace);
 309    cx.add_action(Editor::delete);
 310    cx.add_action(Editor::tab);
 311    cx.add_action(Editor::tab_prev);
 312    cx.add_action(Editor::indent);
 313    cx.add_action(Editor::outdent);
 314    cx.add_action(Editor::delete_line);
 315    cx.add_action(Editor::delete_to_previous_word_start);
 316    cx.add_action(Editor::delete_to_previous_subword_start);
 317    cx.add_action(Editor::delete_to_next_word_end);
 318    cx.add_action(Editor::delete_to_next_subword_end);
 319    cx.add_action(Editor::delete_to_beginning_of_line);
 320    cx.add_action(Editor::delete_to_end_of_line);
 321    cx.add_action(Editor::cut_to_end_of_line);
 322    cx.add_action(Editor::duplicate_line);
 323    cx.add_action(Editor::move_line_up);
 324    cx.add_action(Editor::move_line_down);
 325    cx.add_action(Editor::transpose);
 326    cx.add_action(Editor::cut);
 327    cx.add_action(Editor::copy);
 328    cx.add_action(Editor::paste);
 329    cx.add_action(Editor::undo);
 330    cx.add_action(Editor::redo);
 331    cx.add_action(Editor::move_up);
 332    cx.add_action(Editor::move_page_up);
 333    cx.add_action(Editor::move_down);
 334    cx.add_action(Editor::move_page_down);
 335    cx.add_action(Editor::next_screen);
 336    cx.add_action(Editor::move_left);
 337    cx.add_action(Editor::move_right);
 338    cx.add_action(Editor::move_to_previous_word_start);
 339    cx.add_action(Editor::move_to_previous_subword_start);
 340    cx.add_action(Editor::move_to_next_word_end);
 341    cx.add_action(Editor::move_to_next_subword_end);
 342    cx.add_action(Editor::move_to_beginning_of_line);
 343    cx.add_action(Editor::move_to_end_of_line);
 344    cx.add_action(Editor::move_to_start_of_paragraph);
 345    cx.add_action(Editor::move_to_end_of_paragraph);
 346    cx.add_action(Editor::move_to_beginning);
 347    cx.add_action(Editor::move_to_end);
 348    cx.add_action(Editor::select_up);
 349    cx.add_action(Editor::select_down);
 350    cx.add_action(Editor::select_left);
 351    cx.add_action(Editor::select_right);
 352    cx.add_action(Editor::select_to_previous_word_start);
 353    cx.add_action(Editor::select_to_previous_subword_start);
 354    cx.add_action(Editor::select_to_next_word_end);
 355    cx.add_action(Editor::select_to_next_subword_end);
 356    cx.add_action(Editor::select_to_beginning_of_line);
 357    cx.add_action(Editor::select_to_end_of_line);
 358    cx.add_action(Editor::select_to_start_of_paragraph);
 359    cx.add_action(Editor::select_to_end_of_paragraph);
 360    cx.add_action(Editor::select_to_beginning);
 361    cx.add_action(Editor::select_to_end);
 362    cx.add_action(Editor::select_all);
 363    cx.add_action(Editor::select_line);
 364    cx.add_action(Editor::split_selection_into_lines);
 365    cx.add_action(Editor::add_selection_above);
 366    cx.add_action(Editor::add_selection_below);
 367    cx.add_action(Editor::select_next);
 368    cx.add_action(Editor::toggle_comments);
 369    cx.add_action(Editor::select_larger_syntax_node);
 370    cx.add_action(Editor::select_smaller_syntax_node);
 371    cx.add_action(Editor::move_to_enclosing_bracket);
 372    cx.add_action(Editor::undo_selection);
 373    cx.add_action(Editor::redo_selection);
 374    cx.add_action(Editor::go_to_diagnostic);
 375    cx.add_action(Editor::go_to_prev_diagnostic);
 376    cx.add_action(Editor::go_to_hunk);
 377    cx.add_action(Editor::go_to_prev_hunk);
 378    cx.add_action(Editor::go_to_definition);
 379    cx.add_action(Editor::go_to_type_definition);
 380    cx.add_action(Editor::fold);
 381    cx.add_action(Editor::fold_at);
 382    cx.add_action(Editor::unfold_lines);
 383    cx.add_action(Editor::unfold_at);
 384    cx.add_action(Editor::gutter_hover);
 385    cx.add_action(Editor::fold_selected_ranges);
 386    cx.add_action(Editor::show_completions);
 387    cx.add_action(Editor::toggle_code_actions);
 388    cx.add_action(Editor::open_excerpts);
 389    cx.add_action(Editor::toggle_soft_wrap);
 390    cx.add_action(Editor::reveal_in_finder);
 391    cx.add_action(Editor::copy_path);
 392    cx.add_action(Editor::copy_relative_path);
 393    cx.add_action(Editor::copy_highlight_json);
 394    cx.add_async_action(Editor::format);
 395    cx.add_action(Editor::restart_language_server);
 396    cx.add_action(Editor::show_character_palette);
 397    cx.add_async_action(Editor::confirm_completion);
 398    cx.add_async_action(Editor::confirm_code_action);
 399    cx.add_async_action(Editor::rename);
 400    cx.add_async_action(Editor::confirm_rename);
 401    cx.add_async_action(Editor::find_all_references);
 402    cx.add_action(Editor::next_copilot_suggestion);
 403    cx.add_action(Editor::previous_copilot_suggestion);
 404    cx.add_action(Editor::copilot_suggest);
 405
 406    hover_popover::init(cx);
 407    scroll::actions::init(cx);
 408
 409    workspace::register_project_item::<Editor>(cx);
 410    workspace::register_followable_item::<Editor>(cx);
 411    workspace::register_deserializable_item::<Editor>(cx);
 412}
 413
 414trait InvalidationRegion {
 415    fn ranges(&self) -> &[Range<Anchor>];
 416}
 417
 418#[derive(Clone, Debug, PartialEq)]
 419pub enum SelectPhase {
 420    Begin {
 421        position: DisplayPoint,
 422        add: bool,
 423        click_count: usize,
 424    },
 425    BeginColumnar {
 426        position: DisplayPoint,
 427        goal_column: u32,
 428    },
 429    Extend {
 430        position: DisplayPoint,
 431        click_count: usize,
 432    },
 433    Update {
 434        position: DisplayPoint,
 435        goal_column: u32,
 436        scroll_position: Vector2F,
 437    },
 438    End,
 439}
 440
 441#[derive(Clone, Debug)]
 442pub enum SelectMode {
 443    Character,
 444    Word(Range<Anchor>),
 445    Line(Range<Anchor>),
 446    All,
 447}
 448
 449#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 450pub enum EditorMode {
 451    SingleLine,
 452    AutoHeight { max_lines: usize },
 453    Full,
 454}
 455
 456#[derive(Clone, Debug)]
 457pub enum SoftWrap {
 458    None,
 459    EditorWidth,
 460    Column(u32),
 461}
 462
 463#[derive(Clone)]
 464pub struct EditorStyle {
 465    pub text: TextStyle,
 466    pub placeholder_text: Option<TextStyle>,
 467    pub theme: theme::Editor,
 468    pub theme_id: usize,
 469}
 470
 471type CompletionId = usize;
 472
 473type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 474type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 475
 476pub struct Editor {
 477    handle: WeakViewHandle<Self>,
 478    buffer: ModelHandle<MultiBuffer>,
 479    display_map: ModelHandle<DisplayMap>,
 480    pub selections: SelectionsCollection,
 481    pub scroll_manager: ScrollManager,
 482    columnar_selection_tail: Option<Anchor>,
 483    add_selections_state: Option<AddSelectionsState>,
 484    select_next_state: Option<SelectNextState>,
 485    selection_history: SelectionHistory,
 486    autoclose_regions: Vec<AutocloseRegion>,
 487    snippet_stack: InvalidationStack<SnippetState>,
 488    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 489    ime_transaction: Option<TransactionId>,
 490    active_diagnostics: Option<ActiveDiagnosticGroup>,
 491    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 492    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 493    override_text_style: Option<Box<OverrideTextStyle>>,
 494    project: Option<ModelHandle<Project>>,
 495    focused: bool,
 496    blink_manager: ModelHandle<BlinkManager>,
 497    show_local_selections: bool,
 498    mode: EditorMode,
 499    placeholder_text: Option<Arc<str>>,
 500    highlighted_rows: Option<Range<u32>>,
 501    #[allow(clippy::type_complexity)]
 502    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 503    nav_history: Option<ItemNavHistory>,
 504    context_menu: Option<ContextMenu>,
 505    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 506    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 507    next_completion_id: CompletionId,
 508    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 509    code_actions_task: Option<Task<()>>,
 510    document_highlights_task: Option<Task<()>>,
 511    pending_rename: Option<RenameState>,
 512    searchable: bool,
 513    cursor_shape: CursorShape,
 514    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 515    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 516    input_enabled: bool,
 517    read_only: bool,
 518    leader_replica_id: Option<u16>,
 519    remote_id: Option<ViewId>,
 520    hover_state: HoverState,
 521    gutter_hovered: bool,
 522    link_go_to_definition_state: LinkGoToDefinitionState,
 523    copilot_state: CopilotState,
 524    _subscriptions: Vec<Subscription>,
 525}
 526
 527pub struct EditorSnapshot {
 528    pub mode: EditorMode,
 529    pub display_snapshot: DisplaySnapshot,
 530    pub placeholder_text: Option<Arc<str>>,
 531    is_focused: bool,
 532    scroll_anchor: ScrollAnchor,
 533    ongoing_scroll: OngoingScroll,
 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_start_of_paragraph(
4765        &mut self,
4766        _: &MoveToStartOfParagraph,
4767        cx: &mut ViewContext<Self>,
4768    ) {
4769        if matches!(self.mode, EditorMode::SingleLine) {
4770            cx.propagate_action();
4771            return;
4772        }
4773
4774        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4775            s.move_with(|map, selection| {
4776                selection.collapse_to(
4777                    movement::start_of_paragraph(map, selection.head()),
4778                    SelectionGoal::None,
4779                )
4780            });
4781        })
4782    }
4783
4784    pub fn move_to_end_of_paragraph(
4785        &mut self,
4786        _: &MoveToEndOfParagraph,
4787        cx: &mut ViewContext<Self>,
4788    ) {
4789        if matches!(self.mode, EditorMode::SingleLine) {
4790            cx.propagate_action();
4791            return;
4792        }
4793
4794        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4795            s.move_with(|map, selection| {
4796                selection.collapse_to(
4797                    movement::end_of_paragraph(map, selection.head()),
4798                    SelectionGoal::None,
4799                )
4800            });
4801        })
4802    }
4803
4804    pub fn select_to_start_of_paragraph(
4805        &mut self,
4806        _: &SelectToStartOfParagraph,
4807        cx: &mut ViewContext<Self>,
4808    ) {
4809        if matches!(self.mode, EditorMode::SingleLine) {
4810            cx.propagate_action();
4811            return;
4812        }
4813
4814        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4815            s.move_heads_with(|map, head, _| {
4816                (movement::start_of_paragraph(map, head), SelectionGoal::None)
4817            });
4818        })
4819    }
4820
4821    pub fn select_to_end_of_paragraph(
4822        &mut self,
4823        _: &SelectToEndOfParagraph,
4824        cx: &mut ViewContext<Self>,
4825    ) {
4826        if matches!(self.mode, EditorMode::SingleLine) {
4827            cx.propagate_action();
4828            return;
4829        }
4830
4831        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4832            s.move_heads_with(|map, head, _| {
4833                (movement::end_of_paragraph(map, head), SelectionGoal::None)
4834            });
4835        })
4836    }
4837
4838    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4839        if matches!(self.mode, EditorMode::SingleLine) {
4840            cx.propagate_action();
4841            return;
4842        }
4843
4844        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4845            s.select_ranges(vec![0..0]);
4846        });
4847    }
4848
4849    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4850        let mut selection = self.selections.last::<Point>(cx);
4851        selection.set_head(Point::zero(), SelectionGoal::None);
4852
4853        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4854            s.select(vec![selection]);
4855        });
4856    }
4857
4858    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4859        if matches!(self.mode, EditorMode::SingleLine) {
4860            cx.propagate_action();
4861            return;
4862        }
4863
4864        let cursor = self.buffer.read(cx).read(cx).len();
4865        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4866            s.select_ranges(vec![cursor..cursor])
4867        });
4868    }
4869
4870    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4871        self.nav_history = nav_history;
4872    }
4873
4874    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4875        self.nav_history.as_ref()
4876    }
4877
4878    fn push_to_nav_history(
4879        &self,
4880        cursor_anchor: Anchor,
4881        new_position: Option<Point>,
4882        cx: &mut ViewContext<Self>,
4883    ) {
4884        if let Some(nav_history) = &self.nav_history {
4885            let buffer = self.buffer.read(cx).read(cx);
4886            let cursor_position = cursor_anchor.to_point(&buffer);
4887            let scroll_state = self.scroll_manager.anchor();
4888            let scroll_top_row = scroll_state.top_row(&buffer);
4889            drop(buffer);
4890
4891            if let Some(new_position) = new_position {
4892                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4893                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4894                    return;
4895                }
4896            }
4897
4898            nav_history.push(
4899                Some(NavigationData {
4900                    cursor_anchor,
4901                    cursor_position,
4902                    scroll_anchor: scroll_state,
4903                    scroll_top_row,
4904                }),
4905                cx,
4906            );
4907        }
4908    }
4909
4910    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4911        let buffer = self.buffer.read(cx).snapshot(cx);
4912        let mut selection = self.selections.first::<usize>(cx);
4913        selection.set_head(buffer.len(), SelectionGoal::None);
4914        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4915            s.select(vec![selection]);
4916        });
4917    }
4918
4919    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4920        let end = self.buffer.read(cx).read(cx).len();
4921        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4922            s.select_ranges(vec![0..end]);
4923        });
4924    }
4925
4926    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4927        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4928        let mut selections = self.selections.all::<Point>(cx);
4929        let max_point = display_map.buffer_snapshot.max_point();
4930        for selection in &mut selections {
4931            let rows = selection.spanned_rows(true, &display_map);
4932            selection.start = Point::new(rows.start, 0);
4933            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4934            selection.reversed = false;
4935        }
4936        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4937            s.select(selections);
4938        });
4939    }
4940
4941    pub fn split_selection_into_lines(
4942        &mut self,
4943        _: &SplitSelectionIntoLines,
4944        cx: &mut ViewContext<Self>,
4945    ) {
4946        let mut to_unfold = Vec::new();
4947        let mut new_selection_ranges = Vec::new();
4948        {
4949            let selections = self.selections.all::<Point>(cx);
4950            let buffer = self.buffer.read(cx).read(cx);
4951            for selection in selections {
4952                for row in selection.start.row..selection.end.row {
4953                    let cursor = Point::new(row, buffer.line_len(row));
4954                    new_selection_ranges.push(cursor..cursor);
4955                }
4956                new_selection_ranges.push(selection.end..selection.end);
4957                to_unfold.push(selection.start..selection.end);
4958            }
4959        }
4960        self.unfold_ranges(to_unfold, true, true, cx);
4961        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4962            s.select_ranges(new_selection_ranges);
4963        });
4964    }
4965
4966    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4967        self.add_selection(true, cx);
4968    }
4969
4970    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4971        self.add_selection(false, cx);
4972    }
4973
4974    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4975        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4976        let mut selections = self.selections.all::<Point>(cx);
4977        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4978            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4979            let range = oldest_selection.display_range(&display_map).sorted();
4980            let columns = cmp::min(range.start.column(), range.end.column())
4981                ..cmp::max(range.start.column(), range.end.column());
4982
4983            selections.clear();
4984            let mut stack = Vec::new();
4985            for row in range.start.row()..=range.end.row() {
4986                if let Some(selection) = self.selections.build_columnar_selection(
4987                    &display_map,
4988                    row,
4989                    &columns,
4990                    oldest_selection.reversed,
4991                ) {
4992                    stack.push(selection.id);
4993                    selections.push(selection);
4994                }
4995            }
4996
4997            if above {
4998                stack.reverse();
4999            }
5000
5001            AddSelectionsState { above, stack }
5002        });
5003
5004        let last_added_selection = *state.stack.last().unwrap();
5005        let mut new_selections = Vec::new();
5006        if above == state.above {
5007            let end_row = if above {
5008                0
5009            } else {
5010                display_map.max_point().row()
5011            };
5012
5013            'outer: for selection in selections {
5014                if selection.id == last_added_selection {
5015                    let range = selection.display_range(&display_map).sorted();
5016                    debug_assert_eq!(range.start.row(), range.end.row());
5017                    let mut row = range.start.row();
5018                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5019                    {
5020                        start..end
5021                    } else {
5022                        cmp::min(range.start.column(), range.end.column())
5023                            ..cmp::max(range.start.column(), range.end.column())
5024                    };
5025
5026                    while row != end_row {
5027                        if above {
5028                            row -= 1;
5029                        } else {
5030                            row += 1;
5031                        }
5032
5033                        if let Some(new_selection) = self.selections.build_columnar_selection(
5034                            &display_map,
5035                            row,
5036                            &columns,
5037                            selection.reversed,
5038                        ) {
5039                            state.stack.push(new_selection.id);
5040                            if above {
5041                                new_selections.push(new_selection);
5042                                new_selections.push(selection);
5043                            } else {
5044                                new_selections.push(selection);
5045                                new_selections.push(new_selection);
5046                            }
5047
5048                            continue 'outer;
5049                        }
5050                    }
5051                }
5052
5053                new_selections.push(selection);
5054            }
5055        } else {
5056            new_selections = selections;
5057            new_selections.retain(|s| s.id != last_added_selection);
5058            state.stack.pop();
5059        }
5060
5061        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5062            s.select(new_selections);
5063        });
5064        if state.stack.len() > 1 {
5065            self.add_selections_state = Some(state);
5066        }
5067    }
5068
5069    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5070        self.push_to_selection_history();
5071        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5072        let buffer = &display_map.buffer_snapshot;
5073        let mut selections = self.selections.all::<usize>(cx);
5074        if let Some(mut select_next_state) = self.select_next_state.take() {
5075            let query = &select_next_state.query;
5076            if !select_next_state.done {
5077                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5078                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5079                let mut next_selected_range = None;
5080
5081                let bytes_after_last_selection =
5082                    buffer.bytes_in_range(last_selection.end..buffer.len());
5083                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5084                let query_matches = query
5085                    .stream_find_iter(bytes_after_last_selection)
5086                    .map(|result| (last_selection.end, result))
5087                    .chain(
5088                        query
5089                            .stream_find_iter(bytes_before_first_selection)
5090                            .map(|result| (0, result)),
5091                    );
5092                for (start_offset, query_match) in query_matches {
5093                    let query_match = query_match.unwrap(); // can only fail due to I/O
5094                    let offset_range =
5095                        start_offset + query_match.start()..start_offset + query_match.end();
5096                    let display_range = offset_range.start.to_display_point(&display_map)
5097                        ..offset_range.end.to_display_point(&display_map);
5098
5099                    if !select_next_state.wordwise
5100                        || (!movement::is_inside_word(&display_map, display_range.start)
5101                            && !movement::is_inside_word(&display_map, display_range.end))
5102                    {
5103                        next_selected_range = Some(offset_range);
5104                        break;
5105                    }
5106                }
5107
5108                if let Some(next_selected_range) = next_selected_range {
5109                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5110                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5111                        if action.replace_newest {
5112                            s.delete(s.newest_anchor().id);
5113                        }
5114                        s.insert_range(next_selected_range);
5115                    });
5116                } else {
5117                    select_next_state.done = true;
5118                }
5119            }
5120
5121            self.select_next_state = Some(select_next_state);
5122        } else if selections.len() == 1 {
5123            let selection = selections.last_mut().unwrap();
5124            if selection.start == selection.end {
5125                let word_range = movement::surrounding_word(
5126                    &display_map,
5127                    selection.start.to_display_point(&display_map),
5128                );
5129                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5130                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5131                selection.goal = SelectionGoal::None;
5132                selection.reversed = false;
5133
5134                let query = buffer
5135                    .text_for_range(selection.start..selection.end)
5136                    .collect::<String>();
5137                let select_state = SelectNextState {
5138                    query: AhoCorasick::new_auto_configured(&[query]),
5139                    wordwise: true,
5140                    done: false,
5141                };
5142                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5143                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5144                    s.select(selections);
5145                });
5146                self.select_next_state = Some(select_state);
5147            } else {
5148                let query = buffer
5149                    .text_for_range(selection.start..selection.end)
5150                    .collect::<String>();
5151                self.select_next_state = Some(SelectNextState {
5152                    query: AhoCorasick::new_auto_configured(&[query]),
5153                    wordwise: false,
5154                    done: false,
5155                });
5156                self.select_next(action, cx);
5157            }
5158        }
5159    }
5160
5161    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5162        self.transact(cx, |this, cx| {
5163            let mut selections = this.selections.all::<Point>(cx);
5164            let mut edits = Vec::new();
5165            let mut selection_edit_ranges = Vec::new();
5166            let mut last_toggled_row = None;
5167            let snapshot = this.buffer.read(cx).read(cx);
5168            let empty_str: Arc<str> = "".into();
5169            let mut suffixes_inserted = Vec::new();
5170
5171            fn comment_prefix_range(
5172                snapshot: &MultiBufferSnapshot,
5173                row: u32,
5174                comment_prefix: &str,
5175                comment_prefix_whitespace: &str,
5176            ) -> Range<Point> {
5177                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5178
5179                let mut line_bytes = snapshot
5180                    .bytes_in_range(start..snapshot.max_point())
5181                    .flatten()
5182                    .copied();
5183
5184                // If this line currently begins with the line comment prefix, then record
5185                // the range containing the prefix.
5186                if line_bytes
5187                    .by_ref()
5188                    .take(comment_prefix.len())
5189                    .eq(comment_prefix.bytes())
5190                {
5191                    // Include any whitespace that matches the comment prefix.
5192                    let matching_whitespace_len = line_bytes
5193                        .zip(comment_prefix_whitespace.bytes())
5194                        .take_while(|(a, b)| a == b)
5195                        .count() as u32;
5196                    let end = Point::new(
5197                        start.row,
5198                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5199                    );
5200                    start..end
5201                } else {
5202                    start..start
5203                }
5204            }
5205
5206            fn comment_suffix_range(
5207                snapshot: &MultiBufferSnapshot,
5208                row: u32,
5209                comment_suffix: &str,
5210                comment_suffix_has_leading_space: bool,
5211            ) -> Range<Point> {
5212                let end = Point::new(row, snapshot.line_len(row));
5213                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5214
5215                let mut line_end_bytes = snapshot
5216                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5217                    .flatten()
5218                    .copied();
5219
5220                let leading_space_len = if suffix_start_column > 0
5221                    && line_end_bytes.next() == Some(b' ')
5222                    && comment_suffix_has_leading_space
5223                {
5224                    1
5225                } else {
5226                    0
5227                };
5228
5229                // If this line currently begins with the line comment prefix, then record
5230                // the range containing the prefix.
5231                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5232                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5233                    start..end
5234                } else {
5235                    end..end
5236                }
5237            }
5238
5239            // TODO: Handle selections that cross excerpts
5240            for selection in &mut selections {
5241                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5242                let language = if let Some(language) =
5243                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5244                {
5245                    language
5246                } else {
5247                    continue;
5248                };
5249
5250                selection_edit_ranges.clear();
5251
5252                // If multiple selections contain a given row, avoid processing that
5253                // row more than once.
5254                let mut start_row = selection.start.row;
5255                if last_toggled_row == Some(start_row) {
5256                    start_row += 1;
5257                }
5258                let end_row =
5259                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5260                        selection.end.row - 1
5261                    } else {
5262                        selection.end.row
5263                    };
5264                last_toggled_row = Some(end_row);
5265
5266                if start_row > end_row {
5267                    continue;
5268                }
5269
5270                // If the language has line comments, toggle those.
5271                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5272                    // Split the comment prefix's trailing whitespace into a separate string,
5273                    // as that portion won't be used for detecting if a line is a comment.
5274                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5275                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5276                    let mut all_selection_lines_are_comments = true;
5277
5278                    for row in start_row..=end_row {
5279                        if snapshot.is_line_blank(row) {
5280                            continue;
5281                        }
5282
5283                        let prefix_range = comment_prefix_range(
5284                            snapshot.deref(),
5285                            row,
5286                            comment_prefix,
5287                            comment_prefix_whitespace,
5288                        );
5289                        if prefix_range.is_empty() {
5290                            all_selection_lines_are_comments = false;
5291                        }
5292                        selection_edit_ranges.push(prefix_range);
5293                    }
5294
5295                    if all_selection_lines_are_comments {
5296                        edits.extend(
5297                            selection_edit_ranges
5298                                .iter()
5299                                .cloned()
5300                                .map(|range| (range, empty_str.clone())),
5301                        );
5302                    } else {
5303                        let min_column = selection_edit_ranges
5304                            .iter()
5305                            .map(|r| r.start.column)
5306                            .min()
5307                            .unwrap_or(0);
5308                        edits.extend(selection_edit_ranges.iter().map(|range| {
5309                            let position = Point::new(range.start.row, min_column);
5310                            (position..position, full_comment_prefix.clone())
5311                        }));
5312                    }
5313                } else if let Some((full_comment_prefix, comment_suffix)) =
5314                    language.block_comment_delimiters()
5315                {
5316                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5317                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5318                    let prefix_range = comment_prefix_range(
5319                        snapshot.deref(),
5320                        start_row,
5321                        comment_prefix,
5322                        comment_prefix_whitespace,
5323                    );
5324                    let suffix_range = comment_suffix_range(
5325                        snapshot.deref(),
5326                        end_row,
5327                        comment_suffix.trim_start_matches(' '),
5328                        comment_suffix.starts_with(' '),
5329                    );
5330
5331                    if prefix_range.is_empty() || suffix_range.is_empty() {
5332                        edits.push((
5333                            prefix_range.start..prefix_range.start,
5334                            full_comment_prefix.clone(),
5335                        ));
5336                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5337                        suffixes_inserted.push((end_row, comment_suffix.len()));
5338                    } else {
5339                        edits.push((prefix_range, empty_str.clone()));
5340                        edits.push((suffix_range, empty_str.clone()));
5341                    }
5342                } else {
5343                    continue;
5344                }
5345            }
5346
5347            drop(snapshot);
5348            this.buffer.update(cx, |buffer, cx| {
5349                buffer.edit(edits, None, cx);
5350            });
5351
5352            // Adjust selections so that they end before any comment suffixes that
5353            // were inserted.
5354            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5355            let mut selections = this.selections.all::<Point>(cx);
5356            let snapshot = this.buffer.read(cx).read(cx);
5357            for selection in &mut selections {
5358                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5359                    match row.cmp(&selection.end.row) {
5360                        Ordering::Less => {
5361                            suffixes_inserted.next();
5362                            continue;
5363                        }
5364                        Ordering::Greater => break,
5365                        Ordering::Equal => {
5366                            if selection.end.column == snapshot.line_len(row) {
5367                                if selection.is_empty() {
5368                                    selection.start.column -= suffix_len as u32;
5369                                }
5370                                selection.end.column -= suffix_len as u32;
5371                            }
5372                            break;
5373                        }
5374                    }
5375                }
5376            }
5377
5378            drop(snapshot);
5379            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5380
5381            let selections = this.selections.all::<Point>(cx);
5382            let selections_on_single_row = selections.windows(2).all(|selections| {
5383                selections[0].start.row == selections[1].start.row
5384                    && selections[0].end.row == selections[1].end.row
5385                    && selections[0].start.row == selections[0].end.row
5386            });
5387            let selections_selecting = selections
5388                .iter()
5389                .any(|selection| selection.start != selection.end);
5390            let advance_downwards = action.advance_downwards
5391                && selections_on_single_row
5392                && !selections_selecting
5393                && this.mode != EditorMode::SingleLine;
5394
5395            if advance_downwards {
5396                let snapshot = this.buffer.read(cx).snapshot(cx);
5397
5398                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5399                    s.move_cursors_with(|display_snapshot, display_point, _| {
5400                        let mut point = display_point.to_point(display_snapshot);
5401                        point.row += 1;
5402                        point = snapshot.clip_point(point, Bias::Left);
5403                        let display_point = point.to_display_point(display_snapshot);
5404                        (display_point, SelectionGoal::Column(display_point.column()))
5405                    })
5406                });
5407            }
5408        });
5409    }
5410
5411    pub fn select_larger_syntax_node(
5412        &mut self,
5413        _: &SelectLargerSyntaxNode,
5414        cx: &mut ViewContext<Self>,
5415    ) {
5416        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5417        let buffer = self.buffer.read(cx).snapshot(cx);
5418        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5419
5420        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5421        let mut selected_larger_node = false;
5422        let new_selections = old_selections
5423            .iter()
5424            .map(|selection| {
5425                let old_range = selection.start..selection.end;
5426                let mut new_range = old_range.clone();
5427                while let Some(containing_range) =
5428                    buffer.range_for_syntax_ancestor(new_range.clone())
5429                {
5430                    new_range = containing_range;
5431                    if !display_map.intersects_fold(new_range.start)
5432                        && !display_map.intersects_fold(new_range.end)
5433                    {
5434                        break;
5435                    }
5436                }
5437
5438                selected_larger_node |= new_range != old_range;
5439                Selection {
5440                    id: selection.id,
5441                    start: new_range.start,
5442                    end: new_range.end,
5443                    goal: SelectionGoal::None,
5444                    reversed: selection.reversed,
5445                }
5446            })
5447            .collect::<Vec<_>>();
5448
5449        if selected_larger_node {
5450            stack.push(old_selections);
5451            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5452                s.select(new_selections);
5453            });
5454        }
5455        self.select_larger_syntax_node_stack = stack;
5456    }
5457
5458    pub fn select_smaller_syntax_node(
5459        &mut self,
5460        _: &SelectSmallerSyntaxNode,
5461        cx: &mut ViewContext<Self>,
5462    ) {
5463        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5464        if let Some(selections) = stack.pop() {
5465            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5466                s.select(selections.to_vec());
5467            });
5468        }
5469        self.select_larger_syntax_node_stack = stack;
5470    }
5471
5472    pub fn move_to_enclosing_bracket(
5473        &mut self,
5474        _: &MoveToEnclosingBracket,
5475        cx: &mut ViewContext<Self>,
5476    ) {
5477        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5478            s.move_offsets_with(|snapshot, selection| {
5479                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5480                    return;
5481                };
5482
5483                let mut best_length = usize::MAX;
5484                let mut best_inside = false;
5485                let mut best_in_bracket_range = false;
5486                let mut best_destination = None;
5487                for (open, close) in enclosing_bracket_ranges {
5488                    let close = close.to_inclusive();
5489                    let length = close.end() - open.start;
5490                    let inside = selection.start >= open.end && selection.end <= *close.start();
5491                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5492
5493                    // If best is next to a bracket and current isn't, skip
5494                    if !in_bracket_range && best_in_bracket_range {
5495                        continue;
5496                    }
5497
5498                    // Prefer smaller lengths unless best is inside and current isn't
5499                    if length > best_length && (best_inside || !inside) {
5500                        continue;
5501                    }
5502
5503                    best_length = length;
5504                    best_inside = inside;
5505                    best_in_bracket_range = in_bracket_range;
5506                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5507                        if inside {
5508                            open.end
5509                        } else {
5510                            open.start
5511                        }
5512                    } else {
5513                        if inside {
5514                            *close.start()
5515                        } else {
5516                            *close.end()
5517                        }
5518                    });
5519                }
5520
5521                if let Some(destination) = best_destination {
5522                    selection.collapse_to(destination, SelectionGoal::None);
5523                }
5524            })
5525        });
5526    }
5527
5528    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5529        self.end_selection(cx);
5530        self.selection_history.mode = SelectionHistoryMode::Undoing;
5531        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5532            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5533            self.select_next_state = entry.select_next_state;
5534            self.add_selections_state = entry.add_selections_state;
5535            self.request_autoscroll(Autoscroll::newest(), cx);
5536        }
5537        self.selection_history.mode = SelectionHistoryMode::Normal;
5538    }
5539
5540    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5541        self.end_selection(cx);
5542        self.selection_history.mode = SelectionHistoryMode::Redoing;
5543        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5544            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5545            self.select_next_state = entry.select_next_state;
5546            self.add_selections_state = entry.add_selections_state;
5547            self.request_autoscroll(Autoscroll::newest(), cx);
5548        }
5549        self.selection_history.mode = SelectionHistoryMode::Normal;
5550    }
5551
5552    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5553        self.go_to_diagnostic_impl(Direction::Next, cx)
5554    }
5555
5556    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5557        self.go_to_diagnostic_impl(Direction::Prev, cx)
5558    }
5559
5560    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5561        let buffer = self.buffer.read(cx).snapshot(cx);
5562        let selection = self.selections.newest::<usize>(cx);
5563
5564        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5565        if direction == Direction::Next {
5566            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5567                let (group_id, jump_to) = popover.activation_info();
5568                if self.activate_diagnostics(group_id, cx) {
5569                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5570                        let mut new_selection = s.newest_anchor().clone();
5571                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5572                        s.select_anchors(vec![new_selection.clone()]);
5573                    });
5574                }
5575                return;
5576            }
5577        }
5578
5579        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5580            active_diagnostics
5581                .primary_range
5582                .to_offset(&buffer)
5583                .to_inclusive()
5584        });
5585        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5586            if active_primary_range.contains(&selection.head()) {
5587                *active_primary_range.end()
5588            } else {
5589                selection.head()
5590            }
5591        } else {
5592            selection.head()
5593        };
5594
5595        loop {
5596            let mut diagnostics = if direction == Direction::Prev {
5597                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5598            } else {
5599                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5600            };
5601            let group = diagnostics.find_map(|entry| {
5602                if entry.diagnostic.is_primary
5603                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5604                    && !entry.range.is_empty()
5605                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5606                {
5607                    Some((entry.range, entry.diagnostic.group_id))
5608                } else {
5609                    None
5610                }
5611            });
5612
5613            if let Some((primary_range, group_id)) = group {
5614                if self.activate_diagnostics(group_id, cx) {
5615                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5616                        s.select(vec![Selection {
5617                            id: selection.id,
5618                            start: primary_range.start,
5619                            end: primary_range.start,
5620                            reversed: false,
5621                            goal: SelectionGoal::None,
5622                        }]);
5623                    });
5624                }
5625                break;
5626            } else {
5627                // Cycle around to the start of the buffer, potentially moving back to the start of
5628                // the currently active diagnostic.
5629                active_primary_range.take();
5630                if direction == Direction::Prev {
5631                    if search_start == buffer.len() {
5632                        break;
5633                    } else {
5634                        search_start = buffer.len();
5635                    }
5636                } else if search_start == 0 {
5637                    break;
5638                } else {
5639                    search_start = 0;
5640                }
5641            }
5642        }
5643    }
5644
5645    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5646        let snapshot = self
5647            .display_map
5648            .update(cx, |display_map, cx| display_map.snapshot(cx));
5649        let selection = self.selections.newest::<Point>(cx);
5650
5651        if !self.seek_in_direction(
5652            &snapshot,
5653            selection.head(),
5654            false,
5655            snapshot
5656                .buffer_snapshot
5657                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5658            cx,
5659        ) {
5660            let wrapped_point = Point::zero();
5661            self.seek_in_direction(
5662                &snapshot,
5663                wrapped_point,
5664                true,
5665                snapshot
5666                    .buffer_snapshot
5667                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5668                cx,
5669            );
5670        }
5671    }
5672
5673    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5674        let snapshot = self
5675            .display_map
5676            .update(cx, |display_map, cx| display_map.snapshot(cx));
5677        let selection = self.selections.newest::<Point>(cx);
5678
5679        if !self.seek_in_direction(
5680            &snapshot,
5681            selection.head(),
5682            false,
5683            snapshot
5684                .buffer_snapshot
5685                .git_diff_hunks_in_range_rev(0..selection.head().row),
5686            cx,
5687        ) {
5688            let wrapped_point = snapshot.buffer_snapshot.max_point();
5689            self.seek_in_direction(
5690                &snapshot,
5691                wrapped_point,
5692                true,
5693                snapshot
5694                    .buffer_snapshot
5695                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5696                cx,
5697            );
5698        }
5699    }
5700
5701    fn seek_in_direction(
5702        &mut self,
5703        snapshot: &DisplaySnapshot,
5704        initial_point: Point,
5705        is_wrapped: bool,
5706        hunks: impl Iterator<Item = DiffHunk<u32>>,
5707        cx: &mut ViewContext<Editor>,
5708    ) -> bool {
5709        let display_point = initial_point.to_display_point(snapshot);
5710        let mut hunks = hunks
5711            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5712            .skip_while(|hunk| {
5713                if is_wrapped {
5714                    false
5715                } else {
5716                    hunk.contains_display_row(display_point.row())
5717                }
5718            })
5719            .dedup();
5720
5721        if let Some(hunk) = hunks.next() {
5722            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5723                let row = hunk.start_display_row();
5724                let point = DisplayPoint::new(row, 0);
5725                s.select_display_ranges([point..point]);
5726            });
5727
5728            true
5729        } else {
5730            false
5731        }
5732    }
5733
5734    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5735        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5736    }
5737
5738    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5739        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5740    }
5741
5742    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5743        let Some(workspace) = self.workspace(cx) else { return };
5744        let buffer = self.buffer.read(cx);
5745        let head = self.selections.newest::<usize>(cx).head();
5746        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5747            text_anchor
5748        } else {
5749            return;
5750        };
5751
5752        let project = workspace.read(cx).project().clone();
5753        let definitions = project.update(cx, |project, cx| match kind {
5754            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5755            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5756        });
5757
5758        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5759            let definitions = definitions.await?;
5760            editor.update(&mut cx, |editor, cx| {
5761                editor.navigate_to_definitions(definitions, cx);
5762            })?;
5763            Ok::<(), anyhow::Error>(())
5764        })
5765        .detach_and_log_err(cx);
5766    }
5767
5768    pub fn navigate_to_definitions(
5769        &mut self,
5770        mut definitions: Vec<LocationLink>,
5771        cx: &mut ViewContext<Editor>,
5772    ) {
5773        let Some(workspace) = self.workspace(cx) else { return };
5774        let pane = workspace.read(cx).active_pane().clone();
5775        // If there is one definition, just open it directly
5776        if definitions.len() == 1 {
5777            let definition = definitions.pop().unwrap();
5778            let range = definition
5779                .target
5780                .range
5781                .to_offset(definition.target.buffer.read(cx));
5782
5783            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
5784                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5785                    s.select_ranges([range]);
5786                });
5787            } else {
5788                cx.window_context().defer(move |cx| {
5789                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
5790                        workspace.open_project_item(definition.target.buffer.clone(), cx)
5791                    });
5792                    target_editor.update(cx, |target_editor, cx| {
5793                        // When selecting a definition in a different buffer, disable the nav history
5794                        // to avoid creating a history entry at the previous cursor location.
5795                        pane.update(cx, |pane, _| pane.disable_history());
5796                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5797                            s.select_ranges([range]);
5798                        });
5799                        pane.update(cx, |pane, _| pane.enable_history());
5800                    });
5801                });
5802            }
5803        } else if !definitions.is_empty() {
5804            let replica_id = self.replica_id(cx);
5805            cx.window_context().defer(move |cx| {
5806                let title = definitions
5807                    .iter()
5808                    .find(|definition| definition.origin.is_some())
5809                    .and_then(|definition| {
5810                        definition.origin.as_ref().map(|origin| {
5811                            let buffer = origin.buffer.read(cx);
5812                            format!(
5813                                "Definitions for {}",
5814                                buffer
5815                                    .text_for_range(origin.range.clone())
5816                                    .collect::<String>()
5817                            )
5818                        })
5819                    })
5820                    .unwrap_or("Definitions".to_owned());
5821                let locations = definitions
5822                    .into_iter()
5823                    .map(|definition| definition.target)
5824                    .collect();
5825                workspace.update(cx, |workspace, cx| {
5826                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5827                });
5828            });
5829        }
5830    }
5831
5832    pub fn find_all_references(
5833        workspace: &mut Workspace,
5834        _: &FindAllReferences,
5835        cx: &mut ViewContext<Workspace>,
5836    ) -> Option<Task<Result<()>>> {
5837        let active_item = workspace.active_item(cx)?;
5838        let editor_handle = active_item.act_as::<Self>(cx)?;
5839
5840        let editor = editor_handle.read(cx);
5841        let buffer = editor.buffer.read(cx);
5842        let head = editor.selections.newest::<usize>(cx).head();
5843        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5844        let replica_id = editor.replica_id(cx);
5845
5846        let project = workspace.project().clone();
5847        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5848        Some(cx.spawn_labeled(
5849            "Finding All References...",
5850            |workspace, mut cx| async move {
5851                let locations = references.await?;
5852                if locations.is_empty() {
5853                    return Ok(());
5854                }
5855
5856                workspace.update(&mut cx, |workspace, cx| {
5857                    let title = locations
5858                        .first()
5859                        .as_ref()
5860                        .map(|location| {
5861                            let buffer = location.buffer.read(cx);
5862                            format!(
5863                                "References to `{}`",
5864                                buffer
5865                                    .text_for_range(location.range.clone())
5866                                    .collect::<String>()
5867                            )
5868                        })
5869                        .unwrap();
5870                    Self::open_locations_in_multibuffer(
5871                        workspace, locations, replica_id, title, cx,
5872                    );
5873                })?;
5874
5875                Ok(())
5876            },
5877        ))
5878    }
5879
5880    /// Opens a multibuffer with the given project locations in it
5881    pub fn open_locations_in_multibuffer(
5882        workspace: &mut Workspace,
5883        mut locations: Vec<Location>,
5884        replica_id: ReplicaId,
5885        title: String,
5886        cx: &mut ViewContext<Workspace>,
5887    ) {
5888        // If there are multiple definitions, open them in a multibuffer
5889        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
5890        let mut locations = locations.into_iter().peekable();
5891        let mut ranges_to_highlight = Vec::new();
5892
5893        let excerpt_buffer = cx.add_model(|cx| {
5894            let mut multibuffer = MultiBuffer::new(replica_id);
5895            while let Some(location) = locations.next() {
5896                let buffer = location.buffer.read(cx);
5897                let mut ranges_for_buffer = Vec::new();
5898                let range = location.range.to_offset(buffer);
5899                ranges_for_buffer.push(range.clone());
5900
5901                while let Some(next_location) = locations.peek() {
5902                    if next_location.buffer == location.buffer {
5903                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5904                        locations.next();
5905                    } else {
5906                        break;
5907                    }
5908                }
5909
5910                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5911                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5912                    location.buffer.clone(),
5913                    ranges_for_buffer,
5914                    1,
5915                    cx,
5916                ))
5917            }
5918
5919            multibuffer.with_title(title)
5920        });
5921
5922        let editor = cx.add_view(|cx| {
5923            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5924        });
5925        editor.update(cx, |editor, cx| {
5926            editor.highlight_background::<Self>(
5927                ranges_to_highlight,
5928                |theme| theme.editor.highlighted_line_background,
5929                cx,
5930            );
5931        });
5932        workspace.add_item(Box::new(editor), cx);
5933    }
5934
5935    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5936        use language::ToOffset as _;
5937
5938        let project = self.project.clone()?;
5939        let selection = self.selections.newest_anchor().clone();
5940        let (cursor_buffer, cursor_buffer_position) = self
5941            .buffer
5942            .read(cx)
5943            .text_anchor_for_position(selection.head(), cx)?;
5944        let (tail_buffer, _) = self
5945            .buffer
5946            .read(cx)
5947            .text_anchor_for_position(selection.tail(), cx)?;
5948        if tail_buffer != cursor_buffer {
5949            return None;
5950        }
5951
5952        let snapshot = cursor_buffer.read(cx).snapshot();
5953        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5954        let prepare_rename = project.update(cx, |project, cx| {
5955            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5956        });
5957
5958        Some(cx.spawn(|this, mut cx| async move {
5959            let rename_range = if let Some(range) = prepare_rename.await? {
5960                Some(range)
5961            } else {
5962                this.read_with(&cx, |this, cx| {
5963                    let buffer = this.buffer.read(cx).snapshot(cx);
5964                    let mut buffer_highlights = this
5965                        .document_highlights_for_position(selection.head(), &buffer)
5966                        .filter(|highlight| {
5967                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5968                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5969                        });
5970                    buffer_highlights
5971                        .next()
5972                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5973                })?
5974            };
5975            if let Some(rename_range) = rename_range {
5976                let rename_buffer_range = rename_range.to_offset(&snapshot);
5977                let cursor_offset_in_rename_range =
5978                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5979
5980                this.update(&mut cx, |this, cx| {
5981                    this.take_rename(false, cx);
5982                    let style = this.style(cx);
5983                    let buffer = this.buffer.read(cx).read(cx);
5984                    let cursor_offset = selection.head().to_offset(&buffer);
5985                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5986                    let rename_end = rename_start + rename_buffer_range.len();
5987                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5988                    let mut old_highlight_id = None;
5989                    let old_name: Arc<str> = buffer
5990                        .chunks(rename_start..rename_end, true)
5991                        .map(|chunk| {
5992                            if old_highlight_id.is_none() {
5993                                old_highlight_id = chunk.syntax_highlight_id;
5994                            }
5995                            chunk.text
5996                        })
5997                        .collect::<String>()
5998                        .into();
5999
6000                    drop(buffer);
6001
6002                    // Position the selection in the rename editor so that it matches the current selection.
6003                    this.show_local_selections = false;
6004                    let rename_editor = cx.add_view(|cx| {
6005                        let mut editor = Editor::single_line(None, cx);
6006                        if let Some(old_highlight_id) = old_highlight_id {
6007                            editor.override_text_style =
6008                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6009                        }
6010                        editor.buffer.update(cx, |buffer, cx| {
6011                            buffer.edit([(0..0, old_name.clone())], None, cx)
6012                        });
6013                        editor.select_all(&SelectAll, cx);
6014                        editor
6015                    });
6016
6017                    let ranges = this
6018                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6019                        .into_iter()
6020                        .flat_map(|(_, ranges)| ranges)
6021                        .chain(
6022                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6023                                .into_iter()
6024                                .flat_map(|(_, ranges)| ranges),
6025                        )
6026                        .collect();
6027
6028                    this.highlight_text::<Rename>(
6029                        ranges,
6030                        HighlightStyle {
6031                            fade_out: Some(style.rename_fade),
6032                            ..Default::default()
6033                        },
6034                        cx,
6035                    );
6036                    cx.focus(&rename_editor);
6037                    let block_id = this.insert_blocks(
6038                        [BlockProperties {
6039                            style: BlockStyle::Flex,
6040                            position: range.start.clone(),
6041                            height: 1,
6042                            render: Arc::new({
6043                                let editor = rename_editor.clone();
6044                                move |cx: &mut BlockContext| {
6045                                    ChildView::new(&editor, cx)
6046                                        .contained()
6047                                        .with_padding_left(cx.anchor_x)
6048                                        .into_any()
6049                                }
6050                            }),
6051                            disposition: BlockDisposition::Below,
6052                        }],
6053                        cx,
6054                    )[0];
6055                    this.pending_rename = Some(RenameState {
6056                        range,
6057                        old_name,
6058                        editor: rename_editor,
6059                        block_id,
6060                    });
6061                })?;
6062            }
6063
6064            Ok(())
6065        }))
6066    }
6067
6068    pub fn confirm_rename(
6069        workspace: &mut Workspace,
6070        _: &ConfirmRename,
6071        cx: &mut ViewContext<Workspace>,
6072    ) -> Option<Task<Result<()>>> {
6073        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6074
6075        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6076            let rename = editor.take_rename(false, cx)?;
6077            let buffer = editor.buffer.read(cx);
6078            let (start_buffer, start) =
6079                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6080            let (end_buffer, end) =
6081                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6082            if start_buffer == end_buffer {
6083                let new_name = rename.editor.read(cx).text(cx);
6084                Some((start_buffer, start..end, rename.old_name, new_name))
6085            } else {
6086                None
6087            }
6088        })?;
6089
6090        let rename = workspace.project().clone().update(cx, |project, cx| {
6091            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6092        });
6093
6094        let editor = editor.downgrade();
6095        Some(cx.spawn(|workspace, mut cx| async move {
6096            let project_transaction = rename.await?;
6097            Self::open_project_transaction(
6098                &editor,
6099                workspace,
6100                project_transaction,
6101                format!("Rename: {}{}", old_name, new_name),
6102                cx.clone(),
6103            )
6104            .await?;
6105
6106            editor.update(&mut cx, |editor, cx| {
6107                editor.refresh_document_highlights(cx);
6108            })?;
6109            Ok(())
6110        }))
6111    }
6112
6113    fn take_rename(
6114        &mut self,
6115        moving_cursor: bool,
6116        cx: &mut ViewContext<Self>,
6117    ) -> Option<RenameState> {
6118        let rename = self.pending_rename.take()?;
6119        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
6120        self.clear_text_highlights::<Rename>(cx);
6121        self.show_local_selections = true;
6122
6123        if moving_cursor {
6124            let rename_editor = rename.editor.read(cx);
6125            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6126
6127            // Update the selection to match the position of the selection inside
6128            // the rename editor.
6129            let snapshot = self.buffer.read(cx).read(cx);
6130            let rename_range = rename.range.to_offset(&snapshot);
6131            let cursor_in_editor = snapshot
6132                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6133                .min(rename_range.end);
6134            drop(snapshot);
6135
6136            self.change_selections(None, cx, |s| {
6137                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6138            });
6139        } else {
6140            self.refresh_document_highlights(cx);
6141        }
6142
6143        Some(rename)
6144    }
6145
6146    #[cfg(any(test, feature = "test-support"))]
6147    pub fn pending_rename(&self) -> Option<&RenameState> {
6148        self.pending_rename.as_ref()
6149    }
6150
6151    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6152        let project = match &self.project {
6153            Some(project) => project.clone(),
6154            None => return None,
6155        };
6156
6157        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6158    }
6159
6160    fn perform_format(
6161        &mut self,
6162        project: ModelHandle<Project>,
6163        trigger: FormatTrigger,
6164        cx: &mut ViewContext<Self>,
6165    ) -> Task<Result<()>> {
6166        let buffer = self.buffer().clone();
6167        let buffers = buffer.read(cx).all_buffers();
6168
6169        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6170        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6171
6172        cx.spawn(|_, mut cx| async move {
6173            let transaction = futures::select_biased! {
6174                _ = timeout => {
6175                    log::warn!("timed out waiting for formatting");
6176                    None
6177                }
6178                transaction = format.log_err().fuse() => transaction,
6179            };
6180
6181            buffer.update(&mut cx, |buffer, cx| {
6182                if let Some(transaction) = transaction {
6183                    if !buffer.is_singleton() {
6184                        buffer.push_transaction(&transaction.0, cx);
6185                    }
6186                }
6187
6188                cx.notify();
6189            });
6190
6191            Ok(())
6192        })
6193    }
6194
6195    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6196        if let Some(project) = self.project.clone() {
6197            self.buffer.update(cx, |multi_buffer, cx| {
6198                project.update(cx, |project, cx| {
6199                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6200                });
6201            })
6202        }
6203    }
6204
6205    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6206        cx.show_character_palette();
6207    }
6208
6209    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6210        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6211            let buffer = self.buffer.read(cx).snapshot(cx);
6212            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6213            let is_valid = buffer
6214                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6215                .any(|entry| {
6216                    entry.diagnostic.is_primary
6217                        && !entry.range.is_empty()
6218                        && entry.range.start == primary_range_start
6219                        && entry.diagnostic.message == active_diagnostics.primary_message
6220                });
6221
6222            if is_valid != active_diagnostics.is_valid {
6223                active_diagnostics.is_valid = is_valid;
6224                let mut new_styles = HashMap::default();
6225                for (block_id, diagnostic) in &active_diagnostics.blocks {
6226                    new_styles.insert(
6227                        *block_id,
6228                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6229                    );
6230                }
6231                self.display_map
6232                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6233            }
6234        }
6235    }
6236
6237    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6238        self.dismiss_diagnostics(cx);
6239        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6240            let buffer = self.buffer.read(cx).snapshot(cx);
6241
6242            let mut primary_range = None;
6243            let mut primary_message = None;
6244            let mut group_end = Point::zero();
6245            let diagnostic_group = buffer
6246                .diagnostic_group::<Point>(group_id)
6247                .map(|entry| {
6248                    if entry.range.end > group_end {
6249                        group_end = entry.range.end;
6250                    }
6251                    if entry.diagnostic.is_primary {
6252                        primary_range = Some(entry.range.clone());
6253                        primary_message = Some(entry.diagnostic.message.clone());
6254                    }
6255                    entry
6256                })
6257                .collect::<Vec<_>>();
6258            let primary_range = primary_range?;
6259            let primary_message = primary_message?;
6260            let primary_range =
6261                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6262
6263            let blocks = display_map
6264                .insert_blocks(
6265                    diagnostic_group.iter().map(|entry| {
6266                        let diagnostic = entry.diagnostic.clone();
6267                        let message_height = diagnostic.message.lines().count() as u8;
6268                        BlockProperties {
6269                            style: BlockStyle::Fixed,
6270                            position: buffer.anchor_after(entry.range.start),
6271                            height: message_height,
6272                            render: diagnostic_block_renderer(diagnostic, true),
6273                            disposition: BlockDisposition::Below,
6274                        }
6275                    }),
6276                    cx,
6277                )
6278                .into_iter()
6279                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6280                .collect();
6281
6282            Some(ActiveDiagnosticGroup {
6283                primary_range,
6284                primary_message,
6285                blocks,
6286                is_valid: true,
6287            })
6288        });
6289        self.active_diagnostics.is_some()
6290    }
6291
6292    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6293        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6294            self.display_map.update(cx, |display_map, cx| {
6295                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6296            });
6297            cx.notify();
6298        }
6299    }
6300
6301    pub fn set_selections_from_remote(
6302        &mut self,
6303        selections: Vec<Selection<Anchor>>,
6304        pending_selection: Option<Selection<Anchor>>,
6305        cx: &mut ViewContext<Self>,
6306    ) {
6307        let old_cursor_position = self.selections.newest_anchor().head();
6308        self.selections.change_with(cx, |s| {
6309            s.select_anchors(selections);
6310            if let Some(pending_selection) = pending_selection {
6311                s.set_pending(pending_selection, SelectMode::Character);
6312            } else {
6313                s.clear_pending();
6314            }
6315        });
6316        self.selections_did_change(false, &old_cursor_position, cx);
6317    }
6318
6319    fn push_to_selection_history(&mut self) {
6320        self.selection_history.push(SelectionHistoryEntry {
6321            selections: self.selections.disjoint_anchors(),
6322            select_next_state: self.select_next_state.clone(),
6323            add_selections_state: self.add_selections_state.clone(),
6324        });
6325    }
6326
6327    pub fn transact(
6328        &mut self,
6329        cx: &mut ViewContext<Self>,
6330        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6331    ) -> Option<TransactionId> {
6332        self.start_transaction_at(Instant::now(), cx);
6333        update(self, cx);
6334        self.end_transaction_at(Instant::now(), cx)
6335    }
6336
6337    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6338        self.end_selection(cx);
6339        if let Some(tx_id) = self
6340            .buffer
6341            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6342        {
6343            self.selection_history
6344                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6345        }
6346    }
6347
6348    fn end_transaction_at(
6349        &mut self,
6350        now: Instant,
6351        cx: &mut ViewContext<Self>,
6352    ) -> Option<TransactionId> {
6353        if let Some(tx_id) = self
6354            .buffer
6355            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6356        {
6357            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6358                *end_selections = Some(self.selections.disjoint_anchors());
6359            } else {
6360                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6361            }
6362
6363            cx.emit(Event::Edited);
6364            Some(tx_id)
6365        } else {
6366            None
6367        }
6368    }
6369
6370    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6371        let mut fold_ranges = Vec::new();
6372
6373        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6374
6375        let selections = self.selections.all::<Point>(cx);
6376        for selection in selections {
6377            let range = selection.range().sorted();
6378            let buffer_start_row = range.start.row;
6379
6380            for row in (0..=range.end.row).rev() {
6381                let fold_range = display_map.foldable_range(row);
6382
6383                if let Some(fold_range) = fold_range {
6384                    if fold_range.end.row >= buffer_start_row {
6385                        fold_ranges.push(fold_range);
6386                        if row <= range.start.row {
6387                            break;
6388                        }
6389                    }
6390                }
6391            }
6392        }
6393
6394        self.fold_ranges(fold_ranges, true, cx);
6395    }
6396
6397    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6398        let buffer_row = fold_at.buffer_row;
6399        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6400
6401        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6402            let autoscroll = self
6403                .selections
6404                .all::<Point>(cx)
6405                .iter()
6406                .any(|selection| fold_range.overlaps(&selection.range()));
6407
6408            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6409        }
6410    }
6411
6412    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6413        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6414        let buffer = &display_map.buffer_snapshot;
6415        let selections = self.selections.all::<Point>(cx);
6416        let ranges = selections
6417            .iter()
6418            .map(|s| {
6419                let range = s.display_range(&display_map).sorted();
6420                let mut start = range.start.to_point(&display_map);
6421                let mut end = range.end.to_point(&display_map);
6422                start.column = 0;
6423                end.column = buffer.line_len(end.row);
6424                start..end
6425            })
6426            .collect::<Vec<_>>();
6427
6428        self.unfold_ranges(ranges, true, true, cx);
6429    }
6430
6431    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6432        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6433
6434        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6435            ..Point::new(
6436                unfold_at.buffer_row,
6437                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6438            );
6439
6440        let autoscroll = self
6441            .selections
6442            .all::<Point>(cx)
6443            .iter()
6444            .any(|selection| selection.range().overlaps(&intersection_range));
6445
6446        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6447    }
6448
6449    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6450        let selections = self.selections.all::<Point>(cx);
6451        let ranges = selections.into_iter().map(|s| s.start..s.end);
6452        self.fold_ranges(ranges, true, cx);
6453    }
6454
6455    pub fn fold_ranges<T: ToOffset + Clone>(
6456        &mut self,
6457        ranges: impl IntoIterator<Item = Range<T>>,
6458        auto_scroll: bool,
6459        cx: &mut ViewContext<Self>,
6460    ) {
6461        let mut ranges = ranges.into_iter().peekable();
6462        if ranges.peek().is_some() {
6463            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6464
6465            if auto_scroll {
6466                self.request_autoscroll(Autoscroll::fit(), cx);
6467            }
6468
6469            cx.notify();
6470        }
6471    }
6472
6473    pub fn unfold_ranges<T: ToOffset + Clone>(
6474        &mut self,
6475        ranges: impl IntoIterator<Item = Range<T>>,
6476        inclusive: bool,
6477        auto_scroll: bool,
6478        cx: &mut ViewContext<Self>,
6479    ) {
6480        let mut ranges = ranges.into_iter().peekable();
6481        if ranges.peek().is_some() {
6482            self.display_map
6483                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6484            if auto_scroll {
6485                self.request_autoscroll(Autoscroll::fit(), cx);
6486            }
6487
6488            cx.notify();
6489        }
6490    }
6491
6492    pub fn gutter_hover(
6493        &mut self,
6494        GutterHover { hovered }: &GutterHover,
6495        cx: &mut ViewContext<Self>,
6496    ) {
6497        self.gutter_hovered = *hovered;
6498        cx.notify();
6499    }
6500
6501    pub fn insert_blocks(
6502        &mut self,
6503        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6504        cx: &mut ViewContext<Self>,
6505    ) -> Vec<BlockId> {
6506        let blocks = self
6507            .display_map
6508            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6509        self.request_autoscroll(Autoscroll::fit(), cx);
6510        blocks
6511    }
6512
6513    pub fn replace_blocks(
6514        &mut self,
6515        blocks: HashMap<BlockId, RenderBlock>,
6516        cx: &mut ViewContext<Self>,
6517    ) {
6518        self.display_map
6519            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6520        self.request_autoscroll(Autoscroll::fit(), cx);
6521    }
6522
6523    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6524        self.display_map.update(cx, |display_map, cx| {
6525            display_map.remove_blocks(block_ids, cx)
6526        });
6527    }
6528
6529    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6530        self.display_map
6531            .update(cx, |map, cx| map.snapshot(cx))
6532            .longest_row()
6533    }
6534
6535    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6536        self.display_map
6537            .update(cx, |map, cx| map.snapshot(cx))
6538            .max_point()
6539    }
6540
6541    pub fn text(&self, cx: &AppContext) -> String {
6542        self.buffer.read(cx).read(cx).text()
6543    }
6544
6545    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6546        self.transact(cx, |this, cx| {
6547            this.buffer
6548                .read(cx)
6549                .as_singleton()
6550                .expect("you can only call set_text on editors for singleton buffers")
6551                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6552        });
6553    }
6554
6555    pub fn display_text(&self, cx: &mut AppContext) -> String {
6556        self.display_map
6557            .update(cx, |map, cx| map.snapshot(cx))
6558            .text()
6559    }
6560
6561    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6562        let settings = self.buffer.read(cx).settings_at(0, cx);
6563        let mode = self
6564            .soft_wrap_mode_override
6565            .unwrap_or_else(|| settings.soft_wrap);
6566        match mode {
6567            language_settings::SoftWrap::None => SoftWrap::None,
6568            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6569            language_settings::SoftWrap::PreferredLineLength => {
6570                SoftWrap::Column(settings.preferred_line_length)
6571            }
6572        }
6573    }
6574
6575    pub fn set_soft_wrap_mode(
6576        &mut self,
6577        mode: language_settings::SoftWrap,
6578        cx: &mut ViewContext<Self>,
6579    ) {
6580        self.soft_wrap_mode_override = Some(mode);
6581        cx.notify();
6582    }
6583
6584    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6585        self.display_map
6586            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6587    }
6588
6589    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6590        if self.soft_wrap_mode_override.is_some() {
6591            self.soft_wrap_mode_override.take();
6592        } else {
6593            let soft_wrap = match self.soft_wrap_mode(cx) {
6594                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
6595                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
6596            };
6597            self.soft_wrap_mode_override = Some(soft_wrap);
6598        }
6599        cx.notify();
6600    }
6601
6602    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6603        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6604            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6605                cx.reveal_path(&file.abs_path(cx));
6606            }
6607        }
6608    }
6609
6610    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6611        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6612            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6613                if let Some(path) = file.abs_path(cx).to_str() {
6614                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6615                }
6616            }
6617        }
6618    }
6619
6620    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6621        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6622            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6623                if let Some(path) = file.path().to_str() {
6624                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6625                }
6626            }
6627        }
6628    }
6629
6630    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6631        self.highlighted_rows = rows;
6632    }
6633
6634    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6635        self.highlighted_rows.clone()
6636    }
6637
6638    pub fn highlight_background<T: 'static>(
6639        &mut self,
6640        ranges: Vec<Range<Anchor>>,
6641        color_fetcher: fn(&Theme) -> Color,
6642        cx: &mut ViewContext<Self>,
6643    ) {
6644        self.background_highlights
6645            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6646        cx.notify();
6647    }
6648
6649    #[allow(clippy::type_complexity)]
6650    pub fn clear_background_highlights<T: 'static>(
6651        &mut self,
6652        cx: &mut ViewContext<Self>,
6653    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6654        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6655        if highlights.is_some() {
6656            cx.notify();
6657        }
6658        highlights
6659    }
6660
6661    #[cfg(feature = "test-support")]
6662    pub fn all_background_highlights(
6663        &mut self,
6664        cx: &mut ViewContext<Self>,
6665    ) -> Vec<(Range<DisplayPoint>, Color)> {
6666        let snapshot = self.snapshot(cx);
6667        let buffer = &snapshot.buffer_snapshot;
6668        let start = buffer.anchor_before(0);
6669        let end = buffer.anchor_after(buffer.len());
6670        let theme = theme::current(cx);
6671        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
6672    }
6673
6674    fn document_highlights_for_position<'a>(
6675        &'a self,
6676        position: Anchor,
6677        buffer: &'a MultiBufferSnapshot,
6678    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6679        let read_highlights = self
6680            .background_highlights
6681            .get(&TypeId::of::<DocumentHighlightRead>())
6682            .map(|h| &h.1);
6683        let write_highlights = self
6684            .background_highlights
6685            .get(&TypeId::of::<DocumentHighlightWrite>())
6686            .map(|h| &h.1);
6687        let left_position = position.bias_left(buffer);
6688        let right_position = position.bias_right(buffer);
6689        read_highlights
6690            .into_iter()
6691            .chain(write_highlights)
6692            .flat_map(move |ranges| {
6693                let start_ix = match ranges.binary_search_by(|probe| {
6694                    let cmp = probe.end.cmp(&left_position, buffer);
6695                    if cmp.is_ge() {
6696                        Ordering::Greater
6697                    } else {
6698                        Ordering::Less
6699                    }
6700                }) {
6701                    Ok(i) | Err(i) => i,
6702                };
6703
6704                let right_position = right_position.clone();
6705                ranges[start_ix..]
6706                    .iter()
6707                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6708            })
6709    }
6710
6711    pub fn background_highlights_in_range(
6712        &self,
6713        search_range: Range<Anchor>,
6714        display_snapshot: &DisplaySnapshot,
6715        theme: &Theme,
6716    ) -> Vec<(Range<DisplayPoint>, Color)> {
6717        let mut results = Vec::new();
6718        let buffer = &display_snapshot.buffer_snapshot;
6719        for (color_fetcher, ranges) in self.background_highlights.values() {
6720            let color = color_fetcher(theme);
6721            let start_ix = match ranges.binary_search_by(|probe| {
6722                let cmp = probe.end.cmp(&search_range.start, buffer);
6723                if cmp.is_gt() {
6724                    Ordering::Greater
6725                } else {
6726                    Ordering::Less
6727                }
6728            }) {
6729                Ok(i) | Err(i) => i,
6730            };
6731            for range in &ranges[start_ix..] {
6732                if range.start.cmp(&search_range.end, buffer).is_ge() {
6733                    break;
6734                }
6735                let start = range
6736                    .start
6737                    .to_point(buffer)
6738                    .to_display_point(display_snapshot);
6739                let end = range
6740                    .end
6741                    .to_point(buffer)
6742                    .to_display_point(display_snapshot);
6743                results.push((start..end, color))
6744            }
6745        }
6746        results
6747    }
6748
6749    pub fn highlight_text<T: 'static>(
6750        &mut self,
6751        ranges: Vec<Range<Anchor>>,
6752        style: HighlightStyle,
6753        cx: &mut ViewContext<Self>,
6754    ) {
6755        self.display_map.update(cx, |map, _| {
6756            map.highlight_text(TypeId::of::<T>(), ranges, style)
6757        });
6758        cx.notify();
6759    }
6760
6761    pub fn text_highlights<'a, T: 'static>(
6762        &'a self,
6763        cx: &'a AppContext,
6764    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6765        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6766    }
6767
6768    pub fn clear_text_highlights<T: 'static>(
6769        &mut self,
6770        cx: &mut ViewContext<Self>,
6771    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6772        let highlights = self
6773            .display_map
6774            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6775        if highlights.is_some() {
6776            cx.notify();
6777        }
6778        highlights
6779    }
6780
6781    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6782        self.blink_manager.read(cx).visible() && self.focused
6783    }
6784
6785    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6786        cx.notify();
6787    }
6788
6789    fn on_buffer_event(
6790        &mut self,
6791        _: ModelHandle<MultiBuffer>,
6792        event: &multi_buffer::Event,
6793        cx: &mut ViewContext<Self>,
6794    ) {
6795        match event {
6796            multi_buffer::Event::Edited => {
6797                self.refresh_active_diagnostics(cx);
6798                self.refresh_code_actions(cx);
6799                if self.has_active_copilot_suggestion(cx) {
6800                    self.update_visible_copilot_suggestion(cx);
6801                }
6802                cx.emit(Event::BufferEdited);
6803            }
6804            multi_buffer::Event::ExcerptsAdded {
6805                buffer,
6806                predecessor,
6807                excerpts,
6808            } => cx.emit(Event::ExcerptsAdded {
6809                buffer: buffer.clone(),
6810                predecessor: *predecessor,
6811                excerpts: excerpts.clone(),
6812            }),
6813            multi_buffer::Event::ExcerptsRemoved { ids } => {
6814                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6815            }
6816            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6817            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6818            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6819            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6820            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6821            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6822            multi_buffer::Event::DiagnosticsUpdated => {
6823                self.refresh_active_diagnostics(cx);
6824            }
6825            multi_buffer::Event::LanguageChanged => {}
6826        }
6827    }
6828
6829    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6830        cx.notify();
6831    }
6832
6833    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6834        self.refresh_copilot_suggestions(true, cx);
6835    }
6836
6837    pub fn set_searchable(&mut self, searchable: bool) {
6838        self.searchable = searchable;
6839    }
6840
6841    pub fn searchable(&self) -> bool {
6842        self.searchable
6843    }
6844
6845    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6846        let active_item = workspace.active_item(cx);
6847        let editor_handle = if let Some(editor) = active_item
6848            .as_ref()
6849            .and_then(|item| item.act_as::<Self>(cx))
6850        {
6851            editor
6852        } else {
6853            cx.propagate_action();
6854            return;
6855        };
6856
6857        let editor = editor_handle.read(cx);
6858        let buffer = editor.buffer.read(cx);
6859        if buffer.is_singleton() {
6860            cx.propagate_action();
6861            return;
6862        }
6863
6864        let mut new_selections_by_buffer = HashMap::default();
6865        for selection in editor.selections.all::<usize>(cx) {
6866            for (buffer, mut range) in
6867                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6868            {
6869                if selection.reversed {
6870                    mem::swap(&mut range.start, &mut range.end);
6871                }
6872                new_selections_by_buffer
6873                    .entry(buffer)
6874                    .or_insert(Vec::new())
6875                    .push(range)
6876            }
6877        }
6878
6879        editor_handle.update(cx, |editor, cx| {
6880            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6881        });
6882        let pane = workspace.active_pane().clone();
6883        pane.update(cx, |pane, _| pane.disable_history());
6884
6885        // We defer the pane interaction because we ourselves are a workspace item
6886        // and activating a new item causes the pane to call a method on us reentrantly,
6887        // which panics if we're on the stack.
6888        cx.defer(move |workspace, cx| {
6889            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6890                let editor = workspace.open_project_item::<Self>(buffer, cx);
6891                editor.update(cx, |editor, cx| {
6892                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6893                        s.select_ranges(ranges);
6894                    });
6895                });
6896            }
6897
6898            pane.update(cx, |pane, _| pane.enable_history());
6899        });
6900    }
6901
6902    fn jump(
6903        workspace: &mut Workspace,
6904        path: ProjectPath,
6905        position: Point,
6906        anchor: language::Anchor,
6907        cx: &mut ViewContext<Workspace>,
6908    ) {
6909        let editor = workspace.open_path(path, None, true, cx);
6910        cx.spawn(|_, mut cx| async move {
6911            let editor = editor
6912                .await?
6913                .downcast::<Editor>()
6914                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6915                .downgrade();
6916            editor.update(&mut cx, |editor, cx| {
6917                let buffer = editor
6918                    .buffer()
6919                    .read(cx)
6920                    .as_singleton()
6921                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6922                let buffer = buffer.read(cx);
6923                let cursor = if buffer.can_resolve(&anchor) {
6924                    language::ToPoint::to_point(&anchor, buffer)
6925                } else {
6926                    buffer.clip_point(position, Bias::Left)
6927                };
6928
6929                let nav_history = editor.nav_history.take();
6930                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6931                    s.select_ranges([cursor..cursor]);
6932                });
6933                editor.nav_history = nav_history;
6934
6935                anyhow::Ok(())
6936            })??;
6937
6938            anyhow::Ok(())
6939        })
6940        .detach_and_log_err(cx);
6941    }
6942
6943    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6944        let snapshot = self.buffer.read(cx).read(cx);
6945        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6946        Some(
6947            ranges
6948                .iter()
6949                .map(move |range| {
6950                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6951                })
6952                .collect(),
6953        )
6954    }
6955
6956    fn selection_replacement_ranges(
6957        &self,
6958        range: Range<OffsetUtf16>,
6959        cx: &AppContext,
6960    ) -> Vec<Range<OffsetUtf16>> {
6961        let selections = self.selections.all::<OffsetUtf16>(cx);
6962        let newest_selection = selections
6963            .iter()
6964            .max_by_key(|selection| selection.id)
6965            .unwrap();
6966        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6967        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6968        let snapshot = self.buffer.read(cx).read(cx);
6969        selections
6970            .into_iter()
6971            .map(|mut selection| {
6972                selection.start.0 =
6973                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6974                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6975                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6976                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6977            })
6978            .collect()
6979    }
6980
6981    fn report_copilot_event(
6982        &self,
6983        suggestion_id: Option<String>,
6984        suggestion_accepted: bool,
6985        cx: &AppContext,
6986    ) {
6987        let Some(project) = &self.project else {
6988            return
6989        };
6990
6991        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
6992        let file_extension = self
6993            .buffer
6994            .read(cx)
6995            .as_singleton()
6996            .and_then(|b| b.read(cx).file())
6997            .and_then(|file| Path::new(file.file_name(cx)).extension())
6998            .and_then(|e| e.to_str())
6999            .map(|a| a.to_string());
7000
7001        let telemetry = project.read(cx).client().telemetry().clone();
7002        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7003
7004        let event = ClickhouseEvent::Copilot {
7005            suggestion_id,
7006            suggestion_accepted,
7007            file_extension,
7008        };
7009        telemetry.report_clickhouse_event(event, telemetry_settings);
7010    }
7011
7012    fn report_editor_event(
7013        &self,
7014        name: &'static str,
7015        file_extension: Option<String>,
7016        cx: &AppContext,
7017    ) {
7018        let Some(project) = &self.project else {
7019            return
7020        };
7021
7022        // If None, we are in a file without an extension
7023        let file_extension = file_extension.or(self
7024            .buffer
7025            .read(cx)
7026            .as_singleton()
7027            .and_then(|b| b.read(cx).file())
7028            .and_then(|file| Path::new(file.file_name(cx)).extension())
7029            .and_then(|e| e.to_str())
7030            .map(|a| a.to_string()));
7031
7032        let vim_mode = cx
7033            .global::<SettingsStore>()
7034            .untyped_user_settings()
7035            .get("vim_mode")
7036            == Some(&serde_json::Value::Bool(true));
7037        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7038        let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None);
7039        let copilot_enabled_for_language = self
7040            .buffer
7041            .read(cx)
7042            .settings_at(0, cx)
7043            .show_copilot_suggestions;
7044
7045        let telemetry = project.read(cx).client().telemetry().clone();
7046        telemetry.report_mixpanel_event(
7047            match name {
7048                "open" => "open editor",
7049                "save" => "save editor",
7050                _ => name,
7051            },
7052            json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true  }),
7053            telemetry_settings,
7054        );
7055        let event = ClickhouseEvent::Editor {
7056            file_extension,
7057            vim_mode,
7058            operation: name,
7059            copilot_enabled,
7060            copilot_enabled_for_language,
7061        };
7062        telemetry.report_clickhouse_event(event, telemetry_settings)
7063    }
7064
7065    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7066    /// with each line being an array of {text, highlight} objects.
7067    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7068        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7069            return;
7070        };
7071
7072        #[derive(Serialize)]
7073        struct Chunk<'a> {
7074            text: String,
7075            highlight: Option<&'a str>,
7076        }
7077
7078        let snapshot = buffer.read(cx).snapshot();
7079        let range = self
7080            .selected_text_range(cx)
7081            .and_then(|selected_range| {
7082                if selected_range.is_empty() {
7083                    None
7084                } else {
7085                    Some(selected_range)
7086                }
7087            })
7088            .unwrap_or_else(|| 0..snapshot.len());
7089
7090        let chunks = snapshot.chunks(range, true);
7091        let mut lines = Vec::new();
7092        let mut line: VecDeque<Chunk> = VecDeque::new();
7093
7094        let theme = &theme::current(cx).editor.syntax;
7095
7096        for chunk in chunks {
7097            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7098            let mut chunk_lines = chunk.text.split("\n").peekable();
7099            while let Some(text) = chunk_lines.next() {
7100                let mut merged_with_last_token = false;
7101                if let Some(last_token) = line.back_mut() {
7102                    if last_token.highlight == highlight {
7103                        last_token.text.push_str(text);
7104                        merged_with_last_token = true;
7105                    }
7106                }
7107
7108                if !merged_with_last_token {
7109                    line.push_back(Chunk {
7110                        text: text.into(),
7111                        highlight,
7112                    });
7113                }
7114
7115                if chunk_lines.peek().is_some() {
7116                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7117                        line.pop_front();
7118                    }
7119                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7120                        line.pop_back();
7121                    }
7122
7123                    lines.push(mem::take(&mut line));
7124                }
7125            }
7126        }
7127
7128        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7129        cx.write_to_clipboard(ClipboardItem::new(lines));
7130    }
7131}
7132
7133fn consume_contiguous_rows(
7134    contiguous_row_selections: &mut Vec<Selection<Point>>,
7135    selection: &Selection<Point>,
7136    display_map: &DisplaySnapshot,
7137    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7138) -> (u32, u32) {
7139    contiguous_row_selections.push(selection.clone());
7140    let start_row = selection.start.row;
7141    let mut end_row = ending_row(selection, display_map);
7142
7143    while let Some(next_selection) = selections.peek() {
7144        if next_selection.start.row <= end_row {
7145            end_row = ending_row(next_selection, display_map);
7146            contiguous_row_selections.push(selections.next().unwrap().clone());
7147        } else {
7148            break;
7149        }
7150    }
7151    (start_row, end_row)
7152}
7153
7154fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7155    if next_selection.end.column > 0 || next_selection.is_empty() {
7156        display_map.next_line_boundary(next_selection.end).0.row + 1
7157    } else {
7158        next_selection.end.row
7159    }
7160}
7161
7162impl EditorSnapshot {
7163    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7164        self.display_snapshot.buffer_snapshot.language_at(position)
7165    }
7166
7167    pub fn is_focused(&self) -> bool {
7168        self.is_focused
7169    }
7170
7171    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7172        self.placeholder_text.as_ref()
7173    }
7174
7175    pub fn scroll_position(&self) -> Vector2F {
7176        self.scroll_anchor.scroll_position(&self.display_snapshot)
7177    }
7178}
7179
7180impl Deref for EditorSnapshot {
7181    type Target = DisplaySnapshot;
7182
7183    fn deref(&self) -> &Self::Target {
7184        &self.display_snapshot
7185    }
7186}
7187
7188#[derive(Clone, Debug, PartialEq, Eq)]
7189pub enum Event {
7190    InputIgnored {
7191        text: Arc<str>,
7192    },
7193    ExcerptsAdded {
7194        buffer: ModelHandle<Buffer>,
7195        predecessor: ExcerptId,
7196        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7197    },
7198    ExcerptsRemoved {
7199        ids: Vec<ExcerptId>,
7200    },
7201    BufferEdited,
7202    Edited,
7203    Reparsed,
7204    Focused,
7205    Blurred,
7206    DirtyChanged,
7207    Saved,
7208    TitleChanged,
7209    SelectionsChanged {
7210        local: bool,
7211    },
7212    ScrollPositionChanged {
7213        local: bool,
7214    },
7215    Closed,
7216}
7217
7218pub struct EditorFocused(pub ViewHandle<Editor>);
7219pub struct EditorBlurred(pub ViewHandle<Editor>);
7220pub struct EditorReleased(pub WeakViewHandle<Editor>);
7221
7222impl Entity for Editor {
7223    type Event = Event;
7224
7225    fn release(&mut self, cx: &mut AppContext) {
7226        cx.emit_global(EditorReleased(self.handle.clone()));
7227    }
7228}
7229
7230impl View for Editor {
7231    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7232        let style = self.style(cx);
7233        let font_changed = self.display_map.update(cx, |map, cx| {
7234            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7235            map.set_font(style.text.font_id, style.text.font_size, cx)
7236        });
7237
7238        if font_changed {
7239            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7240                hide_hover(editor, cx);
7241                hide_link_definition(editor, cx);
7242            });
7243        }
7244
7245        Stack::new()
7246            .with_child(EditorElement::new(style.clone()))
7247            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7248            .into_any()
7249    }
7250
7251    fn ui_name() -> &'static str {
7252        "Editor"
7253    }
7254
7255    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7256        if cx.is_self_focused() {
7257            let focused_event = EditorFocused(cx.handle());
7258            cx.emit(Event::Focused);
7259            cx.emit_global(focused_event);
7260        }
7261        if let Some(rename) = self.pending_rename.as_ref() {
7262            cx.focus(&rename.editor);
7263        } else {
7264            if !self.focused {
7265                self.blink_manager.update(cx, BlinkManager::enable);
7266            }
7267            self.focused = true;
7268            self.buffer.update(cx, |buffer, cx| {
7269                buffer.finalize_last_transaction(cx);
7270                if self.leader_replica_id.is_none() {
7271                    buffer.set_active_selections(
7272                        &self.selections.disjoint_anchors(),
7273                        self.selections.line_mode,
7274                        self.cursor_shape,
7275                        cx,
7276                    );
7277                }
7278            });
7279        }
7280    }
7281
7282    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7283        let blurred_event = EditorBlurred(cx.handle());
7284        cx.emit_global(blurred_event);
7285        self.focused = false;
7286        self.blink_manager.update(cx, BlinkManager::disable);
7287        self.buffer
7288            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7289        self.hide_context_menu(cx);
7290        hide_hover(self, cx);
7291        cx.emit(Event::Blurred);
7292        cx.notify();
7293    }
7294
7295    fn modifiers_changed(
7296        &mut self,
7297        event: &gpui::platform::ModifiersChangedEvent,
7298        cx: &mut ViewContext<Self>,
7299    ) -> bool {
7300        let pending_selection = self.has_pending_selection();
7301
7302        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7303            if event.cmd && !pending_selection {
7304                let snapshot = self.snapshot(cx);
7305                let kind = if event.shift {
7306                    LinkDefinitionKind::Type
7307                } else {
7308                    LinkDefinitionKind::Symbol
7309                };
7310
7311                show_link_definition(kind, self, point, snapshot, cx);
7312                return false;
7313            }
7314        }
7315
7316        {
7317            if self.link_go_to_definition_state.symbol_range.is_some()
7318                || !self.link_go_to_definition_state.definitions.is_empty()
7319            {
7320                self.link_go_to_definition_state.symbol_range.take();
7321                self.link_go_to_definition_state.definitions.clear();
7322                cx.notify();
7323            }
7324
7325            self.link_go_to_definition_state.task = None;
7326
7327            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7328        }
7329
7330        false
7331    }
7332
7333    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
7334        Self::reset_to_default_keymap_context(keymap);
7335        let mode = match self.mode {
7336            EditorMode::SingleLine => "single_line",
7337            EditorMode::AutoHeight { .. } => "auto_height",
7338            EditorMode::Full => "full",
7339        };
7340        keymap.add_key("mode", mode);
7341        if self.pending_rename.is_some() {
7342            keymap.add_identifier("renaming");
7343        }
7344        match self.context_menu.as_ref() {
7345            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7346            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7347            None => {}
7348        }
7349
7350        for layer in self.keymap_context_layers.values() {
7351            keymap.extend(layer);
7352        }
7353    }
7354
7355    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7356        Some(
7357            self.buffer
7358                .read(cx)
7359                .read(cx)
7360                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7361                .collect(),
7362        )
7363    }
7364
7365    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7366        // Prevent the IME menu from appearing when holding down an alphabetic key
7367        // while input is disabled.
7368        if !self.input_enabled {
7369            return None;
7370        }
7371
7372        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7373        Some(range.start.0..range.end.0)
7374    }
7375
7376    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7377        let snapshot = self.buffer.read(cx).read(cx);
7378        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7379        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7380    }
7381
7382    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7383        self.clear_text_highlights::<InputComposition>(cx);
7384        self.ime_transaction.take();
7385    }
7386
7387    fn replace_text_in_range(
7388        &mut self,
7389        range_utf16: Option<Range<usize>>,
7390        text: &str,
7391        cx: &mut ViewContext<Self>,
7392    ) {
7393        self.transact(cx, |this, cx| {
7394            if this.input_enabled {
7395                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7396                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7397                    Some(this.selection_replacement_ranges(range_utf16, cx))
7398                } else {
7399                    this.marked_text_ranges(cx)
7400                };
7401
7402                if let Some(new_selected_ranges) = new_selected_ranges {
7403                    this.change_selections(None, cx, |selections| {
7404                        selections.select_ranges(new_selected_ranges)
7405                    });
7406                }
7407            }
7408
7409            this.handle_input(text, cx);
7410        });
7411
7412        if !self.input_enabled {
7413            return;
7414        }
7415
7416        if let Some(transaction) = self.ime_transaction {
7417            self.buffer.update(cx, |buffer, cx| {
7418                buffer.group_until_transaction(transaction, cx);
7419            });
7420        }
7421
7422        self.unmark_text(cx);
7423    }
7424
7425    fn replace_and_mark_text_in_range(
7426        &mut self,
7427        range_utf16: Option<Range<usize>>,
7428        text: &str,
7429        new_selected_range_utf16: Option<Range<usize>>,
7430        cx: &mut ViewContext<Self>,
7431    ) {
7432        if !self.input_enabled {
7433            return;
7434        }
7435
7436        let transaction = self.transact(cx, |this, cx| {
7437            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7438                let snapshot = this.buffer.read(cx).read(cx);
7439                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7440                    for marked_range in &mut marked_ranges {
7441                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7442                        marked_range.start.0 += relative_range_utf16.start;
7443                        marked_range.start =
7444                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7445                        marked_range.end =
7446                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7447                    }
7448                }
7449                Some(marked_ranges)
7450            } else if let Some(range_utf16) = range_utf16 {
7451                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7452                Some(this.selection_replacement_ranges(range_utf16, cx))
7453            } else {
7454                None
7455            };
7456
7457            if let Some(ranges) = ranges_to_replace {
7458                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7459            }
7460
7461            let marked_ranges = {
7462                let snapshot = this.buffer.read(cx).read(cx);
7463                this.selections
7464                    .disjoint_anchors()
7465                    .iter()
7466                    .map(|selection| {
7467                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7468                    })
7469                    .collect::<Vec<_>>()
7470            };
7471
7472            if text.is_empty() {
7473                this.unmark_text(cx);
7474            } else {
7475                this.highlight_text::<InputComposition>(
7476                    marked_ranges.clone(),
7477                    this.style(cx).composition_mark,
7478                    cx,
7479                );
7480            }
7481
7482            this.handle_input(text, cx);
7483
7484            if let Some(new_selected_range) = new_selected_range_utf16 {
7485                let snapshot = this.buffer.read(cx).read(cx);
7486                let new_selected_ranges = marked_ranges
7487                    .into_iter()
7488                    .map(|marked_range| {
7489                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7490                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7491                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7492                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7493                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7494                    })
7495                    .collect::<Vec<_>>();
7496
7497                drop(snapshot);
7498                this.change_selections(None, cx, |selections| {
7499                    selections.select_ranges(new_selected_ranges)
7500                });
7501            }
7502        });
7503
7504        self.ime_transaction = self.ime_transaction.or(transaction);
7505        if let Some(transaction) = self.ime_transaction {
7506            self.buffer.update(cx, |buffer, cx| {
7507                buffer.group_until_transaction(transaction, cx);
7508            });
7509        }
7510
7511        if self.text_highlights::<InputComposition>(cx).is_none() {
7512            self.ime_transaction.take();
7513        }
7514    }
7515}
7516
7517fn build_style(
7518    settings: &ThemeSettings,
7519    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7520    override_text_style: Option<&OverrideTextStyle>,
7521    cx: &AppContext,
7522) -> EditorStyle {
7523    let font_cache = cx.font_cache();
7524
7525    let theme_id = settings.theme.meta.id;
7526    let mut theme = settings.theme.editor.clone();
7527    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7528        let field_editor_theme = get_field_editor_theme(&settings.theme);
7529        theme.text_color = field_editor_theme.text.color;
7530        theme.selection = field_editor_theme.selection;
7531        theme.background = field_editor_theme
7532            .container
7533            .background_color
7534            .unwrap_or_default();
7535        EditorStyle {
7536            text: field_editor_theme.text,
7537            placeholder_text: field_editor_theme.placeholder_text,
7538            theme,
7539            theme_id,
7540        }
7541    } else {
7542        let font_family_id = settings.buffer_font_family;
7543        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7544        let font_properties = Default::default();
7545        let font_id = font_cache
7546            .select_font(font_family_id, &font_properties)
7547            .unwrap();
7548        let font_size = settings.buffer_font_size(cx);
7549        EditorStyle {
7550            text: TextStyle {
7551                color: settings.theme.editor.text_color,
7552                font_family_name,
7553                font_family_id,
7554                font_id,
7555                font_size,
7556                font_properties,
7557                underline: Default::default(),
7558            },
7559            placeholder_text: None,
7560            theme,
7561            theme_id,
7562        }
7563    };
7564
7565    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7566        if let Some(highlighted) = style
7567            .text
7568            .clone()
7569            .highlight(highlight_style, font_cache)
7570            .log_err()
7571        {
7572            style.text = highlighted;
7573        }
7574    }
7575
7576    style
7577}
7578
7579trait SelectionExt {
7580    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7581    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7582    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7583    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7584        -> Range<u32>;
7585}
7586
7587impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7588    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7589        let start = self.start.to_point(buffer);
7590        let end = self.end.to_point(buffer);
7591        if self.reversed {
7592            end..start
7593        } else {
7594            start..end
7595        }
7596    }
7597
7598    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7599        let start = self.start.to_offset(buffer);
7600        let end = self.end.to_offset(buffer);
7601        if self.reversed {
7602            end..start
7603        } else {
7604            start..end
7605        }
7606    }
7607
7608    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7609        let start = self
7610            .start
7611            .to_point(&map.buffer_snapshot)
7612            .to_display_point(map);
7613        let end = self
7614            .end
7615            .to_point(&map.buffer_snapshot)
7616            .to_display_point(map);
7617        if self.reversed {
7618            end..start
7619        } else {
7620            start..end
7621        }
7622    }
7623
7624    fn spanned_rows(
7625        &self,
7626        include_end_if_at_line_start: bool,
7627        map: &DisplaySnapshot,
7628    ) -> Range<u32> {
7629        let start = self.start.to_point(&map.buffer_snapshot);
7630        let mut end = self.end.to_point(&map.buffer_snapshot);
7631        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7632            end.row -= 1;
7633        }
7634
7635        let buffer_start = map.prev_line_boundary(start).0;
7636        let buffer_end = map.next_line_boundary(end).0;
7637        buffer_start.row..buffer_end.row + 1
7638    }
7639}
7640
7641impl<T: InvalidationRegion> InvalidationStack<T> {
7642    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7643    where
7644        S: Clone + ToOffset,
7645    {
7646        while let Some(region) = self.last() {
7647            let all_selections_inside_invalidation_ranges =
7648                if selections.len() == region.ranges().len() {
7649                    selections
7650                        .iter()
7651                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7652                        .all(|(selection, invalidation_range)| {
7653                            let head = selection.head().to_offset(buffer);
7654                            invalidation_range.start <= head && invalidation_range.end >= head
7655                        })
7656                } else {
7657                    false
7658                };
7659
7660            if all_selections_inside_invalidation_ranges {
7661                break;
7662            } else {
7663                self.pop();
7664            }
7665        }
7666    }
7667}
7668
7669impl<T> Default for InvalidationStack<T> {
7670    fn default() -> Self {
7671        Self(Default::default())
7672    }
7673}
7674
7675impl<T> Deref for InvalidationStack<T> {
7676    type Target = Vec<T>;
7677
7678    fn deref(&self) -> &Self::Target {
7679        &self.0
7680    }
7681}
7682
7683impl<T> DerefMut for InvalidationStack<T> {
7684    fn deref_mut(&mut self) -> &mut Self::Target {
7685        &mut self.0
7686    }
7687}
7688
7689impl InvalidationRegion for SnippetState {
7690    fn ranges(&self) -> &[Range<Anchor>] {
7691        &self.ranges[self.active_index]
7692    }
7693}
7694
7695impl Deref for EditorStyle {
7696    type Target = theme::Editor;
7697
7698    fn deref(&self) -> &Self::Target {
7699        &self.theme
7700    }
7701}
7702
7703pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7704    let mut highlighted_lines = Vec::new();
7705    for (index, line) in diagnostic.message.lines().enumerate() {
7706        let line = match &diagnostic.source {
7707            Some(source) if index == 0 => {
7708                let source_highlight = Vec::from_iter(0..source.len());
7709                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7710            }
7711
7712            _ => highlight_diagnostic_message(Vec::new(), line),
7713        };
7714        highlighted_lines.push(line);
7715    }
7716
7717    Arc::new(move |cx: &mut BlockContext| {
7718        let settings = settings::get::<ThemeSettings>(cx);
7719        let theme = &settings.theme.editor;
7720        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7721        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7722        Flex::column()
7723            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7724                Label::new(
7725                    line.clone(),
7726                    style.message.clone().with_font_size(font_size),
7727                )
7728                .with_highlights(highlights.clone())
7729                .contained()
7730                .with_margin_left(cx.anchor_x)
7731            }))
7732            .aligned()
7733            .left()
7734            .into_any()
7735    })
7736}
7737
7738pub fn highlight_diagnostic_message(
7739    inital_highlights: Vec<usize>,
7740    message: &str,
7741) -> (String, Vec<usize>) {
7742    let mut message_without_backticks = String::new();
7743    let mut prev_offset = 0;
7744    let mut inside_block = false;
7745    let mut highlights = inital_highlights;
7746    for (match_ix, (offset, _)) in message
7747        .match_indices('`')
7748        .chain([(message.len(), "")])
7749        .enumerate()
7750    {
7751        message_without_backticks.push_str(&message[prev_offset..offset]);
7752        if inside_block {
7753            highlights.extend(prev_offset - match_ix..offset - match_ix);
7754        }
7755
7756        inside_block = !inside_block;
7757        prev_offset = offset + 1;
7758    }
7759
7760    (message_without_backticks, highlights)
7761}
7762
7763pub fn diagnostic_style(
7764    severity: DiagnosticSeverity,
7765    valid: bool,
7766    theme: &theme::Editor,
7767) -> DiagnosticStyle {
7768    match (severity, valid) {
7769        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7770        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7771        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7772        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7773        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7774        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7775        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7776        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7777        _ => theme.invalid_hint_diagnostic.clone(),
7778    }
7779}
7780
7781pub fn combine_syntax_and_fuzzy_match_highlights(
7782    text: &str,
7783    default_style: HighlightStyle,
7784    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7785    match_indices: &[usize],
7786) -> Vec<(Range<usize>, HighlightStyle)> {
7787    let mut result = Vec::new();
7788    let mut match_indices = match_indices.iter().copied().peekable();
7789
7790    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7791    {
7792        syntax_highlight.weight = None;
7793
7794        // Add highlights for any fuzzy match characters before the next
7795        // syntax highlight range.
7796        while let Some(&match_index) = match_indices.peek() {
7797            if match_index >= range.start {
7798                break;
7799            }
7800            match_indices.next();
7801            let end_index = char_ix_after(match_index, text);
7802            let mut match_style = default_style;
7803            match_style.weight = Some(fonts::Weight::BOLD);
7804            result.push((match_index..end_index, match_style));
7805        }
7806
7807        if range.start == usize::MAX {
7808            break;
7809        }
7810
7811        // Add highlights for any fuzzy match characters within the
7812        // syntax highlight range.
7813        let mut offset = range.start;
7814        while let Some(&match_index) = match_indices.peek() {
7815            if match_index >= range.end {
7816                break;
7817            }
7818
7819            match_indices.next();
7820            if match_index > offset {
7821                result.push((offset..match_index, syntax_highlight));
7822            }
7823
7824            let mut end_index = char_ix_after(match_index, text);
7825            while let Some(&next_match_index) = match_indices.peek() {
7826                if next_match_index == end_index && next_match_index < range.end {
7827                    end_index = char_ix_after(next_match_index, text);
7828                    match_indices.next();
7829                } else {
7830                    break;
7831                }
7832            }
7833
7834            let mut match_style = syntax_highlight;
7835            match_style.weight = Some(fonts::Weight::BOLD);
7836            result.push((match_index..end_index, match_style));
7837            offset = end_index;
7838        }
7839
7840        if offset < range.end {
7841            result.push((offset..range.end, syntax_highlight));
7842        }
7843    }
7844
7845    fn char_ix_after(ix: usize, text: &str) -> usize {
7846        ix + text[ix..].chars().next().unwrap().len_utf8()
7847    }
7848
7849    result
7850}
7851
7852pub fn styled_runs_for_code_label<'a>(
7853    label: &'a CodeLabel,
7854    syntax_theme: &'a theme::SyntaxTheme,
7855) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7856    let fade_out = HighlightStyle {
7857        fade_out: Some(0.35),
7858        ..Default::default()
7859    };
7860
7861    let mut prev_end = label.filter_range.end;
7862    label
7863        .runs
7864        .iter()
7865        .enumerate()
7866        .flat_map(move |(ix, (range, highlight_id))| {
7867            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7868                style
7869            } else {
7870                return Default::default();
7871            };
7872            let mut muted_style = style;
7873            muted_style.highlight(fade_out);
7874
7875            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7876            if range.start >= label.filter_range.end {
7877                if range.start > prev_end {
7878                    runs.push((prev_end..range.start, fade_out));
7879                }
7880                runs.push((range.clone(), muted_style));
7881            } else if range.end <= label.filter_range.end {
7882                runs.push((range.clone(), style));
7883            } else {
7884                runs.push((range.start..label.filter_range.end, style));
7885                runs.push((label.filter_range.end..range.end, muted_style));
7886            }
7887            prev_end = cmp::max(prev_end, range.end);
7888
7889            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7890                runs.push((prev_end..label.text.len(), fade_out));
7891            }
7892
7893            runs
7894        })
7895}
7896
7897pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7898    let mut index = 0;
7899    let mut codepoints = text.char_indices().peekable();
7900
7901    std::iter::from_fn(move || {
7902        let start_index = index;
7903        while let Some((new_index, codepoint)) = codepoints.next() {
7904            index = new_index + codepoint.len_utf8();
7905            let current_upper = codepoint.is_uppercase();
7906            let next_upper = codepoints
7907                .peek()
7908                .map(|(_, c)| c.is_uppercase())
7909                .unwrap_or(false);
7910
7911            if !current_upper && next_upper {
7912                return Some(&text[start_index..index]);
7913            }
7914        }
7915
7916        index = text.len();
7917        if start_index < text.len() {
7918            return Some(&text[start_index..]);
7919        }
7920        None
7921    })
7922    .flat_map(|word| word.split_inclusive('_'))
7923}
7924
7925trait RangeToAnchorExt {
7926    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7927}
7928
7929impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7930    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7931        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7932    }
7933}