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