editor.rs

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