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::{
  35    Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles,
  36};
  37use futures::FutureExt;
  38use fuzzy::{StringMatch, StringMatchCandidate};
  39use gpui::{
  40    actions,
  41    color::Color,
  42    elements::*,
  43    executor,
  44    fonts::{self, HighlightStyle, TextStyle},
  45    geometry::vector::Vector2F,
  46    impl_actions,
  47    keymap_matcher::KeymapContext,
  48    platform::{CursorStyle, MouseButton},
  49    serde_json::{self, json},
  50    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  51    LayoutContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
  52    WindowContext,
  53};
  54use highlight_matching_bracket::refresh_matching_bracket_highlights;
  55use hover_popover::{hide_hover, HoverState};
  56pub use items::MAX_TAB_TITLE_LEN;
  57use itertools::Itertools;
  58pub use language::{char_kind, CharKind};
  59use language::{
  60    language_settings::{self, all_language_settings},
  61    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  62    Diagnostic, DiagnosticSeverity, File, IndentKind, IndentSize, Language, OffsetRangeExt,
  63    OffsetUtf16, Point, Selection, SelectionGoal, TransactionId,
  64};
  65use link_go_to_definition::{
  66    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  67};
  68pub use multi_buffer::{
  69    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  70    ToPoint,
  71};
  72use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  73use ordered_float::OrderedFloat;
  74use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  75use scroll::{
  76    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  77};
  78use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  79use serde::{Deserialize, Serialize};
  80use settings::SettingsStore;
  81use smallvec::SmallVec;
  82use snippet::Snippet;
  83use std::{
  84    any::TypeId,
  85    borrow::Cow,
  86    cmp::{self, Ordering, Reverse},
  87    mem,
  88    num::NonZeroU32,
  89    ops::{Deref, DerefMut, Range},
  90    path::Path,
  91    sync::Arc,
  92    time::{Duration, Instant},
  93};
  94pub use sum_tree::Bias;
  95use theme::{DiagnosticStyle, Theme, ThemeSettings};
  96use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  97use workspace::{ItemNavHistory, ViewId, Workspace};
  98
  99use crate::git::diff_hunk_to_display;
 100
 101const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 102const MAX_LINE_LEN: usize = 1024;
 103const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 104const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 105const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 106
 107pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 108
 109#[derive(Clone, Deserialize, PartialEq, Default)]
 110pub struct SelectNext {
 111    #[serde(default)]
 112    pub replace_newest: bool,
 113}
 114
 115#[derive(Clone, Deserialize, PartialEq)]
 116pub struct SelectToBeginningOfLine {
 117    #[serde(default)]
 118    stop_at_soft_wraps: bool,
 119}
 120
 121#[derive(Clone, Default, Deserialize, PartialEq)]
 122pub struct MovePageUp {
 123    #[serde(default)]
 124    center_cursor: bool,
 125}
 126
 127#[derive(Clone, Default, Deserialize, PartialEq)]
 128pub struct MovePageDown {
 129    #[serde(default)]
 130    center_cursor: bool,
 131}
 132
 133#[derive(Clone, Deserialize, PartialEq)]
 134pub struct SelectToEndOfLine {
 135    #[serde(default)]
 136    stop_at_soft_wraps: bool,
 137}
 138
 139#[derive(Clone, Deserialize, PartialEq)]
 140pub struct ToggleCodeActions {
 141    #[serde(default)]
 142    pub deployed_from_indicator: bool,
 143}
 144
 145#[derive(Clone, Default, Deserialize, PartialEq)]
 146pub struct ConfirmCompletion {
 147    #[serde(default)]
 148    pub item_ix: Option<usize>,
 149}
 150
 151#[derive(Clone, Default, Deserialize, PartialEq)]
 152pub struct ConfirmCodeAction {
 153    #[serde(default)]
 154    pub item_ix: Option<usize>,
 155}
 156
 157#[derive(Clone, Default, Deserialize, PartialEq)]
 158pub struct ToggleComments {
 159    #[serde(default)]
 160    pub advance_downwards: bool,
 161}
 162
 163#[derive(Clone, Default, Deserialize, PartialEq)]
 164pub struct FoldAt {
 165    pub buffer_row: u32,
 166}
 167
 168#[derive(Clone, Default, Deserialize, PartialEq)]
 169pub struct UnfoldAt {
 170    pub buffer_row: u32,
 171}
 172
 173#[derive(Clone, Default, Deserialize, PartialEq)]
 174pub struct GutterHover {
 175    pub hovered: bool,
 176}
 177
 178actions!(
 179    editor,
 180    [
 181        Cancel,
 182        Backspace,
 183        Delete,
 184        Newline,
 185        NewlineAbove,
 186        NewlineBelow,
 187        GoToDiagnostic,
 188        GoToPrevDiagnostic,
 189        GoToHunk,
 190        GoToPrevHunk,
 191        Indent,
 192        Outdent,
 193        DeleteLine,
 194        DeleteToPreviousWordStart,
 195        DeleteToPreviousSubwordStart,
 196        DeleteToNextWordEnd,
 197        DeleteToNextSubwordEnd,
 198        DeleteToBeginningOfLine,
 199        DeleteToEndOfLine,
 200        CutToEndOfLine,
 201        DuplicateLine,
 202        MoveLineUp,
 203        MoveLineDown,
 204        Transpose,
 205        Cut,
 206        Copy,
 207        Paste,
 208        Undo,
 209        Redo,
 210        MoveUp,
 211        PageUp,
 212        MoveDown,
 213        PageDown,
 214        MoveLeft,
 215        MoveRight,
 216        MoveToPreviousWordStart,
 217        MoveToPreviousSubwordStart,
 218        MoveToNextWordEnd,
 219        MoveToNextSubwordEnd,
 220        MoveToBeginningOfLine,
 221        MoveToEndOfLine,
 222        MoveToStartOfParagraph,
 223        MoveToEndOfParagraph,
 224        MoveToBeginning,
 225        MoveToEnd,
 226        SelectUp,
 227        SelectDown,
 228        SelectLeft,
 229        SelectRight,
 230        SelectToPreviousWordStart,
 231        SelectToPreviousSubwordStart,
 232        SelectToNextWordEnd,
 233        SelectToNextSubwordEnd,
 234        SelectToStartOfParagraph,
 235        SelectToEndOfParagraph,
 236        SelectToBeginning,
 237        SelectToEnd,
 238        SelectAll,
 239        SelectLine,
 240        SplitSelectionIntoLines,
 241        AddSelectionAbove,
 242        AddSelectionBelow,
 243        Tab,
 244        TabPrev,
 245        ShowCharacterPalette,
 246        SelectLargerSyntaxNode,
 247        SelectSmallerSyntaxNode,
 248        GoToDefinition,
 249        GoToTypeDefinition,
 250        MoveToEnclosingBracket,
 251        UndoSelection,
 252        RedoSelection,
 253        FindAllReferences,
 254        Rename,
 255        ConfirmRename,
 256        Fold,
 257        UnfoldLines,
 258        FoldSelectedRanges,
 259        ShowCompletions,
 260        OpenExcerpts,
 261        RestartLanguageServer,
 262        Hover,
 263        Format,
 264        ToggleSoftWrap,
 265        RevealInFinder,
 266        CopyPath,
 267        CopyRelativePath,
 268        CopyHighlightJson
 269    ]
 270);
 271
 272impl_actions!(
 273    editor,
 274    [
 275        SelectNext,
 276        SelectToBeginningOfLine,
 277        SelectToEndOfLine,
 278        ToggleCodeActions,
 279        MovePageUp,
 280        MovePageDown,
 281        ConfirmCompletion,
 282        ConfirmCodeAction,
 283        ToggleComments,
 284        FoldAt,
 285        UnfoldAt,
 286        GutterHover
 287    ]
 288);
 289
 290enum DocumentHighlightRead {}
 291enum DocumentHighlightWrite {}
 292enum InputComposition {}
 293
 294#[derive(Copy, Clone, PartialEq, Eq)]
 295pub enum Direction {
 296    Prev,
 297    Next,
 298}
 299
 300pub fn init_settings(cx: &mut AppContext) {
 301    settings::register::<EditorSettings>(cx);
 302}
 303
 304pub fn init(cx: &mut AppContext) {
 305    init_settings(cx);
 306    cx.add_action(Editor::new_file);
 307    cx.add_action(Editor::cancel);
 308    cx.add_action(Editor::newline);
 309    cx.add_action(Editor::newline_above);
 310    cx.add_action(Editor::newline_below);
 311    cx.add_action(Editor::backspace);
 312    cx.add_action(Editor::delete);
 313    cx.add_action(Editor::tab);
 314    cx.add_action(Editor::tab_prev);
 315    cx.add_action(Editor::indent);
 316    cx.add_action(Editor::outdent);
 317    cx.add_action(Editor::delete_line);
 318    cx.add_action(Editor::delete_to_previous_word_start);
 319    cx.add_action(Editor::delete_to_previous_subword_start);
 320    cx.add_action(Editor::delete_to_next_word_end);
 321    cx.add_action(Editor::delete_to_next_subword_end);
 322    cx.add_action(Editor::delete_to_beginning_of_line);
 323    cx.add_action(Editor::delete_to_end_of_line);
 324    cx.add_action(Editor::cut_to_end_of_line);
 325    cx.add_action(Editor::duplicate_line);
 326    cx.add_action(Editor::move_line_up);
 327    cx.add_action(Editor::move_line_down);
 328    cx.add_action(Editor::transpose);
 329    cx.add_action(Editor::cut);
 330    cx.add_action(Editor::copy);
 331    cx.add_action(Editor::paste);
 332    cx.add_action(Editor::undo);
 333    cx.add_action(Editor::redo);
 334    cx.add_action(Editor::move_up);
 335    cx.add_action(Editor::move_page_up);
 336    cx.add_action(Editor::move_down);
 337    cx.add_action(Editor::move_page_down);
 338    cx.add_action(Editor::next_screen);
 339    cx.add_action(Editor::move_left);
 340    cx.add_action(Editor::move_right);
 341    cx.add_action(Editor::move_to_previous_word_start);
 342    cx.add_action(Editor::move_to_previous_subword_start);
 343    cx.add_action(Editor::move_to_next_word_end);
 344    cx.add_action(Editor::move_to_next_subword_end);
 345    cx.add_action(Editor::move_to_beginning_of_line);
 346    cx.add_action(Editor::move_to_end_of_line);
 347    cx.add_action(Editor::move_to_start_of_paragraph);
 348    cx.add_action(Editor::move_to_end_of_paragraph);
 349    cx.add_action(Editor::move_to_beginning);
 350    cx.add_action(Editor::move_to_end);
 351    cx.add_action(Editor::select_up);
 352    cx.add_action(Editor::select_down);
 353    cx.add_action(Editor::select_left);
 354    cx.add_action(Editor::select_right);
 355    cx.add_action(Editor::select_to_previous_word_start);
 356    cx.add_action(Editor::select_to_previous_subword_start);
 357    cx.add_action(Editor::select_to_next_word_end);
 358    cx.add_action(Editor::select_to_next_subword_end);
 359    cx.add_action(Editor::select_to_beginning_of_line);
 360    cx.add_action(Editor::select_to_end_of_line);
 361    cx.add_action(Editor::select_to_start_of_paragraph);
 362    cx.add_action(Editor::select_to_end_of_paragraph);
 363    cx.add_action(Editor::select_to_beginning);
 364    cx.add_action(Editor::select_to_end);
 365    cx.add_action(Editor::select_all);
 366    cx.add_action(Editor::select_line);
 367    cx.add_action(Editor::split_selection_into_lines);
 368    cx.add_action(Editor::add_selection_above);
 369    cx.add_action(Editor::add_selection_below);
 370    cx.add_action(Editor::select_next);
 371    cx.add_action(Editor::toggle_comments);
 372    cx.add_action(Editor::select_larger_syntax_node);
 373    cx.add_action(Editor::select_smaller_syntax_node);
 374    cx.add_action(Editor::move_to_enclosing_bracket);
 375    cx.add_action(Editor::undo_selection);
 376    cx.add_action(Editor::redo_selection);
 377    cx.add_action(Editor::go_to_diagnostic);
 378    cx.add_action(Editor::go_to_prev_diagnostic);
 379    cx.add_action(Editor::go_to_hunk);
 380    cx.add_action(Editor::go_to_prev_hunk);
 381    cx.add_action(Editor::go_to_definition);
 382    cx.add_action(Editor::go_to_type_definition);
 383    cx.add_action(Editor::fold);
 384    cx.add_action(Editor::fold_at);
 385    cx.add_action(Editor::unfold_lines);
 386    cx.add_action(Editor::unfold_at);
 387    cx.add_action(Editor::gutter_hover);
 388    cx.add_action(Editor::fold_selected_ranges);
 389    cx.add_action(Editor::show_completions);
 390    cx.add_action(Editor::toggle_code_actions);
 391    cx.add_action(Editor::open_excerpts);
 392    cx.add_action(Editor::toggle_soft_wrap);
 393    cx.add_action(Editor::reveal_in_finder);
 394    cx.add_action(Editor::copy_path);
 395    cx.add_action(Editor::copy_relative_path);
 396    cx.add_action(Editor::copy_highlight_json);
 397    cx.add_async_action(Editor::format);
 398    cx.add_action(Editor::restart_language_server);
 399    cx.add_action(Editor::show_character_palette);
 400    cx.add_async_action(Editor::confirm_completion);
 401    cx.add_async_action(Editor::confirm_code_action);
 402    cx.add_async_action(Editor::rename);
 403    cx.add_async_action(Editor::confirm_rename);
 404    cx.add_async_action(Editor::find_all_references);
 405    cx.add_action(Editor::next_copilot_suggestion);
 406    cx.add_action(Editor::previous_copilot_suggestion);
 407    cx.add_action(Editor::copilot_suggest);
 408
 409    hover_popover::init(cx);
 410    scroll::actions::init(cx);
 411
 412    workspace::register_project_item::<Editor>(cx);
 413    workspace::register_followable_item::<Editor>(cx);
 414    workspace::register_deserializable_item::<Editor>(cx);
 415}
 416
 417trait InvalidationRegion {
 418    fn ranges(&self) -> &[Range<Anchor>];
 419}
 420
 421#[derive(Clone, Debug, PartialEq)]
 422pub enum SelectPhase {
 423    Begin {
 424        position: DisplayPoint,
 425        add: bool,
 426        click_count: usize,
 427    },
 428    BeginColumnar {
 429        position: DisplayPoint,
 430        goal_column: u32,
 431    },
 432    Extend {
 433        position: DisplayPoint,
 434        click_count: usize,
 435    },
 436    Update {
 437        position: DisplayPoint,
 438        goal_column: u32,
 439        scroll_position: Vector2F,
 440    },
 441    End,
 442}
 443
 444#[derive(Clone, Debug)]
 445pub enum SelectMode {
 446    Character,
 447    Word(Range<Anchor>),
 448    Line(Range<Anchor>),
 449    All,
 450}
 451
 452#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 453pub enum EditorMode {
 454    SingleLine,
 455    AutoHeight { max_lines: usize },
 456    Full,
 457}
 458
 459#[derive(Clone, Debug)]
 460pub enum SoftWrap {
 461    None,
 462    EditorWidth,
 463    Column(u32),
 464}
 465
 466#[derive(Clone)]
 467pub struct EditorStyle {
 468    pub text: TextStyle,
 469    pub placeholder_text: Option<TextStyle>,
 470    pub theme: theme::Editor,
 471    pub theme_id: usize,
 472}
 473
 474type CompletionId = usize;
 475
 476type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 477type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 478
 479pub struct Editor {
 480    handle: WeakViewHandle<Self>,
 481    buffer: ModelHandle<MultiBuffer>,
 482    display_map: ModelHandle<DisplayMap>,
 483    pub selections: SelectionsCollection,
 484    pub scroll_manager: ScrollManager,
 485    columnar_selection_tail: Option<Anchor>,
 486    add_selections_state: Option<AddSelectionsState>,
 487    select_next_state: Option<SelectNextState>,
 488    selection_history: SelectionHistory,
 489    autoclose_regions: Vec<AutocloseRegion>,
 490    snippet_stack: InvalidationStack<SnippetState>,
 491    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 492    ime_transaction: Option<TransactionId>,
 493    active_diagnostics: Option<ActiveDiagnosticGroup>,
 494    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 495    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 496    override_text_style: Option<Box<OverrideTextStyle>>,
 497    project: Option<ModelHandle<Project>>,
 498    focused: bool,
 499    blink_manager: ModelHandle<BlinkManager>,
 500    show_local_selections: bool,
 501    mode: EditorMode,
 502    show_gutter: bool,
 503    placeholder_text: Option<Arc<str>>,
 504    render_excerpt_header: Option<element::RenderExcerptHeader>,
 505    highlighted_rows: Option<Range<u32>>,
 506    #[allow(clippy::type_complexity)]
 507    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 508    nav_history: Option<ItemNavHistory>,
 509    context_menu: Option<ContextMenu>,
 510    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 511    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 512    next_completion_id: CompletionId,
 513    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 514    code_actions_task: Option<Task<()>>,
 515    document_highlights_task: Option<Task<()>>,
 516    pending_rename: Option<RenameState>,
 517    searchable: bool,
 518    cursor_shape: CursorShape,
 519    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 520    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 521    input_enabled: bool,
 522    read_only: bool,
 523    leader_replica_id: Option<u16>,
 524    remote_id: Option<ViewId>,
 525    hover_state: HoverState,
 526    gutter_hovered: bool,
 527    link_go_to_definition_state: LinkGoToDefinitionState,
 528    copilot_state: CopilotState,
 529    _subscriptions: Vec<Subscription>,
 530}
 531
 532pub struct EditorSnapshot {
 533    pub mode: EditorMode,
 534    pub show_gutter: bool,
 535    pub display_snapshot: DisplaySnapshot,
 536    pub placeholder_text: Option<Arc<str>>,
 537    is_focused: bool,
 538    scroll_anchor: ScrollAnchor,
 539    ongoing_scroll: OngoingScroll,
 540}
 541
 542#[derive(Clone, Debug)]
 543struct SelectionHistoryEntry {
 544    selections: Arc<[Selection<Anchor>]>,
 545    select_next_state: Option<SelectNextState>,
 546    add_selections_state: Option<AddSelectionsState>,
 547}
 548
 549enum SelectionHistoryMode {
 550    Normal,
 551    Undoing,
 552    Redoing,
 553}
 554
 555impl Default for SelectionHistoryMode {
 556    fn default() -> Self {
 557        Self::Normal
 558    }
 559}
 560
 561#[derive(Default)]
 562struct SelectionHistory {
 563    #[allow(clippy::type_complexity)]
 564    selections_by_transaction:
 565        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 566    mode: SelectionHistoryMode,
 567    undo_stack: VecDeque<SelectionHistoryEntry>,
 568    redo_stack: VecDeque<SelectionHistoryEntry>,
 569}
 570
 571impl SelectionHistory {
 572    fn insert_transaction(
 573        &mut self,
 574        transaction_id: TransactionId,
 575        selections: Arc<[Selection<Anchor>]>,
 576    ) {
 577        self.selections_by_transaction
 578            .insert(transaction_id, (selections, None));
 579    }
 580
 581    #[allow(clippy::type_complexity)]
 582    fn transaction(
 583        &self,
 584        transaction_id: TransactionId,
 585    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 586        self.selections_by_transaction.get(&transaction_id)
 587    }
 588
 589    #[allow(clippy::type_complexity)]
 590    fn transaction_mut(
 591        &mut self,
 592        transaction_id: TransactionId,
 593    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 594        self.selections_by_transaction.get_mut(&transaction_id)
 595    }
 596
 597    fn push(&mut self, entry: SelectionHistoryEntry) {
 598        if !entry.selections.is_empty() {
 599            match self.mode {
 600                SelectionHistoryMode::Normal => {
 601                    self.push_undo(entry);
 602                    self.redo_stack.clear();
 603                }
 604                SelectionHistoryMode::Undoing => self.push_redo(entry),
 605                SelectionHistoryMode::Redoing => self.push_undo(entry),
 606            }
 607        }
 608    }
 609
 610    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 611        if self
 612            .undo_stack
 613            .back()
 614            .map_or(true, |e| e.selections != entry.selections)
 615        {
 616            self.undo_stack.push_back(entry);
 617            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 618                self.undo_stack.pop_front();
 619            }
 620        }
 621    }
 622
 623    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 624        if self
 625            .redo_stack
 626            .back()
 627            .map_or(true, |e| e.selections != entry.selections)
 628        {
 629            self.redo_stack.push_back(entry);
 630            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 631                self.redo_stack.pop_front();
 632            }
 633        }
 634    }
 635}
 636
 637#[derive(Clone, Debug)]
 638struct AddSelectionsState {
 639    above: bool,
 640    stack: Vec<usize>,
 641}
 642
 643#[derive(Clone, Debug)]
 644struct SelectNextState {
 645    query: AhoCorasick,
 646    wordwise: bool,
 647    done: bool,
 648}
 649
 650#[derive(Debug)]
 651struct AutocloseRegion {
 652    selection_id: usize,
 653    range: Range<Anchor>,
 654    pair: BracketPair,
 655}
 656
 657#[derive(Debug)]
 658struct SnippetState {
 659    ranges: Vec<Vec<Range<Anchor>>>,
 660    active_index: usize,
 661}
 662
 663pub struct RenameState {
 664    pub range: Range<Anchor>,
 665    pub old_name: Arc<str>,
 666    pub editor: ViewHandle<Editor>,
 667    block_id: BlockId,
 668}
 669
 670struct InvalidationStack<T>(Vec<T>);
 671
 672enum ContextMenu {
 673    Completions(CompletionsMenu),
 674    CodeActions(CodeActionsMenu),
 675}
 676
 677impl ContextMenu {
 678    fn select_first(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 679        if self.visible() {
 680            match self {
 681                ContextMenu::Completions(menu) => menu.select_first(cx),
 682                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 683            }
 684            true
 685        } else {
 686            false
 687        }
 688    }
 689
 690    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 691        if self.visible() {
 692            match self {
 693                ContextMenu::Completions(menu) => menu.select_prev(cx),
 694                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 695            }
 696            true
 697        } else {
 698            false
 699        }
 700    }
 701
 702    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 703        if self.visible() {
 704            match self {
 705                ContextMenu::Completions(menu) => menu.select_next(cx),
 706                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 707            }
 708            true
 709        } else {
 710            false
 711        }
 712    }
 713
 714    fn select_last(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 715        if self.visible() {
 716            match self {
 717                ContextMenu::Completions(menu) => menu.select_last(cx),
 718                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 719            }
 720            true
 721        } else {
 722            false
 723        }
 724    }
 725
 726    fn visible(&self) -> bool {
 727        match self {
 728            ContextMenu::Completions(menu) => menu.visible(),
 729            ContextMenu::CodeActions(menu) => menu.visible(),
 730        }
 731    }
 732
 733    fn render(
 734        &self,
 735        cursor_position: DisplayPoint,
 736        style: EditorStyle,
 737        cx: &mut ViewContext<Editor>,
 738    ) -> (DisplayPoint, AnyElement<Editor>) {
 739        match self {
 740            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 741            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 742        }
 743    }
 744}
 745
 746struct CompletionsMenu {
 747    id: CompletionId,
 748    initial_position: Anchor,
 749    buffer: ModelHandle<Buffer>,
 750    completions: Arc<[Completion]>,
 751    match_candidates: Vec<StringMatchCandidate>,
 752    matches: Arc<[StringMatch]>,
 753    selected_item: usize,
 754    list: UniformListState,
 755}
 756
 757impl CompletionsMenu {
 758    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 759        self.selected_item = 0;
 760        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 761        cx.notify();
 762    }
 763
 764    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 765        if self.selected_item > 0 {
 766            self.selected_item -= 1;
 767            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 768        }
 769        cx.notify();
 770    }
 771
 772    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 773        if self.selected_item + 1 < self.matches.len() {
 774            self.selected_item += 1;
 775            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 776        }
 777        cx.notify();
 778    }
 779
 780    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 781        self.selected_item = self.matches.len() - 1;
 782        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 783        cx.notify();
 784    }
 785
 786    fn visible(&self) -> bool {
 787        !self.matches.is_empty()
 788    }
 789
 790    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
 791        enum CompletionTag {}
 792
 793        let completions = self.completions.clone();
 794        let matches = self.matches.clone();
 795        let selected_item = self.selected_item;
 796        let container_style = style.autocomplete.container;
 797        UniformList::new(
 798            self.list.clone(),
 799            matches.len(),
 800            cx,
 801            move |_, range, items, cx| {
 802                let start_ix = range.start;
 803                for (ix, mat) in matches[range].iter().enumerate() {
 804                    let completion = &completions[mat.candidate_id];
 805                    let item_ix = start_ix + ix;
 806                    items.push(
 807                        MouseEventHandler::<CompletionTag, _>::new(
 808                            mat.candidate_id,
 809                            cx,
 810                            |state, _| {
 811                                let item_style = if item_ix == selected_item {
 812                                    style.autocomplete.selected_item
 813                                } else if state.hovered() {
 814                                    style.autocomplete.hovered_item
 815                                } else {
 816                                    style.autocomplete.item
 817                                };
 818
 819                                Text::new(completion.label.text.clone(), style.text.clone())
 820                                    .with_soft_wrap(false)
 821                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 822                                        &completion.label.text,
 823                                        style.text.color.into(),
 824                                        styled_runs_for_code_label(
 825                                            &completion.label,
 826                                            &style.syntax,
 827                                        ),
 828                                        &mat.positions,
 829                                    ))
 830                                    .contained()
 831                                    .with_style(item_style)
 832                            },
 833                        )
 834                        .with_cursor_style(CursorStyle::PointingHand)
 835                        .on_down(MouseButton::Left, move |_, this, cx| {
 836                            this.confirm_completion(
 837                                &ConfirmCompletion {
 838                                    item_ix: Some(item_ix),
 839                                },
 840                                cx,
 841                            );
 842                        })
 843                        .into_any(),
 844                    );
 845                }
 846            },
 847        )
 848        .with_width_from_item(
 849            self.matches
 850                .iter()
 851                .enumerate()
 852                .max_by_key(|(_, mat)| {
 853                    self.completions[mat.candidate_id]
 854                        .label
 855                        .text
 856                        .chars()
 857                        .count()
 858                })
 859                .map(|(ix, _)| ix),
 860        )
 861        .contained()
 862        .with_style(container_style)
 863        .into_any()
 864    }
 865
 866    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 867        let mut matches = if let Some(query) = query {
 868            fuzzy::match_strings(
 869                &self.match_candidates,
 870                query,
 871                query.chars().any(|c| c.is_uppercase()),
 872                100,
 873                &Default::default(),
 874                executor,
 875            )
 876            .await
 877        } else {
 878            self.match_candidates
 879                .iter()
 880                .enumerate()
 881                .map(|(candidate_id, candidate)| StringMatch {
 882                    candidate_id,
 883                    score: Default::default(),
 884                    positions: Default::default(),
 885                    string: candidate.string.clone(),
 886                })
 887                .collect()
 888        };
 889
 890        //Remove all candidates where the query's start does not match the start of any word in the candidate
 891        if let Some(query) = query {
 892            if let Some(query_start) = query.chars().next() {
 893                matches.retain(|string_match| {
 894                    split_words(&string_match.string).any(|word| {
 895                        //Check that the first codepoint of the word as lowercase matches the first
 896                        //codepoint of the query as lowercase
 897                        word.chars()
 898                            .flat_map(|codepoint| codepoint.to_lowercase())
 899                            .zip(query_start.to_lowercase())
 900                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 901                    })
 902                });
 903            }
 904        }
 905
 906        matches.sort_unstable_by_key(|mat| {
 907            let completion = &self.completions[mat.candidate_id];
 908            (
 909                completion.lsp_completion.sort_text.as_ref(),
 910                Reverse(OrderedFloat(mat.score)),
 911                completion.sort_key(),
 912            )
 913        });
 914
 915        for mat in &mut matches {
 916            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 917            for position in &mut mat.positions {
 918                *position += filter_start;
 919            }
 920        }
 921
 922        self.matches = matches.into();
 923    }
 924}
 925
 926#[derive(Clone)]
 927struct CodeActionsMenu {
 928    actions: Arc<[CodeAction]>,
 929    buffer: ModelHandle<Buffer>,
 930    selected_item: usize,
 931    list: UniformListState,
 932    deployed_from_indicator: bool,
 933}
 934
 935impl CodeActionsMenu {
 936    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 937        self.selected_item = 0;
 938        cx.notify()
 939    }
 940
 941    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 942        if self.selected_item > 0 {
 943            self.selected_item -= 1;
 944            cx.notify()
 945        }
 946    }
 947
 948    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 949        if self.selected_item + 1 < self.actions.len() {
 950            self.selected_item += 1;
 951            cx.notify()
 952        }
 953    }
 954
 955    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 956        self.selected_item = self.actions.len() - 1;
 957        cx.notify()
 958    }
 959
 960    fn visible(&self) -> bool {
 961        !self.actions.is_empty()
 962    }
 963
 964    fn render(
 965        &self,
 966        mut cursor_position: DisplayPoint,
 967        style: EditorStyle,
 968        cx: &mut ViewContext<Editor>,
 969    ) -> (DisplayPoint, AnyElement<Editor>) {
 970        enum ActionTag {}
 971
 972        let container_style = style.autocomplete.container;
 973        let actions = self.actions.clone();
 974        let selected_item = self.selected_item;
 975        let element = UniformList::new(
 976            self.list.clone(),
 977            actions.len(),
 978            cx,
 979            move |_, range, items, cx| {
 980                let start_ix = range.start;
 981                for (ix, action) in actions[range].iter().enumerate() {
 982                    let item_ix = start_ix + ix;
 983                    items.push(
 984                        MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| {
 985                            let item_style = if item_ix == selected_item {
 986                                style.autocomplete.selected_item
 987                            } else if state.hovered() {
 988                                style.autocomplete.hovered_item
 989                            } else {
 990                                style.autocomplete.item
 991                            };
 992
 993                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 994                                .with_soft_wrap(false)
 995                                .contained()
 996                                .with_style(item_style)
 997                        })
 998                        .with_cursor_style(CursorStyle::PointingHand)
 999                        .on_down(MouseButton::Left, move |_, this, cx| {
1000                            let workspace = this
1001                                .workspace
1002                                .as_ref()
1003                                .and_then(|(workspace, _)| workspace.upgrade(cx));
1004                            cx.window_context().defer(move |cx| {
1005                                if let Some(workspace) = workspace {
1006                                    workspace.update(cx, |workspace, cx| {
1007                                        if let Some(task) = Editor::confirm_code_action(
1008                                            workspace,
1009                                            &Default::default(),
1010                                            cx,
1011                                        ) {
1012                                            task.detach_and_log_err(cx);
1013                                        }
1014                                    });
1015                                }
1016                            });
1017                        })
1018                        .into_any(),
1019                    );
1020                }
1021            },
1022        )
1023        .with_width_from_item(
1024            self.actions
1025                .iter()
1026                .enumerate()
1027                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1028                .map(|(ix, _)| ix),
1029        )
1030        .contained()
1031        .with_style(container_style)
1032        .into_any();
1033
1034        if self.deployed_from_indicator {
1035            *cursor_position.column_mut() = 0;
1036        }
1037
1038        (cursor_position, element)
1039    }
1040}
1041
1042pub struct CopilotState {
1043    excerpt_id: Option<ExcerptId>,
1044    pending_refresh: Task<Option<()>>,
1045    pending_cycling_refresh: Task<Option<()>>,
1046    cycled: bool,
1047    completions: Vec<copilot::Completion>,
1048    active_completion_index: usize,
1049}
1050
1051impl Default for CopilotState {
1052    fn default() -> Self {
1053        Self {
1054            excerpt_id: None,
1055            pending_cycling_refresh: Task::ready(Some(())),
1056            pending_refresh: Task::ready(Some(())),
1057            completions: Default::default(),
1058            active_completion_index: 0,
1059            cycled: false,
1060        }
1061    }
1062}
1063
1064impl CopilotState {
1065    fn active_completion(&self) -> Option<&copilot::Completion> {
1066        self.completions.get(self.active_completion_index)
1067    }
1068
1069    fn text_for_active_completion(
1070        &self,
1071        cursor: Anchor,
1072        buffer: &MultiBufferSnapshot,
1073    ) -> Option<&str> {
1074        use language::ToOffset as _;
1075
1076        let completion = self.active_completion()?;
1077        let excerpt_id = self.excerpt_id?;
1078        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1079        if excerpt_id != cursor.excerpt_id
1080            || !completion.range.start.is_valid(completion_buffer)
1081            || !completion.range.end.is_valid(completion_buffer)
1082        {
1083            return None;
1084        }
1085
1086        let mut completion_range = completion.range.to_offset(&completion_buffer);
1087        let prefix_len = Self::common_prefix(
1088            completion_buffer.chars_for_range(completion_range.clone()),
1089            completion.text.chars(),
1090        );
1091        completion_range.start += prefix_len;
1092        let suffix_len = Self::common_prefix(
1093            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1094            completion.text[prefix_len..].chars().rev(),
1095        );
1096        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1097
1098        if completion_range.is_empty()
1099            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1100        {
1101            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1102        } else {
1103            None
1104        }
1105    }
1106
1107    fn cycle_completions(&mut self, direction: Direction) {
1108        match direction {
1109            Direction::Prev => {
1110                self.active_completion_index = if self.active_completion_index == 0 {
1111                    self.completions.len().saturating_sub(1)
1112                } else {
1113                    self.active_completion_index - 1
1114                };
1115            }
1116            Direction::Next => {
1117                if self.completions.len() == 0 {
1118                    self.active_completion_index = 0
1119                } else {
1120                    self.active_completion_index =
1121                        (self.active_completion_index + 1) % self.completions.len();
1122                }
1123            }
1124        }
1125    }
1126
1127    fn push_completion(&mut self, new_completion: copilot::Completion) {
1128        for completion in &self.completions {
1129            if completion.text == new_completion.text && completion.range == new_completion.range {
1130                return;
1131            }
1132        }
1133        self.completions.push(new_completion);
1134    }
1135
1136    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1137        a.zip(b)
1138            .take_while(|(a, b)| a == b)
1139            .map(|(a, _)| a.len_utf8())
1140            .sum()
1141    }
1142}
1143
1144#[derive(Debug)]
1145struct ActiveDiagnosticGroup {
1146    primary_range: Range<Anchor>,
1147    primary_message: String,
1148    blocks: HashMap<BlockId, Diagnostic>,
1149    is_valid: bool,
1150}
1151
1152#[derive(Serialize, Deserialize)]
1153pub struct ClipboardSelection {
1154    pub len: usize,
1155    pub is_entire_line: bool,
1156    pub first_line_indent: u32,
1157}
1158
1159#[derive(Debug)]
1160pub struct NavigationData {
1161    cursor_anchor: Anchor,
1162    cursor_position: Point,
1163    scroll_anchor: ScrollAnchor,
1164    scroll_top_row: u32,
1165}
1166
1167pub struct EditorCreated(pub ViewHandle<Editor>);
1168
1169enum GotoDefinitionKind {
1170    Symbol,
1171    Type,
1172}
1173
1174impl Editor {
1175    pub fn single_line(
1176        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1177        cx: &mut ViewContext<Self>,
1178    ) -> Self {
1179        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1180        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1181        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1182    }
1183
1184    pub fn multi_line(
1185        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1186        cx: &mut ViewContext<Self>,
1187    ) -> Self {
1188        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1189        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1190        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1191    }
1192
1193    pub fn auto_height(
1194        max_lines: usize,
1195        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1196        cx: &mut ViewContext<Self>,
1197    ) -> Self {
1198        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1199        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1200        Self::new(
1201            EditorMode::AutoHeight { max_lines },
1202            buffer,
1203            None,
1204            field_editor_style,
1205            cx,
1206        )
1207    }
1208
1209    pub fn for_buffer(
1210        buffer: ModelHandle<Buffer>,
1211        project: Option<ModelHandle<Project>>,
1212        cx: &mut ViewContext<Self>,
1213    ) -> Self {
1214        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1215        Self::new(EditorMode::Full, buffer, project, None, cx)
1216    }
1217
1218    pub fn for_multibuffer(
1219        buffer: ModelHandle<MultiBuffer>,
1220        project: Option<ModelHandle<Project>>,
1221        cx: &mut ViewContext<Self>,
1222    ) -> Self {
1223        Self::new(EditorMode::Full, buffer, project, None, cx)
1224    }
1225
1226    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1227        let mut clone = Self::new(
1228            self.mode,
1229            self.buffer.clone(),
1230            self.project.clone(),
1231            self.get_field_editor_theme.clone(),
1232            cx,
1233        );
1234        self.display_map.update(cx, |display_map, cx| {
1235            let snapshot = display_map.snapshot(cx);
1236            clone.display_map.update(cx, |display_map, cx| {
1237                display_map.set_state(&snapshot, cx);
1238            });
1239        });
1240        clone.selections.clone_state(&self.selections);
1241        clone.scroll_manager.clone_state(&self.scroll_manager);
1242        clone.searchable = self.searchable;
1243        clone
1244    }
1245
1246    fn new(
1247        mode: EditorMode,
1248        buffer: ModelHandle<MultiBuffer>,
1249        project: Option<ModelHandle<Project>>,
1250        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1251        cx: &mut ViewContext<Self>,
1252    ) -> Self {
1253        let editor_view_id = cx.view_id();
1254        let display_map = cx.add_model(|cx| {
1255            let settings = settings::get::<ThemeSettings>(cx);
1256            let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
1257            DisplayMap::new(
1258                buffer.clone(),
1259                style.text.font_id,
1260                style.text.font_size,
1261                None,
1262                2,
1263                1,
1264                cx,
1265            )
1266        });
1267
1268        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1269
1270        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1271
1272        let soft_wrap_mode_override =
1273            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1274
1275        let mut project_subscription = None;
1276        if mode == EditorMode::Full && buffer.read(cx).is_singleton() {
1277            if let Some(project) = project.as_ref() {
1278                project_subscription = Some(cx.observe(project, |_, _, cx| {
1279                    cx.emit(Event::TitleChanged);
1280                }))
1281            }
1282        }
1283
1284        let mut this = Self {
1285            handle: cx.weak_handle(),
1286            buffer: buffer.clone(),
1287            display_map: display_map.clone(),
1288            selections,
1289            scroll_manager: ScrollManager::new(),
1290            columnar_selection_tail: None,
1291            add_selections_state: None,
1292            select_next_state: None,
1293            selection_history: Default::default(),
1294            autoclose_regions: Default::default(),
1295            snippet_stack: Default::default(),
1296            select_larger_syntax_node_stack: Vec::new(),
1297            ime_transaction: Default::default(),
1298            active_diagnostics: None,
1299            soft_wrap_mode_override,
1300            get_field_editor_theme,
1301            project,
1302            focused: false,
1303            blink_manager: blink_manager.clone(),
1304            show_local_selections: true,
1305            mode,
1306            show_gutter: mode == EditorMode::Full,
1307            placeholder_text: None,
1308            render_excerpt_header: None,
1309            highlighted_rows: None,
1310            background_highlights: Default::default(),
1311            nav_history: None,
1312            context_menu: None,
1313            mouse_context_menu: cx
1314                .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
1315            completion_tasks: Default::default(),
1316            next_completion_id: 0,
1317            available_code_actions: Default::default(),
1318            code_actions_task: Default::default(),
1319            document_highlights_task: Default::default(),
1320            pending_rename: Default::default(),
1321            searchable: true,
1322            override_text_style: None,
1323            cursor_shape: Default::default(),
1324            workspace: None,
1325            keymap_context_layers: Default::default(),
1326            input_enabled: true,
1327            read_only: false,
1328            leader_replica_id: None,
1329            remote_id: None,
1330            hover_state: Default::default(),
1331            link_go_to_definition_state: Default::default(),
1332            copilot_state: Default::default(),
1333            gutter_hovered: false,
1334            _subscriptions: vec![
1335                cx.observe(&buffer, Self::on_buffer_changed),
1336                cx.subscribe(&buffer, Self::on_buffer_event),
1337                cx.observe(&display_map, Self::on_display_map_changed),
1338                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1339                cx.observe_global::<SettingsStore, _>(Self::settings_changed),
1340            ],
1341        };
1342
1343        if let Some(project_subscription) = project_subscription {
1344            this._subscriptions.push(project_subscription);
1345        }
1346
1347        this.end_selection(cx);
1348        this.scroll_manager.show_scrollbar(cx);
1349
1350        let editor_created_event = EditorCreated(cx.handle());
1351        cx.emit_global(editor_created_event);
1352
1353        if mode == EditorMode::Full {
1354            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1355            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1356        }
1357
1358        this.report_editor_event("open", None, cx);
1359        this
1360    }
1361
1362    pub fn new_file(
1363        workspace: &mut Workspace,
1364        _: &workspace::NewFile,
1365        cx: &mut ViewContext<Workspace>,
1366    ) {
1367        let project = workspace.project().clone();
1368        if project.read(cx).is_remote() {
1369            cx.propagate_action();
1370        } else if let Some(buffer) = project
1371            .update(cx, |project, cx| project.create_buffer("", None, cx))
1372            .log_err()
1373        {
1374            workspace.add_item(
1375                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1376                cx,
1377            );
1378        }
1379    }
1380
1381    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1382        self.buffer.read(cx).replica_id()
1383    }
1384
1385    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1386        self.leader_replica_id
1387    }
1388
1389    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1390        &self.buffer
1391    }
1392
1393    fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
1394        self.workspace.as_ref()?.0.upgrade(cx)
1395    }
1396
1397    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1398        self.buffer().read(cx).title(cx)
1399    }
1400
1401    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1402        EditorSnapshot {
1403            mode: self.mode,
1404            show_gutter: self.show_gutter,
1405            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1406            scroll_anchor: self.scroll_manager.anchor(),
1407            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1408            placeholder_text: self.placeholder_text.clone(),
1409            is_focused: self
1410                .handle
1411                .upgrade(cx)
1412                .map_or(false, |handle| handle.is_focused(cx)),
1413        }
1414    }
1415
1416    pub fn language_at<'a, T: ToOffset>(
1417        &self,
1418        point: T,
1419        cx: &'a AppContext,
1420    ) -> Option<Arc<Language>> {
1421        self.buffer.read(cx).language_at(point, cx)
1422    }
1423
1424    pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
1425        self.buffer.read(cx).read(cx).file_at(point).cloned()
1426    }
1427
1428    pub fn active_excerpt(
1429        &self,
1430        cx: &AppContext,
1431    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1432        self.buffer
1433            .read(cx)
1434            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1435    }
1436
1437    fn style(&self, cx: &AppContext) -> EditorStyle {
1438        build_style(
1439            settings::get::<ThemeSettings>(cx),
1440            self.get_field_editor_theme.as_deref(),
1441            self.override_text_style.as_deref(),
1442            cx,
1443        )
1444    }
1445
1446    pub fn mode(&self) -> EditorMode {
1447        self.mode
1448    }
1449
1450    pub fn set_placeholder_text(
1451        &mut self,
1452        placeholder_text: impl Into<Arc<str>>,
1453        cx: &mut ViewContext<Self>,
1454    ) {
1455        self.placeholder_text = Some(placeholder_text.into());
1456        cx.notify();
1457    }
1458
1459    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1460        self.cursor_shape = cursor_shape;
1461        cx.notify();
1462    }
1463
1464    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1465        if self.display_map.read(cx).clip_at_line_ends != clip {
1466            self.display_map
1467                .update(cx, |map, _| map.clip_at_line_ends = clip);
1468        }
1469    }
1470
1471    pub fn set_keymap_context_layer<Tag: 'static>(
1472        &mut self,
1473        context: KeymapContext,
1474        cx: &mut ViewContext<Self>,
1475    ) {
1476        self.keymap_context_layers
1477            .insert(TypeId::of::<Tag>(), context);
1478        cx.notify();
1479    }
1480
1481    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1482        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1483        cx.notify();
1484    }
1485
1486    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1487        self.input_enabled = input_enabled;
1488    }
1489
1490    pub fn set_read_only(&mut self, read_only: bool) {
1491        self.read_only = read_only;
1492    }
1493
1494    fn selections_did_change(
1495        &mut self,
1496        local: bool,
1497        old_cursor_position: &Anchor,
1498        cx: &mut ViewContext<Self>,
1499    ) {
1500        if self.focused && self.leader_replica_id.is_none() {
1501            self.buffer.update(cx, |buffer, cx| {
1502                buffer.set_active_selections(
1503                    &self.selections.disjoint_anchors(),
1504                    self.selections.line_mode,
1505                    self.cursor_shape,
1506                    cx,
1507                )
1508            });
1509        }
1510
1511        let display_map = self
1512            .display_map
1513            .update(cx, |display_map, cx| display_map.snapshot(cx));
1514        let buffer = &display_map.buffer_snapshot;
1515        self.add_selections_state = None;
1516        self.select_next_state = None;
1517        self.select_larger_syntax_node_stack.clear();
1518        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1519        self.snippet_stack
1520            .invalidate(&self.selections.disjoint_anchors(), buffer);
1521        self.take_rename(false, cx);
1522
1523        let new_cursor_position = self.selections.newest_anchor().head();
1524
1525        self.push_to_nav_history(
1526            old_cursor_position.clone(),
1527            Some(new_cursor_position.to_point(buffer)),
1528            cx,
1529        );
1530
1531        if local {
1532            let new_cursor_position = self.selections.newest_anchor().head();
1533            let completion_menu = match self.context_menu.as_mut() {
1534                Some(ContextMenu::Completions(menu)) => Some(menu),
1535                _ => {
1536                    self.context_menu.take();
1537                    None
1538                }
1539            };
1540
1541            if let Some(completion_menu) = completion_menu {
1542                let cursor_position = new_cursor_position.to_offset(buffer);
1543                let (word_range, kind) =
1544                    buffer.surrounding_word(completion_menu.initial_position.clone());
1545                if kind == Some(CharKind::Word)
1546                    && word_range.to_inclusive().contains(&cursor_position)
1547                {
1548                    let query = Self::completion_query(buffer, cursor_position);
1549                    cx.background()
1550                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1551                    self.show_completions(&ShowCompletions, cx);
1552                } else {
1553                    self.hide_context_menu(cx);
1554                }
1555            }
1556
1557            hide_hover(self, cx);
1558
1559            if old_cursor_position.to_display_point(&display_map).row()
1560                != new_cursor_position.to_display_point(&display_map).row()
1561            {
1562                self.available_code_actions.take();
1563            }
1564            self.refresh_code_actions(cx);
1565            self.refresh_document_highlights(cx);
1566            refresh_matching_bracket_highlights(self, cx);
1567            self.discard_copilot_suggestion(cx);
1568        }
1569
1570        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1571        cx.emit(Event::SelectionsChanged { local });
1572        cx.notify();
1573    }
1574
1575    pub fn change_selections<R>(
1576        &mut self,
1577        autoscroll: Option<Autoscroll>,
1578        cx: &mut ViewContext<Self>,
1579        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1580    ) -> R {
1581        let old_cursor_position = self.selections.newest_anchor().head();
1582        self.push_to_selection_history();
1583
1584        let (changed, result) = self.selections.change_with(cx, change);
1585
1586        if changed {
1587            if let Some(autoscroll) = autoscroll {
1588                self.request_autoscroll(autoscroll, cx);
1589            }
1590            self.selections_did_change(true, &old_cursor_position, cx);
1591        }
1592
1593        result
1594    }
1595
1596    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1597    where
1598        I: IntoIterator<Item = (Range<S>, T)>,
1599        S: ToOffset,
1600        T: Into<Arc<str>>,
1601    {
1602        if self.read_only {
1603            return;
1604        }
1605
1606        self.buffer
1607            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1608    }
1609
1610    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1611    where
1612        I: IntoIterator<Item = (Range<S>, T)>,
1613        S: ToOffset,
1614        T: Into<Arc<str>>,
1615    {
1616        if self.read_only {
1617            return;
1618        }
1619
1620        self.buffer.update(cx, |buffer, cx| {
1621            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
1622        });
1623    }
1624
1625    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
1626        self.hide_context_menu(cx);
1627
1628        match phase {
1629            SelectPhase::Begin {
1630                position,
1631                add,
1632                click_count,
1633            } => self.begin_selection(position, add, click_count, cx),
1634            SelectPhase::BeginColumnar {
1635                position,
1636                goal_column,
1637            } => self.begin_columnar_selection(position, goal_column, cx),
1638            SelectPhase::Extend {
1639                position,
1640                click_count,
1641            } => self.extend_selection(position, click_count, cx),
1642            SelectPhase::Update {
1643                position,
1644                goal_column,
1645                scroll_position,
1646            } => self.update_selection(position, goal_column, scroll_position, cx),
1647            SelectPhase::End => self.end_selection(cx),
1648        }
1649    }
1650
1651    fn extend_selection(
1652        &mut self,
1653        position: DisplayPoint,
1654        click_count: usize,
1655        cx: &mut ViewContext<Self>,
1656    ) {
1657        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1658        let tail = self.selections.newest::<usize>(cx).tail();
1659        self.begin_selection(position, false, click_count, cx);
1660
1661        let position = position.to_offset(&display_map, Bias::Left);
1662        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1663
1664        let mut pending_selection = self
1665            .selections
1666            .pending_anchor()
1667            .expect("extend_selection not called with pending selection");
1668        if position >= tail {
1669            pending_selection.start = tail_anchor;
1670        } else {
1671            pending_selection.end = tail_anchor;
1672            pending_selection.reversed = true;
1673        }
1674
1675        let mut pending_mode = self.selections.pending_mode().unwrap();
1676        match &mut pending_mode {
1677            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1678            _ => {}
1679        }
1680
1681        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1682            s.set_pending(pending_selection, pending_mode)
1683        });
1684    }
1685
1686    fn begin_selection(
1687        &mut self,
1688        position: DisplayPoint,
1689        add: bool,
1690        click_count: usize,
1691        cx: &mut ViewContext<Self>,
1692    ) {
1693        if !self.focused {
1694            cx.focus_self();
1695        }
1696
1697        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1698        let buffer = &display_map.buffer_snapshot;
1699        let newest_selection = self.selections.newest_anchor().clone();
1700        let position = display_map.clip_point(position, Bias::Left);
1701
1702        let start;
1703        let end;
1704        let mode;
1705        let auto_scroll;
1706        match click_count {
1707            1 => {
1708                start = buffer.anchor_before(position.to_point(&display_map));
1709                end = start.clone();
1710                mode = SelectMode::Character;
1711                auto_scroll = true;
1712            }
1713            2 => {
1714                let range = movement::surrounding_word(&display_map, position);
1715                start = buffer.anchor_before(range.start.to_point(&display_map));
1716                end = buffer.anchor_before(range.end.to_point(&display_map));
1717                mode = SelectMode::Word(start.clone()..end.clone());
1718                auto_scroll = true;
1719            }
1720            3 => {
1721                let position = display_map
1722                    .clip_point(position, Bias::Left)
1723                    .to_point(&display_map);
1724                let line_start = display_map.prev_line_boundary(position).0;
1725                let next_line_start = buffer.clip_point(
1726                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1727                    Bias::Left,
1728                );
1729                start = buffer.anchor_before(line_start);
1730                end = buffer.anchor_before(next_line_start);
1731                mode = SelectMode::Line(start.clone()..end.clone());
1732                auto_scroll = true;
1733            }
1734            _ => {
1735                start = buffer.anchor_before(0);
1736                end = buffer.anchor_before(buffer.len());
1737                mode = SelectMode::All;
1738                auto_scroll = false;
1739            }
1740        }
1741
1742        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
1743            if !add {
1744                s.clear_disjoint();
1745            } else if click_count > 1 {
1746                s.delete(newest_selection.id)
1747            }
1748
1749            s.set_pending_anchor_range(start..end, mode);
1750        });
1751    }
1752
1753    fn begin_columnar_selection(
1754        &mut self,
1755        position: DisplayPoint,
1756        goal_column: u32,
1757        cx: &mut ViewContext<Self>,
1758    ) {
1759        if !self.focused {
1760            cx.focus_self();
1761        }
1762
1763        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1764        let tail = self.selections.newest::<Point>(cx).tail();
1765        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1766
1767        self.select_columns(
1768            tail.to_display_point(&display_map),
1769            position,
1770            goal_column,
1771            &display_map,
1772            cx,
1773        );
1774    }
1775
1776    fn update_selection(
1777        &mut self,
1778        position: DisplayPoint,
1779        goal_column: u32,
1780        scroll_position: Vector2F,
1781        cx: &mut ViewContext<Self>,
1782    ) {
1783        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1784
1785        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1786            let tail = tail.to_display_point(&display_map);
1787            self.select_columns(tail, position, goal_column, &display_map, cx);
1788        } else if let Some(mut pending) = self.selections.pending_anchor() {
1789            let buffer = self.buffer.read(cx).snapshot(cx);
1790            let head;
1791            let tail;
1792            let mode = self.selections.pending_mode().unwrap();
1793            match &mode {
1794                SelectMode::Character => {
1795                    head = position.to_point(&display_map);
1796                    tail = pending.tail().to_point(&buffer);
1797                }
1798                SelectMode::Word(original_range) => {
1799                    let original_display_range = original_range.start.to_display_point(&display_map)
1800                        ..original_range.end.to_display_point(&display_map);
1801                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1802                        ..original_display_range.end.to_point(&display_map);
1803                    if movement::is_inside_word(&display_map, position)
1804                        || original_display_range.contains(&position)
1805                    {
1806                        let word_range = movement::surrounding_word(&display_map, position);
1807                        if word_range.start < original_display_range.start {
1808                            head = word_range.start.to_point(&display_map);
1809                        } else {
1810                            head = word_range.end.to_point(&display_map);
1811                        }
1812                    } else {
1813                        head = position.to_point(&display_map);
1814                    }
1815
1816                    if head <= original_buffer_range.start {
1817                        tail = original_buffer_range.end;
1818                    } else {
1819                        tail = original_buffer_range.start;
1820                    }
1821                }
1822                SelectMode::Line(original_range) => {
1823                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1824
1825                    let position = display_map
1826                        .clip_point(position, Bias::Left)
1827                        .to_point(&display_map);
1828                    let line_start = display_map.prev_line_boundary(position).0;
1829                    let next_line_start = buffer.clip_point(
1830                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1831                        Bias::Left,
1832                    );
1833
1834                    if line_start < original_range.start {
1835                        head = line_start
1836                    } else {
1837                        head = next_line_start
1838                    }
1839
1840                    if head <= original_range.start {
1841                        tail = original_range.end;
1842                    } else {
1843                        tail = original_range.start;
1844                    }
1845                }
1846                SelectMode::All => {
1847                    return;
1848                }
1849            };
1850
1851            if head < tail {
1852                pending.start = buffer.anchor_before(head);
1853                pending.end = buffer.anchor_before(tail);
1854                pending.reversed = true;
1855            } else {
1856                pending.start = buffer.anchor_before(tail);
1857                pending.end = buffer.anchor_before(head);
1858                pending.reversed = false;
1859            }
1860
1861            self.change_selections(None, cx, |s| {
1862                s.set_pending(pending, mode);
1863            });
1864        } else {
1865            log::error!("update_selection dispatched with no pending selection");
1866            return;
1867        }
1868
1869        self.set_scroll_position(scroll_position, cx);
1870        cx.notify();
1871    }
1872
1873    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1874        self.columnar_selection_tail.take();
1875        if self.selections.pending_anchor().is_some() {
1876            let selections = self.selections.all::<usize>(cx);
1877            self.change_selections(None, cx, |s| {
1878                s.select(selections);
1879                s.clear_pending();
1880            });
1881        }
1882    }
1883
1884    fn select_columns(
1885        &mut self,
1886        tail: DisplayPoint,
1887        head: DisplayPoint,
1888        goal_column: u32,
1889        display_map: &DisplaySnapshot,
1890        cx: &mut ViewContext<Self>,
1891    ) {
1892        let start_row = cmp::min(tail.row(), head.row());
1893        let end_row = cmp::max(tail.row(), head.row());
1894        let start_column = cmp::min(tail.column(), goal_column);
1895        let end_column = cmp::max(tail.column(), goal_column);
1896        let reversed = start_column < tail.column();
1897
1898        let selection_ranges = (start_row..=end_row)
1899            .filter_map(|row| {
1900                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1901                    let start = display_map
1902                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1903                        .to_point(display_map);
1904                    let end = display_map
1905                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1906                        .to_point(display_map);
1907                    if reversed {
1908                        Some(end..start)
1909                    } else {
1910                        Some(start..end)
1911                    }
1912                } else {
1913                    None
1914                }
1915            })
1916            .collect::<Vec<_>>();
1917
1918        self.change_selections(None, cx, |s| {
1919            s.select_ranges(selection_ranges);
1920        });
1921        cx.notify();
1922    }
1923
1924    pub fn has_pending_nonempty_selection(&self) -> bool {
1925        let pending_nonempty_selection = match self.selections.pending_anchor() {
1926            Some(Selection { start, end, .. }) => start != end,
1927            None => false,
1928        };
1929        pending_nonempty_selection || self.columnar_selection_tail.is_some()
1930    }
1931
1932    pub fn has_pending_selection(&self) -> bool {
1933        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1934    }
1935
1936    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1937        if self.take_rename(false, cx).is_some() {
1938            return;
1939        }
1940
1941        if hide_hover(self, cx) {
1942            return;
1943        }
1944
1945        if self.hide_context_menu(cx).is_some() {
1946            return;
1947        }
1948
1949        if self.discard_copilot_suggestion(cx) {
1950            return;
1951        }
1952
1953        if self.snippet_stack.pop().is_some() {
1954            return;
1955        }
1956
1957        if self.mode == EditorMode::Full {
1958            if self.active_diagnostics.is_some() {
1959                self.dismiss_diagnostics(cx);
1960                return;
1961            }
1962
1963            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
1964                return;
1965            }
1966        }
1967
1968        cx.propagate_action();
1969    }
1970
1971    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1972        let text: Arc<str> = text.into();
1973
1974        if self.read_only {
1975            return;
1976        }
1977        if !self.input_enabled {
1978            cx.emit(Event::InputIgnored { text });
1979            return;
1980        }
1981
1982        let selections = self.selections.all_adjusted(cx);
1983        let mut edits = Vec::new();
1984        let mut new_selections = Vec::with_capacity(selections.len());
1985        let mut new_autoclose_regions = Vec::new();
1986        let snapshot = self.buffer.read(cx).read(cx);
1987
1988        for (selection, autoclose_region) in
1989            self.selections_with_autoclose_regions(selections, &snapshot)
1990        {
1991            if let Some(language) = snapshot.language_scope_at(selection.head()) {
1992                // Determine if the inserted text matches the opening or closing
1993                // bracket of any of this language's bracket pairs.
1994                let mut bracket_pair = None;
1995                let mut is_bracket_pair_start = false;
1996                for (pair, enabled) in language.brackets() {
1997                    if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
1998                        bracket_pair = Some(pair.clone());
1999                        is_bracket_pair_start = true;
2000                        break;
2001                    } else if pair.end.as_str() == text.as_ref() {
2002                        bracket_pair = Some(pair.clone());
2003                        break;
2004                    }
2005                }
2006
2007                if let Some(bracket_pair) = bracket_pair {
2008                    if selection.is_empty() {
2009                        if is_bracket_pair_start {
2010                            let prefix_len = bracket_pair.start.len() - text.len();
2011
2012                            // If the inserted text is a suffix of an opening bracket and the
2013                            // selection is preceded by the rest of the opening bracket, then
2014                            // insert the closing bracket.
2015                            let following_text_allows_autoclose = snapshot
2016                                .chars_at(selection.start)
2017                                .next()
2018                                .map_or(true, |c| language.should_autoclose_before(c));
2019                            let preceding_text_matches_prefix = prefix_len == 0
2020                                || (selection.start.column >= (prefix_len as u32)
2021                                    && snapshot.contains_str_at(
2022                                        Point::new(
2023                                            selection.start.row,
2024                                            selection.start.column - (prefix_len as u32),
2025                                        ),
2026                                        &bracket_pair.start[..prefix_len],
2027                                    ));
2028                            if following_text_allows_autoclose && preceding_text_matches_prefix {
2029                                let anchor = snapshot.anchor_before(selection.end);
2030                                new_selections.push((selection.map(|_| anchor), text.len()));
2031                                new_autoclose_regions.push((
2032                                    anchor,
2033                                    text.len(),
2034                                    selection.id,
2035                                    bracket_pair.clone(),
2036                                ));
2037                                edits.push((
2038                                    selection.range(),
2039                                    format!("{}{}", text, bracket_pair.end).into(),
2040                                ));
2041                                continue;
2042                            }
2043                        }
2044
2045                        if let Some(region) = autoclose_region {
2046                            // If the selection is followed by an auto-inserted closing bracket,
2047                            // then don't insert that closing bracket again; just move the selection
2048                            // past the closing bracket.
2049                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2050                                && text.as_ref() == region.pair.end.as_str();
2051                            if should_skip {
2052                                let anchor = snapshot.anchor_after(selection.end);
2053                                new_selections
2054                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2055                                continue;
2056                            }
2057                        }
2058                    }
2059                    // If an opening bracket is 1 character long and is typed while
2060                    // text is selected, then surround that text with the bracket pair.
2061                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2062                        edits.push((selection.start..selection.start, text.clone()));
2063                        edits.push((
2064                            selection.end..selection.end,
2065                            bracket_pair.end.as_str().into(),
2066                        ));
2067                        new_selections.push((
2068                            Selection {
2069                                id: selection.id,
2070                                start: snapshot.anchor_after(selection.start),
2071                                end: snapshot.anchor_before(selection.end),
2072                                reversed: selection.reversed,
2073                                goal: selection.goal,
2074                            },
2075                            0,
2076                        ));
2077                        continue;
2078                    }
2079                }
2080            }
2081
2082            // If not handling any auto-close operation, then just replace the selected
2083            // text with the given input and move the selection to the end of the
2084            // newly inserted text.
2085            let anchor = snapshot.anchor_after(selection.end);
2086            new_selections.push((selection.map(|_| anchor), 0));
2087            edits.push((selection.start..selection.end, text.clone()));
2088        }
2089
2090        drop(snapshot);
2091        self.transact(cx, |this, cx| {
2092            this.buffer.update(cx, |buffer, cx| {
2093                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
2094            });
2095
2096            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2097            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2098            let snapshot = this.buffer.read(cx).read(cx);
2099            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2100                .zip(new_selection_deltas)
2101                .map(|(selection, delta)| selection.map(|e| e + delta))
2102                .collect::<Vec<_>>();
2103
2104            let mut i = 0;
2105            for (position, delta, selection_id, pair) in new_autoclose_regions {
2106                let position = position.to_offset(&snapshot) + delta;
2107                let start = snapshot.anchor_before(position);
2108                let end = snapshot.anchor_after(position);
2109                while let Some(existing_state) = this.autoclose_regions.get(i) {
2110                    match existing_state.range.start.cmp(&start, &snapshot) {
2111                        Ordering::Less => i += 1,
2112                        Ordering::Greater => break,
2113                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2114                            Ordering::Less => i += 1,
2115                            Ordering::Equal => break,
2116                            Ordering::Greater => break,
2117                        },
2118                    }
2119                }
2120                this.autoclose_regions.insert(
2121                    i,
2122                    AutocloseRegion {
2123                        selection_id,
2124                        range: start..end,
2125                        pair,
2126                    },
2127                );
2128            }
2129
2130            drop(snapshot);
2131            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2132            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2133
2134            // When buffer contents is updated and caret is moved, try triggering on type formatting.
2135            if settings::get::<EditorSettings>(cx).use_on_type_format {
2136                if let Some(on_type_format_task) =
2137                    this.trigger_on_type_formatting(text.to_string(), cx)
2138                {
2139                    on_type_format_task.detach_and_log_err(cx);
2140                }
2141            }
2142
2143            if had_active_copilot_suggestion {
2144                this.refresh_copilot_suggestions(true, cx);
2145                if !this.has_active_copilot_suggestion(cx) {
2146                    this.trigger_completion_on_input(&text, cx);
2147                }
2148            } else {
2149                this.trigger_completion_on_input(&text, cx);
2150                this.refresh_copilot_suggestions(true, cx);
2151            }
2152        });
2153    }
2154
2155    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2156        self.transact(cx, |this, cx| {
2157            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2158                let selections = this.selections.all::<usize>(cx);
2159
2160                let buffer = this.buffer.read(cx).snapshot(cx);
2161                selections
2162                    .iter()
2163                    .map(|selection| {
2164                        let start_point = selection.start.to_point(&buffer);
2165                        let mut indent = buffer.indent_size_for_line(start_point.row);
2166                        indent.len = cmp::min(indent.len, start_point.column);
2167                        let start = selection.start;
2168                        let end = selection.end;
2169
2170                        let mut insert_extra_newline = false;
2171                        if let Some(language) = buffer.language_scope_at(start) {
2172                            let leading_whitespace_len = buffer
2173                                .reversed_chars_at(start)
2174                                .take_while(|c| c.is_whitespace() && *c != '\n')
2175                                .map(|c| c.len_utf8())
2176                                .sum::<usize>();
2177
2178                            let trailing_whitespace_len = buffer
2179                                .chars_at(end)
2180                                .take_while(|c| c.is_whitespace() && *c != '\n')
2181                                .map(|c| c.len_utf8())
2182                                .sum::<usize>();
2183
2184                            insert_extra_newline = language.brackets().any(|(pair, enabled)| {
2185                                let pair_start = pair.start.trim_end();
2186                                let pair_end = pair.end.trim_start();
2187
2188                                enabled
2189                                    && pair.newline
2190                                    && buffer
2191                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
2192                                    && buffer.contains_str_at(
2193                                        (start - leading_whitespace_len)
2194                                            .saturating_sub(pair_start.len()),
2195                                        pair_start,
2196                                    )
2197                            });
2198                        }
2199
2200                        let mut new_text = String::with_capacity(1 + indent.len as usize);
2201                        new_text.push('\n');
2202                        new_text.extend(indent.chars());
2203                        if insert_extra_newline {
2204                            new_text = new_text.repeat(2);
2205                        }
2206
2207                        let anchor = buffer.anchor_after(end);
2208                        let new_selection = selection.map(|_| anchor);
2209                        (
2210                            (start..end, new_text),
2211                            (insert_extra_newline, new_selection),
2212                        )
2213                    })
2214                    .unzip()
2215            };
2216
2217            this.edit_with_autoindent(edits, cx);
2218            let buffer = this.buffer.read(cx).snapshot(cx);
2219            let new_selections = selection_fixup_info
2220                .into_iter()
2221                .map(|(extra_newline_inserted, new_selection)| {
2222                    let mut cursor = new_selection.end.to_point(&buffer);
2223                    if extra_newline_inserted {
2224                        cursor.row -= 1;
2225                        cursor.column = buffer.line_len(cursor.row);
2226                    }
2227                    new_selection.map(|_| cursor)
2228                })
2229                .collect();
2230
2231            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2232            this.refresh_copilot_suggestions(true, cx);
2233        });
2234    }
2235
2236    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2237        let buffer = self.buffer.read(cx);
2238        let snapshot = buffer.snapshot(cx);
2239
2240        let mut edits = Vec::new();
2241        let mut rows = Vec::new();
2242        let mut rows_inserted = 0;
2243
2244        for selection in self.selections.all_adjusted(cx) {
2245            let cursor = selection.head();
2246            let row = cursor.row;
2247
2248            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2249
2250            let newline = "\n".to_string();
2251            edits.push((start_of_line..start_of_line, newline));
2252
2253            rows.push(row + rows_inserted);
2254            rows_inserted += 1;
2255        }
2256
2257        self.transact(cx, |editor, cx| {
2258            editor.edit(edits, cx);
2259
2260            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2261                let mut index = 0;
2262                s.move_cursors_with(|map, _, _| {
2263                    let row = rows[index];
2264                    index += 1;
2265
2266                    let point = Point::new(row, 0);
2267                    let boundary = map.next_line_boundary(point).1;
2268                    let clipped = map.clip_point(boundary, Bias::Left);
2269
2270                    (clipped, SelectionGoal::None)
2271                });
2272            });
2273
2274            let mut indent_edits = Vec::new();
2275            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2276            for row in rows {
2277                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2278                for (row, indent) in indents {
2279                    if indent.len == 0 {
2280                        continue;
2281                    }
2282
2283                    let text = match indent.kind {
2284                        IndentKind::Space => " ".repeat(indent.len as usize),
2285                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2286                    };
2287                    let point = Point::new(row, 0);
2288                    indent_edits.push((point..point, text));
2289                }
2290            }
2291            editor.edit(indent_edits, cx);
2292        });
2293    }
2294
2295    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2296        let buffer = self.buffer.read(cx);
2297        let snapshot = buffer.snapshot(cx);
2298
2299        let mut edits = Vec::new();
2300        let mut rows = Vec::new();
2301        let mut rows_inserted = 0;
2302
2303        for selection in self.selections.all_adjusted(cx) {
2304            let cursor = selection.head();
2305            let row = cursor.row;
2306
2307            let point = Point::new(row + 1, 0);
2308            let start_of_line = snapshot.clip_point(point, Bias::Left);
2309
2310            let newline = "\n".to_string();
2311            edits.push((start_of_line..start_of_line, newline));
2312
2313            rows_inserted += 1;
2314            rows.push(row + rows_inserted);
2315        }
2316
2317        self.transact(cx, |editor, cx| {
2318            editor.edit(edits, cx);
2319
2320            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2321                let mut index = 0;
2322                s.move_cursors_with(|map, _, _| {
2323                    let row = rows[index];
2324                    index += 1;
2325
2326                    let point = Point::new(row, 0);
2327                    let boundary = map.next_line_boundary(point).1;
2328                    let clipped = map.clip_point(boundary, Bias::Left);
2329
2330                    (clipped, SelectionGoal::None)
2331                });
2332            });
2333
2334            let mut indent_edits = Vec::new();
2335            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2336            for row in rows {
2337                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2338                for (row, indent) in indents {
2339                    if indent.len == 0 {
2340                        continue;
2341                    }
2342
2343                    let text = match indent.kind {
2344                        IndentKind::Space => " ".repeat(indent.len as usize),
2345                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2346                    };
2347                    let point = Point::new(row, 0);
2348                    indent_edits.push((point..point, text));
2349                }
2350            }
2351            editor.edit(indent_edits, cx);
2352        });
2353    }
2354
2355    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2356        self.insert_with_autoindent_mode(
2357            text,
2358            Some(AutoindentMode::Block {
2359                original_indent_columns: Vec::new(),
2360            }),
2361            cx,
2362        );
2363    }
2364
2365    fn insert_with_autoindent_mode(
2366        &mut self,
2367        text: &str,
2368        autoindent_mode: Option<AutoindentMode>,
2369        cx: &mut ViewContext<Self>,
2370    ) {
2371        if self.read_only {
2372            return;
2373        }
2374
2375        let text: Arc<str> = text.into();
2376        self.transact(cx, |this, cx| {
2377            let old_selections = this.selections.all_adjusted(cx);
2378            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2379                let anchors = {
2380                    let snapshot = buffer.read(cx);
2381                    old_selections
2382                        .iter()
2383                        .map(|s| {
2384                            let anchor = snapshot.anchor_after(s.end);
2385                            s.map(|_| anchor)
2386                        })
2387                        .collect::<Vec<_>>()
2388                };
2389                buffer.edit(
2390                    old_selections
2391                        .iter()
2392                        .map(|s| (s.start..s.end, text.clone())),
2393                    autoindent_mode,
2394                    cx,
2395                );
2396                anchors
2397            });
2398
2399            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2400                s.select_anchors(selection_anchors);
2401            })
2402        });
2403    }
2404
2405    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2406        if !settings::get::<EditorSettings>(cx).show_completions_on_input {
2407            return;
2408        }
2409
2410        let selection = self.selections.newest_anchor();
2411        if self
2412            .buffer
2413            .read(cx)
2414            .is_completion_trigger(selection.head(), text, cx)
2415        {
2416            self.show_completions(&ShowCompletions, cx);
2417        } else {
2418            self.hide_context_menu(cx);
2419        }
2420    }
2421
2422    /// If any empty selections is touching the start of its innermost containing autoclose
2423    /// region, expand it to select the brackets.
2424    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2425        let selections = self.selections.all::<usize>(cx);
2426        let buffer = self.buffer.read(cx).read(cx);
2427        let mut new_selections = Vec::new();
2428        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2429            if let (Some(region), true) = (region, selection.is_empty()) {
2430                let mut range = region.range.to_offset(&buffer);
2431                if selection.start == range.start {
2432                    if range.start >= region.pair.start.len() {
2433                        range.start -= region.pair.start.len();
2434                        if buffer.contains_str_at(range.start, &region.pair.start) {
2435                            if buffer.contains_str_at(range.end, &region.pair.end) {
2436                                range.end += region.pair.end.len();
2437                                selection.start = range.start;
2438                                selection.end = range.end;
2439                            }
2440                        }
2441                    }
2442                }
2443            }
2444            new_selections.push(selection);
2445        }
2446
2447        drop(buffer);
2448        self.change_selections(None, cx, |selections| selections.select(new_selections));
2449    }
2450
2451    /// Iterate the given selections, and for each one, find the smallest surrounding
2452    /// autoclose region. This uses the ordering of the selections and the autoclose
2453    /// regions to avoid repeated comparisons.
2454    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2455        &'a self,
2456        selections: impl IntoIterator<Item = Selection<D>>,
2457        buffer: &'a MultiBufferSnapshot,
2458    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2459        let mut i = 0;
2460        let mut regions = self.autoclose_regions.as_slice();
2461        selections.into_iter().map(move |selection| {
2462            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2463
2464            let mut enclosing = None;
2465            while let Some(pair_state) = regions.get(i) {
2466                if pair_state.range.end.to_offset(buffer) < range.start {
2467                    regions = &regions[i + 1..];
2468                    i = 0;
2469                } else if pair_state.range.start.to_offset(buffer) > range.end {
2470                    break;
2471                } else if pair_state.selection_id == selection.id {
2472                    enclosing = Some(pair_state);
2473                    i += 1;
2474                }
2475            }
2476
2477            (selection.clone(), enclosing)
2478        })
2479    }
2480
2481    /// Remove any autoclose regions that no longer contain their selection.
2482    fn invalidate_autoclose_regions(
2483        &mut self,
2484        mut selections: &[Selection<Anchor>],
2485        buffer: &MultiBufferSnapshot,
2486    ) {
2487        self.autoclose_regions.retain(|state| {
2488            let mut i = 0;
2489            while let Some(selection) = selections.get(i) {
2490                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2491                    selections = &selections[1..];
2492                    continue;
2493                }
2494                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2495                    break;
2496                }
2497                if selection.id == state.selection_id {
2498                    return true;
2499                } else {
2500                    i += 1;
2501                }
2502            }
2503            false
2504        });
2505    }
2506
2507    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2508        let offset = position.to_offset(buffer);
2509        let (word_range, kind) = buffer.surrounding_word(offset);
2510        if offset > word_range.start && kind == Some(CharKind::Word) {
2511            Some(
2512                buffer
2513                    .text_for_range(word_range.start..offset)
2514                    .collect::<String>(),
2515            )
2516        } else {
2517            None
2518        }
2519    }
2520
2521    fn trigger_on_type_formatting(
2522        &self,
2523        input: String,
2524        cx: &mut ViewContext<Self>,
2525    ) -> Option<Task<Result<()>>> {
2526        if input.len() != 1 {
2527            return None;
2528        }
2529
2530        let project = self.project.as_ref()?;
2531        let position = self.selections.newest_anchor().head();
2532        let (buffer, buffer_position) = self
2533            .buffer
2534            .read(cx)
2535            .text_anchor_for_position(position.clone(), cx)?;
2536
2537        // OnTypeFormatting retuns a list of edits, no need to pass them between Zed instances,
2538        // hence we do LSP request & edit on host side only — add formats to host's history.
2539        let push_to_lsp_host_history = true;
2540        // If this is not the host, append its history with new edits.
2541        let push_to_client_history = project.read(cx).is_remote();
2542
2543        let on_type_formatting = project.update(cx, |project, cx| {
2544            project.on_type_format(
2545                buffer.clone(),
2546                buffer_position,
2547                input,
2548                push_to_lsp_host_history,
2549                cx,
2550            )
2551        });
2552        Some(cx.spawn(|editor, mut cx| async move {
2553            if let Some(transaction) = on_type_formatting.await? {
2554                if push_to_client_history {
2555                    buffer.update(&mut cx, |buffer, _| {
2556                        buffer.push_transaction(transaction, Instant::now());
2557                    });
2558                }
2559                editor.update(&mut cx, |editor, cx| {
2560                    editor.refresh_document_highlights(cx);
2561                })?;
2562            }
2563            Ok(())
2564        }))
2565    }
2566
2567    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2568        if self.pending_rename.is_some() {
2569            return;
2570        }
2571
2572        let project = if let Some(project) = self.project.clone() {
2573            project
2574        } else {
2575            return;
2576        };
2577
2578        let position = self.selections.newest_anchor().head();
2579        let (buffer, buffer_position) = if let Some(output) = self
2580            .buffer
2581            .read(cx)
2582            .text_anchor_for_position(position.clone(), cx)
2583        {
2584            output
2585        } else {
2586            return;
2587        };
2588
2589        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2590        let completions = project.update(cx, |project, cx| {
2591            project.completions(&buffer, buffer_position, cx)
2592        });
2593
2594        let id = post_inc(&mut self.next_completion_id);
2595        let task = cx.spawn(|this, mut cx| {
2596            async move {
2597                let menu = if let Some(completions) = completions.await.log_err() {
2598                    let mut menu = CompletionsMenu {
2599                        id,
2600                        initial_position: position,
2601                        match_candidates: completions
2602                            .iter()
2603                            .enumerate()
2604                            .map(|(id, completion)| {
2605                                StringMatchCandidate::new(
2606                                    id,
2607                                    completion.label.text[completion.label.filter_range.clone()]
2608                                        .into(),
2609                                )
2610                            })
2611                            .collect(),
2612                        buffer,
2613                        completions: completions.into(),
2614                        matches: Vec::new().into(),
2615                        selected_item: 0,
2616                        list: Default::default(),
2617                    };
2618                    menu.filter(query.as_deref(), cx.background()).await;
2619                    if menu.matches.is_empty() {
2620                        None
2621                    } else {
2622                        Some(menu)
2623                    }
2624                } else {
2625                    None
2626                };
2627
2628                this.update(&mut cx, |this, cx| {
2629                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2630
2631                    match this.context_menu.as_ref() {
2632                        None => {}
2633                        Some(ContextMenu::Completions(prev_menu)) => {
2634                            if prev_menu.id > id {
2635                                return;
2636                            }
2637                        }
2638                        _ => return,
2639                    }
2640
2641                    if this.focused && menu.is_some() {
2642                        let menu = menu.unwrap();
2643                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2644                    } else if this.completion_tasks.is_empty() {
2645                        // If there are no more completion tasks and the last menu was
2646                        // empty, we should hide it. If it was already hidden, we should
2647                        // also show the copilot suggestion when available.
2648                        if this.hide_context_menu(cx).is_none() {
2649                            this.update_visible_copilot_suggestion(cx);
2650                        }
2651                    }
2652                })?;
2653
2654                Ok::<_, anyhow::Error>(())
2655            }
2656            .log_err()
2657        });
2658        self.completion_tasks.push((id, task));
2659    }
2660
2661    pub fn confirm_completion(
2662        &mut self,
2663        action: &ConfirmCompletion,
2664        cx: &mut ViewContext<Self>,
2665    ) -> Option<Task<Result<()>>> {
2666        use language::ToOffset as _;
2667
2668        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2669            menu
2670        } else {
2671            return None;
2672        };
2673
2674        let mat = completions_menu
2675            .matches
2676            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2677        let buffer_handle = completions_menu.buffer;
2678        let completion = completions_menu.completions.get(mat.candidate_id)?;
2679
2680        let snippet;
2681        let text;
2682        if completion.is_snippet() {
2683            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2684            text = snippet.as_ref().unwrap().text.clone();
2685        } else {
2686            snippet = None;
2687            text = completion.new_text.clone();
2688        };
2689        let selections = self.selections.all::<usize>(cx);
2690        let buffer = buffer_handle.read(cx);
2691        let old_range = completion.old_range.to_offset(buffer);
2692        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2693
2694        let newest_selection = self.selections.newest_anchor();
2695        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2696            return None;
2697        }
2698
2699        let lookbehind = newest_selection
2700            .start
2701            .text_anchor
2702            .to_offset(buffer)
2703            .saturating_sub(old_range.start);
2704        let lookahead = old_range
2705            .end
2706            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2707        let mut common_prefix_len = old_text
2708            .bytes()
2709            .zip(text.bytes())
2710            .take_while(|(a, b)| a == b)
2711            .count();
2712
2713        let snapshot = self.buffer.read(cx).snapshot(cx);
2714        let mut ranges = Vec::new();
2715        for selection in &selections {
2716            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2717                let start = selection.start.saturating_sub(lookbehind);
2718                let end = selection.end + lookahead;
2719                ranges.push(start + common_prefix_len..end);
2720            } else {
2721                common_prefix_len = 0;
2722                ranges.clear();
2723                ranges.extend(selections.iter().map(|s| {
2724                    if s.id == newest_selection.id {
2725                        old_range.clone()
2726                    } else {
2727                        s.start..s.end
2728                    }
2729                }));
2730                break;
2731            }
2732        }
2733        let text = &text[common_prefix_len..];
2734
2735        self.transact(cx, |this, cx| {
2736            if let Some(mut snippet) = snippet {
2737                snippet.text = text.to_string();
2738                for tabstop in snippet.tabstops.iter_mut().flatten() {
2739                    tabstop.start -= common_prefix_len as isize;
2740                    tabstop.end -= common_prefix_len as isize;
2741                }
2742
2743                this.insert_snippet(&ranges, snippet, cx).log_err();
2744            } else {
2745                this.buffer.update(cx, |buffer, cx| {
2746                    buffer.edit(
2747                        ranges.iter().map(|range| (range.clone(), text)),
2748                        Some(AutoindentMode::EachLine),
2749                        cx,
2750                    );
2751                });
2752            }
2753
2754            this.refresh_copilot_suggestions(true, cx);
2755        });
2756
2757        let project = self.project.clone()?;
2758        let apply_edits = project.update(cx, |project, cx| {
2759            project.apply_additional_edits_for_completion(
2760                buffer_handle,
2761                completion.clone(),
2762                true,
2763                cx,
2764            )
2765        });
2766        Some(cx.foreground().spawn(async move {
2767            apply_edits.await?;
2768            Ok(())
2769        }))
2770    }
2771
2772    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2773        if matches!(
2774            self.context_menu.as_ref(),
2775            Some(ContextMenu::CodeActions(_))
2776        ) {
2777            self.context_menu.take();
2778            cx.notify();
2779            return;
2780        }
2781
2782        let deployed_from_indicator = action.deployed_from_indicator;
2783        let mut task = self.code_actions_task.take();
2784        cx.spawn(|this, mut cx| async move {
2785            while let Some(prev_task) = task {
2786                prev_task.await;
2787                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
2788            }
2789
2790            this.update(&mut cx, |this, cx| {
2791                if this.focused {
2792                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
2793                        this.show_context_menu(
2794                            ContextMenu::CodeActions(CodeActionsMenu {
2795                                buffer,
2796                                actions,
2797                                selected_item: Default::default(),
2798                                list: Default::default(),
2799                                deployed_from_indicator,
2800                            }),
2801                            cx,
2802                        );
2803                    }
2804                }
2805            })?;
2806
2807            Ok::<_, anyhow::Error>(())
2808        })
2809        .detach_and_log_err(cx);
2810    }
2811
2812    pub fn confirm_code_action(
2813        workspace: &mut Workspace,
2814        action: &ConfirmCodeAction,
2815        cx: &mut ViewContext<Workspace>,
2816    ) -> Option<Task<Result<()>>> {
2817        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2818        let actions_menu = if let ContextMenu::CodeActions(menu) =
2819            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2820        {
2821            menu
2822        } else {
2823            return None;
2824        };
2825        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2826        let action = actions_menu.actions.get(action_ix)?.clone();
2827        let title = action.lsp_action.title.clone();
2828        let buffer = actions_menu.buffer;
2829
2830        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2831            project.apply_code_action(buffer, action, true, cx)
2832        });
2833        let editor = editor.downgrade();
2834        Some(cx.spawn(|workspace, cx| async move {
2835            let project_transaction = apply_code_actions.await?;
2836            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
2837        }))
2838    }
2839
2840    async fn open_project_transaction(
2841        this: &WeakViewHandle<Editor>,
2842        workspace: WeakViewHandle<Workspace>,
2843        transaction: ProjectTransaction,
2844        title: String,
2845        mut cx: AsyncAppContext,
2846    ) -> Result<()> {
2847        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
2848
2849        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2850        entries.sort_unstable_by_key(|(buffer, _)| {
2851            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2852        });
2853
2854        // If the project transaction's edits are all contained within this editor, then
2855        // avoid opening a new editor to display them.
2856
2857        if let Some((buffer, transaction)) = entries.first() {
2858            if entries.len() == 1 {
2859                let excerpt = this.read_with(&cx, |editor, cx| {
2860                    editor
2861                        .buffer()
2862                        .read(cx)
2863                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2864                })?;
2865                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2866                    if excerpted_buffer == *buffer {
2867                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2868                            let excerpt_range = excerpt_range.to_offset(buffer);
2869                            buffer
2870                                .edited_ranges_for_transaction::<usize>(transaction)
2871                                .all(|range| {
2872                                    excerpt_range.start <= range.start
2873                                        && excerpt_range.end >= range.end
2874                                })
2875                        });
2876
2877                        if all_edits_within_excerpt {
2878                            return Ok(());
2879                        }
2880                    }
2881                }
2882            }
2883        } else {
2884            return Ok(());
2885        }
2886
2887        let mut ranges_to_highlight = Vec::new();
2888        let excerpt_buffer = cx.add_model(|cx| {
2889            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2890            for (buffer_handle, transaction) in &entries {
2891                let buffer = buffer_handle.read(cx);
2892                ranges_to_highlight.extend(
2893                    multibuffer.push_excerpts_with_context_lines(
2894                        buffer_handle.clone(),
2895                        buffer
2896                            .edited_ranges_for_transaction::<usize>(transaction)
2897                            .collect(),
2898                        1,
2899                        cx,
2900                    ),
2901                );
2902            }
2903            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
2904            multibuffer
2905        });
2906
2907        workspace.update(&mut cx, |workspace, cx| {
2908            let project = workspace.project().clone();
2909            let editor =
2910                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2911            workspace.add_item(Box::new(editor.clone()), cx);
2912            editor.update(cx, |editor, cx| {
2913                editor.highlight_background::<Self>(
2914                    ranges_to_highlight,
2915                    |theme| theme.editor.highlighted_line_background,
2916                    cx,
2917                );
2918            });
2919        })?;
2920
2921        Ok(())
2922    }
2923
2924    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2925        let project = self.project.as_ref()?;
2926        let buffer = self.buffer.read(cx);
2927        let newest_selection = self.selections.newest_anchor().clone();
2928        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2929        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2930        if start_buffer != end_buffer {
2931            return None;
2932        }
2933
2934        let actions = project.update(cx, |project, cx| {
2935            project.code_actions(&start_buffer, start..end, cx)
2936        });
2937        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
2938            let actions = actions.await;
2939            this.update(&mut cx, |this, cx| {
2940                this.available_code_actions = actions.log_err().and_then(|actions| {
2941                    if actions.is_empty() {
2942                        None
2943                    } else {
2944                        Some((start_buffer, actions.into()))
2945                    }
2946                });
2947                cx.notify();
2948            })
2949            .log_err();
2950        }));
2951        None
2952    }
2953
2954    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2955        if self.pending_rename.is_some() {
2956            return None;
2957        }
2958
2959        let project = self.project.as_ref()?;
2960        let buffer = self.buffer.read(cx);
2961        let newest_selection = self.selections.newest_anchor().clone();
2962        let cursor_position = newest_selection.head();
2963        let (cursor_buffer, cursor_buffer_position) =
2964            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2965        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2966        if cursor_buffer != tail_buffer {
2967            return None;
2968        }
2969
2970        let highlights = project.update(cx, |project, cx| {
2971            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2972        });
2973
2974        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
2975            if let Some(highlights) = highlights.await.log_err() {
2976                this.update(&mut cx, |this, cx| {
2977                    if this.pending_rename.is_some() {
2978                        return;
2979                    }
2980
2981                    let buffer_id = cursor_position.buffer_id;
2982                    let buffer = this.buffer.read(cx);
2983                    if !buffer
2984                        .text_anchor_for_position(cursor_position, cx)
2985                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2986                    {
2987                        return;
2988                    }
2989
2990                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2991                    let mut write_ranges = Vec::new();
2992                    let mut read_ranges = Vec::new();
2993                    for highlight in highlights {
2994                        for (excerpt_id, excerpt_range) in
2995                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2996                        {
2997                            let start = highlight
2998                                .range
2999                                .start
3000                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3001                            let end = highlight
3002                                .range
3003                                .end
3004                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3005                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3006                                continue;
3007                            }
3008
3009                            let range = Anchor {
3010                                buffer_id,
3011                                excerpt_id: excerpt_id.clone(),
3012                                text_anchor: start,
3013                            }..Anchor {
3014                                buffer_id,
3015                                excerpt_id,
3016                                text_anchor: end,
3017                            };
3018                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3019                                write_ranges.push(range);
3020                            } else {
3021                                read_ranges.push(range);
3022                            }
3023                        }
3024                    }
3025
3026                    this.highlight_background::<DocumentHighlightRead>(
3027                        read_ranges,
3028                        |theme| theme.editor.document_highlight_read_background,
3029                        cx,
3030                    );
3031                    this.highlight_background::<DocumentHighlightWrite>(
3032                        write_ranges,
3033                        |theme| theme.editor.document_highlight_write_background,
3034                        cx,
3035                    );
3036                    cx.notify();
3037                })
3038                .log_err();
3039            }
3040        }));
3041        None
3042    }
3043
3044    fn refresh_copilot_suggestions(
3045        &mut self,
3046        debounce: bool,
3047        cx: &mut ViewContext<Self>,
3048    ) -> Option<()> {
3049        let copilot = Copilot::global(cx)?;
3050        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3051            self.clear_copilot_suggestions(cx);
3052            return None;
3053        }
3054        self.update_visible_copilot_suggestion(cx);
3055
3056        let snapshot = self.buffer.read(cx).snapshot(cx);
3057        let cursor = self.selections.newest_anchor().head();
3058        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3059            self.clear_copilot_suggestions(cx);
3060            return None;
3061        }
3062
3063        let (buffer, buffer_position) =
3064            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3065        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3066            if debounce {
3067                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3068            }
3069
3070            let completions = copilot
3071                .update(&mut cx, |copilot, cx| {
3072                    copilot.completions(&buffer, buffer_position, cx)
3073                })
3074                .await
3075                .log_err()
3076                .into_iter()
3077                .flatten()
3078                .collect_vec();
3079
3080            this.update(&mut cx, |this, cx| {
3081                if !completions.is_empty() {
3082                    this.copilot_state.cycled = false;
3083                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3084                    this.copilot_state.completions.clear();
3085                    this.copilot_state.active_completion_index = 0;
3086                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3087                    for completion in completions {
3088                        this.copilot_state.push_completion(completion);
3089                    }
3090                    this.update_visible_copilot_suggestion(cx);
3091                }
3092            })
3093            .log_err()?;
3094            Some(())
3095        });
3096
3097        Some(())
3098    }
3099
3100    fn cycle_copilot_suggestions(
3101        &mut self,
3102        direction: Direction,
3103        cx: &mut ViewContext<Self>,
3104    ) -> Option<()> {
3105        let copilot = Copilot::global(cx)?;
3106        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3107            return None;
3108        }
3109
3110        if self.copilot_state.cycled {
3111            self.copilot_state.cycle_completions(direction);
3112            self.update_visible_copilot_suggestion(cx);
3113        } else {
3114            let cursor = self.selections.newest_anchor().head();
3115            let (buffer, buffer_position) =
3116                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3117            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3118                let completions = copilot
3119                    .update(&mut cx, |copilot, cx| {
3120                        copilot.completions_cycling(&buffer, buffer_position, cx)
3121                    })
3122                    .await;
3123
3124                this.update(&mut cx, |this, cx| {
3125                    this.copilot_state.cycled = true;
3126                    for completion in completions.log_err().into_iter().flatten() {
3127                        this.copilot_state.push_completion(completion);
3128                    }
3129                    this.copilot_state.cycle_completions(direction);
3130                    this.update_visible_copilot_suggestion(cx);
3131                })
3132                .log_err()?;
3133
3134                Some(())
3135            });
3136        }
3137
3138        Some(())
3139    }
3140
3141    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3142        if !self.has_active_copilot_suggestion(cx) {
3143            self.refresh_copilot_suggestions(false, cx);
3144            return;
3145        }
3146
3147        self.update_visible_copilot_suggestion(cx);
3148    }
3149
3150    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3151        if self.has_active_copilot_suggestion(cx) {
3152            self.cycle_copilot_suggestions(Direction::Next, cx);
3153        } else {
3154            self.refresh_copilot_suggestions(false, cx);
3155        }
3156    }
3157
3158    fn previous_copilot_suggestion(
3159        &mut self,
3160        _: &copilot::PreviousSuggestion,
3161        cx: &mut ViewContext<Self>,
3162    ) {
3163        if self.has_active_copilot_suggestion(cx) {
3164            self.cycle_copilot_suggestions(Direction::Prev, cx);
3165        } else {
3166            self.refresh_copilot_suggestions(false, cx);
3167        }
3168    }
3169
3170    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3171        if let Some(suggestion) = self
3172            .display_map
3173            .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx))
3174        {
3175            if let Some((copilot, completion)) =
3176                Copilot::global(cx).zip(self.copilot_state.active_completion())
3177            {
3178                copilot
3179                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3180                    .detach_and_log_err(cx);
3181
3182                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3183            }
3184            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3185            cx.notify();
3186            true
3187        } else {
3188            false
3189        }
3190    }
3191
3192    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3193        if self.has_active_copilot_suggestion(cx) {
3194            if let Some(copilot) = Copilot::global(cx) {
3195                copilot
3196                    .update(cx, |copilot, cx| {
3197                        copilot.discard_completions(&self.copilot_state.completions, cx)
3198                    })
3199                    .detach_and_log_err(cx);
3200
3201                self.report_copilot_event(None, false, cx)
3202            }
3203
3204            self.display_map
3205                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
3206            cx.notify();
3207            true
3208        } else {
3209            false
3210        }
3211    }
3212
3213    fn is_copilot_enabled_at(
3214        &self,
3215        location: Anchor,
3216        snapshot: &MultiBufferSnapshot,
3217        cx: &mut ViewContext<Self>,
3218    ) -> bool {
3219        let file = snapshot.file_at(location);
3220        let language = snapshot.language_at(location);
3221        let settings = all_language_settings(file, cx);
3222        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3223    }
3224
3225    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3226        self.display_map.read(cx).has_suggestion()
3227    }
3228
3229    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3230        let snapshot = self.buffer.read(cx).snapshot(cx);
3231        let selection = self.selections.newest_anchor();
3232        let cursor = selection.head();
3233
3234        if self.context_menu.is_some()
3235            || !self.completion_tasks.is_empty()
3236            || selection.start != selection.end
3237        {
3238            self.discard_copilot_suggestion(cx);
3239        } else if let Some(text) = self
3240            .copilot_state
3241            .text_for_active_completion(cursor, &snapshot)
3242        {
3243            self.display_map.update(cx, move |map, cx| {
3244                map.replace_suggestion(
3245                    Some(Suggestion {
3246                        position: cursor,
3247                        text: text.trim_end().into(),
3248                    }),
3249                    cx,
3250                )
3251            });
3252            cx.notify();
3253        } else {
3254            self.discard_copilot_suggestion(cx);
3255        }
3256    }
3257
3258    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3259        self.copilot_state = Default::default();
3260        self.discard_copilot_suggestion(cx);
3261    }
3262
3263    pub fn render_code_actions_indicator(
3264        &self,
3265        style: &EditorStyle,
3266        active: bool,
3267        cx: &mut ViewContext<Self>,
3268    ) -> Option<AnyElement<Self>> {
3269        if self.available_code_actions.is_some() {
3270            enum CodeActions {}
3271            Some(
3272                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3273                    Svg::new("icons/bolt_8.svg")
3274                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3275                })
3276                .with_cursor_style(CursorStyle::PointingHand)
3277                .with_padding(Padding::uniform(3.))
3278                .on_down(MouseButton::Left, |_, this, cx| {
3279                    this.toggle_code_actions(
3280                        &ToggleCodeActions {
3281                            deployed_from_indicator: true,
3282                        },
3283                        cx,
3284                    );
3285                })
3286                .into_any(),
3287            )
3288        } else {
3289            None
3290        }
3291    }
3292
3293    pub fn render_fold_indicators(
3294        &self,
3295        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3296        style: &EditorStyle,
3297        gutter_hovered: bool,
3298        line_height: f32,
3299        gutter_margin: f32,
3300        cx: &mut ViewContext<Self>,
3301    ) -> Vec<Option<AnyElement<Self>>> {
3302        enum FoldIndicators {}
3303
3304        let style = style.folds.clone();
3305
3306        fold_data
3307            .iter()
3308            .enumerate()
3309            .map(|(ix, fold_data)| {
3310                fold_data
3311                    .map(|(fold_status, buffer_row, active)| {
3312                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3313                            MouseEventHandler::<FoldIndicators, _>::new(
3314                                ix as usize,
3315                                cx,
3316                                |mouse_state, _| {
3317                                    Svg::new(match fold_status {
3318                                        FoldStatus::Folded => style.folded_icon.clone(),
3319                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3320                                    })
3321                                    .with_color(
3322                                        style
3323                                            .indicator
3324                                            .style_for(
3325                                                mouse_state,
3326                                                fold_status == FoldStatus::Folded,
3327                                            )
3328                                            .color,
3329                                    )
3330                                    .constrained()
3331                                    .with_width(gutter_margin * style.icon_margin_scale)
3332                                    .aligned()
3333                                    .constrained()
3334                                    .with_height(line_height)
3335                                    .with_width(gutter_margin)
3336                                    .aligned()
3337                                },
3338                            )
3339                            .with_cursor_style(CursorStyle::PointingHand)
3340                            .with_padding(Padding::uniform(3.))
3341                            .on_click(MouseButton::Left, {
3342                                move |_, editor, cx| match fold_status {
3343                                    FoldStatus::Folded => {
3344                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3345                                    }
3346                                    FoldStatus::Foldable => {
3347                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3348                                    }
3349                                }
3350                            })
3351                            .into_any()
3352                        })
3353                    })
3354                    .flatten()
3355            })
3356            .collect()
3357    }
3358
3359    pub fn context_menu_visible(&self) -> bool {
3360        self.context_menu
3361            .as_ref()
3362            .map_or(false, |menu| menu.visible())
3363    }
3364
3365    pub fn render_context_menu(
3366        &self,
3367        cursor_position: DisplayPoint,
3368        style: EditorStyle,
3369        cx: &mut ViewContext<Editor>,
3370    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3371        self.context_menu
3372            .as_ref()
3373            .map(|menu| menu.render(cursor_position, style, cx))
3374    }
3375
3376    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3377        if !matches!(menu, ContextMenu::Completions(_)) {
3378            self.completion_tasks.clear();
3379        }
3380        self.context_menu = Some(menu);
3381        self.discard_copilot_suggestion(cx);
3382        cx.notify();
3383    }
3384
3385    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3386        cx.notify();
3387        self.completion_tasks.clear();
3388        let context_menu = self.context_menu.take();
3389        if context_menu.is_some() {
3390            self.update_visible_copilot_suggestion(cx);
3391        }
3392        context_menu
3393    }
3394
3395    pub fn insert_snippet(
3396        &mut self,
3397        insertion_ranges: &[Range<usize>],
3398        snippet: Snippet,
3399        cx: &mut ViewContext<Self>,
3400    ) -> Result<()> {
3401        let tabstops = self.buffer.update(cx, |buffer, cx| {
3402            let snippet_text: Arc<str> = snippet.text.clone().into();
3403            buffer.edit(
3404                insertion_ranges
3405                    .iter()
3406                    .cloned()
3407                    .map(|range| (range, snippet_text.clone())),
3408                Some(AutoindentMode::EachLine),
3409                cx,
3410            );
3411
3412            let snapshot = &*buffer.read(cx);
3413            let snippet = &snippet;
3414            snippet
3415                .tabstops
3416                .iter()
3417                .map(|tabstop| {
3418                    let mut tabstop_ranges = tabstop
3419                        .iter()
3420                        .flat_map(|tabstop_range| {
3421                            let mut delta = 0_isize;
3422                            insertion_ranges.iter().map(move |insertion_range| {
3423                                let insertion_start = insertion_range.start as isize + delta;
3424                                delta +=
3425                                    snippet.text.len() as isize - insertion_range.len() as isize;
3426
3427                                let start = snapshot.anchor_before(
3428                                    (insertion_start + tabstop_range.start) as usize,
3429                                );
3430                                let end = snapshot
3431                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3432                                start..end
3433                            })
3434                        })
3435                        .collect::<Vec<_>>();
3436                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3437                    tabstop_ranges
3438                })
3439                .collect::<Vec<_>>()
3440        });
3441
3442        if let Some(tabstop) = tabstops.first() {
3443            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3444                s.select_ranges(tabstop.iter().cloned());
3445            });
3446            self.snippet_stack.push(SnippetState {
3447                active_index: 0,
3448                ranges: tabstops,
3449            });
3450        }
3451
3452        Ok(())
3453    }
3454
3455    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3456        self.move_to_snippet_tabstop(Bias::Right, cx)
3457    }
3458
3459    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3460        self.move_to_snippet_tabstop(Bias::Left, cx)
3461    }
3462
3463    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3464        if let Some(mut snippet) = self.snippet_stack.pop() {
3465            match bias {
3466                Bias::Left => {
3467                    if snippet.active_index > 0 {
3468                        snippet.active_index -= 1;
3469                    } else {
3470                        self.snippet_stack.push(snippet);
3471                        return false;
3472                    }
3473                }
3474                Bias::Right => {
3475                    if snippet.active_index + 1 < snippet.ranges.len() {
3476                        snippet.active_index += 1;
3477                    } else {
3478                        self.snippet_stack.push(snippet);
3479                        return false;
3480                    }
3481                }
3482            }
3483            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3484                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3485                    s.select_anchor_ranges(current_ranges.iter().cloned())
3486                });
3487                // If snippet state is not at the last tabstop, push it back on the stack
3488                if snippet.active_index + 1 < snippet.ranges.len() {
3489                    self.snippet_stack.push(snippet);
3490                }
3491                return true;
3492            }
3493        }
3494
3495        false
3496    }
3497
3498    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3499        self.transact(cx, |this, cx| {
3500            this.select_all(&SelectAll, cx);
3501            this.insert("", cx);
3502        });
3503    }
3504
3505    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3506        self.transact(cx, |this, cx| {
3507            this.select_autoclose_pair(cx);
3508            let mut selections = this.selections.all::<Point>(cx);
3509            if !this.selections.line_mode {
3510                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3511                for selection in &mut selections {
3512                    if selection.is_empty() {
3513                        let old_head = selection.head();
3514                        let mut new_head =
3515                            movement::left(&display_map, old_head.to_display_point(&display_map))
3516                                .to_point(&display_map);
3517                        if let Some((buffer, line_buffer_range)) = display_map
3518                            .buffer_snapshot
3519                            .buffer_line_for_row(old_head.row)
3520                        {
3521                            let indent_size =
3522                                buffer.indent_size_for_line(line_buffer_range.start.row);
3523                            let indent_len = match indent_size.kind {
3524                                IndentKind::Space => {
3525                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3526                                }
3527                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3528                            };
3529                            if old_head.column <= indent_size.len && old_head.column > 0 {
3530                                let indent_len = indent_len.get();
3531                                new_head = cmp::min(
3532                                    new_head,
3533                                    Point::new(
3534                                        old_head.row,
3535                                        ((old_head.column - 1) / indent_len) * indent_len,
3536                                    ),
3537                                );
3538                            }
3539                        }
3540
3541                        selection.set_head(new_head, SelectionGoal::None);
3542                    }
3543                }
3544            }
3545
3546            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3547            this.insert("", cx);
3548            this.refresh_copilot_suggestions(true, cx);
3549        });
3550    }
3551
3552    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3553        self.transact(cx, |this, cx| {
3554            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3555                let line_mode = s.line_mode;
3556                s.move_with(|map, selection| {
3557                    if selection.is_empty() && !line_mode {
3558                        let cursor = movement::right(map, selection.head());
3559                        selection.set_head(cursor, SelectionGoal::None);
3560                    }
3561                })
3562            });
3563            this.insert("", cx);
3564            this.refresh_copilot_suggestions(true, cx);
3565        });
3566    }
3567
3568    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3569        if self.move_to_prev_snippet_tabstop(cx) {
3570            return;
3571        }
3572
3573        self.outdent(&Outdent, cx);
3574    }
3575
3576    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3577        if self.move_to_next_snippet_tabstop(cx) {
3578            return;
3579        }
3580
3581        let mut selections = self.selections.all_adjusted(cx);
3582        let buffer = self.buffer.read(cx);
3583        let snapshot = buffer.snapshot(cx);
3584        let rows_iter = selections.iter().map(|s| s.head().row);
3585        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3586
3587        let mut edits = Vec::new();
3588        let mut prev_edited_row = 0;
3589        let mut row_delta = 0;
3590        for selection in &mut selections {
3591            if selection.start.row != prev_edited_row {
3592                row_delta = 0;
3593            }
3594            prev_edited_row = selection.end.row;
3595
3596            // If the selection is non-empty, then increase the indentation of the selected lines.
3597            if !selection.is_empty() {
3598                row_delta =
3599                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3600                continue;
3601            }
3602
3603            // If the selection is empty and the cursor is in the leading whitespace before the
3604            // suggested indentation, then auto-indent the line.
3605            let cursor = selection.head();
3606            let current_indent = snapshot.indent_size_for_line(cursor.row);
3607            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3608                if cursor.column < suggested_indent.len
3609                    && cursor.column <= current_indent.len
3610                    && current_indent.len <= suggested_indent.len
3611                {
3612                    selection.start = Point::new(cursor.row, suggested_indent.len);
3613                    selection.end = selection.start;
3614                    if row_delta == 0 {
3615                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3616                            cursor.row,
3617                            current_indent,
3618                            suggested_indent,
3619                        ));
3620                        row_delta = suggested_indent.len - current_indent.len;
3621                    }
3622                    continue;
3623                }
3624            }
3625
3626            // Accept copilot suggestion if there is only one selection and the cursor is not
3627            // in the leading whitespace.
3628            if self.selections.count() == 1
3629                && cursor.column >= current_indent.len
3630                && self.has_active_copilot_suggestion(cx)
3631            {
3632                self.accept_copilot_suggestion(cx);
3633                return;
3634            }
3635
3636            // Otherwise, insert a hard or soft tab.
3637            let settings = buffer.settings_at(cursor, cx);
3638            let tab_size = if settings.hard_tabs {
3639                IndentSize::tab()
3640            } else {
3641                let tab_size = settings.tab_size.get();
3642                let char_column = snapshot
3643                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3644                    .flat_map(str::chars)
3645                    .count()
3646                    + row_delta as usize;
3647                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3648                IndentSize::spaces(chars_to_next_tab_stop)
3649            };
3650            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3651            selection.end = selection.start;
3652            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3653            row_delta += tab_size.len;
3654        }
3655
3656        self.transact(cx, |this, cx| {
3657            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3658            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3659            this.refresh_copilot_suggestions(true, cx);
3660        });
3661    }
3662
3663    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3664        let mut selections = self.selections.all::<Point>(cx);
3665        let mut prev_edited_row = 0;
3666        let mut row_delta = 0;
3667        let mut edits = Vec::new();
3668        let buffer = self.buffer.read(cx);
3669        let snapshot = buffer.snapshot(cx);
3670        for selection in &mut selections {
3671            if selection.start.row != prev_edited_row {
3672                row_delta = 0;
3673            }
3674            prev_edited_row = selection.end.row;
3675
3676            row_delta =
3677                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3678        }
3679
3680        self.transact(cx, |this, cx| {
3681            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3682            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3683        });
3684    }
3685
3686    fn indent_selection(
3687        buffer: &MultiBuffer,
3688        snapshot: &MultiBufferSnapshot,
3689        selection: &mut Selection<Point>,
3690        edits: &mut Vec<(Range<Point>, String)>,
3691        delta_for_start_row: u32,
3692        cx: &AppContext,
3693    ) -> u32 {
3694        let settings = buffer.settings_at(selection.start, cx);
3695        let tab_size = settings.tab_size.get();
3696        let indent_kind = if settings.hard_tabs {
3697            IndentKind::Tab
3698        } else {
3699            IndentKind::Space
3700        };
3701        let mut start_row = selection.start.row;
3702        let mut end_row = selection.end.row + 1;
3703
3704        // If a selection ends at the beginning of a line, don't indent
3705        // that last line.
3706        if selection.end.column == 0 {
3707            end_row -= 1;
3708        }
3709
3710        // Avoid re-indenting a row that has already been indented by a
3711        // previous selection, but still update this selection's column
3712        // to reflect that indentation.
3713        if delta_for_start_row > 0 {
3714            start_row += 1;
3715            selection.start.column += delta_for_start_row;
3716            if selection.end.row == selection.start.row {
3717                selection.end.column += delta_for_start_row;
3718            }
3719        }
3720
3721        let mut delta_for_end_row = 0;
3722        for row in start_row..end_row {
3723            let current_indent = snapshot.indent_size_for_line(row);
3724            let indent_delta = match (current_indent.kind, indent_kind) {
3725                (IndentKind::Space, IndentKind::Space) => {
3726                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3727                    IndentSize::spaces(columns_to_next_tab_stop)
3728                }
3729                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3730                (_, IndentKind::Tab) => IndentSize::tab(),
3731            };
3732
3733            let row_start = Point::new(row, 0);
3734            edits.push((
3735                row_start..row_start,
3736                indent_delta.chars().collect::<String>(),
3737            ));
3738
3739            // Update this selection's endpoints to reflect the indentation.
3740            if row == selection.start.row {
3741                selection.start.column += indent_delta.len;
3742            }
3743            if row == selection.end.row {
3744                selection.end.column += indent_delta.len;
3745                delta_for_end_row = indent_delta.len;
3746            }
3747        }
3748
3749        if selection.start.row == selection.end.row {
3750            delta_for_start_row + delta_for_end_row
3751        } else {
3752            delta_for_end_row
3753        }
3754    }
3755
3756    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3757        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3758        let selections = self.selections.all::<Point>(cx);
3759        let mut deletion_ranges = Vec::new();
3760        let mut last_outdent = None;
3761        {
3762            let buffer = self.buffer.read(cx);
3763            let snapshot = buffer.snapshot(cx);
3764            for selection in &selections {
3765                let settings = buffer.settings_at(selection.start, cx);
3766                let tab_size = settings.tab_size.get();
3767                let mut rows = selection.spanned_rows(false, &display_map);
3768
3769                // Avoid re-outdenting a row that has already been outdented by a
3770                // previous selection.
3771                if let Some(last_row) = last_outdent {
3772                    if last_row == rows.start {
3773                        rows.start += 1;
3774                    }
3775                }
3776
3777                for row in rows {
3778                    let indent_size = snapshot.indent_size_for_line(row);
3779                    if indent_size.len > 0 {
3780                        let deletion_len = match indent_size.kind {
3781                            IndentKind::Space => {
3782                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3783                                if columns_to_prev_tab_stop == 0 {
3784                                    tab_size
3785                                } else {
3786                                    columns_to_prev_tab_stop
3787                                }
3788                            }
3789                            IndentKind::Tab => 1,
3790                        };
3791                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3792                        last_outdent = Some(row);
3793                    }
3794                }
3795            }
3796        }
3797
3798        self.transact(cx, |this, cx| {
3799            this.buffer.update(cx, |buffer, cx| {
3800                let empty_str: Arc<str> = "".into();
3801                buffer.edit(
3802                    deletion_ranges
3803                        .into_iter()
3804                        .map(|range| (range, empty_str.clone())),
3805                    None,
3806                    cx,
3807                );
3808            });
3809            let selections = this.selections.all::<usize>(cx);
3810            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3811        });
3812    }
3813
3814    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3815        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3816        let selections = self.selections.all::<Point>(cx);
3817
3818        let mut new_cursors = Vec::new();
3819        let mut edit_ranges = Vec::new();
3820        let mut selections = selections.iter().peekable();
3821        while let Some(selection) = selections.next() {
3822            let mut rows = selection.spanned_rows(false, &display_map);
3823            let goal_display_column = selection.head().to_display_point(&display_map).column();
3824
3825            // Accumulate contiguous regions of rows that we want to delete.
3826            while let Some(next_selection) = selections.peek() {
3827                let next_rows = next_selection.spanned_rows(false, &display_map);
3828                if next_rows.start <= rows.end {
3829                    rows.end = next_rows.end;
3830                    selections.next().unwrap();
3831                } else {
3832                    break;
3833                }
3834            }
3835
3836            let buffer = &display_map.buffer_snapshot;
3837            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3838            let edit_end;
3839            let cursor_buffer_row;
3840            if buffer.max_point().row >= rows.end {
3841                // If there's a line after the range, delete the \n from the end of the row range
3842                // and position the cursor on the next line.
3843                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3844                cursor_buffer_row = rows.end;
3845            } else {
3846                // If there isn't a line after the range, delete the \n from the line before the
3847                // start of the row range and position the cursor there.
3848                edit_start = edit_start.saturating_sub(1);
3849                edit_end = buffer.len();
3850                cursor_buffer_row = rows.start.saturating_sub(1);
3851            }
3852
3853            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3854            *cursor.column_mut() =
3855                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3856
3857            new_cursors.push((
3858                selection.id,
3859                buffer.anchor_after(cursor.to_point(&display_map)),
3860            ));
3861            edit_ranges.push(edit_start..edit_end);
3862        }
3863
3864        self.transact(cx, |this, cx| {
3865            let buffer = this.buffer.update(cx, |buffer, cx| {
3866                let empty_str: Arc<str> = "".into();
3867                buffer.edit(
3868                    edit_ranges
3869                        .into_iter()
3870                        .map(|range| (range, empty_str.clone())),
3871                    None,
3872                    cx,
3873                );
3874                buffer.snapshot(cx)
3875            });
3876            let new_selections = new_cursors
3877                .into_iter()
3878                .map(|(id, cursor)| {
3879                    let cursor = cursor.to_point(&buffer);
3880                    Selection {
3881                        id,
3882                        start: cursor,
3883                        end: cursor,
3884                        reversed: false,
3885                        goal: SelectionGoal::None,
3886                    }
3887                })
3888                .collect();
3889
3890            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3891                s.select(new_selections);
3892            });
3893        });
3894    }
3895
3896    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3897        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3898        let buffer = &display_map.buffer_snapshot;
3899        let selections = self.selections.all::<Point>(cx);
3900
3901        let mut edits = Vec::new();
3902        let mut selections_iter = selections.iter().peekable();
3903        while let Some(selection) = selections_iter.next() {
3904            // Avoid duplicating the same lines twice.
3905            let mut rows = selection.spanned_rows(false, &display_map);
3906
3907            while let Some(next_selection) = selections_iter.peek() {
3908                let next_rows = next_selection.spanned_rows(false, &display_map);
3909                if next_rows.start < rows.end {
3910                    rows.end = next_rows.end;
3911                    selections_iter.next().unwrap();
3912                } else {
3913                    break;
3914                }
3915            }
3916
3917            // Copy the text from the selected row region and splice it at the start of the region.
3918            let start = Point::new(rows.start, 0);
3919            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3920            let text = buffer
3921                .text_for_range(start..end)
3922                .chain(Some("\n"))
3923                .collect::<String>();
3924            edits.push((start..start, text));
3925        }
3926
3927        self.transact(cx, |this, cx| {
3928            this.buffer.update(cx, |buffer, cx| {
3929                buffer.edit(edits, None, cx);
3930            });
3931
3932            this.request_autoscroll(Autoscroll::fit(), cx);
3933        });
3934    }
3935
3936    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3937        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3938        let buffer = self.buffer.read(cx).snapshot(cx);
3939
3940        let mut edits = Vec::new();
3941        let mut unfold_ranges = Vec::new();
3942        let mut refold_ranges = Vec::new();
3943
3944        let selections = self.selections.all::<Point>(cx);
3945        let mut selections = selections.iter().peekable();
3946        let mut contiguous_row_selections = Vec::new();
3947        let mut new_selections = Vec::new();
3948
3949        while let Some(selection) = selections.next() {
3950            // Find all the selections that span a contiguous row range
3951            let (start_row, end_row) = consume_contiguous_rows(
3952                &mut contiguous_row_selections,
3953                selection,
3954                &display_map,
3955                &mut selections,
3956            );
3957
3958            // Move the text spanned by the row range to be before the line preceding the row range
3959            if start_row > 0 {
3960                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3961                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3962                let insertion_point = display_map
3963                    .prev_line_boundary(Point::new(start_row - 1, 0))
3964                    .0;
3965
3966                // Don't move lines across excerpts
3967                if buffer
3968                    .excerpt_boundaries_in_range((
3969                        Bound::Excluded(insertion_point),
3970                        Bound::Included(range_to_move.end),
3971                    ))
3972                    .next()
3973                    .is_none()
3974                {
3975                    let text = buffer
3976                        .text_for_range(range_to_move.clone())
3977                        .flat_map(|s| s.chars())
3978                        .skip(1)
3979                        .chain(['\n'])
3980                        .collect::<String>();
3981
3982                    edits.push((
3983                        buffer.anchor_after(range_to_move.start)
3984                            ..buffer.anchor_before(range_to_move.end),
3985                        String::new(),
3986                    ));
3987                    let insertion_anchor = buffer.anchor_after(insertion_point);
3988                    edits.push((insertion_anchor..insertion_anchor, text));
3989
3990                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3991
3992                    // Move selections up
3993                    new_selections.extend(contiguous_row_selections.drain(..).map(
3994                        |mut selection| {
3995                            selection.start.row -= row_delta;
3996                            selection.end.row -= row_delta;
3997                            selection
3998                        },
3999                    ));
4000
4001                    // Move folds up
4002                    unfold_ranges.push(range_to_move.clone());
4003                    for fold in display_map.folds_in_range(
4004                        buffer.anchor_before(range_to_move.start)
4005                            ..buffer.anchor_after(range_to_move.end),
4006                    ) {
4007                        let mut start = fold.start.to_point(&buffer);
4008                        let mut end = fold.end.to_point(&buffer);
4009                        start.row -= row_delta;
4010                        end.row -= row_delta;
4011                        refold_ranges.push(start..end);
4012                    }
4013                }
4014            }
4015
4016            // If we didn't move line(s), preserve the existing selections
4017            new_selections.append(&mut contiguous_row_selections);
4018        }
4019
4020        self.transact(cx, |this, cx| {
4021            this.unfold_ranges(unfold_ranges, true, true, cx);
4022            this.buffer.update(cx, |buffer, cx| {
4023                for (range, text) in edits {
4024                    buffer.edit([(range, text)], None, cx);
4025                }
4026            });
4027            this.fold_ranges(refold_ranges, true, cx);
4028            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4029                s.select(new_selections);
4030            })
4031        });
4032    }
4033
4034    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4035        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4036        let buffer = self.buffer.read(cx).snapshot(cx);
4037
4038        let mut edits = Vec::new();
4039        let mut unfold_ranges = Vec::new();
4040        let mut refold_ranges = Vec::new();
4041
4042        let selections = self.selections.all::<Point>(cx);
4043        let mut selections = selections.iter().peekable();
4044        let mut contiguous_row_selections = Vec::new();
4045        let mut new_selections = Vec::new();
4046
4047        while let Some(selection) = selections.next() {
4048            // Find all the selections that span a contiguous row range
4049            let (start_row, end_row) = consume_contiguous_rows(
4050                &mut contiguous_row_selections,
4051                selection,
4052                &display_map,
4053                &mut selections,
4054            );
4055
4056            // Move the text spanned by the row range to be after the last line of the row range
4057            if end_row <= buffer.max_point().row {
4058                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4059                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4060
4061                // Don't move lines across excerpt boundaries
4062                if buffer
4063                    .excerpt_boundaries_in_range((
4064                        Bound::Excluded(range_to_move.start),
4065                        Bound::Included(insertion_point),
4066                    ))
4067                    .next()
4068                    .is_none()
4069                {
4070                    let mut text = String::from("\n");
4071                    text.extend(buffer.text_for_range(range_to_move.clone()));
4072                    text.pop(); // Drop trailing newline
4073                    edits.push((
4074                        buffer.anchor_after(range_to_move.start)
4075                            ..buffer.anchor_before(range_to_move.end),
4076                        String::new(),
4077                    ));
4078                    let insertion_anchor = buffer.anchor_after(insertion_point);
4079                    edits.push((insertion_anchor..insertion_anchor, text));
4080
4081                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4082
4083                    // Move selections down
4084                    new_selections.extend(contiguous_row_selections.drain(..).map(
4085                        |mut selection| {
4086                            selection.start.row += row_delta;
4087                            selection.end.row += row_delta;
4088                            selection
4089                        },
4090                    ));
4091
4092                    // Move folds down
4093                    unfold_ranges.push(range_to_move.clone());
4094                    for fold in display_map.folds_in_range(
4095                        buffer.anchor_before(range_to_move.start)
4096                            ..buffer.anchor_after(range_to_move.end),
4097                    ) {
4098                        let mut start = fold.start.to_point(&buffer);
4099                        let mut end = fold.end.to_point(&buffer);
4100                        start.row += row_delta;
4101                        end.row += row_delta;
4102                        refold_ranges.push(start..end);
4103                    }
4104                }
4105            }
4106
4107            // If we didn't move line(s), preserve the existing selections
4108            new_selections.append(&mut contiguous_row_selections);
4109        }
4110
4111        self.transact(cx, |this, cx| {
4112            this.unfold_ranges(unfold_ranges, true, true, cx);
4113            this.buffer.update(cx, |buffer, cx| {
4114                for (range, text) in edits {
4115                    buffer.edit([(range, text)], None, cx);
4116                }
4117            });
4118            this.fold_ranges(refold_ranges, true, cx);
4119            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4120        });
4121    }
4122
4123    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4124        self.transact(cx, |this, cx| {
4125            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4126                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4127                let line_mode = s.line_mode;
4128                s.move_with(|display_map, selection| {
4129                    if !selection.is_empty() || line_mode {
4130                        return;
4131                    }
4132
4133                    let mut head = selection.head();
4134                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4135                    if head.column() == display_map.line_len(head.row()) {
4136                        transpose_offset = display_map
4137                            .buffer_snapshot
4138                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4139                    }
4140
4141                    if transpose_offset == 0 {
4142                        return;
4143                    }
4144
4145                    *head.column_mut() += 1;
4146                    head = display_map.clip_point(head, Bias::Right);
4147                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4148
4149                    let transpose_start = display_map
4150                        .buffer_snapshot
4151                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4152                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4153                        let transpose_end = display_map
4154                            .buffer_snapshot
4155                            .clip_offset(transpose_offset + 1, Bias::Right);
4156                        if let Some(ch) =
4157                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4158                        {
4159                            edits.push((transpose_start..transpose_offset, String::new()));
4160                            edits.push((transpose_end..transpose_end, ch.to_string()));
4161                        }
4162                    }
4163                });
4164                edits
4165            });
4166            this.buffer
4167                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4168            let selections = this.selections.all::<usize>(cx);
4169            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4170                s.select(selections);
4171            });
4172        });
4173    }
4174
4175    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4176        let mut text = String::new();
4177        let buffer = self.buffer.read(cx).snapshot(cx);
4178        let mut selections = self.selections.all::<Point>(cx);
4179        let mut clipboard_selections = Vec::with_capacity(selections.len());
4180        {
4181            let max_point = buffer.max_point();
4182            for selection in &mut selections {
4183                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4184                if is_entire_line {
4185                    selection.start = Point::new(selection.start.row, 0);
4186                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4187                    selection.goal = SelectionGoal::None;
4188                }
4189                let mut len = 0;
4190                for chunk in buffer.text_for_range(selection.start..selection.end) {
4191                    text.push_str(chunk);
4192                    len += chunk.len();
4193                }
4194                clipboard_selections.push(ClipboardSelection {
4195                    len,
4196                    is_entire_line,
4197                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4198                });
4199            }
4200        }
4201
4202        self.transact(cx, |this, cx| {
4203            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4204                s.select(selections);
4205            });
4206            this.insert("", cx);
4207            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4208        });
4209    }
4210
4211    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4212        let selections = self.selections.all::<Point>(cx);
4213        let buffer = self.buffer.read(cx).read(cx);
4214        let mut text = String::new();
4215
4216        let mut clipboard_selections = Vec::with_capacity(selections.len());
4217        {
4218            let max_point = buffer.max_point();
4219            for selection in selections.iter() {
4220                let mut start = selection.start;
4221                let mut end = selection.end;
4222                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4223                if is_entire_line {
4224                    start = Point::new(start.row, 0);
4225                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4226                }
4227                let mut len = 0;
4228                for chunk in buffer.text_for_range(start..end) {
4229                    text.push_str(chunk);
4230                    len += chunk.len();
4231                }
4232                clipboard_selections.push(ClipboardSelection {
4233                    len,
4234                    is_entire_line,
4235                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4236                });
4237            }
4238        }
4239
4240        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4241    }
4242
4243    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4244        self.transact(cx, |this, cx| {
4245            if let Some(item) = cx.read_from_clipboard() {
4246                let mut clipboard_text = Cow::Borrowed(item.text());
4247                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4248                    let old_selections = this.selections.all::<usize>(cx);
4249                    let all_selections_were_entire_line =
4250                        clipboard_selections.iter().all(|s| s.is_entire_line);
4251                    let first_selection_indent_column =
4252                        clipboard_selections.first().map(|s| s.first_line_indent);
4253                    if clipboard_selections.len() != old_selections.len() {
4254                        let mut newline_separated_text = String::new();
4255                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4256                        let mut ix = 0;
4257                        while let Some(clipboard_selection) = clipboard_selections.next() {
4258                            newline_separated_text
4259                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4260                            ix += clipboard_selection.len;
4261                            if clipboard_selections.peek().is_some() {
4262                                newline_separated_text.push('\n');
4263                            }
4264                        }
4265                        clipboard_text = Cow::Owned(newline_separated_text);
4266                    }
4267
4268                    this.buffer.update(cx, |buffer, cx| {
4269                        let snapshot = buffer.read(cx);
4270                        let mut start_offset = 0;
4271                        let mut edits = Vec::new();
4272                        let mut original_indent_columns = Vec::new();
4273                        let line_mode = this.selections.line_mode;
4274                        for (ix, selection) in old_selections.iter().enumerate() {
4275                            let to_insert;
4276                            let entire_line;
4277                            let original_indent_column;
4278                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4279                                let end_offset = start_offset + clipboard_selection.len;
4280                                to_insert = &clipboard_text[start_offset..end_offset];
4281                                entire_line = clipboard_selection.is_entire_line;
4282                                start_offset = end_offset;
4283                                original_indent_column =
4284                                    Some(clipboard_selection.first_line_indent);
4285                            } else {
4286                                to_insert = clipboard_text.as_str();
4287                                entire_line = all_selections_were_entire_line;
4288                                original_indent_column = first_selection_indent_column
4289                            }
4290
4291                            // If the corresponding selection was empty when this slice of the
4292                            // clipboard text was written, then the entire line containing the
4293                            // selection was copied. If this selection is also currently empty,
4294                            // then paste the line before the current line of the buffer.
4295                            let range = if selection.is_empty() && !line_mode && entire_line {
4296                                let column = selection.start.to_point(&snapshot).column as usize;
4297                                let line_start = selection.start - column;
4298                                line_start..line_start
4299                            } else {
4300                                selection.range()
4301                            };
4302
4303                            edits.push((range, to_insert));
4304                            original_indent_columns.extend(original_indent_column);
4305                        }
4306                        drop(snapshot);
4307
4308                        buffer.edit(
4309                            edits,
4310                            Some(AutoindentMode::Block {
4311                                original_indent_columns,
4312                            }),
4313                            cx,
4314                        );
4315                    });
4316
4317                    let selections = this.selections.all::<usize>(cx);
4318                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4319                } else {
4320                    this.insert(&clipboard_text, cx);
4321                }
4322            }
4323        });
4324    }
4325
4326    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4327        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4328            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4329                self.change_selections(None, cx, |s| {
4330                    s.select_anchors(selections.to_vec());
4331                });
4332            }
4333            self.request_autoscroll(Autoscroll::fit(), cx);
4334            self.unmark_text(cx);
4335            self.refresh_copilot_suggestions(true, cx);
4336            cx.emit(Event::Edited);
4337        }
4338    }
4339
4340    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4341        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4342            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4343            {
4344                self.change_selections(None, cx, |s| {
4345                    s.select_anchors(selections.to_vec());
4346                });
4347            }
4348            self.request_autoscroll(Autoscroll::fit(), cx);
4349            self.unmark_text(cx);
4350            self.refresh_copilot_suggestions(true, cx);
4351            cx.emit(Event::Edited);
4352        }
4353    }
4354
4355    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4356        self.buffer
4357            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4358    }
4359
4360    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4361        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4362            let line_mode = s.line_mode;
4363            s.move_with(|map, selection| {
4364                let cursor = if selection.is_empty() && !line_mode {
4365                    movement::left(map, selection.start)
4366                } else {
4367                    selection.start
4368                };
4369                selection.collapse_to(cursor, SelectionGoal::None);
4370            });
4371        })
4372    }
4373
4374    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4375        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4376            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4377        })
4378    }
4379
4380    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4381        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4382            let line_mode = s.line_mode;
4383            s.move_with(|map, selection| {
4384                let cursor = if selection.is_empty() && !line_mode {
4385                    movement::right(map, selection.end)
4386                } else {
4387                    selection.end
4388                };
4389                selection.collapse_to(cursor, SelectionGoal::None)
4390            });
4391        })
4392    }
4393
4394    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4395        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4396            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4397        })
4398    }
4399
4400    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4401        if self.take_rename(true, cx).is_some() {
4402            return;
4403        }
4404
4405        if let Some(context_menu) = self.context_menu.as_mut() {
4406            if context_menu.select_prev(cx) {
4407                return;
4408            }
4409        }
4410
4411        if matches!(self.mode, EditorMode::SingleLine) {
4412            cx.propagate_action();
4413            return;
4414        }
4415
4416        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4417            let line_mode = s.line_mode;
4418            s.move_with(|map, selection| {
4419                if !selection.is_empty() && !line_mode {
4420                    selection.goal = SelectionGoal::None;
4421                }
4422                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4423                selection.collapse_to(cursor, goal);
4424            });
4425        })
4426    }
4427
4428    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4429        if self.take_rename(true, cx).is_some() {
4430            return;
4431        }
4432
4433        if self
4434            .context_menu
4435            .as_mut()
4436            .map(|menu| menu.select_first(cx))
4437            .unwrap_or(false)
4438        {
4439            return;
4440        }
4441
4442        if matches!(self.mode, EditorMode::SingleLine) {
4443            cx.propagate_action();
4444            return;
4445        }
4446
4447        let row_count = if let Some(row_count) = self.visible_line_count() {
4448            row_count as u32 - 1
4449        } else {
4450            return;
4451        };
4452
4453        let autoscroll = if action.center_cursor {
4454            Autoscroll::center()
4455        } else {
4456            Autoscroll::fit()
4457        };
4458
4459        self.change_selections(Some(autoscroll), cx, |s| {
4460            let line_mode = s.line_mode;
4461            s.move_with(|map, selection| {
4462                if !selection.is_empty() && !line_mode {
4463                    selection.goal = SelectionGoal::None;
4464                }
4465                let (cursor, goal) =
4466                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4467                selection.collapse_to(cursor, goal);
4468            });
4469        });
4470    }
4471
4472    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4473        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4474            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4475        })
4476    }
4477
4478    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4479        self.take_rename(true, cx);
4480
4481        if let Some(context_menu) = self.context_menu.as_mut() {
4482            if context_menu.select_next(cx) {
4483                return;
4484            }
4485        }
4486
4487        if self.mode == EditorMode::SingleLine {
4488            cx.propagate_action();
4489            return;
4490        }
4491
4492        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4493            let line_mode = s.line_mode;
4494            s.move_with(|map, selection| {
4495                if !selection.is_empty() && !line_mode {
4496                    selection.goal = SelectionGoal::None;
4497                }
4498                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4499                selection.collapse_to(cursor, goal);
4500            });
4501        });
4502    }
4503
4504    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4505        if self.take_rename(true, cx).is_some() {
4506            return;
4507        }
4508
4509        if self
4510            .context_menu
4511            .as_mut()
4512            .map(|menu| menu.select_last(cx))
4513            .unwrap_or(false)
4514        {
4515            return;
4516        }
4517
4518        if matches!(self.mode, EditorMode::SingleLine) {
4519            cx.propagate_action();
4520            return;
4521        }
4522
4523        let row_count = if let Some(row_count) = self.visible_line_count() {
4524            row_count as u32 - 1
4525        } else {
4526            return;
4527        };
4528
4529        let autoscroll = if action.center_cursor {
4530            Autoscroll::center()
4531        } else {
4532            Autoscroll::fit()
4533        };
4534
4535        self.change_selections(Some(autoscroll), cx, |s| {
4536            let line_mode = s.line_mode;
4537            s.move_with(|map, selection| {
4538                if !selection.is_empty() && !line_mode {
4539                    selection.goal = SelectionGoal::None;
4540                }
4541                let (cursor, goal) =
4542                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4543                selection.collapse_to(cursor, goal);
4544            });
4545        });
4546    }
4547
4548    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4549        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4550            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4551        });
4552    }
4553
4554    pub fn move_to_previous_word_start(
4555        &mut self,
4556        _: &MoveToPreviousWordStart,
4557        cx: &mut ViewContext<Self>,
4558    ) {
4559        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4560            s.move_cursors_with(|map, head, _| {
4561                (
4562                    movement::previous_word_start(map, head),
4563                    SelectionGoal::None,
4564                )
4565            });
4566        })
4567    }
4568
4569    pub fn move_to_previous_subword_start(
4570        &mut self,
4571        _: &MoveToPreviousSubwordStart,
4572        cx: &mut ViewContext<Self>,
4573    ) {
4574        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4575            s.move_cursors_with(|map, head, _| {
4576                (
4577                    movement::previous_subword_start(map, head),
4578                    SelectionGoal::None,
4579                )
4580            });
4581        })
4582    }
4583
4584    pub fn select_to_previous_word_start(
4585        &mut self,
4586        _: &SelectToPreviousWordStart,
4587        cx: &mut ViewContext<Self>,
4588    ) {
4589        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4590            s.move_heads_with(|map, head, _| {
4591                (
4592                    movement::previous_word_start(map, head),
4593                    SelectionGoal::None,
4594                )
4595            });
4596        })
4597    }
4598
4599    pub fn select_to_previous_subword_start(
4600        &mut self,
4601        _: &SelectToPreviousSubwordStart,
4602        cx: &mut ViewContext<Self>,
4603    ) {
4604        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4605            s.move_heads_with(|map, head, _| {
4606                (
4607                    movement::previous_subword_start(map, head),
4608                    SelectionGoal::None,
4609                )
4610            });
4611        })
4612    }
4613
4614    pub fn delete_to_previous_word_start(
4615        &mut self,
4616        _: &DeleteToPreviousWordStart,
4617        cx: &mut ViewContext<Self>,
4618    ) {
4619        self.transact(cx, |this, cx| {
4620            this.select_autoclose_pair(cx);
4621            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4622                let line_mode = s.line_mode;
4623                s.move_with(|map, selection| {
4624                    if selection.is_empty() && !line_mode {
4625                        let cursor = movement::previous_word_start(map, selection.head());
4626                        selection.set_head(cursor, SelectionGoal::None);
4627                    }
4628                });
4629            });
4630            this.insert("", cx);
4631        });
4632    }
4633
4634    pub fn delete_to_previous_subword_start(
4635        &mut self,
4636        _: &DeleteToPreviousSubwordStart,
4637        cx: &mut ViewContext<Self>,
4638    ) {
4639        self.transact(cx, |this, cx| {
4640            this.select_autoclose_pair(cx);
4641            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4642                let line_mode = s.line_mode;
4643                s.move_with(|map, selection| {
4644                    if selection.is_empty() && !line_mode {
4645                        let cursor = movement::previous_subword_start(map, selection.head());
4646                        selection.set_head(cursor, SelectionGoal::None);
4647                    }
4648                });
4649            });
4650            this.insert("", cx);
4651        });
4652    }
4653
4654    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4655        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4656            s.move_cursors_with(|map, head, _| {
4657                (movement::next_word_end(map, head), SelectionGoal::None)
4658            });
4659        })
4660    }
4661
4662    pub fn move_to_next_subword_end(
4663        &mut self,
4664        _: &MoveToNextSubwordEnd,
4665        cx: &mut ViewContext<Self>,
4666    ) {
4667        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4668            s.move_cursors_with(|map, head, _| {
4669                (movement::next_subword_end(map, head), SelectionGoal::None)
4670            });
4671        })
4672    }
4673
4674    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4675        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4676            s.move_heads_with(|map, head, _| {
4677                (movement::next_word_end(map, head), SelectionGoal::None)
4678            });
4679        })
4680    }
4681
4682    pub fn select_to_next_subword_end(
4683        &mut self,
4684        _: &SelectToNextSubwordEnd,
4685        cx: &mut ViewContext<Self>,
4686    ) {
4687        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4688            s.move_heads_with(|map, head, _| {
4689                (movement::next_subword_end(map, head), SelectionGoal::None)
4690            });
4691        })
4692    }
4693
4694    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4695        self.transact(cx, |this, cx| {
4696            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4697                let line_mode = s.line_mode;
4698                s.move_with(|map, selection| {
4699                    if selection.is_empty() && !line_mode {
4700                        let cursor = movement::next_word_end(map, selection.head());
4701                        selection.set_head(cursor, SelectionGoal::None);
4702                    }
4703                });
4704            });
4705            this.insert("", cx);
4706        });
4707    }
4708
4709    pub fn delete_to_next_subword_end(
4710        &mut self,
4711        _: &DeleteToNextSubwordEnd,
4712        cx: &mut ViewContext<Self>,
4713    ) {
4714        self.transact(cx, |this, cx| {
4715            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4716                s.move_with(|map, selection| {
4717                    if selection.is_empty() {
4718                        let cursor = movement::next_subword_end(map, selection.head());
4719                        selection.set_head(cursor, SelectionGoal::None);
4720                    }
4721                });
4722            });
4723            this.insert("", cx);
4724        });
4725    }
4726
4727    pub fn move_to_beginning_of_line(
4728        &mut self,
4729        _: &MoveToBeginningOfLine,
4730        cx: &mut ViewContext<Self>,
4731    ) {
4732        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4733            s.move_cursors_with(|map, head, _| {
4734                (
4735                    movement::indented_line_beginning(map, head, true),
4736                    SelectionGoal::None,
4737                )
4738            });
4739        })
4740    }
4741
4742    pub fn select_to_beginning_of_line(
4743        &mut self,
4744        action: &SelectToBeginningOfLine,
4745        cx: &mut ViewContext<Self>,
4746    ) {
4747        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4748            s.move_heads_with(|map, head, _| {
4749                (
4750                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4751                    SelectionGoal::None,
4752                )
4753            });
4754        });
4755    }
4756
4757    pub fn delete_to_beginning_of_line(
4758        &mut self,
4759        _: &DeleteToBeginningOfLine,
4760        cx: &mut ViewContext<Self>,
4761    ) {
4762        self.transact(cx, |this, cx| {
4763            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4764                s.move_with(|_, selection| {
4765                    selection.reversed = true;
4766                });
4767            });
4768
4769            this.select_to_beginning_of_line(
4770                &SelectToBeginningOfLine {
4771                    stop_at_soft_wraps: false,
4772                },
4773                cx,
4774            );
4775            this.backspace(&Backspace, cx);
4776        });
4777    }
4778
4779    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4780        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4781            s.move_cursors_with(|map, head, _| {
4782                (movement::line_end(map, head, true), SelectionGoal::None)
4783            });
4784        })
4785    }
4786
4787    pub fn select_to_end_of_line(
4788        &mut self,
4789        action: &SelectToEndOfLine,
4790        cx: &mut ViewContext<Self>,
4791    ) {
4792        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4793            s.move_heads_with(|map, head, _| {
4794                (
4795                    movement::line_end(map, head, action.stop_at_soft_wraps),
4796                    SelectionGoal::None,
4797                )
4798            });
4799        })
4800    }
4801
4802    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4803        self.transact(cx, |this, cx| {
4804            this.select_to_end_of_line(
4805                &SelectToEndOfLine {
4806                    stop_at_soft_wraps: false,
4807                },
4808                cx,
4809            );
4810            this.delete(&Delete, cx);
4811        });
4812    }
4813
4814    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4815        self.transact(cx, |this, cx| {
4816            this.select_to_end_of_line(
4817                &SelectToEndOfLine {
4818                    stop_at_soft_wraps: false,
4819                },
4820                cx,
4821            );
4822            this.cut(&Cut, cx);
4823        });
4824    }
4825
4826    pub fn move_to_start_of_paragraph(
4827        &mut self,
4828        _: &MoveToStartOfParagraph,
4829        cx: &mut ViewContext<Self>,
4830    ) {
4831        if matches!(self.mode, EditorMode::SingleLine) {
4832            cx.propagate_action();
4833            return;
4834        }
4835
4836        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4837            s.move_with(|map, selection| {
4838                selection.collapse_to(
4839                    movement::start_of_paragraph(map, selection.head()),
4840                    SelectionGoal::None,
4841                )
4842            });
4843        })
4844    }
4845
4846    pub fn move_to_end_of_paragraph(
4847        &mut self,
4848        _: &MoveToEndOfParagraph,
4849        cx: &mut ViewContext<Self>,
4850    ) {
4851        if matches!(self.mode, EditorMode::SingleLine) {
4852            cx.propagate_action();
4853            return;
4854        }
4855
4856        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4857            s.move_with(|map, selection| {
4858                selection.collapse_to(
4859                    movement::end_of_paragraph(map, selection.head()),
4860                    SelectionGoal::None,
4861                )
4862            });
4863        })
4864    }
4865
4866    pub fn select_to_start_of_paragraph(
4867        &mut self,
4868        _: &SelectToStartOfParagraph,
4869        cx: &mut ViewContext<Self>,
4870    ) {
4871        if matches!(self.mode, EditorMode::SingleLine) {
4872            cx.propagate_action();
4873            return;
4874        }
4875
4876        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4877            s.move_heads_with(|map, head, _| {
4878                (movement::start_of_paragraph(map, head), SelectionGoal::None)
4879            });
4880        })
4881    }
4882
4883    pub fn select_to_end_of_paragraph(
4884        &mut self,
4885        _: &SelectToEndOfParagraph,
4886        cx: &mut ViewContext<Self>,
4887    ) {
4888        if matches!(self.mode, EditorMode::SingleLine) {
4889            cx.propagate_action();
4890            return;
4891        }
4892
4893        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4894            s.move_heads_with(|map, head, _| {
4895                (movement::end_of_paragraph(map, head), SelectionGoal::None)
4896            });
4897        })
4898    }
4899
4900    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4901        if matches!(self.mode, EditorMode::SingleLine) {
4902            cx.propagate_action();
4903            return;
4904        }
4905
4906        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4907            s.select_ranges(vec![0..0]);
4908        });
4909    }
4910
4911    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4912        let mut selection = self.selections.last::<Point>(cx);
4913        selection.set_head(Point::zero(), SelectionGoal::None);
4914
4915        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4916            s.select(vec![selection]);
4917        });
4918    }
4919
4920    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4921        if matches!(self.mode, EditorMode::SingleLine) {
4922            cx.propagate_action();
4923            return;
4924        }
4925
4926        let cursor = self.buffer.read(cx).read(cx).len();
4927        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4928            s.select_ranges(vec![cursor..cursor])
4929        });
4930    }
4931
4932    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4933        self.nav_history = nav_history;
4934    }
4935
4936    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4937        self.nav_history.as_ref()
4938    }
4939
4940    fn push_to_nav_history(
4941        &mut self,
4942        cursor_anchor: Anchor,
4943        new_position: Option<Point>,
4944        cx: &mut ViewContext<Self>,
4945    ) {
4946        if let Some(nav_history) = self.nav_history.as_mut() {
4947            let buffer = self.buffer.read(cx).read(cx);
4948            let cursor_position = cursor_anchor.to_point(&buffer);
4949            let scroll_state = self.scroll_manager.anchor();
4950            let scroll_top_row = scroll_state.top_row(&buffer);
4951            drop(buffer);
4952
4953            if let Some(new_position) = new_position {
4954                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4955                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4956                    return;
4957                }
4958            }
4959
4960            nav_history.push(
4961                Some(NavigationData {
4962                    cursor_anchor,
4963                    cursor_position,
4964                    scroll_anchor: scroll_state,
4965                    scroll_top_row,
4966                }),
4967                cx,
4968            );
4969        }
4970    }
4971
4972    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4973        let buffer = self.buffer.read(cx).snapshot(cx);
4974        let mut selection = self.selections.first::<usize>(cx);
4975        selection.set_head(buffer.len(), SelectionGoal::None);
4976        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4977            s.select(vec![selection]);
4978        });
4979    }
4980
4981    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4982        let end = self.buffer.read(cx).read(cx).len();
4983        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4984            s.select_ranges(vec![0..end]);
4985        });
4986    }
4987
4988    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4989        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4990        let mut selections = self.selections.all::<Point>(cx);
4991        let max_point = display_map.buffer_snapshot.max_point();
4992        for selection in &mut selections {
4993            let rows = selection.spanned_rows(true, &display_map);
4994            selection.start = Point::new(rows.start, 0);
4995            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4996            selection.reversed = false;
4997        }
4998        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4999            s.select(selections);
5000        });
5001    }
5002
5003    pub fn split_selection_into_lines(
5004        &mut self,
5005        _: &SplitSelectionIntoLines,
5006        cx: &mut ViewContext<Self>,
5007    ) {
5008        let mut to_unfold = Vec::new();
5009        let mut new_selection_ranges = Vec::new();
5010        {
5011            let selections = self.selections.all::<Point>(cx);
5012            let buffer = self.buffer.read(cx).read(cx);
5013            for selection in selections {
5014                for row in selection.start.row..selection.end.row {
5015                    let cursor = Point::new(row, buffer.line_len(row));
5016                    new_selection_ranges.push(cursor..cursor);
5017                }
5018                new_selection_ranges.push(selection.end..selection.end);
5019                to_unfold.push(selection.start..selection.end);
5020            }
5021        }
5022        self.unfold_ranges(to_unfold, true, true, cx);
5023        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5024            s.select_ranges(new_selection_ranges);
5025        });
5026    }
5027
5028    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5029        self.add_selection(true, cx);
5030    }
5031
5032    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5033        self.add_selection(false, cx);
5034    }
5035
5036    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5037        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5038        let mut selections = self.selections.all::<Point>(cx);
5039        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5040            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5041            let range = oldest_selection.display_range(&display_map).sorted();
5042            let columns = cmp::min(range.start.column(), range.end.column())
5043                ..cmp::max(range.start.column(), range.end.column());
5044
5045            selections.clear();
5046            let mut stack = Vec::new();
5047            for row in range.start.row()..=range.end.row() {
5048                if let Some(selection) = self.selections.build_columnar_selection(
5049                    &display_map,
5050                    row,
5051                    &columns,
5052                    oldest_selection.reversed,
5053                ) {
5054                    stack.push(selection.id);
5055                    selections.push(selection);
5056                }
5057            }
5058
5059            if above {
5060                stack.reverse();
5061            }
5062
5063            AddSelectionsState { above, stack }
5064        });
5065
5066        let last_added_selection = *state.stack.last().unwrap();
5067        let mut new_selections = Vec::new();
5068        if above == state.above {
5069            let end_row = if above {
5070                0
5071            } else {
5072                display_map.max_point().row()
5073            };
5074
5075            'outer: for selection in selections {
5076                if selection.id == last_added_selection {
5077                    let range = selection.display_range(&display_map).sorted();
5078                    debug_assert_eq!(range.start.row(), range.end.row());
5079                    let mut row = range.start.row();
5080                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5081                    {
5082                        start..end
5083                    } else {
5084                        cmp::min(range.start.column(), range.end.column())
5085                            ..cmp::max(range.start.column(), range.end.column())
5086                    };
5087
5088                    while row != end_row {
5089                        if above {
5090                            row -= 1;
5091                        } else {
5092                            row += 1;
5093                        }
5094
5095                        if let Some(new_selection) = self.selections.build_columnar_selection(
5096                            &display_map,
5097                            row,
5098                            &columns,
5099                            selection.reversed,
5100                        ) {
5101                            state.stack.push(new_selection.id);
5102                            if above {
5103                                new_selections.push(new_selection);
5104                                new_selections.push(selection);
5105                            } else {
5106                                new_selections.push(selection);
5107                                new_selections.push(new_selection);
5108                            }
5109
5110                            continue 'outer;
5111                        }
5112                    }
5113                }
5114
5115                new_selections.push(selection);
5116            }
5117        } else {
5118            new_selections = selections;
5119            new_selections.retain(|s| s.id != last_added_selection);
5120            state.stack.pop();
5121        }
5122
5123        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5124            s.select(new_selections);
5125        });
5126        if state.stack.len() > 1 {
5127            self.add_selections_state = Some(state);
5128        }
5129    }
5130
5131    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5132        self.push_to_selection_history();
5133        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5134        let buffer = &display_map.buffer_snapshot;
5135        let mut selections = self.selections.all::<usize>(cx);
5136        if let Some(mut select_next_state) = self.select_next_state.take() {
5137            let query = &select_next_state.query;
5138            if !select_next_state.done {
5139                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5140                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5141                let mut next_selected_range = None;
5142
5143                let bytes_after_last_selection =
5144                    buffer.bytes_in_range(last_selection.end..buffer.len());
5145                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5146                let query_matches = query
5147                    .stream_find_iter(bytes_after_last_selection)
5148                    .map(|result| (last_selection.end, result))
5149                    .chain(
5150                        query
5151                            .stream_find_iter(bytes_before_first_selection)
5152                            .map(|result| (0, result)),
5153                    );
5154                for (start_offset, query_match) in query_matches {
5155                    let query_match = query_match.unwrap(); // can only fail due to I/O
5156                    let offset_range =
5157                        start_offset + query_match.start()..start_offset + query_match.end();
5158                    let display_range = offset_range.start.to_display_point(&display_map)
5159                        ..offset_range.end.to_display_point(&display_map);
5160
5161                    if !select_next_state.wordwise
5162                        || (!movement::is_inside_word(&display_map, display_range.start)
5163                            && !movement::is_inside_word(&display_map, display_range.end))
5164                    {
5165                        next_selected_range = Some(offset_range);
5166                        break;
5167                    }
5168                }
5169
5170                if let Some(next_selected_range) = next_selected_range {
5171                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5172                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5173                        if action.replace_newest {
5174                            s.delete(s.newest_anchor().id);
5175                        }
5176                        s.insert_range(next_selected_range);
5177                    });
5178                } else {
5179                    select_next_state.done = true;
5180                }
5181            }
5182
5183            self.select_next_state = Some(select_next_state);
5184        } else if selections.len() == 1 {
5185            let selection = selections.last_mut().unwrap();
5186            if selection.start == selection.end {
5187                let word_range = movement::surrounding_word(
5188                    &display_map,
5189                    selection.start.to_display_point(&display_map),
5190                );
5191                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5192                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5193                selection.goal = SelectionGoal::None;
5194                selection.reversed = false;
5195
5196                let query = buffer
5197                    .text_for_range(selection.start..selection.end)
5198                    .collect::<String>();
5199                let select_state = SelectNextState {
5200                    query: AhoCorasick::new_auto_configured(&[query]),
5201                    wordwise: true,
5202                    done: false,
5203                };
5204                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5205                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5206                    s.select(selections);
5207                });
5208                self.select_next_state = Some(select_state);
5209            } else {
5210                let query = buffer
5211                    .text_for_range(selection.start..selection.end)
5212                    .collect::<String>();
5213                self.select_next_state = Some(SelectNextState {
5214                    query: AhoCorasick::new_auto_configured(&[query]),
5215                    wordwise: false,
5216                    done: false,
5217                });
5218                self.select_next(action, cx);
5219            }
5220        }
5221    }
5222
5223    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5224        self.transact(cx, |this, cx| {
5225            let mut selections = this.selections.all::<Point>(cx);
5226            let mut edits = Vec::new();
5227            let mut selection_edit_ranges = Vec::new();
5228            let mut last_toggled_row = None;
5229            let snapshot = this.buffer.read(cx).read(cx);
5230            let empty_str: Arc<str> = "".into();
5231            let mut suffixes_inserted = Vec::new();
5232
5233            fn comment_prefix_range(
5234                snapshot: &MultiBufferSnapshot,
5235                row: u32,
5236                comment_prefix: &str,
5237                comment_prefix_whitespace: &str,
5238            ) -> Range<Point> {
5239                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5240
5241                let mut line_bytes = snapshot
5242                    .bytes_in_range(start..snapshot.max_point())
5243                    .flatten()
5244                    .copied();
5245
5246                // If this line currently begins with the line comment prefix, then record
5247                // the range containing the prefix.
5248                if line_bytes
5249                    .by_ref()
5250                    .take(comment_prefix.len())
5251                    .eq(comment_prefix.bytes())
5252                {
5253                    // Include any whitespace that matches the comment prefix.
5254                    let matching_whitespace_len = line_bytes
5255                        .zip(comment_prefix_whitespace.bytes())
5256                        .take_while(|(a, b)| a == b)
5257                        .count() as u32;
5258                    let end = Point::new(
5259                        start.row,
5260                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5261                    );
5262                    start..end
5263                } else {
5264                    start..start
5265                }
5266            }
5267
5268            fn comment_suffix_range(
5269                snapshot: &MultiBufferSnapshot,
5270                row: u32,
5271                comment_suffix: &str,
5272                comment_suffix_has_leading_space: bool,
5273            ) -> Range<Point> {
5274                let end = Point::new(row, snapshot.line_len(row));
5275                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5276
5277                let mut line_end_bytes = snapshot
5278                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5279                    .flatten()
5280                    .copied();
5281
5282                let leading_space_len = if suffix_start_column > 0
5283                    && line_end_bytes.next() == Some(b' ')
5284                    && comment_suffix_has_leading_space
5285                {
5286                    1
5287                } else {
5288                    0
5289                };
5290
5291                // If this line currently begins with the line comment prefix, then record
5292                // the range containing the prefix.
5293                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5294                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5295                    start..end
5296                } else {
5297                    end..end
5298                }
5299            }
5300
5301            // TODO: Handle selections that cross excerpts
5302            for selection in &mut selections {
5303                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5304                let language = if let Some(language) =
5305                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5306                {
5307                    language
5308                } else {
5309                    continue;
5310                };
5311
5312                selection_edit_ranges.clear();
5313
5314                // If multiple selections contain a given row, avoid processing that
5315                // row more than once.
5316                let mut start_row = selection.start.row;
5317                if last_toggled_row == Some(start_row) {
5318                    start_row += 1;
5319                }
5320                let end_row =
5321                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5322                        selection.end.row - 1
5323                    } else {
5324                        selection.end.row
5325                    };
5326                last_toggled_row = Some(end_row);
5327
5328                if start_row > end_row {
5329                    continue;
5330                }
5331
5332                // If the language has line comments, toggle those.
5333                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5334                    // Split the comment prefix's trailing whitespace into a separate string,
5335                    // as that portion won't be used for detecting if a line is a comment.
5336                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5337                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5338                    let mut all_selection_lines_are_comments = true;
5339
5340                    for row in start_row..=end_row {
5341                        if snapshot.is_line_blank(row) {
5342                            continue;
5343                        }
5344
5345                        let prefix_range = comment_prefix_range(
5346                            snapshot.deref(),
5347                            row,
5348                            comment_prefix,
5349                            comment_prefix_whitespace,
5350                        );
5351                        if prefix_range.is_empty() {
5352                            all_selection_lines_are_comments = false;
5353                        }
5354                        selection_edit_ranges.push(prefix_range);
5355                    }
5356
5357                    if all_selection_lines_are_comments {
5358                        edits.extend(
5359                            selection_edit_ranges
5360                                .iter()
5361                                .cloned()
5362                                .map(|range| (range, empty_str.clone())),
5363                        );
5364                    } else {
5365                        let min_column = selection_edit_ranges
5366                            .iter()
5367                            .map(|r| r.start.column)
5368                            .min()
5369                            .unwrap_or(0);
5370                        edits.extend(selection_edit_ranges.iter().map(|range| {
5371                            let position = Point::new(range.start.row, min_column);
5372                            (position..position, full_comment_prefix.clone())
5373                        }));
5374                    }
5375                } else if let Some((full_comment_prefix, comment_suffix)) =
5376                    language.block_comment_delimiters()
5377                {
5378                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5379                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5380                    let prefix_range = comment_prefix_range(
5381                        snapshot.deref(),
5382                        start_row,
5383                        comment_prefix,
5384                        comment_prefix_whitespace,
5385                    );
5386                    let suffix_range = comment_suffix_range(
5387                        snapshot.deref(),
5388                        end_row,
5389                        comment_suffix.trim_start_matches(' '),
5390                        comment_suffix.starts_with(' '),
5391                    );
5392
5393                    if prefix_range.is_empty() || suffix_range.is_empty() {
5394                        edits.push((
5395                            prefix_range.start..prefix_range.start,
5396                            full_comment_prefix.clone(),
5397                        ));
5398                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5399                        suffixes_inserted.push((end_row, comment_suffix.len()));
5400                    } else {
5401                        edits.push((prefix_range, empty_str.clone()));
5402                        edits.push((suffix_range, empty_str.clone()));
5403                    }
5404                } else {
5405                    continue;
5406                }
5407            }
5408
5409            drop(snapshot);
5410            this.buffer.update(cx, |buffer, cx| {
5411                buffer.edit(edits, None, cx);
5412            });
5413
5414            // Adjust selections so that they end before any comment suffixes that
5415            // were inserted.
5416            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5417            let mut selections = this.selections.all::<Point>(cx);
5418            let snapshot = this.buffer.read(cx).read(cx);
5419            for selection in &mut selections {
5420                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5421                    match row.cmp(&selection.end.row) {
5422                        Ordering::Less => {
5423                            suffixes_inserted.next();
5424                            continue;
5425                        }
5426                        Ordering::Greater => break,
5427                        Ordering::Equal => {
5428                            if selection.end.column == snapshot.line_len(row) {
5429                                if selection.is_empty() {
5430                                    selection.start.column -= suffix_len as u32;
5431                                }
5432                                selection.end.column -= suffix_len as u32;
5433                            }
5434                            break;
5435                        }
5436                    }
5437                }
5438            }
5439
5440            drop(snapshot);
5441            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5442
5443            let selections = this.selections.all::<Point>(cx);
5444            let selections_on_single_row = selections.windows(2).all(|selections| {
5445                selections[0].start.row == selections[1].start.row
5446                    && selections[0].end.row == selections[1].end.row
5447                    && selections[0].start.row == selections[0].end.row
5448            });
5449            let selections_selecting = selections
5450                .iter()
5451                .any(|selection| selection.start != selection.end);
5452            let advance_downwards = action.advance_downwards
5453                && selections_on_single_row
5454                && !selections_selecting
5455                && this.mode != EditorMode::SingleLine;
5456
5457            if advance_downwards {
5458                let snapshot = this.buffer.read(cx).snapshot(cx);
5459
5460                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5461                    s.move_cursors_with(|display_snapshot, display_point, _| {
5462                        let mut point = display_point.to_point(display_snapshot);
5463                        point.row += 1;
5464                        point = snapshot.clip_point(point, Bias::Left);
5465                        let display_point = point.to_display_point(display_snapshot);
5466                        (display_point, SelectionGoal::Column(display_point.column()))
5467                    })
5468                });
5469            }
5470        });
5471    }
5472
5473    pub fn select_larger_syntax_node(
5474        &mut self,
5475        _: &SelectLargerSyntaxNode,
5476        cx: &mut ViewContext<Self>,
5477    ) {
5478        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5479        let buffer = self.buffer.read(cx).snapshot(cx);
5480        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5481
5482        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5483        let mut selected_larger_node = false;
5484        let new_selections = old_selections
5485            .iter()
5486            .map(|selection| {
5487                let old_range = selection.start..selection.end;
5488                let mut new_range = old_range.clone();
5489                while let Some(containing_range) =
5490                    buffer.range_for_syntax_ancestor(new_range.clone())
5491                {
5492                    new_range = containing_range;
5493                    if !display_map.intersects_fold(new_range.start)
5494                        && !display_map.intersects_fold(new_range.end)
5495                    {
5496                        break;
5497                    }
5498                }
5499
5500                selected_larger_node |= new_range != old_range;
5501                Selection {
5502                    id: selection.id,
5503                    start: new_range.start,
5504                    end: new_range.end,
5505                    goal: SelectionGoal::None,
5506                    reversed: selection.reversed,
5507                }
5508            })
5509            .collect::<Vec<_>>();
5510
5511        if selected_larger_node {
5512            stack.push(old_selections);
5513            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5514                s.select(new_selections);
5515            });
5516        }
5517        self.select_larger_syntax_node_stack = stack;
5518    }
5519
5520    pub fn select_smaller_syntax_node(
5521        &mut self,
5522        _: &SelectSmallerSyntaxNode,
5523        cx: &mut ViewContext<Self>,
5524    ) {
5525        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5526        if let Some(selections) = stack.pop() {
5527            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5528                s.select(selections.to_vec());
5529            });
5530        }
5531        self.select_larger_syntax_node_stack = stack;
5532    }
5533
5534    pub fn move_to_enclosing_bracket(
5535        &mut self,
5536        _: &MoveToEnclosingBracket,
5537        cx: &mut ViewContext<Self>,
5538    ) {
5539        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5540            s.move_offsets_with(|snapshot, selection| {
5541                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5542                    return;
5543                };
5544
5545                let mut best_length = usize::MAX;
5546                let mut best_inside = false;
5547                let mut best_in_bracket_range = false;
5548                let mut best_destination = None;
5549                for (open, close) in enclosing_bracket_ranges {
5550                    let close = close.to_inclusive();
5551                    let length = close.end() - open.start;
5552                    let inside = selection.start >= open.end && selection.end <= *close.start();
5553                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5554
5555                    // If best is next to a bracket and current isn't, skip
5556                    if !in_bracket_range && best_in_bracket_range {
5557                        continue;
5558                    }
5559
5560                    // Prefer smaller lengths unless best is inside and current isn't
5561                    if length > best_length && (best_inside || !inside) {
5562                        continue;
5563                    }
5564
5565                    best_length = length;
5566                    best_inside = inside;
5567                    best_in_bracket_range = in_bracket_range;
5568                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5569                        if inside {
5570                            open.end
5571                        } else {
5572                            open.start
5573                        }
5574                    } else {
5575                        if inside {
5576                            *close.start()
5577                        } else {
5578                            *close.end()
5579                        }
5580                    });
5581                }
5582
5583                if let Some(destination) = best_destination {
5584                    selection.collapse_to(destination, SelectionGoal::None);
5585                }
5586            })
5587        });
5588    }
5589
5590    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5591        self.end_selection(cx);
5592        self.selection_history.mode = SelectionHistoryMode::Undoing;
5593        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5594            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5595            self.select_next_state = entry.select_next_state;
5596            self.add_selections_state = entry.add_selections_state;
5597            self.request_autoscroll(Autoscroll::newest(), cx);
5598        }
5599        self.selection_history.mode = SelectionHistoryMode::Normal;
5600    }
5601
5602    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5603        self.end_selection(cx);
5604        self.selection_history.mode = SelectionHistoryMode::Redoing;
5605        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5606            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5607            self.select_next_state = entry.select_next_state;
5608            self.add_selections_state = entry.add_selections_state;
5609            self.request_autoscroll(Autoscroll::newest(), cx);
5610        }
5611        self.selection_history.mode = SelectionHistoryMode::Normal;
5612    }
5613
5614    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5615        self.go_to_diagnostic_impl(Direction::Next, cx)
5616    }
5617
5618    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5619        self.go_to_diagnostic_impl(Direction::Prev, cx)
5620    }
5621
5622    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5623        let buffer = self.buffer.read(cx).snapshot(cx);
5624        let selection = self.selections.newest::<usize>(cx);
5625
5626        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5627        if direction == Direction::Next {
5628            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5629                let (group_id, jump_to) = popover.activation_info();
5630                if self.activate_diagnostics(group_id, cx) {
5631                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5632                        let mut new_selection = s.newest_anchor().clone();
5633                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5634                        s.select_anchors(vec![new_selection.clone()]);
5635                    });
5636                }
5637                return;
5638            }
5639        }
5640
5641        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5642            active_diagnostics
5643                .primary_range
5644                .to_offset(&buffer)
5645                .to_inclusive()
5646        });
5647        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5648            if active_primary_range.contains(&selection.head()) {
5649                *active_primary_range.end()
5650            } else {
5651                selection.head()
5652            }
5653        } else {
5654            selection.head()
5655        };
5656
5657        loop {
5658            let mut diagnostics = if direction == Direction::Prev {
5659                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5660            } else {
5661                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5662            };
5663            let group = diagnostics.find_map(|entry| {
5664                if entry.diagnostic.is_primary
5665                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5666                    && !entry.range.is_empty()
5667                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5668                {
5669                    Some((entry.range, entry.diagnostic.group_id))
5670                } else {
5671                    None
5672                }
5673            });
5674
5675            if let Some((primary_range, group_id)) = group {
5676                if self.activate_diagnostics(group_id, cx) {
5677                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5678                        s.select(vec![Selection {
5679                            id: selection.id,
5680                            start: primary_range.start,
5681                            end: primary_range.start,
5682                            reversed: false,
5683                            goal: SelectionGoal::None,
5684                        }]);
5685                    });
5686                }
5687                break;
5688            } else {
5689                // Cycle around to the start of the buffer, potentially moving back to the start of
5690                // the currently active diagnostic.
5691                active_primary_range.take();
5692                if direction == Direction::Prev {
5693                    if search_start == buffer.len() {
5694                        break;
5695                    } else {
5696                        search_start = buffer.len();
5697                    }
5698                } else if search_start == 0 {
5699                    break;
5700                } else {
5701                    search_start = 0;
5702                }
5703            }
5704        }
5705    }
5706
5707    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5708        let snapshot = self
5709            .display_map
5710            .update(cx, |display_map, cx| display_map.snapshot(cx));
5711        let selection = self.selections.newest::<Point>(cx);
5712
5713        if !self.seek_in_direction(
5714            &snapshot,
5715            selection.head(),
5716            false,
5717            snapshot
5718                .buffer_snapshot
5719                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5720            cx,
5721        ) {
5722            let wrapped_point = Point::zero();
5723            self.seek_in_direction(
5724                &snapshot,
5725                wrapped_point,
5726                true,
5727                snapshot
5728                    .buffer_snapshot
5729                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5730                cx,
5731            );
5732        }
5733    }
5734
5735    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5736        let snapshot = self
5737            .display_map
5738            .update(cx, |display_map, cx| display_map.snapshot(cx));
5739        let selection = self.selections.newest::<Point>(cx);
5740
5741        if !self.seek_in_direction(
5742            &snapshot,
5743            selection.head(),
5744            false,
5745            snapshot
5746                .buffer_snapshot
5747                .git_diff_hunks_in_range_rev(0..selection.head().row),
5748            cx,
5749        ) {
5750            let wrapped_point = snapshot.buffer_snapshot.max_point();
5751            self.seek_in_direction(
5752                &snapshot,
5753                wrapped_point,
5754                true,
5755                snapshot
5756                    .buffer_snapshot
5757                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5758                cx,
5759            );
5760        }
5761    }
5762
5763    fn seek_in_direction(
5764        &mut self,
5765        snapshot: &DisplaySnapshot,
5766        initial_point: Point,
5767        is_wrapped: bool,
5768        hunks: impl Iterator<Item = DiffHunk<u32>>,
5769        cx: &mut ViewContext<Editor>,
5770    ) -> bool {
5771        let display_point = initial_point.to_display_point(snapshot);
5772        let mut hunks = hunks
5773            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5774            .skip_while(|hunk| {
5775                if is_wrapped {
5776                    false
5777                } else {
5778                    hunk.contains_display_row(display_point.row())
5779                }
5780            })
5781            .dedup();
5782
5783        if let Some(hunk) = hunks.next() {
5784            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5785                let row = hunk.start_display_row();
5786                let point = DisplayPoint::new(row, 0);
5787                s.select_display_ranges([point..point]);
5788            });
5789
5790            true
5791        } else {
5792            false
5793        }
5794    }
5795
5796    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5797        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5798    }
5799
5800    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5801        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5802    }
5803
5804    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5805        let Some(workspace) = self.workspace(cx) else { return };
5806        let buffer = self.buffer.read(cx);
5807        let head = self.selections.newest::<usize>(cx).head();
5808        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5809            text_anchor
5810        } else {
5811            return;
5812        };
5813
5814        let project = workspace.read(cx).project().clone();
5815        let definitions = project.update(cx, |project, cx| match kind {
5816            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5817            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5818        });
5819
5820        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5821            let definitions = definitions.await?;
5822            editor.update(&mut cx, |editor, cx| {
5823                editor.navigate_to_definitions(definitions, cx);
5824            })?;
5825            Ok::<(), anyhow::Error>(())
5826        })
5827        .detach_and_log_err(cx);
5828    }
5829
5830    pub fn navigate_to_definitions(
5831        &mut self,
5832        mut definitions: Vec<LocationLink>,
5833        cx: &mut ViewContext<Editor>,
5834    ) {
5835        let Some(workspace) = self.workspace(cx) else { return };
5836        let pane = workspace.read(cx).active_pane().clone();
5837        // If there is one definition, just open it directly
5838        if definitions.len() == 1 {
5839            let definition = definitions.pop().unwrap();
5840            let range = definition
5841                .target
5842                .range
5843                .to_offset(definition.target.buffer.read(cx));
5844
5845            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
5846                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5847                    s.select_ranges([range]);
5848                });
5849            } else {
5850                cx.window_context().defer(move |cx| {
5851                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
5852                        workspace.open_project_item(definition.target.buffer.clone(), cx)
5853                    });
5854                    target_editor.update(cx, |target_editor, cx| {
5855                        // When selecting a definition in a different buffer, disable the nav history
5856                        // to avoid creating a history entry at the previous cursor location.
5857                        pane.update(cx, |pane, _| pane.disable_history());
5858                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5859                            s.select_ranges([range]);
5860                        });
5861                        pane.update(cx, |pane, _| pane.enable_history());
5862                    });
5863                });
5864            }
5865        } else if !definitions.is_empty() {
5866            let replica_id = self.replica_id(cx);
5867            cx.window_context().defer(move |cx| {
5868                let title = definitions
5869                    .iter()
5870                    .find(|definition| definition.origin.is_some())
5871                    .and_then(|definition| {
5872                        definition.origin.as_ref().map(|origin| {
5873                            let buffer = origin.buffer.read(cx);
5874                            format!(
5875                                "Definitions for {}",
5876                                buffer
5877                                    .text_for_range(origin.range.clone())
5878                                    .collect::<String>()
5879                            )
5880                        })
5881                    })
5882                    .unwrap_or("Definitions".to_owned());
5883                let locations = definitions
5884                    .into_iter()
5885                    .map(|definition| definition.target)
5886                    .collect();
5887                workspace.update(cx, |workspace, cx| {
5888                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5889                });
5890            });
5891        }
5892    }
5893
5894    pub fn find_all_references(
5895        workspace: &mut Workspace,
5896        _: &FindAllReferences,
5897        cx: &mut ViewContext<Workspace>,
5898    ) -> Option<Task<Result<()>>> {
5899        let active_item = workspace.active_item(cx)?;
5900        let editor_handle = active_item.act_as::<Self>(cx)?;
5901
5902        let editor = editor_handle.read(cx);
5903        let buffer = editor.buffer.read(cx);
5904        let head = editor.selections.newest::<usize>(cx).head();
5905        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5906        let replica_id = editor.replica_id(cx);
5907
5908        let project = workspace.project().clone();
5909        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5910        Some(cx.spawn_labeled(
5911            "Finding All References...",
5912            |workspace, mut cx| async move {
5913                let locations = references.await?;
5914                if locations.is_empty() {
5915                    return Ok(());
5916                }
5917
5918                workspace.update(&mut cx, |workspace, cx| {
5919                    let title = locations
5920                        .first()
5921                        .as_ref()
5922                        .map(|location| {
5923                            let buffer = location.buffer.read(cx);
5924                            format!(
5925                                "References to `{}`",
5926                                buffer
5927                                    .text_for_range(location.range.clone())
5928                                    .collect::<String>()
5929                            )
5930                        })
5931                        .unwrap();
5932                    Self::open_locations_in_multibuffer(
5933                        workspace, locations, replica_id, title, cx,
5934                    );
5935                })?;
5936
5937                Ok(())
5938            },
5939        ))
5940    }
5941
5942    /// Opens a multibuffer with the given project locations in it
5943    pub fn open_locations_in_multibuffer(
5944        workspace: &mut Workspace,
5945        mut locations: Vec<Location>,
5946        replica_id: ReplicaId,
5947        title: String,
5948        cx: &mut ViewContext<Workspace>,
5949    ) {
5950        // If there are multiple definitions, open them in a multibuffer
5951        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
5952        let mut locations = locations.into_iter().peekable();
5953        let mut ranges_to_highlight = Vec::new();
5954
5955        let excerpt_buffer = cx.add_model(|cx| {
5956            let mut multibuffer = MultiBuffer::new(replica_id);
5957            while let Some(location) = locations.next() {
5958                let buffer = location.buffer.read(cx);
5959                let mut ranges_for_buffer = Vec::new();
5960                let range = location.range.to_offset(buffer);
5961                ranges_for_buffer.push(range.clone());
5962
5963                while let Some(next_location) = locations.peek() {
5964                    if next_location.buffer == location.buffer {
5965                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5966                        locations.next();
5967                    } else {
5968                        break;
5969                    }
5970                }
5971
5972                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5973                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5974                    location.buffer.clone(),
5975                    ranges_for_buffer,
5976                    1,
5977                    cx,
5978                ))
5979            }
5980
5981            multibuffer.with_title(title)
5982        });
5983
5984        let editor = cx.add_view(|cx| {
5985            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5986        });
5987        editor.update(cx, |editor, cx| {
5988            editor.highlight_background::<Self>(
5989                ranges_to_highlight,
5990                |theme| theme.editor.highlighted_line_background,
5991                cx,
5992            );
5993        });
5994        workspace.add_item(Box::new(editor), cx);
5995    }
5996
5997    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5998        use language::ToOffset as _;
5999
6000        let project = self.project.clone()?;
6001        let selection = self.selections.newest_anchor().clone();
6002        let (cursor_buffer, cursor_buffer_position) = self
6003            .buffer
6004            .read(cx)
6005            .text_anchor_for_position(selection.head(), cx)?;
6006        let (tail_buffer, _) = self
6007            .buffer
6008            .read(cx)
6009            .text_anchor_for_position(selection.tail(), cx)?;
6010        if tail_buffer != cursor_buffer {
6011            return None;
6012        }
6013
6014        let snapshot = cursor_buffer.read(cx).snapshot();
6015        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6016        let prepare_rename = project.update(cx, |project, cx| {
6017            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6018        });
6019
6020        Some(cx.spawn(|this, mut cx| async move {
6021            let rename_range = if let Some(range) = prepare_rename.await? {
6022                Some(range)
6023            } else {
6024                this.read_with(&cx, |this, cx| {
6025                    let buffer = this.buffer.read(cx).snapshot(cx);
6026                    let mut buffer_highlights = this
6027                        .document_highlights_for_position(selection.head(), &buffer)
6028                        .filter(|highlight| {
6029                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6030                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6031                        });
6032                    buffer_highlights
6033                        .next()
6034                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6035                })?
6036            };
6037            if let Some(rename_range) = rename_range {
6038                let rename_buffer_range = rename_range.to_offset(&snapshot);
6039                let cursor_offset_in_rename_range =
6040                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6041
6042                this.update(&mut cx, |this, cx| {
6043                    this.take_rename(false, cx);
6044                    let style = this.style(cx);
6045                    let buffer = this.buffer.read(cx).read(cx);
6046                    let cursor_offset = selection.head().to_offset(&buffer);
6047                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6048                    let rename_end = rename_start + rename_buffer_range.len();
6049                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6050                    let mut old_highlight_id = None;
6051                    let old_name: Arc<str> = buffer
6052                        .chunks(rename_start..rename_end, true)
6053                        .map(|chunk| {
6054                            if old_highlight_id.is_none() {
6055                                old_highlight_id = chunk.syntax_highlight_id;
6056                            }
6057                            chunk.text
6058                        })
6059                        .collect::<String>()
6060                        .into();
6061
6062                    drop(buffer);
6063
6064                    // Position the selection in the rename editor so that it matches the current selection.
6065                    this.show_local_selections = false;
6066                    let rename_editor = cx.add_view(|cx| {
6067                        let mut editor = Editor::single_line(None, cx);
6068                        if let Some(old_highlight_id) = old_highlight_id {
6069                            editor.override_text_style =
6070                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6071                        }
6072                        editor.buffer.update(cx, |buffer, cx| {
6073                            buffer.edit([(0..0, old_name.clone())], None, cx)
6074                        });
6075                        editor.select_all(&SelectAll, cx);
6076                        editor
6077                    });
6078
6079                    let ranges = this
6080                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6081                        .into_iter()
6082                        .flat_map(|(_, ranges)| ranges)
6083                        .chain(
6084                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6085                                .into_iter()
6086                                .flat_map(|(_, ranges)| ranges),
6087                        )
6088                        .collect();
6089
6090                    this.highlight_text::<Rename>(
6091                        ranges,
6092                        HighlightStyle {
6093                            fade_out: Some(style.rename_fade),
6094                            ..Default::default()
6095                        },
6096                        cx,
6097                    );
6098                    cx.focus(&rename_editor);
6099                    let block_id = this.insert_blocks(
6100                        [BlockProperties {
6101                            style: BlockStyle::Flex,
6102                            position: range.start.clone(),
6103                            height: 1,
6104                            render: Arc::new({
6105                                let editor = rename_editor.clone();
6106                                move |cx: &mut BlockContext| {
6107                                    ChildView::new(&editor, cx)
6108                                        .contained()
6109                                        .with_padding_left(cx.anchor_x)
6110                                        .into_any()
6111                                }
6112                            }),
6113                            disposition: BlockDisposition::Below,
6114                        }],
6115                        cx,
6116                    )[0];
6117                    this.pending_rename = Some(RenameState {
6118                        range,
6119                        old_name,
6120                        editor: rename_editor,
6121                        block_id,
6122                    });
6123                })?;
6124            }
6125
6126            Ok(())
6127        }))
6128    }
6129
6130    pub fn confirm_rename(
6131        workspace: &mut Workspace,
6132        _: &ConfirmRename,
6133        cx: &mut ViewContext<Workspace>,
6134    ) -> Option<Task<Result<()>>> {
6135        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6136
6137        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6138            let rename = editor.take_rename(false, cx)?;
6139            let buffer = editor.buffer.read(cx);
6140            let (start_buffer, start) =
6141                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6142            let (end_buffer, end) =
6143                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6144            if start_buffer == end_buffer {
6145                let new_name = rename.editor.read(cx).text(cx);
6146                Some((start_buffer, start..end, rename.old_name, new_name))
6147            } else {
6148                None
6149            }
6150        })?;
6151
6152        let rename = workspace.project().clone().update(cx, |project, cx| {
6153            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6154        });
6155
6156        let editor = editor.downgrade();
6157        Some(cx.spawn(|workspace, mut cx| async move {
6158            let project_transaction = rename.await?;
6159            Self::open_project_transaction(
6160                &editor,
6161                workspace,
6162                project_transaction,
6163                format!("Rename: {}{}", old_name, new_name),
6164                cx.clone(),
6165            )
6166            .await?;
6167
6168            editor.update(&mut cx, |editor, cx| {
6169                editor.refresh_document_highlights(cx);
6170            })?;
6171            Ok(())
6172        }))
6173    }
6174
6175    fn take_rename(
6176        &mut self,
6177        moving_cursor: bool,
6178        cx: &mut ViewContext<Self>,
6179    ) -> Option<RenameState> {
6180        let rename = self.pending_rename.take()?;
6181        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
6182        self.clear_text_highlights::<Rename>(cx);
6183        self.show_local_selections = true;
6184
6185        if moving_cursor {
6186            let rename_editor = rename.editor.read(cx);
6187            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6188
6189            // Update the selection to match the position of the selection inside
6190            // the rename editor.
6191            let snapshot = self.buffer.read(cx).read(cx);
6192            let rename_range = rename.range.to_offset(&snapshot);
6193            let cursor_in_editor = snapshot
6194                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6195                .min(rename_range.end);
6196            drop(snapshot);
6197
6198            self.change_selections(None, cx, |s| {
6199                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6200            });
6201        } else {
6202            self.refresh_document_highlights(cx);
6203        }
6204
6205        Some(rename)
6206    }
6207
6208    #[cfg(any(test, feature = "test-support"))]
6209    pub fn pending_rename(&self) -> Option<&RenameState> {
6210        self.pending_rename.as_ref()
6211    }
6212
6213    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6214        let project = match &self.project {
6215            Some(project) => project.clone(),
6216            None => return None,
6217        };
6218
6219        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6220    }
6221
6222    fn perform_format(
6223        &mut self,
6224        project: ModelHandle<Project>,
6225        trigger: FormatTrigger,
6226        cx: &mut ViewContext<Self>,
6227    ) -> Task<Result<()>> {
6228        let buffer = self.buffer().clone();
6229        let buffers = buffer.read(cx).all_buffers();
6230
6231        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6232        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6233
6234        cx.spawn(|_, mut cx| async move {
6235            let transaction = futures::select_biased! {
6236                _ = timeout => {
6237                    log::warn!("timed out waiting for formatting");
6238                    None
6239                }
6240                transaction = format.log_err().fuse() => transaction,
6241            };
6242
6243            buffer.update(&mut cx, |buffer, cx| {
6244                if let Some(transaction) = transaction {
6245                    if !buffer.is_singleton() {
6246                        buffer.push_transaction(&transaction.0, cx);
6247                    }
6248                }
6249
6250                cx.notify();
6251            });
6252
6253            Ok(())
6254        })
6255    }
6256
6257    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6258        if let Some(project) = self.project.clone() {
6259            self.buffer.update(cx, |multi_buffer, cx| {
6260                project.update(cx, |project, cx| {
6261                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6262                });
6263            })
6264        }
6265    }
6266
6267    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6268        cx.show_character_palette();
6269    }
6270
6271    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6272        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6273            let buffer = self.buffer.read(cx).snapshot(cx);
6274            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6275            let is_valid = buffer
6276                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6277                .any(|entry| {
6278                    entry.diagnostic.is_primary
6279                        && !entry.range.is_empty()
6280                        && entry.range.start == primary_range_start
6281                        && entry.diagnostic.message == active_diagnostics.primary_message
6282                });
6283
6284            if is_valid != active_diagnostics.is_valid {
6285                active_diagnostics.is_valid = is_valid;
6286                let mut new_styles = HashMap::default();
6287                for (block_id, diagnostic) in &active_diagnostics.blocks {
6288                    new_styles.insert(
6289                        *block_id,
6290                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6291                    );
6292                }
6293                self.display_map
6294                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6295            }
6296        }
6297    }
6298
6299    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6300        self.dismiss_diagnostics(cx);
6301        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6302            let buffer = self.buffer.read(cx).snapshot(cx);
6303
6304            let mut primary_range = None;
6305            let mut primary_message = None;
6306            let mut group_end = Point::zero();
6307            let diagnostic_group = buffer
6308                .diagnostic_group::<Point>(group_id)
6309                .map(|entry| {
6310                    if entry.range.end > group_end {
6311                        group_end = entry.range.end;
6312                    }
6313                    if entry.diagnostic.is_primary {
6314                        primary_range = Some(entry.range.clone());
6315                        primary_message = Some(entry.diagnostic.message.clone());
6316                    }
6317                    entry
6318                })
6319                .collect::<Vec<_>>();
6320            let primary_range = primary_range?;
6321            let primary_message = primary_message?;
6322            let primary_range =
6323                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6324
6325            let blocks = display_map
6326                .insert_blocks(
6327                    diagnostic_group.iter().map(|entry| {
6328                        let diagnostic = entry.diagnostic.clone();
6329                        let message_height = diagnostic.message.lines().count() as u8;
6330                        BlockProperties {
6331                            style: BlockStyle::Fixed,
6332                            position: buffer.anchor_after(entry.range.start),
6333                            height: message_height,
6334                            render: diagnostic_block_renderer(diagnostic, true),
6335                            disposition: BlockDisposition::Below,
6336                        }
6337                    }),
6338                    cx,
6339                )
6340                .into_iter()
6341                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6342                .collect();
6343
6344            Some(ActiveDiagnosticGroup {
6345                primary_range,
6346                primary_message,
6347                blocks,
6348                is_valid: true,
6349            })
6350        });
6351        self.active_diagnostics.is_some()
6352    }
6353
6354    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6355        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6356            self.display_map.update(cx, |display_map, cx| {
6357                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6358            });
6359            cx.notify();
6360        }
6361    }
6362
6363    pub fn set_selections_from_remote(
6364        &mut self,
6365        selections: Vec<Selection<Anchor>>,
6366        pending_selection: Option<Selection<Anchor>>,
6367        cx: &mut ViewContext<Self>,
6368    ) {
6369        let old_cursor_position = self.selections.newest_anchor().head();
6370        self.selections.change_with(cx, |s| {
6371            s.select_anchors(selections);
6372            if let Some(pending_selection) = pending_selection {
6373                s.set_pending(pending_selection, SelectMode::Character);
6374            } else {
6375                s.clear_pending();
6376            }
6377        });
6378        self.selections_did_change(false, &old_cursor_position, cx);
6379    }
6380
6381    fn push_to_selection_history(&mut self) {
6382        self.selection_history.push(SelectionHistoryEntry {
6383            selections: self.selections.disjoint_anchors(),
6384            select_next_state: self.select_next_state.clone(),
6385            add_selections_state: self.add_selections_state.clone(),
6386        });
6387    }
6388
6389    pub fn transact(
6390        &mut self,
6391        cx: &mut ViewContext<Self>,
6392        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6393    ) -> Option<TransactionId> {
6394        self.start_transaction_at(Instant::now(), cx);
6395        update(self, cx);
6396        self.end_transaction_at(Instant::now(), cx)
6397    }
6398
6399    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6400        self.end_selection(cx);
6401        if let Some(tx_id) = self
6402            .buffer
6403            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6404        {
6405            self.selection_history
6406                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6407        }
6408    }
6409
6410    fn end_transaction_at(
6411        &mut self,
6412        now: Instant,
6413        cx: &mut ViewContext<Self>,
6414    ) -> Option<TransactionId> {
6415        if let Some(tx_id) = self
6416            .buffer
6417            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6418        {
6419            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6420                *end_selections = Some(self.selections.disjoint_anchors());
6421            } else {
6422                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6423            }
6424
6425            cx.emit(Event::Edited);
6426            Some(tx_id)
6427        } else {
6428            None
6429        }
6430    }
6431
6432    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6433        let mut fold_ranges = Vec::new();
6434
6435        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6436
6437        let selections = self.selections.all::<Point>(cx);
6438        for selection in selections {
6439            let range = selection.range().sorted();
6440            let buffer_start_row = range.start.row;
6441
6442            for row in (0..=range.end.row).rev() {
6443                let fold_range = display_map.foldable_range(row);
6444
6445                if let Some(fold_range) = fold_range {
6446                    if fold_range.end.row >= buffer_start_row {
6447                        fold_ranges.push(fold_range);
6448                        if row <= range.start.row {
6449                            break;
6450                        }
6451                    }
6452                }
6453            }
6454        }
6455
6456        self.fold_ranges(fold_ranges, true, cx);
6457    }
6458
6459    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6460        let buffer_row = fold_at.buffer_row;
6461        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6462
6463        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6464            let autoscroll = self
6465                .selections
6466                .all::<Point>(cx)
6467                .iter()
6468                .any(|selection| fold_range.overlaps(&selection.range()));
6469
6470            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6471        }
6472    }
6473
6474    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6475        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6476        let buffer = &display_map.buffer_snapshot;
6477        let selections = self.selections.all::<Point>(cx);
6478        let ranges = selections
6479            .iter()
6480            .map(|s| {
6481                let range = s.display_range(&display_map).sorted();
6482                let mut start = range.start.to_point(&display_map);
6483                let mut end = range.end.to_point(&display_map);
6484                start.column = 0;
6485                end.column = buffer.line_len(end.row);
6486                start..end
6487            })
6488            .collect::<Vec<_>>();
6489
6490        self.unfold_ranges(ranges, true, true, cx);
6491    }
6492
6493    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6494        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6495
6496        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6497            ..Point::new(
6498                unfold_at.buffer_row,
6499                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6500            );
6501
6502        let autoscroll = self
6503            .selections
6504            .all::<Point>(cx)
6505            .iter()
6506            .any(|selection| selection.range().overlaps(&intersection_range));
6507
6508        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6509    }
6510
6511    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6512        let selections = self.selections.all::<Point>(cx);
6513        let ranges = selections.into_iter().map(|s| s.start..s.end);
6514        self.fold_ranges(ranges, true, cx);
6515    }
6516
6517    pub fn fold_ranges<T: ToOffset + Clone>(
6518        &mut self,
6519        ranges: impl IntoIterator<Item = Range<T>>,
6520        auto_scroll: bool,
6521        cx: &mut ViewContext<Self>,
6522    ) {
6523        let mut ranges = ranges.into_iter().peekable();
6524        if ranges.peek().is_some() {
6525            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6526
6527            if auto_scroll {
6528                self.request_autoscroll(Autoscroll::fit(), cx);
6529            }
6530
6531            cx.notify();
6532        }
6533    }
6534
6535    pub fn unfold_ranges<T: ToOffset + Clone>(
6536        &mut self,
6537        ranges: impl IntoIterator<Item = Range<T>>,
6538        inclusive: bool,
6539        auto_scroll: bool,
6540        cx: &mut ViewContext<Self>,
6541    ) {
6542        let mut ranges = ranges.into_iter().peekable();
6543        if ranges.peek().is_some() {
6544            self.display_map
6545                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6546            if auto_scroll {
6547                self.request_autoscroll(Autoscroll::fit(), cx);
6548            }
6549
6550            cx.notify();
6551        }
6552    }
6553
6554    pub fn gutter_hover(
6555        &mut self,
6556        GutterHover { hovered }: &GutterHover,
6557        cx: &mut ViewContext<Self>,
6558    ) {
6559        self.gutter_hovered = *hovered;
6560        cx.notify();
6561    }
6562
6563    pub fn insert_blocks(
6564        &mut self,
6565        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6566        cx: &mut ViewContext<Self>,
6567    ) -> Vec<BlockId> {
6568        let blocks = self
6569            .display_map
6570            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6571        self.request_autoscroll(Autoscroll::fit(), cx);
6572        blocks
6573    }
6574
6575    pub fn replace_blocks(
6576        &mut self,
6577        blocks: HashMap<BlockId, RenderBlock>,
6578        cx: &mut ViewContext<Self>,
6579    ) {
6580        self.display_map
6581            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6582        self.request_autoscroll(Autoscroll::fit(), cx);
6583    }
6584
6585    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6586        self.display_map.update(cx, |display_map, cx| {
6587            display_map.remove_blocks(block_ids, cx)
6588        });
6589    }
6590
6591    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6592        self.display_map
6593            .update(cx, |map, cx| map.snapshot(cx))
6594            .longest_row()
6595    }
6596
6597    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6598        self.display_map
6599            .update(cx, |map, cx| map.snapshot(cx))
6600            .max_point()
6601    }
6602
6603    pub fn text(&self, cx: &AppContext) -> String {
6604        self.buffer.read(cx).read(cx).text()
6605    }
6606
6607    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6608        self.transact(cx, |this, cx| {
6609            this.buffer
6610                .read(cx)
6611                .as_singleton()
6612                .expect("you can only call set_text on editors for singleton buffers")
6613                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6614        });
6615    }
6616
6617    pub fn display_text(&self, cx: &mut AppContext) -> String {
6618        self.display_map
6619            .update(cx, |map, cx| map.snapshot(cx))
6620            .text()
6621    }
6622
6623    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6624        let settings = self.buffer.read(cx).settings_at(0, cx);
6625        let mode = self
6626            .soft_wrap_mode_override
6627            .unwrap_or_else(|| settings.soft_wrap);
6628        match mode {
6629            language_settings::SoftWrap::None => SoftWrap::None,
6630            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6631            language_settings::SoftWrap::PreferredLineLength => {
6632                SoftWrap::Column(settings.preferred_line_length)
6633            }
6634        }
6635    }
6636
6637    pub fn set_soft_wrap_mode(
6638        &mut self,
6639        mode: language_settings::SoftWrap,
6640        cx: &mut ViewContext<Self>,
6641    ) {
6642        self.soft_wrap_mode_override = Some(mode);
6643        cx.notify();
6644    }
6645
6646    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6647        self.display_map
6648            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6649    }
6650
6651    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6652        if self.soft_wrap_mode_override.is_some() {
6653            self.soft_wrap_mode_override.take();
6654        } else {
6655            let soft_wrap = match self.soft_wrap_mode(cx) {
6656                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
6657                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
6658            };
6659            self.soft_wrap_mode_override = Some(soft_wrap);
6660        }
6661        cx.notify();
6662    }
6663
6664    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
6665        self.show_gutter = show_gutter;
6666        cx.notify();
6667    }
6668
6669    pub fn set_render_excerpt_header(
6670        &mut self,
6671        render_excerpt_header: impl 'static
6672            + Fn(
6673                &mut Editor,
6674                RenderExcerptHeaderParams,
6675                &mut LayoutContext<Editor>,
6676            ) -> AnyElement<Editor>,
6677        cx: &mut ViewContext<Self>,
6678    ) {
6679        self.render_excerpt_header = Some(Arc::new(render_excerpt_header));
6680        cx.notify();
6681    }
6682
6683    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6684        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6685            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6686                cx.reveal_path(&file.abs_path(cx));
6687            }
6688        }
6689    }
6690
6691    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6692        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6693            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6694                if let Some(path) = file.abs_path(cx).to_str() {
6695                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6696                }
6697            }
6698        }
6699    }
6700
6701    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6702        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6703            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6704                if let Some(path) = file.path().to_str() {
6705                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6706                }
6707            }
6708        }
6709    }
6710
6711    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6712        self.highlighted_rows = rows;
6713    }
6714
6715    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6716        self.highlighted_rows.clone()
6717    }
6718
6719    pub fn highlight_background<T: 'static>(
6720        &mut self,
6721        ranges: Vec<Range<Anchor>>,
6722        color_fetcher: fn(&Theme) -> Color,
6723        cx: &mut ViewContext<Self>,
6724    ) {
6725        self.background_highlights
6726            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6727        cx.notify();
6728    }
6729
6730    #[allow(clippy::type_complexity)]
6731    pub fn clear_background_highlights<T: 'static>(
6732        &mut self,
6733        cx: &mut ViewContext<Self>,
6734    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6735        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6736        if highlights.is_some() {
6737            cx.notify();
6738        }
6739        highlights
6740    }
6741
6742    #[cfg(feature = "test-support")]
6743    pub fn all_background_highlights(
6744        &mut self,
6745        cx: &mut ViewContext<Self>,
6746    ) -> Vec<(Range<DisplayPoint>, Color)> {
6747        let snapshot = self.snapshot(cx);
6748        let buffer = &snapshot.buffer_snapshot;
6749        let start = buffer.anchor_before(0);
6750        let end = buffer.anchor_after(buffer.len());
6751        let theme = theme::current(cx);
6752        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
6753    }
6754
6755    fn document_highlights_for_position<'a>(
6756        &'a self,
6757        position: Anchor,
6758        buffer: &'a MultiBufferSnapshot,
6759    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6760        let read_highlights = self
6761            .background_highlights
6762            .get(&TypeId::of::<DocumentHighlightRead>())
6763            .map(|h| &h.1);
6764        let write_highlights = self
6765            .background_highlights
6766            .get(&TypeId::of::<DocumentHighlightWrite>())
6767            .map(|h| &h.1);
6768        let left_position = position.bias_left(buffer);
6769        let right_position = position.bias_right(buffer);
6770        read_highlights
6771            .into_iter()
6772            .chain(write_highlights)
6773            .flat_map(move |ranges| {
6774                let start_ix = match ranges.binary_search_by(|probe| {
6775                    let cmp = probe.end.cmp(&left_position, buffer);
6776                    if cmp.is_ge() {
6777                        Ordering::Greater
6778                    } else {
6779                        Ordering::Less
6780                    }
6781                }) {
6782                    Ok(i) | Err(i) => i,
6783                };
6784
6785                let right_position = right_position.clone();
6786                ranges[start_ix..]
6787                    .iter()
6788                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6789            })
6790    }
6791
6792    pub fn background_highlights_in_range(
6793        &self,
6794        search_range: Range<Anchor>,
6795        display_snapshot: &DisplaySnapshot,
6796        theme: &Theme,
6797    ) -> Vec<(Range<DisplayPoint>, Color)> {
6798        let mut results = Vec::new();
6799        let buffer = &display_snapshot.buffer_snapshot;
6800        for (color_fetcher, ranges) in self.background_highlights.values() {
6801            let color = color_fetcher(theme);
6802            let start_ix = match ranges.binary_search_by(|probe| {
6803                let cmp = probe.end.cmp(&search_range.start, buffer);
6804                if cmp.is_gt() {
6805                    Ordering::Greater
6806                } else {
6807                    Ordering::Less
6808                }
6809            }) {
6810                Ok(i) | Err(i) => i,
6811            };
6812            for range in &ranges[start_ix..] {
6813                if range.start.cmp(&search_range.end, buffer).is_ge() {
6814                    break;
6815                }
6816                let start = range
6817                    .start
6818                    .to_point(buffer)
6819                    .to_display_point(display_snapshot);
6820                let end = range
6821                    .end
6822                    .to_point(buffer)
6823                    .to_display_point(display_snapshot);
6824                results.push((start..end, color))
6825            }
6826        }
6827        results
6828    }
6829
6830    pub fn highlight_text<T: 'static>(
6831        &mut self,
6832        ranges: Vec<Range<Anchor>>,
6833        style: HighlightStyle,
6834        cx: &mut ViewContext<Self>,
6835    ) {
6836        self.display_map.update(cx, |map, _| {
6837            map.highlight_text(TypeId::of::<T>(), ranges, style)
6838        });
6839        cx.notify();
6840    }
6841
6842    pub fn text_highlights<'a, T: 'static>(
6843        &'a self,
6844        cx: &'a AppContext,
6845    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6846        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6847    }
6848
6849    pub fn clear_text_highlights<T: 'static>(
6850        &mut self,
6851        cx: &mut ViewContext<Self>,
6852    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6853        let highlights = self
6854            .display_map
6855            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6856        if highlights.is_some() {
6857            cx.notify();
6858        }
6859        highlights
6860    }
6861
6862    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6863        self.blink_manager.read(cx).visible() && self.focused
6864    }
6865
6866    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6867        cx.notify();
6868    }
6869
6870    fn on_buffer_event(
6871        &mut self,
6872        _: ModelHandle<MultiBuffer>,
6873        event: &multi_buffer::Event,
6874        cx: &mut ViewContext<Self>,
6875    ) {
6876        match event {
6877            multi_buffer::Event::Edited => {
6878                self.refresh_active_diagnostics(cx);
6879                self.refresh_code_actions(cx);
6880                if self.has_active_copilot_suggestion(cx) {
6881                    self.update_visible_copilot_suggestion(cx);
6882                }
6883                cx.emit(Event::BufferEdited);
6884            }
6885            multi_buffer::Event::ExcerptsAdded {
6886                buffer,
6887                predecessor,
6888                excerpts,
6889            } => cx.emit(Event::ExcerptsAdded {
6890                buffer: buffer.clone(),
6891                predecessor: *predecessor,
6892                excerpts: excerpts.clone(),
6893            }),
6894            multi_buffer::Event::ExcerptsRemoved { ids } => {
6895                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6896            }
6897            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6898            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6899            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6900            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6901            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6902            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
6903            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6904            multi_buffer::Event::DiagnosticsUpdated => {
6905                self.refresh_active_diagnostics(cx);
6906            }
6907            multi_buffer::Event::LanguageChanged => {}
6908        }
6909    }
6910
6911    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6912        cx.notify();
6913    }
6914
6915    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6916        self.refresh_copilot_suggestions(true, cx);
6917    }
6918
6919    pub fn set_searchable(&mut self, searchable: bool) {
6920        self.searchable = searchable;
6921    }
6922
6923    pub fn searchable(&self) -> bool {
6924        self.searchable
6925    }
6926
6927    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6928        let active_item = workspace.active_item(cx);
6929        let editor_handle = if let Some(editor) = active_item
6930            .as_ref()
6931            .and_then(|item| item.act_as::<Self>(cx))
6932        {
6933            editor
6934        } else {
6935            cx.propagate_action();
6936            return;
6937        };
6938
6939        let editor = editor_handle.read(cx);
6940        let buffer = editor.buffer.read(cx);
6941        if buffer.is_singleton() {
6942            cx.propagate_action();
6943            return;
6944        }
6945
6946        let mut new_selections_by_buffer = HashMap::default();
6947        for selection in editor.selections.all::<usize>(cx) {
6948            for (buffer, mut range) in
6949                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6950            {
6951                if selection.reversed {
6952                    mem::swap(&mut range.start, &mut range.end);
6953                }
6954                new_selections_by_buffer
6955                    .entry(buffer)
6956                    .or_insert(Vec::new())
6957                    .push(range)
6958            }
6959        }
6960
6961        editor_handle.update(cx, |editor, cx| {
6962            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6963        });
6964        let pane = workspace.active_pane().clone();
6965        pane.update(cx, |pane, _| pane.disable_history());
6966
6967        // We defer the pane interaction because we ourselves are a workspace item
6968        // and activating a new item causes the pane to call a method on us reentrantly,
6969        // which panics if we're on the stack.
6970        cx.defer(move |workspace, cx| {
6971            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6972                let editor = workspace.open_project_item::<Self>(buffer, cx);
6973                editor.update(cx, |editor, cx| {
6974                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6975                        s.select_ranges(ranges);
6976                    });
6977                });
6978            }
6979
6980            pane.update(cx, |pane, _| pane.enable_history());
6981        });
6982    }
6983
6984    fn jump(
6985        workspace: &mut Workspace,
6986        path: ProjectPath,
6987        position: Point,
6988        anchor: language::Anchor,
6989        cx: &mut ViewContext<Workspace>,
6990    ) {
6991        let editor = workspace.open_path(path, None, true, cx);
6992        cx.spawn(|_, mut cx| async move {
6993            let editor = editor
6994                .await?
6995                .downcast::<Editor>()
6996                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6997                .downgrade();
6998            editor.update(&mut cx, |editor, cx| {
6999                let buffer = editor
7000                    .buffer()
7001                    .read(cx)
7002                    .as_singleton()
7003                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7004                let buffer = buffer.read(cx);
7005                let cursor = if buffer.can_resolve(&anchor) {
7006                    language::ToPoint::to_point(&anchor, buffer)
7007                } else {
7008                    buffer.clip_point(position, Bias::Left)
7009                };
7010
7011                let nav_history = editor.nav_history.take();
7012                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7013                    s.select_ranges([cursor..cursor]);
7014                });
7015                editor.nav_history = nav_history;
7016
7017                anyhow::Ok(())
7018            })??;
7019
7020            anyhow::Ok(())
7021        })
7022        .detach_and_log_err(cx);
7023    }
7024
7025    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7026        let snapshot = self.buffer.read(cx).read(cx);
7027        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7028        Some(
7029            ranges
7030                .iter()
7031                .map(move |range| {
7032                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7033                })
7034                .collect(),
7035        )
7036    }
7037
7038    fn selection_replacement_ranges(
7039        &self,
7040        range: Range<OffsetUtf16>,
7041        cx: &AppContext,
7042    ) -> Vec<Range<OffsetUtf16>> {
7043        let selections = self.selections.all::<OffsetUtf16>(cx);
7044        let newest_selection = selections
7045            .iter()
7046            .max_by_key(|selection| selection.id)
7047            .unwrap();
7048        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7049        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7050        let snapshot = self.buffer.read(cx).read(cx);
7051        selections
7052            .into_iter()
7053            .map(|mut selection| {
7054                selection.start.0 =
7055                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7056                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7057                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7058                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7059            })
7060            .collect()
7061    }
7062
7063    fn report_copilot_event(
7064        &self,
7065        suggestion_id: Option<String>,
7066        suggestion_accepted: bool,
7067        cx: &AppContext,
7068    ) {
7069        let Some(project) = &self.project else {
7070            return
7071        };
7072
7073        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7074        let file_extension = self
7075            .buffer
7076            .read(cx)
7077            .as_singleton()
7078            .and_then(|b| b.read(cx).file())
7079            .and_then(|file| Path::new(file.file_name(cx)).extension())
7080            .and_then(|e| e.to_str())
7081            .map(|a| a.to_string());
7082
7083        let telemetry = project.read(cx).client().telemetry().clone();
7084        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7085
7086        let event = ClickhouseEvent::Copilot {
7087            suggestion_id,
7088            suggestion_accepted,
7089            file_extension,
7090        };
7091        telemetry.report_clickhouse_event(event, telemetry_settings);
7092    }
7093
7094    fn report_editor_event(
7095        &self,
7096        name: &'static str,
7097        file_extension: Option<String>,
7098        cx: &AppContext,
7099    ) {
7100        let Some(project) = &self.project else {
7101            return
7102        };
7103
7104        // If None, we are in a file without an extension
7105        let file = self
7106            .buffer
7107            .read(cx)
7108            .as_singleton()
7109            .and_then(|b| b.read(cx).file());
7110        let file_extension = file_extension.or(file
7111            .as_ref()
7112            .and_then(|file| Path::new(file.file_name(cx)).extension())
7113            .and_then(|e| e.to_str())
7114            .map(|a| a.to_string()));
7115
7116        let vim_mode = cx
7117            .global::<SettingsStore>()
7118            .untyped_user_settings()
7119            .get("vim_mode")
7120            == Some(&serde_json::Value::Bool(true));
7121        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7122        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7123        let copilot_enabled_for_language = self
7124            .buffer
7125            .read(cx)
7126            .settings_at(0, cx)
7127            .show_copilot_suggestions;
7128
7129        let telemetry = project.read(cx).client().telemetry().clone();
7130        telemetry.report_mixpanel_event(
7131            match name {
7132                "open" => "open editor",
7133                "save" => "save editor",
7134                _ => name,
7135            },
7136            json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true  }),
7137            telemetry_settings,
7138        );
7139        let event = ClickhouseEvent::Editor {
7140            file_extension,
7141            vim_mode,
7142            operation: name,
7143            copilot_enabled,
7144            copilot_enabled_for_language,
7145        };
7146        telemetry.report_clickhouse_event(event, telemetry_settings)
7147    }
7148
7149    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7150    /// with each line being an array of {text, highlight} objects.
7151    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7152        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7153            return;
7154        };
7155
7156        #[derive(Serialize)]
7157        struct Chunk<'a> {
7158            text: String,
7159            highlight: Option<&'a str>,
7160        }
7161
7162        let snapshot = buffer.read(cx).snapshot();
7163        let range = self
7164            .selected_text_range(cx)
7165            .and_then(|selected_range| {
7166                if selected_range.is_empty() {
7167                    None
7168                } else {
7169                    Some(selected_range)
7170                }
7171            })
7172            .unwrap_or_else(|| 0..snapshot.len());
7173
7174        let chunks = snapshot.chunks(range, true);
7175        let mut lines = Vec::new();
7176        let mut line: VecDeque<Chunk> = VecDeque::new();
7177
7178        let theme = &theme::current(cx).editor.syntax;
7179
7180        for chunk in chunks {
7181            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7182            let mut chunk_lines = chunk.text.split("\n").peekable();
7183            while let Some(text) = chunk_lines.next() {
7184                let mut merged_with_last_token = false;
7185                if let Some(last_token) = line.back_mut() {
7186                    if last_token.highlight == highlight {
7187                        last_token.text.push_str(text);
7188                        merged_with_last_token = true;
7189                    }
7190                }
7191
7192                if !merged_with_last_token {
7193                    line.push_back(Chunk {
7194                        text: text.into(),
7195                        highlight,
7196                    });
7197                }
7198
7199                if chunk_lines.peek().is_some() {
7200                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7201                        line.pop_front();
7202                    }
7203                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7204                        line.pop_back();
7205                    }
7206
7207                    lines.push(mem::take(&mut line));
7208                }
7209            }
7210        }
7211
7212        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7213        cx.write_to_clipboard(ClipboardItem::new(lines));
7214    }
7215}
7216
7217fn consume_contiguous_rows(
7218    contiguous_row_selections: &mut Vec<Selection<Point>>,
7219    selection: &Selection<Point>,
7220    display_map: &DisplaySnapshot,
7221    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7222) -> (u32, u32) {
7223    contiguous_row_selections.push(selection.clone());
7224    let start_row = selection.start.row;
7225    let mut end_row = ending_row(selection, display_map);
7226
7227    while let Some(next_selection) = selections.peek() {
7228        if next_selection.start.row <= end_row {
7229            end_row = ending_row(next_selection, display_map);
7230            contiguous_row_selections.push(selections.next().unwrap().clone());
7231        } else {
7232            break;
7233        }
7234    }
7235    (start_row, end_row)
7236}
7237
7238fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7239    if next_selection.end.column > 0 || next_selection.is_empty() {
7240        display_map.next_line_boundary(next_selection.end).0.row + 1
7241    } else {
7242        next_selection.end.row
7243    }
7244}
7245
7246impl EditorSnapshot {
7247    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7248        self.display_snapshot.buffer_snapshot.language_at(position)
7249    }
7250
7251    pub fn is_focused(&self) -> bool {
7252        self.is_focused
7253    }
7254
7255    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7256        self.placeholder_text.as_ref()
7257    }
7258
7259    pub fn scroll_position(&self) -> Vector2F {
7260        self.scroll_anchor.scroll_position(&self.display_snapshot)
7261    }
7262}
7263
7264impl Deref for EditorSnapshot {
7265    type Target = DisplaySnapshot;
7266
7267    fn deref(&self) -> &Self::Target {
7268        &self.display_snapshot
7269    }
7270}
7271
7272#[derive(Clone, Debug, PartialEq, Eq)]
7273pub enum Event {
7274    InputIgnored {
7275        text: Arc<str>,
7276    },
7277    ExcerptsAdded {
7278        buffer: ModelHandle<Buffer>,
7279        predecessor: ExcerptId,
7280        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7281    },
7282    ExcerptsRemoved {
7283        ids: Vec<ExcerptId>,
7284    },
7285    BufferEdited,
7286    Edited,
7287    Reparsed,
7288    Focused,
7289    Blurred,
7290    DirtyChanged,
7291    Saved,
7292    TitleChanged,
7293    DiffBaseChanged,
7294    SelectionsChanged {
7295        local: bool,
7296    },
7297    ScrollPositionChanged {
7298        local: bool,
7299    },
7300    Closed,
7301}
7302
7303pub struct EditorFocused(pub ViewHandle<Editor>);
7304pub struct EditorBlurred(pub ViewHandle<Editor>);
7305pub struct EditorReleased(pub WeakViewHandle<Editor>);
7306
7307impl Entity for Editor {
7308    type Event = Event;
7309
7310    fn release(&mut self, cx: &mut AppContext) {
7311        cx.emit_global(EditorReleased(self.handle.clone()));
7312    }
7313}
7314
7315impl View for Editor {
7316    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7317        let style = self.style(cx);
7318        let font_changed = self.display_map.update(cx, |map, cx| {
7319            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7320            map.set_font(style.text.font_id, style.text.font_size, cx)
7321        });
7322
7323        if font_changed {
7324            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7325                hide_hover(editor, cx);
7326                hide_link_definition(editor, cx);
7327            });
7328        }
7329
7330        let mut editor = EditorElement::new(style.clone());
7331        if let Some(render_excerpt_header) = self.render_excerpt_header.clone() {
7332            editor = editor.with_render_excerpt_header(render_excerpt_header);
7333        }
7334        Stack::new()
7335            .with_child(editor)
7336            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7337            .into_any()
7338    }
7339
7340    fn ui_name() -> &'static str {
7341        "Editor"
7342    }
7343
7344    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7345        if cx.is_self_focused() {
7346            let focused_event = EditorFocused(cx.handle());
7347            cx.emit(Event::Focused);
7348            cx.emit_global(focused_event);
7349        }
7350        if let Some(rename) = self.pending_rename.as_ref() {
7351            cx.focus(&rename.editor);
7352        } else {
7353            if !self.focused {
7354                self.blink_manager.update(cx, BlinkManager::enable);
7355            }
7356            self.focused = true;
7357            self.buffer.update(cx, |buffer, cx| {
7358                buffer.finalize_last_transaction(cx);
7359                if self.leader_replica_id.is_none() {
7360                    buffer.set_active_selections(
7361                        &self.selections.disjoint_anchors(),
7362                        self.selections.line_mode,
7363                        self.cursor_shape,
7364                        cx,
7365                    );
7366                }
7367            });
7368        }
7369    }
7370
7371    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7372        let blurred_event = EditorBlurred(cx.handle());
7373        cx.emit_global(blurred_event);
7374        self.focused = false;
7375        self.blink_manager.update(cx, BlinkManager::disable);
7376        self.buffer
7377            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7378        self.hide_context_menu(cx);
7379        hide_hover(self, cx);
7380        cx.emit(Event::Blurred);
7381        cx.notify();
7382    }
7383
7384    fn modifiers_changed(
7385        &mut self,
7386        event: &gpui::platform::ModifiersChangedEvent,
7387        cx: &mut ViewContext<Self>,
7388    ) -> bool {
7389        let pending_selection = self.has_pending_selection();
7390
7391        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7392            if event.cmd && !pending_selection {
7393                let snapshot = self.snapshot(cx);
7394                let kind = if event.shift {
7395                    LinkDefinitionKind::Type
7396                } else {
7397                    LinkDefinitionKind::Symbol
7398                };
7399
7400                show_link_definition(kind, self, point, snapshot, cx);
7401                return false;
7402            }
7403        }
7404
7405        {
7406            if self.link_go_to_definition_state.symbol_range.is_some()
7407                || !self.link_go_to_definition_state.definitions.is_empty()
7408            {
7409                self.link_go_to_definition_state.symbol_range.take();
7410                self.link_go_to_definition_state.definitions.clear();
7411                cx.notify();
7412            }
7413
7414            self.link_go_to_definition_state.task = None;
7415
7416            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7417        }
7418
7419        false
7420    }
7421
7422    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
7423        Self::reset_to_default_keymap_context(keymap);
7424        let mode = match self.mode {
7425            EditorMode::SingleLine => "single_line",
7426            EditorMode::AutoHeight { .. } => "auto_height",
7427            EditorMode::Full => "full",
7428        };
7429        keymap.add_key("mode", mode);
7430        if self.pending_rename.is_some() {
7431            keymap.add_identifier("renaming");
7432        }
7433        match self.context_menu.as_ref() {
7434            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7435            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7436            None => {}
7437        }
7438        for layer in self.keymap_context_layers.values() {
7439            keymap.extend(layer);
7440        }
7441
7442        if let Some(extension) = self
7443            .buffer
7444            .read(cx)
7445            .as_singleton()
7446            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
7447        {
7448            keymap.add_key("extension", extension.to_string());
7449        }
7450    }
7451
7452    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7453        Some(
7454            self.buffer
7455                .read(cx)
7456                .read(cx)
7457                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7458                .collect(),
7459        )
7460    }
7461
7462    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7463        // Prevent the IME menu from appearing when holding down an alphabetic key
7464        // while input is disabled.
7465        if !self.input_enabled {
7466            return None;
7467        }
7468
7469        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7470        Some(range.start.0..range.end.0)
7471    }
7472
7473    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7474        let snapshot = self.buffer.read(cx).read(cx);
7475        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7476        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7477    }
7478
7479    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7480        self.clear_text_highlights::<InputComposition>(cx);
7481        self.ime_transaction.take();
7482    }
7483
7484    fn replace_text_in_range(
7485        &mut self,
7486        range_utf16: Option<Range<usize>>,
7487        text: &str,
7488        cx: &mut ViewContext<Self>,
7489    ) {
7490        self.transact(cx, |this, cx| {
7491            if this.input_enabled {
7492                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7493                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7494                    Some(this.selection_replacement_ranges(range_utf16, cx))
7495                } else {
7496                    this.marked_text_ranges(cx)
7497                };
7498
7499                if let Some(new_selected_ranges) = new_selected_ranges {
7500                    this.change_selections(None, cx, |selections| {
7501                        selections.select_ranges(new_selected_ranges)
7502                    });
7503                }
7504            }
7505
7506            this.handle_input(text, cx);
7507        });
7508
7509        if !self.input_enabled {
7510            return;
7511        }
7512
7513        if let Some(transaction) = self.ime_transaction {
7514            self.buffer.update(cx, |buffer, cx| {
7515                buffer.group_until_transaction(transaction, cx);
7516            });
7517        }
7518
7519        self.unmark_text(cx);
7520    }
7521
7522    fn replace_and_mark_text_in_range(
7523        &mut self,
7524        range_utf16: Option<Range<usize>>,
7525        text: &str,
7526        new_selected_range_utf16: Option<Range<usize>>,
7527        cx: &mut ViewContext<Self>,
7528    ) {
7529        if !self.input_enabled {
7530            return;
7531        }
7532
7533        let transaction = self.transact(cx, |this, cx| {
7534            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7535                let snapshot = this.buffer.read(cx).read(cx);
7536                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7537                    for marked_range in &mut marked_ranges {
7538                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7539                        marked_range.start.0 += relative_range_utf16.start;
7540                        marked_range.start =
7541                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7542                        marked_range.end =
7543                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7544                    }
7545                }
7546                Some(marked_ranges)
7547            } else if let Some(range_utf16) = range_utf16 {
7548                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7549                Some(this.selection_replacement_ranges(range_utf16, cx))
7550            } else {
7551                None
7552            };
7553
7554            if let Some(ranges) = ranges_to_replace {
7555                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7556            }
7557
7558            let marked_ranges = {
7559                let snapshot = this.buffer.read(cx).read(cx);
7560                this.selections
7561                    .disjoint_anchors()
7562                    .iter()
7563                    .map(|selection| {
7564                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7565                    })
7566                    .collect::<Vec<_>>()
7567            };
7568
7569            if text.is_empty() {
7570                this.unmark_text(cx);
7571            } else {
7572                this.highlight_text::<InputComposition>(
7573                    marked_ranges.clone(),
7574                    this.style(cx).composition_mark,
7575                    cx,
7576                );
7577            }
7578
7579            this.handle_input(text, cx);
7580
7581            if let Some(new_selected_range) = new_selected_range_utf16 {
7582                let snapshot = this.buffer.read(cx).read(cx);
7583                let new_selected_ranges = marked_ranges
7584                    .into_iter()
7585                    .map(|marked_range| {
7586                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7587                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7588                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7589                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7590                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7591                    })
7592                    .collect::<Vec<_>>();
7593
7594                drop(snapshot);
7595                this.change_selections(None, cx, |selections| {
7596                    selections.select_ranges(new_selected_ranges)
7597                });
7598            }
7599        });
7600
7601        self.ime_transaction = self.ime_transaction.or(transaction);
7602        if let Some(transaction) = self.ime_transaction {
7603            self.buffer.update(cx, |buffer, cx| {
7604                buffer.group_until_transaction(transaction, cx);
7605            });
7606        }
7607
7608        if self.text_highlights::<InputComposition>(cx).is_none() {
7609            self.ime_transaction.take();
7610        }
7611    }
7612}
7613
7614fn build_style(
7615    settings: &ThemeSettings,
7616    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7617    override_text_style: Option<&OverrideTextStyle>,
7618    cx: &AppContext,
7619) -> EditorStyle {
7620    let font_cache = cx.font_cache();
7621
7622    let theme_id = settings.theme.meta.id;
7623    let mut theme = settings.theme.editor.clone();
7624    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7625        let field_editor_theme = get_field_editor_theme(&settings.theme);
7626        theme.text_color = field_editor_theme.text.color;
7627        theme.selection = field_editor_theme.selection;
7628        theme.background = field_editor_theme
7629            .container
7630            .background_color
7631            .unwrap_or_default();
7632        EditorStyle {
7633            text: field_editor_theme.text,
7634            placeholder_text: field_editor_theme.placeholder_text,
7635            theme,
7636            theme_id,
7637        }
7638    } else {
7639        let font_family_id = settings.buffer_font_family;
7640        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7641        let font_properties = Default::default();
7642        let font_id = font_cache
7643            .select_font(font_family_id, &font_properties)
7644            .unwrap();
7645        let font_size = settings.buffer_font_size(cx);
7646        EditorStyle {
7647            text: TextStyle {
7648                color: settings.theme.editor.text_color,
7649                font_family_name,
7650                font_family_id,
7651                font_id,
7652                font_size,
7653                font_properties,
7654                underline: Default::default(),
7655            },
7656            placeholder_text: None,
7657            theme,
7658            theme_id,
7659        }
7660    };
7661
7662    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7663        if let Some(highlighted) = style
7664            .text
7665            .clone()
7666            .highlight(highlight_style, font_cache)
7667            .log_err()
7668        {
7669            style.text = highlighted;
7670        }
7671    }
7672
7673    style
7674}
7675
7676trait SelectionExt {
7677    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7678    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7679    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7680    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7681        -> Range<u32>;
7682}
7683
7684impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7685    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7686        let start = self.start.to_point(buffer);
7687        let end = self.end.to_point(buffer);
7688        if self.reversed {
7689            end..start
7690        } else {
7691            start..end
7692        }
7693    }
7694
7695    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7696        let start = self.start.to_offset(buffer);
7697        let end = self.end.to_offset(buffer);
7698        if self.reversed {
7699            end..start
7700        } else {
7701            start..end
7702        }
7703    }
7704
7705    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7706        let start = self
7707            .start
7708            .to_point(&map.buffer_snapshot)
7709            .to_display_point(map);
7710        let end = self
7711            .end
7712            .to_point(&map.buffer_snapshot)
7713            .to_display_point(map);
7714        if self.reversed {
7715            end..start
7716        } else {
7717            start..end
7718        }
7719    }
7720
7721    fn spanned_rows(
7722        &self,
7723        include_end_if_at_line_start: bool,
7724        map: &DisplaySnapshot,
7725    ) -> Range<u32> {
7726        let start = self.start.to_point(&map.buffer_snapshot);
7727        let mut end = self.end.to_point(&map.buffer_snapshot);
7728        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7729            end.row -= 1;
7730        }
7731
7732        let buffer_start = map.prev_line_boundary(start).0;
7733        let buffer_end = map.next_line_boundary(end).0;
7734        buffer_start.row..buffer_end.row + 1
7735    }
7736}
7737
7738impl<T: InvalidationRegion> InvalidationStack<T> {
7739    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7740    where
7741        S: Clone + ToOffset,
7742    {
7743        while let Some(region) = self.last() {
7744            let all_selections_inside_invalidation_ranges =
7745                if selections.len() == region.ranges().len() {
7746                    selections
7747                        .iter()
7748                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7749                        .all(|(selection, invalidation_range)| {
7750                            let head = selection.head().to_offset(buffer);
7751                            invalidation_range.start <= head && invalidation_range.end >= head
7752                        })
7753                } else {
7754                    false
7755                };
7756
7757            if all_selections_inside_invalidation_ranges {
7758                break;
7759            } else {
7760                self.pop();
7761            }
7762        }
7763    }
7764}
7765
7766impl<T> Default for InvalidationStack<T> {
7767    fn default() -> Self {
7768        Self(Default::default())
7769    }
7770}
7771
7772impl<T> Deref for InvalidationStack<T> {
7773    type Target = Vec<T>;
7774
7775    fn deref(&self) -> &Self::Target {
7776        &self.0
7777    }
7778}
7779
7780impl<T> DerefMut for InvalidationStack<T> {
7781    fn deref_mut(&mut self) -> &mut Self::Target {
7782        &mut self.0
7783    }
7784}
7785
7786impl InvalidationRegion for SnippetState {
7787    fn ranges(&self) -> &[Range<Anchor>] {
7788        &self.ranges[self.active_index]
7789    }
7790}
7791
7792impl Deref for EditorStyle {
7793    type Target = theme::Editor;
7794
7795    fn deref(&self) -> &Self::Target {
7796        &self.theme
7797    }
7798}
7799
7800pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7801    let mut highlighted_lines = Vec::new();
7802    for (index, line) in diagnostic.message.lines().enumerate() {
7803        let line = match &diagnostic.source {
7804            Some(source) if index == 0 => {
7805                let source_highlight = Vec::from_iter(0..source.len());
7806                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7807            }
7808
7809            _ => highlight_diagnostic_message(Vec::new(), line),
7810        };
7811        highlighted_lines.push(line);
7812    }
7813
7814    Arc::new(move |cx: &mut BlockContext| {
7815        let settings = settings::get::<ThemeSettings>(cx);
7816        let theme = &settings.theme.editor;
7817        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7818        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7819        Flex::column()
7820            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7821                Label::new(
7822                    line.clone(),
7823                    style.message.clone().with_font_size(font_size),
7824                )
7825                .with_highlights(highlights.clone())
7826                .contained()
7827                .with_margin_left(cx.anchor_x)
7828            }))
7829            .aligned()
7830            .left()
7831            .into_any()
7832    })
7833}
7834
7835pub fn highlight_diagnostic_message(
7836    inital_highlights: Vec<usize>,
7837    message: &str,
7838) -> (String, Vec<usize>) {
7839    let mut message_without_backticks = String::new();
7840    let mut prev_offset = 0;
7841    let mut inside_block = false;
7842    let mut highlights = inital_highlights;
7843    for (match_ix, (offset, _)) in message
7844        .match_indices('`')
7845        .chain([(message.len(), "")])
7846        .enumerate()
7847    {
7848        message_without_backticks.push_str(&message[prev_offset..offset]);
7849        if inside_block {
7850            highlights.extend(prev_offset - match_ix..offset - match_ix);
7851        }
7852
7853        inside_block = !inside_block;
7854        prev_offset = offset + 1;
7855    }
7856
7857    (message_without_backticks, highlights)
7858}
7859
7860pub fn diagnostic_style(
7861    severity: DiagnosticSeverity,
7862    valid: bool,
7863    theme: &theme::Editor,
7864) -> DiagnosticStyle {
7865    match (severity, valid) {
7866        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7867        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7868        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7869        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7870        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7871        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7872        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7873        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7874        _ => theme.invalid_hint_diagnostic.clone(),
7875    }
7876}
7877
7878pub fn combine_syntax_and_fuzzy_match_highlights(
7879    text: &str,
7880    default_style: HighlightStyle,
7881    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7882    match_indices: &[usize],
7883) -> Vec<(Range<usize>, HighlightStyle)> {
7884    let mut result = Vec::new();
7885    let mut match_indices = match_indices.iter().copied().peekable();
7886
7887    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7888    {
7889        syntax_highlight.weight = None;
7890
7891        // Add highlights for any fuzzy match characters before the next
7892        // syntax highlight range.
7893        while let Some(&match_index) = match_indices.peek() {
7894            if match_index >= range.start {
7895                break;
7896            }
7897            match_indices.next();
7898            let end_index = char_ix_after(match_index, text);
7899            let mut match_style = default_style;
7900            match_style.weight = Some(fonts::Weight::BOLD);
7901            result.push((match_index..end_index, match_style));
7902        }
7903
7904        if range.start == usize::MAX {
7905            break;
7906        }
7907
7908        // Add highlights for any fuzzy match characters within the
7909        // syntax highlight range.
7910        let mut offset = range.start;
7911        while let Some(&match_index) = match_indices.peek() {
7912            if match_index >= range.end {
7913                break;
7914            }
7915
7916            match_indices.next();
7917            if match_index > offset {
7918                result.push((offset..match_index, syntax_highlight));
7919            }
7920
7921            let mut end_index = char_ix_after(match_index, text);
7922            while let Some(&next_match_index) = match_indices.peek() {
7923                if next_match_index == end_index && next_match_index < range.end {
7924                    end_index = char_ix_after(next_match_index, text);
7925                    match_indices.next();
7926                } else {
7927                    break;
7928                }
7929            }
7930
7931            let mut match_style = syntax_highlight;
7932            match_style.weight = Some(fonts::Weight::BOLD);
7933            result.push((match_index..end_index, match_style));
7934            offset = end_index;
7935        }
7936
7937        if offset < range.end {
7938            result.push((offset..range.end, syntax_highlight));
7939        }
7940    }
7941
7942    fn char_ix_after(ix: usize, text: &str) -> usize {
7943        ix + text[ix..].chars().next().unwrap().len_utf8()
7944    }
7945
7946    result
7947}
7948
7949pub fn styled_runs_for_code_label<'a>(
7950    label: &'a CodeLabel,
7951    syntax_theme: &'a theme::SyntaxTheme,
7952) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7953    let fade_out = HighlightStyle {
7954        fade_out: Some(0.35),
7955        ..Default::default()
7956    };
7957
7958    let mut prev_end = label.filter_range.end;
7959    label
7960        .runs
7961        .iter()
7962        .enumerate()
7963        .flat_map(move |(ix, (range, highlight_id))| {
7964            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7965                style
7966            } else {
7967                return Default::default();
7968            };
7969            let mut muted_style = style;
7970            muted_style.highlight(fade_out);
7971
7972            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7973            if range.start >= label.filter_range.end {
7974                if range.start > prev_end {
7975                    runs.push((prev_end..range.start, fade_out));
7976                }
7977                runs.push((range.clone(), muted_style));
7978            } else if range.end <= label.filter_range.end {
7979                runs.push((range.clone(), style));
7980            } else {
7981                runs.push((range.start..label.filter_range.end, style));
7982                runs.push((label.filter_range.end..range.end, muted_style));
7983            }
7984            prev_end = cmp::max(prev_end, range.end);
7985
7986            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7987                runs.push((prev_end..label.text.len(), fade_out));
7988            }
7989
7990            runs
7991        })
7992}
7993
7994pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7995    let mut index = 0;
7996    let mut codepoints = text.char_indices().peekable();
7997
7998    std::iter::from_fn(move || {
7999        let start_index = index;
8000        while let Some((new_index, codepoint)) = codepoints.next() {
8001            index = new_index + codepoint.len_utf8();
8002            let current_upper = codepoint.is_uppercase();
8003            let next_upper = codepoints
8004                .peek()
8005                .map(|(_, c)| c.is_uppercase())
8006                .unwrap_or(false);
8007
8008            if !current_upper && next_upper {
8009                return Some(&text[start_index..index]);
8010            }
8011        }
8012
8013        index = text.len();
8014        if start_index < text.len() {
8015            return Some(&text[start_index..]);
8016        }
8017        None
8018    })
8019    .flat_map(|word| word.split_inclusive('_'))
8020}
8021
8022trait RangeToAnchorExt {
8023    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8024}
8025
8026impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8027    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8028        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8029    }
8030}