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