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