editor.rs

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