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        &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 {
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::Closed => cx.emit(Event::Closed),
6877            multi_buffer::Event::DiagnosticsUpdated => {
6878                self.refresh_active_diagnostics(cx);
6879            }
6880            multi_buffer::Event::LanguageChanged => {}
6881        }
6882    }
6883
6884    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6885        cx.notify();
6886    }
6887
6888    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6889        self.refresh_copilot_suggestions(true, cx);
6890    }
6891
6892    pub fn set_searchable(&mut self, searchable: bool) {
6893        self.searchable = searchable;
6894    }
6895
6896    pub fn searchable(&self) -> bool {
6897        self.searchable
6898    }
6899
6900    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6901        let active_item = workspace.active_item(cx);
6902        let editor_handle = if let Some(editor) = active_item
6903            .as_ref()
6904            .and_then(|item| item.act_as::<Self>(cx))
6905        {
6906            editor
6907        } else {
6908            cx.propagate_action();
6909            return;
6910        };
6911
6912        let editor = editor_handle.read(cx);
6913        let buffer = editor.buffer.read(cx);
6914        if buffer.is_singleton() {
6915            cx.propagate_action();
6916            return;
6917        }
6918
6919        let mut new_selections_by_buffer = HashMap::default();
6920        for selection in editor.selections.all::<usize>(cx) {
6921            for (buffer, mut range) in
6922                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6923            {
6924                if selection.reversed {
6925                    mem::swap(&mut range.start, &mut range.end);
6926                }
6927                new_selections_by_buffer
6928                    .entry(buffer)
6929                    .or_insert(Vec::new())
6930                    .push(range)
6931            }
6932        }
6933
6934        editor_handle.update(cx, |editor, cx| {
6935            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6936        });
6937        let pane = workspace.active_pane().clone();
6938        pane.update(cx, |pane, _| pane.disable_history());
6939
6940        // We defer the pane interaction because we ourselves are a workspace item
6941        // and activating a new item causes the pane to call a method on us reentrantly,
6942        // which panics if we're on the stack.
6943        cx.defer(move |workspace, cx| {
6944            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6945                let editor = workspace.open_project_item::<Self>(buffer, cx);
6946                editor.update(cx, |editor, cx| {
6947                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6948                        s.select_ranges(ranges);
6949                    });
6950                });
6951            }
6952
6953            pane.update(cx, |pane, _| pane.enable_history());
6954        });
6955    }
6956
6957    fn jump(
6958        workspace: &mut Workspace,
6959        path: ProjectPath,
6960        position: Point,
6961        anchor: language::Anchor,
6962        cx: &mut ViewContext<Workspace>,
6963    ) {
6964        let editor = workspace.open_path(path, None, true, cx);
6965        cx.spawn(|_, mut cx| async move {
6966            let editor = editor
6967                .await?
6968                .downcast::<Editor>()
6969                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6970                .downgrade();
6971            editor.update(&mut cx, |editor, cx| {
6972                let buffer = editor
6973                    .buffer()
6974                    .read(cx)
6975                    .as_singleton()
6976                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6977                let buffer = buffer.read(cx);
6978                let cursor = if buffer.can_resolve(&anchor) {
6979                    language::ToPoint::to_point(&anchor, buffer)
6980                } else {
6981                    buffer.clip_point(position, Bias::Left)
6982                };
6983
6984                let nav_history = editor.nav_history.take();
6985                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6986                    s.select_ranges([cursor..cursor]);
6987                });
6988                editor.nav_history = nav_history;
6989
6990                anyhow::Ok(())
6991            })??;
6992
6993            anyhow::Ok(())
6994        })
6995        .detach_and_log_err(cx);
6996    }
6997
6998    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6999        let snapshot = self.buffer.read(cx).read(cx);
7000        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7001        Some(
7002            ranges
7003                .iter()
7004                .map(move |range| {
7005                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7006                })
7007                .collect(),
7008        )
7009    }
7010
7011    fn selection_replacement_ranges(
7012        &self,
7013        range: Range<OffsetUtf16>,
7014        cx: &AppContext,
7015    ) -> Vec<Range<OffsetUtf16>> {
7016        let selections = self.selections.all::<OffsetUtf16>(cx);
7017        let newest_selection = selections
7018            .iter()
7019            .max_by_key(|selection| selection.id)
7020            .unwrap();
7021        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7022        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7023        let snapshot = self.buffer.read(cx).read(cx);
7024        selections
7025            .into_iter()
7026            .map(|mut selection| {
7027                selection.start.0 =
7028                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7029                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7030                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7031                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7032            })
7033            .collect()
7034    }
7035
7036    fn report_copilot_event(
7037        &self,
7038        suggestion_id: Option<String>,
7039        suggestion_accepted: bool,
7040        cx: &AppContext,
7041    ) {
7042        let Some(project) = &self.project else {
7043            return
7044        };
7045
7046        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7047        let file_extension = self
7048            .buffer
7049            .read(cx)
7050            .as_singleton()
7051            .and_then(|b| b.read(cx).file())
7052            .and_then(|file| Path::new(file.file_name(cx)).extension())
7053            .and_then(|e| e.to_str())
7054            .map(|a| a.to_string());
7055
7056        let telemetry = project.read(cx).client().telemetry().clone();
7057        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7058
7059        let event = ClickhouseEvent::Copilot {
7060            suggestion_id,
7061            suggestion_accepted,
7062            file_extension,
7063        };
7064        telemetry.report_clickhouse_event(event, telemetry_settings);
7065    }
7066
7067    fn report_editor_event(
7068        &self,
7069        name: &'static str,
7070        file_extension: Option<String>,
7071        cx: &AppContext,
7072    ) {
7073        let Some(project) = &self.project else {
7074            return
7075        };
7076
7077        // If None, we are in a file without an extension
7078        let file_extension = file_extension.or(self
7079            .buffer
7080            .read(cx)
7081            .as_singleton()
7082            .and_then(|b| b.read(cx).file())
7083            .and_then(|file| Path::new(file.file_name(cx)).extension())
7084            .and_then(|e| e.to_str())
7085            .map(|a| a.to_string()));
7086
7087        let vim_mode = cx
7088            .global::<SettingsStore>()
7089            .untyped_user_settings()
7090            .get("vim_mode")
7091            == Some(&serde_json::Value::Bool(true));
7092        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7093        let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None);
7094        let copilot_enabled_for_language = self
7095            .buffer
7096            .read(cx)
7097            .settings_at(0, cx)
7098            .show_copilot_suggestions;
7099
7100        let telemetry = project.read(cx).client().telemetry().clone();
7101        telemetry.report_mixpanel_event(
7102            match name {
7103                "open" => "open editor",
7104                "save" => "save editor",
7105                _ => name,
7106            },
7107            json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true  }),
7108            telemetry_settings,
7109        );
7110        let event = ClickhouseEvent::Editor {
7111            file_extension,
7112            vim_mode,
7113            operation: name,
7114            copilot_enabled,
7115            copilot_enabled_for_language,
7116        };
7117        telemetry.report_clickhouse_event(event, telemetry_settings)
7118    }
7119
7120    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7121    /// with each line being an array of {text, highlight} objects.
7122    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7123        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7124            return;
7125        };
7126
7127        #[derive(Serialize)]
7128        struct Chunk<'a> {
7129            text: String,
7130            highlight: Option<&'a str>,
7131        }
7132
7133        let snapshot = buffer.read(cx).snapshot();
7134        let range = self
7135            .selected_text_range(cx)
7136            .and_then(|selected_range| {
7137                if selected_range.is_empty() {
7138                    None
7139                } else {
7140                    Some(selected_range)
7141                }
7142            })
7143            .unwrap_or_else(|| 0..snapshot.len());
7144
7145        let chunks = snapshot.chunks(range, true);
7146        let mut lines = Vec::new();
7147        let mut line: VecDeque<Chunk> = VecDeque::new();
7148
7149        let theme = &theme::current(cx).editor.syntax;
7150
7151        for chunk in chunks {
7152            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7153            let mut chunk_lines = chunk.text.split("\n").peekable();
7154            while let Some(text) = chunk_lines.next() {
7155                let mut merged_with_last_token = false;
7156                if let Some(last_token) = line.back_mut() {
7157                    if last_token.highlight == highlight {
7158                        last_token.text.push_str(text);
7159                        merged_with_last_token = true;
7160                    }
7161                }
7162
7163                if !merged_with_last_token {
7164                    line.push_back(Chunk {
7165                        text: text.into(),
7166                        highlight,
7167                    });
7168                }
7169
7170                if chunk_lines.peek().is_some() {
7171                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7172                        line.pop_front();
7173                    }
7174                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7175                        line.pop_back();
7176                    }
7177
7178                    lines.push(mem::take(&mut line));
7179                }
7180            }
7181        }
7182
7183        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7184        cx.write_to_clipboard(ClipboardItem::new(lines));
7185    }
7186}
7187
7188fn consume_contiguous_rows(
7189    contiguous_row_selections: &mut Vec<Selection<Point>>,
7190    selection: &Selection<Point>,
7191    display_map: &DisplaySnapshot,
7192    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7193) -> (u32, u32) {
7194    contiguous_row_selections.push(selection.clone());
7195    let start_row = selection.start.row;
7196    let mut end_row = ending_row(selection, display_map);
7197
7198    while let Some(next_selection) = selections.peek() {
7199        if next_selection.start.row <= end_row {
7200            end_row = ending_row(next_selection, display_map);
7201            contiguous_row_selections.push(selections.next().unwrap().clone());
7202        } else {
7203            break;
7204        }
7205    }
7206    (start_row, end_row)
7207}
7208
7209fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7210    if next_selection.end.column > 0 || next_selection.is_empty() {
7211        display_map.next_line_boundary(next_selection.end).0.row + 1
7212    } else {
7213        next_selection.end.row
7214    }
7215}
7216
7217impl EditorSnapshot {
7218    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7219        self.display_snapshot.buffer_snapshot.language_at(position)
7220    }
7221
7222    pub fn is_focused(&self) -> bool {
7223        self.is_focused
7224    }
7225
7226    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7227        self.placeholder_text.as_ref()
7228    }
7229
7230    pub fn scroll_position(&self) -> Vector2F {
7231        self.scroll_anchor.scroll_position(&self.display_snapshot)
7232    }
7233}
7234
7235impl Deref for EditorSnapshot {
7236    type Target = DisplaySnapshot;
7237
7238    fn deref(&self) -> &Self::Target {
7239        &self.display_snapshot
7240    }
7241}
7242
7243#[derive(Clone, Debug, PartialEq, Eq)]
7244pub enum Event {
7245    InputIgnored {
7246        text: Arc<str>,
7247    },
7248    ExcerptsAdded {
7249        buffer: ModelHandle<Buffer>,
7250        predecessor: ExcerptId,
7251        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7252    },
7253    ExcerptsRemoved {
7254        ids: Vec<ExcerptId>,
7255    },
7256    BufferEdited,
7257    Edited,
7258    Reparsed,
7259    Focused,
7260    Blurred,
7261    DirtyChanged,
7262    Saved,
7263    TitleChanged,
7264    SelectionsChanged {
7265        local: bool,
7266    },
7267    ScrollPositionChanged {
7268        local: bool,
7269    },
7270    Closed,
7271}
7272
7273pub struct EditorFocused(pub ViewHandle<Editor>);
7274pub struct EditorBlurred(pub ViewHandle<Editor>);
7275pub struct EditorReleased(pub WeakViewHandle<Editor>);
7276
7277impl Entity for Editor {
7278    type Event = Event;
7279
7280    fn release(&mut self, cx: &mut AppContext) {
7281        cx.emit_global(EditorReleased(self.handle.clone()));
7282    }
7283}
7284
7285impl View for Editor {
7286    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7287        let style = self.style(cx);
7288        let font_changed = self.display_map.update(cx, |map, cx| {
7289            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7290            map.set_font(style.text.font_id, style.text.font_size, cx)
7291        });
7292
7293        if font_changed {
7294            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7295                hide_hover(editor, cx);
7296                hide_link_definition(editor, cx);
7297            });
7298        }
7299
7300        Stack::new()
7301            .with_child(EditorElement::new(style.clone()))
7302            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7303            .into_any()
7304    }
7305
7306    fn ui_name() -> &'static str {
7307        "Editor"
7308    }
7309
7310    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7311        if cx.is_self_focused() {
7312            let focused_event = EditorFocused(cx.handle());
7313            cx.emit(Event::Focused);
7314            cx.emit_global(focused_event);
7315        }
7316        if let Some(rename) = self.pending_rename.as_ref() {
7317            cx.focus(&rename.editor);
7318        } else {
7319            if !self.focused {
7320                self.blink_manager.update(cx, BlinkManager::enable);
7321            }
7322            self.focused = true;
7323            self.buffer.update(cx, |buffer, cx| {
7324                buffer.finalize_last_transaction(cx);
7325                if self.leader_replica_id.is_none() {
7326                    buffer.set_active_selections(
7327                        &self.selections.disjoint_anchors(),
7328                        self.selections.line_mode,
7329                        self.cursor_shape,
7330                        cx,
7331                    );
7332                }
7333            });
7334        }
7335    }
7336
7337    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7338        let blurred_event = EditorBlurred(cx.handle());
7339        cx.emit_global(blurred_event);
7340        self.focused = false;
7341        self.blink_manager.update(cx, BlinkManager::disable);
7342        self.buffer
7343            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7344        self.hide_context_menu(cx);
7345        hide_hover(self, cx);
7346        cx.emit(Event::Blurred);
7347        cx.notify();
7348    }
7349
7350    fn modifiers_changed(
7351        &mut self,
7352        event: &gpui::platform::ModifiersChangedEvent,
7353        cx: &mut ViewContext<Self>,
7354    ) -> bool {
7355        let pending_selection = self.has_pending_selection();
7356
7357        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7358            if event.cmd && !pending_selection {
7359                let snapshot = self.snapshot(cx);
7360                let kind = if event.shift {
7361                    LinkDefinitionKind::Type
7362                } else {
7363                    LinkDefinitionKind::Symbol
7364                };
7365
7366                show_link_definition(kind, self, point, snapshot, cx);
7367                return false;
7368            }
7369        }
7370
7371        {
7372            if self.link_go_to_definition_state.symbol_range.is_some()
7373                || !self.link_go_to_definition_state.definitions.is_empty()
7374            {
7375                self.link_go_to_definition_state.symbol_range.take();
7376                self.link_go_to_definition_state.definitions.clear();
7377                cx.notify();
7378            }
7379
7380            self.link_go_to_definition_state.task = None;
7381
7382            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7383        }
7384
7385        false
7386    }
7387
7388    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7389        Self::reset_to_default_keymap_context(keymap);
7390        let mode = match self.mode {
7391            EditorMode::SingleLine => "single_line",
7392            EditorMode::AutoHeight { .. } => "auto_height",
7393            EditorMode::Full => "full",
7394        };
7395        keymap.add_key("mode", mode);
7396        if self.pending_rename.is_some() {
7397            keymap.add_identifier("renaming");
7398        }
7399        match self.context_menu.as_ref() {
7400            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7401            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7402            None => {}
7403        }
7404        for layer in self.keymap_context_layers.values() {
7405            keymap.extend(layer);
7406        }
7407
7408        if let Some(extension) = self
7409            .buffer
7410            .read(cx)
7411            .as_singleton()
7412            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7413        {
7414            keymap.add_key("extension", extension.to_string());
7415        }
7416    }
7417
7418    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7419        Some(
7420            self.buffer
7421                .read(cx)
7422                .read(cx)
7423                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7424                .collect(),
7425        )
7426    }
7427
7428    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7429        // Prevent the IME menu from appearing when holding down an alphabetic key
7430        // while input is disabled.
7431        if !self.input_enabled {
7432            return None;
7433        }
7434
7435        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7436        Some(range.start.0..range.end.0)
7437    }
7438
7439    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7440        let snapshot = self.buffer.read(cx).read(cx);
7441        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7442        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7443    }
7444
7445    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7446        self.clear_text_highlights::<InputComposition>(cx);
7447        self.ime_transaction.take();
7448    }
7449
7450    fn replace_text_in_range(
7451        &mut self,
7452        range_utf16: Option<Range<usize>>,
7453        text: &str,
7454        cx: &mut ViewContext<Self>,
7455    ) {
7456        self.transact(cx, |this, cx| {
7457            if this.input_enabled {
7458                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7459                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7460                    Some(this.selection_replacement_ranges(range_utf16, cx))
7461                } else {
7462                    this.marked_text_ranges(cx)
7463                };
7464
7465                if let Some(new_selected_ranges) = new_selected_ranges {
7466                    this.change_selections(None, cx, |selections| {
7467                        selections.select_ranges(new_selected_ranges)
7468                    });
7469                }
7470            }
7471
7472            this.handle_input(text, cx);
7473        });
7474
7475        if !self.input_enabled {
7476            return;
7477        }
7478
7479        if let Some(transaction) = self.ime_transaction {
7480            self.buffer.update(cx, |buffer, cx| {
7481                buffer.group_until_transaction(transaction, cx);
7482            });
7483        }
7484
7485        self.unmark_text(cx);
7486    }
7487
7488    fn replace_and_mark_text_in_range(
7489        &mut self,
7490        range_utf16: Option<Range<usize>>,
7491        text: &str,
7492        new_selected_range_utf16: Option<Range<usize>>,
7493        cx: &mut ViewContext<Self>,
7494    ) {
7495        if !self.input_enabled {
7496            return;
7497        }
7498
7499        let transaction = self.transact(cx, |this, cx| {
7500            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7501                let snapshot = this.buffer.read(cx).read(cx);
7502                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7503                    for marked_range in &mut marked_ranges {
7504                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7505                        marked_range.start.0 += relative_range_utf16.start;
7506                        marked_range.start =
7507                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7508                        marked_range.end =
7509                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7510                    }
7511                }
7512                Some(marked_ranges)
7513            } else if let Some(range_utf16) = range_utf16 {
7514                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7515                Some(this.selection_replacement_ranges(range_utf16, cx))
7516            } else {
7517                None
7518            };
7519
7520            if let Some(ranges) = ranges_to_replace {
7521                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7522            }
7523
7524            let marked_ranges = {
7525                let snapshot = this.buffer.read(cx).read(cx);
7526                this.selections
7527                    .disjoint_anchors()
7528                    .iter()
7529                    .map(|selection| {
7530                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7531                    })
7532                    .collect::<Vec<_>>()
7533            };
7534
7535            if text.is_empty() {
7536                this.unmark_text(cx);
7537            } else {
7538                this.highlight_text::<InputComposition>(
7539                    marked_ranges.clone(),
7540                    this.style(cx).composition_mark,
7541                    cx,
7542                );
7543            }
7544
7545            this.handle_input(text, cx);
7546
7547            if let Some(new_selected_range) = new_selected_range_utf16 {
7548                let snapshot = this.buffer.read(cx).read(cx);
7549                let new_selected_ranges = marked_ranges
7550                    .into_iter()
7551                    .map(|marked_range| {
7552                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7553                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7554                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7555                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7556                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7557                    })
7558                    .collect::<Vec<_>>();
7559
7560                drop(snapshot);
7561                this.change_selections(None, cx, |selections| {
7562                    selections.select_ranges(new_selected_ranges)
7563                });
7564            }
7565        });
7566
7567        self.ime_transaction = self.ime_transaction.or(transaction);
7568        if let Some(transaction) = self.ime_transaction {
7569            self.buffer.update(cx, |buffer, cx| {
7570                buffer.group_until_transaction(transaction, cx);
7571            });
7572        }
7573
7574        if self.text_highlights::<InputComposition>(cx).is_none() {
7575            self.ime_transaction.take();
7576        }
7577    }
7578}
7579
7580fn build_style(
7581    settings: &ThemeSettings,
7582    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7583    override_text_style: Option<&OverrideTextStyle>,
7584    cx: &AppContext,
7585) -> EditorStyle {
7586    let font_cache = cx.font_cache();
7587
7588    let theme_id = settings.theme.meta.id;
7589    let mut theme = settings.theme.editor.clone();
7590    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7591        let field_editor_theme = get_field_editor_theme(&settings.theme);
7592        theme.text_color = field_editor_theme.text.color;
7593        theme.selection = field_editor_theme.selection;
7594        theme.background = field_editor_theme
7595            .container
7596            .background_color
7597            .unwrap_or_default();
7598        EditorStyle {
7599            text: field_editor_theme.text,
7600            placeholder_text: field_editor_theme.placeholder_text,
7601            theme,
7602            theme_id,
7603        }
7604    } else {
7605        let font_family_id = settings.buffer_font_family;
7606        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7607        let font_properties = Default::default();
7608        let font_id = font_cache
7609            .select_font(font_family_id, &font_properties)
7610            .unwrap();
7611        let font_size = settings.buffer_font_size(cx);
7612        EditorStyle {
7613            text: TextStyle {
7614                color: settings.theme.editor.text_color,
7615                font_family_name,
7616                font_family_id,
7617                font_id,
7618                font_size,
7619                font_properties,
7620                underline: Default::default(),
7621            },
7622            placeholder_text: None,
7623            theme,
7624            theme_id,
7625        }
7626    };
7627
7628    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7629        if let Some(highlighted) = style
7630            .text
7631            .clone()
7632            .highlight(highlight_style, font_cache)
7633            .log_err()
7634        {
7635            style.text = highlighted;
7636        }
7637    }
7638
7639    style
7640}
7641
7642trait SelectionExt {
7643    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7644    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7645    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7646    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7647        -> Range<u32>;
7648}
7649
7650impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7651    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7652        let start = self.start.to_point(buffer);
7653        let end = self.end.to_point(buffer);
7654        if self.reversed {
7655            end..start
7656        } else {
7657            start..end
7658        }
7659    }
7660
7661    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7662        let start = self.start.to_offset(buffer);
7663        let end = self.end.to_offset(buffer);
7664        if self.reversed {
7665            end..start
7666        } else {
7667            start..end
7668        }
7669    }
7670
7671    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7672        let start = self
7673            .start
7674            .to_point(&map.buffer_snapshot)
7675            .to_display_point(map);
7676        let end = self
7677            .end
7678            .to_point(&map.buffer_snapshot)
7679            .to_display_point(map);
7680        if self.reversed {
7681            end..start
7682        } else {
7683            start..end
7684        }
7685    }
7686
7687    fn spanned_rows(
7688        &self,
7689        include_end_if_at_line_start: bool,
7690        map: &DisplaySnapshot,
7691    ) -> Range<u32> {
7692        let start = self.start.to_point(&map.buffer_snapshot);
7693        let mut end = self.end.to_point(&map.buffer_snapshot);
7694        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7695            end.row -= 1;
7696        }
7697
7698        let buffer_start = map.prev_line_boundary(start).0;
7699        let buffer_end = map.next_line_boundary(end).0;
7700        buffer_start.row..buffer_end.row + 1
7701    }
7702}
7703
7704impl<T: InvalidationRegion> InvalidationStack<T> {
7705    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7706    where
7707        S: Clone + ToOffset,
7708    {
7709        while let Some(region) = self.last() {
7710            let all_selections_inside_invalidation_ranges =
7711                if selections.len() == region.ranges().len() {
7712                    selections
7713                        .iter()
7714                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7715                        .all(|(selection, invalidation_range)| {
7716                            let head = selection.head().to_offset(buffer);
7717                            invalidation_range.start <= head && invalidation_range.end >= head
7718                        })
7719                } else {
7720                    false
7721                };
7722
7723            if all_selections_inside_invalidation_ranges {
7724                break;
7725            } else {
7726                self.pop();
7727            }
7728        }
7729    }
7730}
7731
7732impl<T> Default for InvalidationStack<T> {
7733    fn default() -> Self {
7734        Self(Default::default())
7735    }
7736}
7737
7738impl<T> Deref for InvalidationStack<T> {
7739    type Target = Vec<T>;
7740
7741    fn deref(&self) -> &Self::Target {
7742        &self.0
7743    }
7744}
7745
7746impl<T> DerefMut for InvalidationStack<T> {
7747    fn deref_mut(&mut self) -> &mut Self::Target {
7748        &mut self.0
7749    }
7750}
7751
7752impl InvalidationRegion for SnippetState {
7753    fn ranges(&self) -> &[Range<Anchor>] {
7754        &self.ranges[self.active_index]
7755    }
7756}
7757
7758impl Deref for EditorStyle {
7759    type Target = theme::Editor;
7760
7761    fn deref(&self) -> &Self::Target {
7762        &self.theme
7763    }
7764}
7765
7766pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7767    let mut highlighted_lines = Vec::new();
7768    for (index, line) in diagnostic.message.lines().enumerate() {
7769        let line = match &diagnostic.source {
7770            Some(source) if index == 0 => {
7771                let source_highlight = Vec::from_iter(0..source.len());
7772                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7773            }
7774
7775            _ => highlight_diagnostic_message(Vec::new(), line),
7776        };
7777        highlighted_lines.push(line);
7778    }
7779
7780    Arc::new(move |cx: &mut BlockContext| {
7781        let settings = settings::get::<ThemeSettings>(cx);
7782        let theme = &settings.theme.editor;
7783        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7784        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7785        Flex::column()
7786            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7787                Label::new(
7788                    line.clone(),
7789                    style.message.clone().with_font_size(font_size),
7790                )
7791                .with_highlights(highlights.clone())
7792                .contained()
7793                .with_margin_left(cx.anchor_x)
7794            }))
7795            .aligned()
7796            .left()
7797            .into_any()
7798    })
7799}
7800
7801pub fn highlight_diagnostic_message(
7802    inital_highlights: Vec<usize>,
7803    message: &str,
7804) -> (String, Vec<usize>) {
7805    let mut message_without_backticks = String::new();
7806    let mut prev_offset = 0;
7807    let mut inside_block = false;
7808    let mut highlights = inital_highlights;
7809    for (match_ix, (offset, _)) in message
7810        .match_indices('`')
7811        .chain([(message.len(), "")])
7812        .enumerate()
7813    {
7814        message_without_backticks.push_str(&message[prev_offset..offset]);
7815        if inside_block {
7816            highlights.extend(prev_offset - match_ix..offset - match_ix);
7817        }
7818
7819        inside_block = !inside_block;
7820        prev_offset = offset + 1;
7821    }
7822
7823    (message_without_backticks, highlights)
7824}
7825
7826pub fn diagnostic_style(
7827    severity: DiagnosticSeverity,
7828    valid: bool,
7829    theme: &theme::Editor,
7830) -> DiagnosticStyle {
7831    match (severity, valid) {
7832        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7833        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7834        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7835        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7836        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7837        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7838        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7839        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7840        _ => theme.invalid_hint_diagnostic.clone(),
7841    }
7842}
7843
7844pub fn combine_syntax_and_fuzzy_match_highlights(
7845    text: &str,
7846    default_style: HighlightStyle,
7847    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7848    match_indices: &[usize],
7849) -> Vec<(Range<usize>, HighlightStyle)> {
7850    let mut result = Vec::new();
7851    let mut match_indices = match_indices.iter().copied().peekable();
7852
7853    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7854    {
7855        syntax_highlight.weight = None;
7856
7857        // Add highlights for any fuzzy match characters before the next
7858        // syntax highlight range.
7859        while let Some(&match_index) = match_indices.peek() {
7860            if match_index >= range.start {
7861                break;
7862            }
7863            match_indices.next();
7864            let end_index = char_ix_after(match_index, text);
7865            let mut match_style = default_style;
7866            match_style.weight = Some(fonts::Weight::BOLD);
7867            result.push((match_index..end_index, match_style));
7868        }
7869
7870        if range.start == usize::MAX {
7871            break;
7872        }
7873
7874        // Add highlights for any fuzzy match characters within the
7875        // syntax highlight range.
7876        let mut offset = range.start;
7877        while let Some(&match_index) = match_indices.peek() {
7878            if match_index >= range.end {
7879                break;
7880            }
7881
7882            match_indices.next();
7883            if match_index > offset {
7884                result.push((offset..match_index, syntax_highlight));
7885            }
7886
7887            let mut end_index = char_ix_after(match_index, text);
7888            while let Some(&next_match_index) = match_indices.peek() {
7889                if next_match_index == end_index && next_match_index < range.end {
7890                    end_index = char_ix_after(next_match_index, text);
7891                    match_indices.next();
7892                } else {
7893                    break;
7894                }
7895            }
7896
7897            let mut match_style = syntax_highlight;
7898            match_style.weight = Some(fonts::Weight::BOLD);
7899            result.push((match_index..end_index, match_style));
7900            offset = end_index;
7901        }
7902
7903        if offset < range.end {
7904            result.push((offset..range.end, syntax_highlight));
7905        }
7906    }
7907
7908    fn char_ix_after(ix: usize, text: &str) -> usize {
7909        ix + text[ix..].chars().next().unwrap().len_utf8()
7910    }
7911
7912    result
7913}
7914
7915pub fn styled_runs_for_code_label<'a>(
7916    label: &'a CodeLabel,
7917    syntax_theme: &'a theme::SyntaxTheme,
7918) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7919    let fade_out = HighlightStyle {
7920        fade_out: Some(0.35),
7921        ..Default::default()
7922    };
7923
7924    let mut prev_end = label.filter_range.end;
7925    label
7926        .runs
7927        .iter()
7928        .enumerate()
7929        .flat_map(move |(ix, (range, highlight_id))| {
7930            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7931                style
7932            } else {
7933                return Default::default();
7934            };
7935            let mut muted_style = style;
7936            muted_style.highlight(fade_out);
7937
7938            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7939            if range.start >= label.filter_range.end {
7940                if range.start > prev_end {
7941                    runs.push((prev_end..range.start, fade_out));
7942                }
7943                runs.push((range.clone(), muted_style));
7944            } else if range.end <= label.filter_range.end {
7945                runs.push((range.clone(), style));
7946            } else {
7947                runs.push((range.start..label.filter_range.end, style));
7948                runs.push((label.filter_range.end..range.end, muted_style));
7949            }
7950            prev_end = cmp::max(prev_end, range.end);
7951
7952            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7953                runs.push((prev_end..label.text.len(), fade_out));
7954            }
7955
7956            runs
7957        })
7958}
7959
7960pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7961    let mut index = 0;
7962    let mut codepoints = text.char_indices().peekable();
7963
7964    std::iter::from_fn(move || {
7965        let start_index = index;
7966        while let Some((new_index, codepoint)) = codepoints.next() {
7967            index = new_index + codepoint.len_utf8();
7968            let current_upper = codepoint.is_uppercase();
7969            let next_upper = codepoints
7970                .peek()
7971                .map(|(_, c)| c.is_uppercase())
7972                .unwrap_or(false);
7973
7974            if !current_upper && next_upper {
7975                return Some(&text[start_index..index]);
7976            }
7977        }
7978
7979        index = text.len();
7980        if start_index < text.len() {
7981            return Some(&text[start_index..]);
7982        }
7983        None
7984    })
7985    .flat_map(|word| word.split_inclusive('_'))
7986}
7987
7988trait RangeToAnchorExt {
7989    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7990}
7991
7992impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7993    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7994        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7995    }
7996}