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