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