editor.rs

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