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