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