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