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