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