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            cx.background().timer(Duration::from_millis(75)).await;
2794            let (completion, completions_cycling) = copilot.update(&mut cx, |copilot, cx| {
2795                (
2796                    copilot.completions(&buffer, buffer_position, cx),
2797                    copilot.completions_cycling(&buffer, buffer_position, cx),
2798                )
2799            });
2800
2801            let (completion, completions_cycling) = futures::join!(completion, completions_cycling);
2802            let mut completions = Vec::new();
2803            completions.extend(completion.log_err().into_iter().flatten());
2804            completions.extend(completions_cycling.log_err().into_iter().flatten());
2805            this.upgrade(&cx)?.update(&mut cx, |this, cx| {
2806                if !completions.is_empty() {
2807                    this.copilot_state.completions.clear();
2808                    this.copilot_state.active_completion_index = 0;
2809                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
2810                    for completion in completions {
2811                        this.copilot_state.push_completion(completion);
2812                    }
2813                    this.refresh_active_copilot_suggestion(cx);
2814                }
2815            });
2816
2817            Some(())
2818        });
2819
2820        Some(())
2821    }
2822
2823    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
2824        if self.copilot_state.completions.is_empty() {
2825            self.refresh_copilot_suggestions(cx);
2826            return;
2827        }
2828
2829        self.copilot_state.active_completion_index =
2830            (self.copilot_state.active_completion_index + 1) % self.copilot_state.completions.len();
2831
2832        self.refresh_active_copilot_suggestion(cx);
2833    }
2834
2835    fn previous_copilot_suggestion(
2836        &mut self,
2837        _: &copilot::PreviousSuggestion,
2838        cx: &mut ViewContext<Self>,
2839    ) {
2840        if self.copilot_state.completions.is_empty() {
2841            self.refresh_copilot_suggestions(cx);
2842            return;
2843        }
2844
2845        self.copilot_state.active_completion_index =
2846            if self.copilot_state.active_completion_index == 0 {
2847                self.copilot_state.completions.len() - 1
2848            } else {
2849                self.copilot_state.active_completion_index - 1
2850            };
2851
2852        self.refresh_active_copilot_suggestion(cx);
2853    }
2854
2855    fn refresh_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
2856        let snapshot = self.buffer.read(cx).snapshot(cx);
2857        let selection = self.selections.newest_anchor();
2858        let cursor = selection.head();
2859
2860        if self.context_menu.is_some() || selection.start != selection.end {
2861            self.display_map
2862                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
2863            cx.notify();
2864        } else if let Some(text) = self
2865            .copilot_state
2866            .text_for_active_completion(cursor, &snapshot)
2867        {
2868            self.display_map.update(cx, |map, cx| {
2869                map.replace_suggestion(
2870                    Some(Suggestion {
2871                        position: cursor,
2872                        text: text.into(),
2873                    }),
2874                    cx,
2875                )
2876            });
2877            cx.notify();
2878        } else if self.has_active_copilot_suggestion(cx) {
2879            self.display_map
2880                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
2881            cx.notify();
2882        }
2883    }
2884
2885    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
2886        let snapshot = self.buffer.read(cx).snapshot(cx);
2887        let cursor = self.selections.newest_anchor().head();
2888        if let Some(text) = self
2889            .copilot_state
2890            .text_for_active_completion(cursor, &snapshot)
2891        {
2892            self.insert_with_autoindent_mode(&text.to_string(), None, cx);
2893            self.clear_copilot_suggestions(cx);
2894            true
2895        } else {
2896            false
2897        }
2898    }
2899
2900    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) -> bool {
2901        self.display_map
2902            .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
2903        let was_empty = self.copilot_state.completions.is_empty();
2904        self.copilot_state.completions.clear();
2905        self.copilot_state.active_completion_index = 0;
2906        self.copilot_state.pending_refresh = Task::ready(None);
2907        self.copilot_state.excerpt_id = None;
2908        cx.notify();
2909        !was_empty
2910    }
2911
2912    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
2913        self.display_map.read(cx).has_suggestion()
2914    }
2915
2916    pub fn render_code_actions_indicator(
2917        &self,
2918        style: &EditorStyle,
2919        active: bool,
2920        cx: &mut RenderContext<Self>,
2921    ) -> Option<ElementBox> {
2922        if self.available_code_actions.is_some() {
2923            enum CodeActions {}
2924            Some(
2925                MouseEventHandler::<CodeActions>::new(0, cx, |state, _| {
2926                    Svg::new("icons/bolt_8.svg")
2927                        .with_color(style.code_actions.indicator.style_for(state, active).color)
2928                        .boxed()
2929                })
2930                .with_cursor_style(CursorStyle::PointingHand)
2931                .with_padding(Padding::uniform(3.))
2932                .on_down(MouseButton::Left, |_, cx| {
2933                    cx.dispatch_action(ToggleCodeActions {
2934                        deployed_from_indicator: true,
2935                    });
2936                })
2937                .boxed(),
2938            )
2939        } else {
2940            None
2941        }
2942    }
2943
2944    pub fn render_fold_indicators(
2945        &self,
2946        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
2947        style: &EditorStyle,
2948        gutter_hovered: bool,
2949        line_height: f32,
2950        gutter_margin: f32,
2951        cx: &mut RenderContext<Self>,
2952    ) -> Vec<Option<ElementBox>> {
2953        enum FoldIndicators {}
2954
2955        let style = style.folds.clone();
2956
2957        fold_data
2958            .iter()
2959            .enumerate()
2960            .map(|(ix, fold_data)| {
2961                fold_data
2962                    .map(|(fold_status, buffer_row, active)| {
2963                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
2964                            MouseEventHandler::<FoldIndicators>::new(
2965                                ix as usize,
2966                                cx,
2967                                |mouse_state, _| -> ElementBox {
2968                                    Svg::new(match fold_status {
2969                                        FoldStatus::Folded => style.folded_icon.clone(),
2970                                        FoldStatus::Foldable => style.foldable_icon.clone(),
2971                                    })
2972                                    .with_color(
2973                                        style
2974                                            .indicator
2975                                            .style_for(
2976                                                mouse_state,
2977                                                fold_status == FoldStatus::Folded,
2978                                            )
2979                                            .color,
2980                                    )
2981                                    .constrained()
2982                                    .with_width(gutter_margin * style.icon_margin_scale)
2983                                    .aligned()
2984                                    .constrained()
2985                                    .with_height(line_height)
2986                                    .with_width(gutter_margin)
2987                                    .aligned()
2988                                    .boxed()
2989                                },
2990                            )
2991                            .with_cursor_style(CursorStyle::PointingHand)
2992                            .with_padding(Padding::uniform(3.))
2993                            .on_click(MouseButton::Left, {
2994                                move |_, cx| {
2995                                    cx.dispatch_any_action(match fold_status {
2996                                        FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
2997                                        FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
2998                                    });
2999                                }
3000                            })
3001                            .boxed()
3002                        })
3003                    })
3004                    .flatten()
3005            })
3006            .collect()
3007    }
3008
3009    pub fn context_menu_visible(&self) -> bool {
3010        self.context_menu
3011            .as_ref()
3012            .map_or(false, |menu| menu.visible())
3013    }
3014
3015    pub fn render_context_menu(
3016        &self,
3017        cursor_position: DisplayPoint,
3018        style: EditorStyle,
3019        cx: &mut RenderContext<Editor>,
3020    ) -> Option<(DisplayPoint, ElementBox)> {
3021        self.context_menu
3022            .as_ref()
3023            .map(|menu| menu.render(cursor_position, style, cx))
3024    }
3025
3026    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3027        if !matches!(menu, ContextMenu::Completions(_)) {
3028            self.completion_tasks.clear();
3029        }
3030        self.context_menu = Some(menu);
3031        self.refresh_active_copilot_suggestion(cx);
3032        cx.notify();
3033    }
3034
3035    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3036        cx.notify();
3037        self.completion_tasks.clear();
3038        let context_menu = self.context_menu.take();
3039        self.refresh_active_copilot_suggestion(cx);
3040        context_menu
3041    }
3042
3043    pub fn insert_snippet(
3044        &mut self,
3045        insertion_ranges: &[Range<usize>],
3046        snippet: Snippet,
3047        cx: &mut ViewContext<Self>,
3048    ) -> Result<()> {
3049        let tabstops = self.buffer.update(cx, |buffer, cx| {
3050            let snippet_text: Arc<str> = snippet.text.clone().into();
3051            buffer.edit(
3052                insertion_ranges
3053                    .iter()
3054                    .cloned()
3055                    .map(|range| (range, snippet_text.clone())),
3056                Some(AutoindentMode::EachLine),
3057                cx,
3058            );
3059
3060            let snapshot = &*buffer.read(cx);
3061            let snippet = &snippet;
3062            snippet
3063                .tabstops
3064                .iter()
3065                .map(|tabstop| {
3066                    let mut tabstop_ranges = tabstop
3067                        .iter()
3068                        .flat_map(|tabstop_range| {
3069                            let mut delta = 0_isize;
3070                            insertion_ranges.iter().map(move |insertion_range| {
3071                                let insertion_start = insertion_range.start as isize + delta;
3072                                delta +=
3073                                    snippet.text.len() as isize - insertion_range.len() as isize;
3074
3075                                let start = snapshot.anchor_before(
3076                                    (insertion_start + tabstop_range.start) as usize,
3077                                );
3078                                let end = snapshot
3079                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3080                                start..end
3081                            })
3082                        })
3083                        .collect::<Vec<_>>();
3084                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3085                    tabstop_ranges
3086                })
3087                .collect::<Vec<_>>()
3088        });
3089
3090        if let Some(tabstop) = tabstops.first() {
3091            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3092                s.select_ranges(tabstop.iter().cloned());
3093            });
3094            self.snippet_stack.push(SnippetState {
3095                active_index: 0,
3096                ranges: tabstops,
3097            });
3098        }
3099
3100        Ok(())
3101    }
3102
3103    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3104        self.move_to_snippet_tabstop(Bias::Right, cx)
3105    }
3106
3107    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3108        self.move_to_snippet_tabstop(Bias::Left, cx)
3109    }
3110
3111    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3112        if let Some(mut snippet) = self.snippet_stack.pop() {
3113            match bias {
3114                Bias::Left => {
3115                    if snippet.active_index > 0 {
3116                        snippet.active_index -= 1;
3117                    } else {
3118                        self.snippet_stack.push(snippet);
3119                        return false;
3120                    }
3121                }
3122                Bias::Right => {
3123                    if snippet.active_index + 1 < snippet.ranges.len() {
3124                        snippet.active_index += 1;
3125                    } else {
3126                        self.snippet_stack.push(snippet);
3127                        return false;
3128                    }
3129                }
3130            }
3131            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3132                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3133                    s.select_anchor_ranges(current_ranges.iter().cloned())
3134                });
3135                // If snippet state is not at the last tabstop, push it back on the stack
3136                if snippet.active_index + 1 < snippet.ranges.len() {
3137                    self.snippet_stack.push(snippet);
3138                }
3139                return true;
3140            }
3141        }
3142
3143        false
3144    }
3145
3146    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3147        self.transact(cx, |this, cx| {
3148            this.select_all(&SelectAll, cx);
3149            this.insert("", cx);
3150        });
3151    }
3152
3153    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3154        self.transact(cx, |this, cx| {
3155            this.select_autoclose_pair(cx);
3156            let mut selections = this.selections.all::<Point>(cx);
3157            if !this.selections.line_mode {
3158                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3159                for selection in &mut selections {
3160                    if selection.is_empty() {
3161                        let old_head = selection.head();
3162                        let mut new_head =
3163                            movement::left(&display_map, old_head.to_display_point(&display_map))
3164                                .to_point(&display_map);
3165                        if let Some((buffer, line_buffer_range)) = display_map
3166                            .buffer_snapshot
3167                            .buffer_line_for_row(old_head.row)
3168                        {
3169                            let indent_size =
3170                                buffer.indent_size_for_line(line_buffer_range.start.row);
3171                            let language_name = buffer
3172                                .language_at(line_buffer_range.start)
3173                                .map(|language| language.name());
3174                            let indent_len = match indent_size.kind {
3175                                IndentKind::Space => {
3176                                    cx.global::<Settings>().tab_size(language_name.as_deref())
3177                                }
3178                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3179                            };
3180                            if old_head.column <= indent_size.len && old_head.column > 0 {
3181                                let indent_len = indent_len.get();
3182                                new_head = cmp::min(
3183                                    new_head,
3184                                    Point::new(
3185                                        old_head.row,
3186                                        ((old_head.column - 1) / indent_len) * indent_len,
3187                                    ),
3188                                );
3189                            }
3190                        }
3191
3192                        selection.set_head(new_head, SelectionGoal::None);
3193                    }
3194                }
3195            }
3196
3197            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3198            this.insert("", cx);
3199        });
3200    }
3201
3202    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3203        self.transact(cx, |this, cx| {
3204            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3205                let line_mode = s.line_mode;
3206                s.move_with(|map, selection| {
3207                    if selection.is_empty() && !line_mode {
3208                        let cursor = movement::right(map, selection.head());
3209                        selection.set_head(cursor, SelectionGoal::None);
3210                    }
3211                })
3212            });
3213            this.insert("", cx);
3214        });
3215    }
3216
3217    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3218        if self.move_to_prev_snippet_tabstop(cx) {
3219            return;
3220        }
3221
3222        self.outdent(&Outdent, cx);
3223    }
3224
3225    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3226        if self.accept_copilot_suggestion(cx) {
3227            return;
3228        }
3229
3230        if self.move_to_next_snippet_tabstop(cx) {
3231            return;
3232        }
3233
3234        let mut selections = self.selections.all_adjusted(cx);
3235        let buffer = self.buffer.read(cx);
3236        let snapshot = buffer.snapshot(cx);
3237        let rows_iter = selections.iter().map(|s| s.head().row);
3238        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3239
3240        let mut edits = Vec::new();
3241        let mut prev_edited_row = 0;
3242        let mut row_delta = 0;
3243        for selection in &mut selections {
3244            if selection.start.row != prev_edited_row {
3245                row_delta = 0;
3246            }
3247            prev_edited_row = selection.end.row;
3248
3249            // If the selection is non-empty, then increase the indentation of the selected lines.
3250            if !selection.is_empty() {
3251                row_delta =
3252                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3253                continue;
3254            }
3255
3256            // If the selection is empty and the cursor is in the leading whitespace before the
3257            // suggested indentation, then auto-indent the line.
3258            let cursor = selection.head();
3259            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3260                let current_indent = snapshot.indent_size_for_line(cursor.row);
3261                if cursor.column < suggested_indent.len
3262                    && cursor.column <= current_indent.len
3263                    && current_indent.len <= suggested_indent.len
3264                {
3265                    selection.start = Point::new(cursor.row, suggested_indent.len);
3266                    selection.end = selection.start;
3267                    if row_delta == 0 {
3268                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3269                            cursor.row,
3270                            current_indent,
3271                            suggested_indent,
3272                        ));
3273                        row_delta = suggested_indent.len - current_indent.len;
3274                    }
3275                    continue;
3276                }
3277            }
3278
3279            // Otherwise, insert a hard or soft tab.
3280            let settings = cx.global::<Settings>();
3281            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3282            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3283                IndentSize::tab()
3284            } else {
3285                let tab_size = settings.tab_size(language_name.as_deref()).get();
3286                let char_column = snapshot
3287                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3288                    .flat_map(str::chars)
3289                    .count()
3290                    + row_delta as usize;
3291                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3292                IndentSize::spaces(chars_to_next_tab_stop)
3293            };
3294            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3295            selection.end = selection.start;
3296            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3297            row_delta += tab_size.len;
3298        }
3299
3300        self.transact(cx, |this, cx| {
3301            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3302            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections))
3303        });
3304    }
3305
3306    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3307        let mut selections = self.selections.all::<Point>(cx);
3308        let mut prev_edited_row = 0;
3309        let mut row_delta = 0;
3310        let mut edits = Vec::new();
3311        let buffer = self.buffer.read(cx);
3312        let snapshot = buffer.snapshot(cx);
3313        for selection in &mut selections {
3314            if selection.start.row != prev_edited_row {
3315                row_delta = 0;
3316            }
3317            prev_edited_row = selection.end.row;
3318
3319            row_delta =
3320                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3321        }
3322
3323        self.transact(cx, |this, cx| {
3324            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3325            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3326        });
3327    }
3328
3329    fn indent_selection(
3330        buffer: &MultiBuffer,
3331        snapshot: &MultiBufferSnapshot,
3332        selection: &mut Selection<Point>,
3333        edits: &mut Vec<(Range<Point>, String)>,
3334        delta_for_start_row: u32,
3335        cx: &AppContext,
3336    ) -> u32 {
3337        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3338        let settings = cx.global::<Settings>();
3339        let tab_size = settings.tab_size(language_name.as_deref()).get();
3340        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3341            IndentKind::Tab
3342        } else {
3343            IndentKind::Space
3344        };
3345        let mut start_row = selection.start.row;
3346        let mut end_row = selection.end.row + 1;
3347
3348        // If a selection ends at the beginning of a line, don't indent
3349        // that last line.
3350        if selection.end.column == 0 {
3351            end_row -= 1;
3352        }
3353
3354        // Avoid re-indenting a row that has already been indented by a
3355        // previous selection, but still update this selection's column
3356        // to reflect that indentation.
3357        if delta_for_start_row > 0 {
3358            start_row += 1;
3359            selection.start.column += delta_for_start_row;
3360            if selection.end.row == selection.start.row {
3361                selection.end.column += delta_for_start_row;
3362            }
3363        }
3364
3365        let mut delta_for_end_row = 0;
3366        for row in start_row..end_row {
3367            let current_indent = snapshot.indent_size_for_line(row);
3368            let indent_delta = match (current_indent.kind, indent_kind) {
3369                (IndentKind::Space, IndentKind::Space) => {
3370                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3371                    IndentSize::spaces(columns_to_next_tab_stop)
3372                }
3373                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3374                (_, IndentKind::Tab) => IndentSize::tab(),
3375            };
3376
3377            let row_start = Point::new(row, 0);
3378            edits.push((
3379                row_start..row_start,
3380                indent_delta.chars().collect::<String>(),
3381            ));
3382
3383            // Update this selection's endpoints to reflect the indentation.
3384            if row == selection.start.row {
3385                selection.start.column += indent_delta.len;
3386            }
3387            if row == selection.end.row {
3388                selection.end.column += indent_delta.len;
3389                delta_for_end_row = indent_delta.len;
3390            }
3391        }
3392
3393        if selection.start.row == selection.end.row {
3394            delta_for_start_row + delta_for_end_row
3395        } else {
3396            delta_for_end_row
3397        }
3398    }
3399
3400    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3401        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3402        let selections = self.selections.all::<Point>(cx);
3403        let mut deletion_ranges = Vec::new();
3404        let mut last_outdent = None;
3405        {
3406            let buffer = self.buffer.read(cx);
3407            let snapshot = buffer.snapshot(cx);
3408            for selection in &selections {
3409                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3410                let tab_size = cx
3411                    .global::<Settings>()
3412                    .tab_size(language_name.as_deref())
3413                    .get();
3414                let mut rows = selection.spanned_rows(false, &display_map);
3415
3416                // Avoid re-outdenting a row that has already been outdented by a
3417                // previous selection.
3418                if let Some(last_row) = last_outdent {
3419                    if last_row == rows.start {
3420                        rows.start += 1;
3421                    }
3422                }
3423
3424                for row in rows {
3425                    let indent_size = snapshot.indent_size_for_line(row);
3426                    if indent_size.len > 0 {
3427                        let deletion_len = match indent_size.kind {
3428                            IndentKind::Space => {
3429                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3430                                if columns_to_prev_tab_stop == 0 {
3431                                    tab_size
3432                                } else {
3433                                    columns_to_prev_tab_stop
3434                                }
3435                            }
3436                            IndentKind::Tab => 1,
3437                        };
3438                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3439                        last_outdent = Some(row);
3440                    }
3441                }
3442            }
3443        }
3444
3445        self.transact(cx, |this, cx| {
3446            this.buffer.update(cx, |buffer, cx| {
3447                let empty_str: Arc<str> = "".into();
3448                buffer.edit(
3449                    deletion_ranges
3450                        .into_iter()
3451                        .map(|range| (range, empty_str.clone())),
3452                    None,
3453                    cx,
3454                );
3455            });
3456            let selections = this.selections.all::<usize>(cx);
3457            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3458        });
3459    }
3460
3461    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3462        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3463        let selections = self.selections.all::<Point>(cx);
3464
3465        let mut new_cursors = Vec::new();
3466        let mut edit_ranges = Vec::new();
3467        let mut selections = selections.iter().peekable();
3468        while let Some(selection) = selections.next() {
3469            let mut rows = selection.spanned_rows(false, &display_map);
3470            let goal_display_column = selection.head().to_display_point(&display_map).column();
3471
3472            // Accumulate contiguous regions of rows that we want to delete.
3473            while let Some(next_selection) = selections.peek() {
3474                let next_rows = next_selection.spanned_rows(false, &display_map);
3475                if next_rows.start <= rows.end {
3476                    rows.end = next_rows.end;
3477                    selections.next().unwrap();
3478                } else {
3479                    break;
3480                }
3481            }
3482
3483            let buffer = &display_map.buffer_snapshot;
3484            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3485            let edit_end;
3486            let cursor_buffer_row;
3487            if buffer.max_point().row >= rows.end {
3488                // If there's a line after the range, delete the \n from the end of the row range
3489                // and position the cursor on the next line.
3490                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3491                cursor_buffer_row = rows.end;
3492            } else {
3493                // If there isn't a line after the range, delete the \n from the line before the
3494                // start of the row range and position the cursor there.
3495                edit_start = edit_start.saturating_sub(1);
3496                edit_end = buffer.len();
3497                cursor_buffer_row = rows.start.saturating_sub(1);
3498            }
3499
3500            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3501            *cursor.column_mut() =
3502                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3503
3504            new_cursors.push((
3505                selection.id,
3506                buffer.anchor_after(cursor.to_point(&display_map)),
3507            ));
3508            edit_ranges.push(edit_start..edit_end);
3509        }
3510
3511        self.transact(cx, |this, cx| {
3512            let buffer = this.buffer.update(cx, |buffer, cx| {
3513                let empty_str: Arc<str> = "".into();
3514                buffer.edit(
3515                    edit_ranges
3516                        .into_iter()
3517                        .map(|range| (range, empty_str.clone())),
3518                    None,
3519                    cx,
3520                );
3521                buffer.snapshot(cx)
3522            });
3523            let new_selections = new_cursors
3524                .into_iter()
3525                .map(|(id, cursor)| {
3526                    let cursor = cursor.to_point(&buffer);
3527                    Selection {
3528                        id,
3529                        start: cursor,
3530                        end: cursor,
3531                        reversed: false,
3532                        goal: SelectionGoal::None,
3533                    }
3534                })
3535                .collect();
3536
3537            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3538                s.select(new_selections);
3539            });
3540        });
3541    }
3542
3543    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3544        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3545        let buffer = &display_map.buffer_snapshot;
3546        let selections = self.selections.all::<Point>(cx);
3547
3548        let mut edits = Vec::new();
3549        let mut selections_iter = selections.iter().peekable();
3550        while let Some(selection) = selections_iter.next() {
3551            // Avoid duplicating the same lines twice.
3552            let mut rows = selection.spanned_rows(false, &display_map);
3553
3554            while let Some(next_selection) = selections_iter.peek() {
3555                let next_rows = next_selection.spanned_rows(false, &display_map);
3556                if next_rows.start < rows.end {
3557                    rows.end = next_rows.end;
3558                    selections_iter.next().unwrap();
3559                } else {
3560                    break;
3561                }
3562            }
3563
3564            // Copy the text from the selected row region and splice it at the start of the region.
3565            let start = Point::new(rows.start, 0);
3566            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3567            let text = buffer
3568                .text_for_range(start..end)
3569                .chain(Some("\n"))
3570                .collect::<String>();
3571            edits.push((start..start, text));
3572        }
3573
3574        self.transact(cx, |this, cx| {
3575            this.buffer.update(cx, |buffer, cx| {
3576                buffer.edit(edits, None, cx);
3577            });
3578
3579            this.request_autoscroll(Autoscroll::fit(), cx);
3580        });
3581    }
3582
3583    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3584        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3585        let buffer = self.buffer.read(cx).snapshot(cx);
3586
3587        let mut edits = Vec::new();
3588        let mut unfold_ranges = Vec::new();
3589        let mut refold_ranges = Vec::new();
3590
3591        let selections = self.selections.all::<Point>(cx);
3592        let mut selections = selections.iter().peekable();
3593        let mut contiguous_row_selections = Vec::new();
3594        let mut new_selections = Vec::new();
3595
3596        while let Some(selection) = selections.next() {
3597            // Find all the selections that span a contiguous row range
3598            let (start_row, end_row) = consume_contiguous_rows(
3599                &mut contiguous_row_selections,
3600                selection,
3601                &display_map,
3602                &mut selections,
3603            );
3604
3605            // Move the text spanned by the row range to be before the line preceding the row range
3606            if start_row > 0 {
3607                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3608                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3609                let insertion_point = display_map
3610                    .prev_line_boundary(Point::new(start_row - 1, 0))
3611                    .0;
3612
3613                // Don't move lines across excerpts
3614                if buffer
3615                    .excerpt_boundaries_in_range((
3616                        Bound::Excluded(insertion_point),
3617                        Bound::Included(range_to_move.end),
3618                    ))
3619                    .next()
3620                    .is_none()
3621                {
3622                    let text = buffer
3623                        .text_for_range(range_to_move.clone())
3624                        .flat_map(|s| s.chars())
3625                        .skip(1)
3626                        .chain(['\n'])
3627                        .collect::<String>();
3628
3629                    edits.push((
3630                        buffer.anchor_after(range_to_move.start)
3631                            ..buffer.anchor_before(range_to_move.end),
3632                        String::new(),
3633                    ));
3634                    let insertion_anchor = buffer.anchor_after(insertion_point);
3635                    edits.push((insertion_anchor..insertion_anchor, text));
3636
3637                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3638
3639                    // Move selections up
3640                    new_selections.extend(contiguous_row_selections.drain(..).map(
3641                        |mut selection| {
3642                            selection.start.row -= row_delta;
3643                            selection.end.row -= row_delta;
3644                            selection
3645                        },
3646                    ));
3647
3648                    // Move folds up
3649                    unfold_ranges.push(range_to_move.clone());
3650                    for fold in display_map.folds_in_range(
3651                        buffer.anchor_before(range_to_move.start)
3652                            ..buffer.anchor_after(range_to_move.end),
3653                    ) {
3654                        let mut start = fold.start.to_point(&buffer);
3655                        let mut end = fold.end.to_point(&buffer);
3656                        start.row -= row_delta;
3657                        end.row -= row_delta;
3658                        refold_ranges.push(start..end);
3659                    }
3660                }
3661            }
3662
3663            // If we didn't move line(s), preserve the existing selections
3664            new_selections.append(&mut contiguous_row_selections);
3665        }
3666
3667        self.transact(cx, |this, cx| {
3668            this.unfold_ranges(unfold_ranges, true, true, cx);
3669            this.buffer.update(cx, |buffer, cx| {
3670                for (range, text) in edits {
3671                    buffer.edit([(range, text)], None, cx);
3672                }
3673            });
3674            this.fold_ranges(refold_ranges, true, cx);
3675            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3676                s.select(new_selections);
3677            })
3678        });
3679    }
3680
3681    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3682        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3683        let buffer = self.buffer.read(cx).snapshot(cx);
3684
3685        let mut edits = Vec::new();
3686        let mut unfold_ranges = Vec::new();
3687        let mut refold_ranges = Vec::new();
3688
3689        let selections = self.selections.all::<Point>(cx);
3690        let mut selections = selections.iter().peekable();
3691        let mut contiguous_row_selections = Vec::new();
3692        let mut new_selections = Vec::new();
3693
3694        while let Some(selection) = selections.next() {
3695            // Find all the selections that span a contiguous row range
3696            let (start_row, end_row) = consume_contiguous_rows(
3697                &mut contiguous_row_selections,
3698                selection,
3699                &display_map,
3700                &mut selections,
3701            );
3702
3703            // Move the text spanned by the row range to be after the last line of the row range
3704            if end_row <= buffer.max_point().row {
3705                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3706                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3707
3708                // Don't move lines across excerpt boundaries
3709                if buffer
3710                    .excerpt_boundaries_in_range((
3711                        Bound::Excluded(range_to_move.start),
3712                        Bound::Included(insertion_point),
3713                    ))
3714                    .next()
3715                    .is_none()
3716                {
3717                    let mut text = String::from("\n");
3718                    text.extend(buffer.text_for_range(range_to_move.clone()));
3719                    text.pop(); // Drop trailing newline
3720                    edits.push((
3721                        buffer.anchor_after(range_to_move.start)
3722                            ..buffer.anchor_before(range_to_move.end),
3723                        String::new(),
3724                    ));
3725                    let insertion_anchor = buffer.anchor_after(insertion_point);
3726                    edits.push((insertion_anchor..insertion_anchor, text));
3727
3728                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3729
3730                    // Move selections down
3731                    new_selections.extend(contiguous_row_selections.drain(..).map(
3732                        |mut selection| {
3733                            selection.start.row += row_delta;
3734                            selection.end.row += row_delta;
3735                            selection
3736                        },
3737                    ));
3738
3739                    // Move folds down
3740                    unfold_ranges.push(range_to_move.clone());
3741                    for fold in display_map.folds_in_range(
3742                        buffer.anchor_before(range_to_move.start)
3743                            ..buffer.anchor_after(range_to_move.end),
3744                    ) {
3745                        let mut start = fold.start.to_point(&buffer);
3746                        let mut end = fold.end.to_point(&buffer);
3747                        start.row += row_delta;
3748                        end.row += row_delta;
3749                        refold_ranges.push(start..end);
3750                    }
3751                }
3752            }
3753
3754            // If we didn't move line(s), preserve the existing selections
3755            new_selections.append(&mut contiguous_row_selections);
3756        }
3757
3758        self.transact(cx, |this, cx| {
3759            this.unfold_ranges(unfold_ranges, true, true, cx);
3760            this.buffer.update(cx, |buffer, cx| {
3761                for (range, text) in edits {
3762                    buffer.edit([(range, text)], None, cx);
3763                }
3764            });
3765            this.fold_ranges(refold_ranges, true, cx);
3766            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
3767        });
3768    }
3769
3770    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3771        self.transact(cx, |this, cx| {
3772            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3773                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3774                let line_mode = s.line_mode;
3775                s.move_with(|display_map, selection| {
3776                    if !selection.is_empty() || line_mode {
3777                        return;
3778                    }
3779
3780                    let mut head = selection.head();
3781                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3782                    if head.column() == display_map.line_len(head.row()) {
3783                        transpose_offset = display_map
3784                            .buffer_snapshot
3785                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3786                    }
3787
3788                    if transpose_offset == 0 {
3789                        return;
3790                    }
3791
3792                    *head.column_mut() += 1;
3793                    head = display_map.clip_point(head, Bias::Right);
3794                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3795
3796                    let transpose_start = display_map
3797                        .buffer_snapshot
3798                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3799                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3800                        let transpose_end = display_map
3801                            .buffer_snapshot
3802                            .clip_offset(transpose_offset + 1, Bias::Right);
3803                        if let Some(ch) =
3804                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3805                        {
3806                            edits.push((transpose_start..transpose_offset, String::new()));
3807                            edits.push((transpose_end..transpose_end, ch.to_string()));
3808                        }
3809                    }
3810                });
3811                edits
3812            });
3813            this.buffer
3814                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3815            let selections = this.selections.all::<usize>(cx);
3816            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3817                s.select(selections);
3818            });
3819        });
3820    }
3821
3822    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3823        let mut text = String::new();
3824        let buffer = self.buffer.read(cx).snapshot(cx);
3825        let mut selections = self.selections.all::<Point>(cx);
3826        let mut clipboard_selections = Vec::with_capacity(selections.len());
3827        {
3828            let max_point = buffer.max_point();
3829            for selection in &mut selections {
3830                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3831                if is_entire_line {
3832                    selection.start = Point::new(selection.start.row, 0);
3833                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3834                    selection.goal = SelectionGoal::None;
3835                }
3836                let mut len = 0;
3837                for chunk in buffer.text_for_range(selection.start..selection.end) {
3838                    text.push_str(chunk);
3839                    len += chunk.len();
3840                }
3841                clipboard_selections.push(ClipboardSelection {
3842                    len,
3843                    is_entire_line,
3844                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3845                });
3846            }
3847        }
3848
3849        self.transact(cx, |this, cx| {
3850            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3851                s.select(selections);
3852            });
3853            this.insert("", cx);
3854            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3855        });
3856    }
3857
3858    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3859        let selections = self.selections.all::<Point>(cx);
3860        let buffer = self.buffer.read(cx).read(cx);
3861        let mut text = String::new();
3862
3863        let mut clipboard_selections = Vec::with_capacity(selections.len());
3864        {
3865            let max_point = buffer.max_point();
3866            for selection in selections.iter() {
3867                let mut start = selection.start;
3868                let mut end = selection.end;
3869                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3870                if is_entire_line {
3871                    start = Point::new(start.row, 0);
3872                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3873                }
3874                let mut len = 0;
3875                for chunk in buffer.text_for_range(start..end) {
3876                    text.push_str(chunk);
3877                    len += chunk.len();
3878                }
3879                clipboard_selections.push(ClipboardSelection {
3880                    len,
3881                    is_entire_line,
3882                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3883                });
3884            }
3885        }
3886
3887        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3888    }
3889
3890    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3891        self.transact(cx, |this, cx| {
3892            if let Some(item) = cx.as_mut().read_from_clipboard() {
3893                let mut clipboard_text = Cow::Borrowed(item.text());
3894                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3895                    let old_selections = this.selections.all::<usize>(cx);
3896                    let all_selections_were_entire_line =
3897                        clipboard_selections.iter().all(|s| s.is_entire_line);
3898                    let first_selection_indent_column =
3899                        clipboard_selections.first().map(|s| s.first_line_indent);
3900                    if clipboard_selections.len() != old_selections.len() {
3901                        let mut newline_separated_text = String::new();
3902                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3903                        let mut ix = 0;
3904                        while let Some(clipboard_selection) = clipboard_selections.next() {
3905                            newline_separated_text
3906                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3907                            ix += clipboard_selection.len;
3908                            if clipboard_selections.peek().is_some() {
3909                                newline_separated_text.push('\n');
3910                            }
3911                        }
3912                        clipboard_text = Cow::Owned(newline_separated_text);
3913                    }
3914
3915                    this.buffer.update(cx, |buffer, cx| {
3916                        let snapshot = buffer.read(cx);
3917                        let mut start_offset = 0;
3918                        let mut edits = Vec::new();
3919                        let mut original_indent_columns = Vec::new();
3920                        let line_mode = this.selections.line_mode;
3921                        for (ix, selection) in old_selections.iter().enumerate() {
3922                            let to_insert;
3923                            let entire_line;
3924                            let original_indent_column;
3925                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3926                                let end_offset = start_offset + clipboard_selection.len;
3927                                to_insert = &clipboard_text[start_offset..end_offset];
3928                                entire_line = clipboard_selection.is_entire_line;
3929                                start_offset = end_offset;
3930                                original_indent_column =
3931                                    Some(clipboard_selection.first_line_indent);
3932                            } else {
3933                                to_insert = clipboard_text.as_str();
3934                                entire_line = all_selections_were_entire_line;
3935                                original_indent_column = first_selection_indent_column
3936                            }
3937
3938                            // If the corresponding selection was empty when this slice of the
3939                            // clipboard text was written, then the entire line containing the
3940                            // selection was copied. If this selection is also currently empty,
3941                            // then paste the line before the current line of the buffer.
3942                            let range = if selection.is_empty() && !line_mode && entire_line {
3943                                let column = selection.start.to_point(&snapshot).column as usize;
3944                                let line_start = selection.start - column;
3945                                line_start..line_start
3946                            } else {
3947                                selection.range()
3948                            };
3949
3950                            edits.push((range, to_insert));
3951                            original_indent_columns.extend(original_indent_column);
3952                        }
3953                        drop(snapshot);
3954
3955                        buffer.edit(
3956                            edits,
3957                            Some(AutoindentMode::Block {
3958                                original_indent_columns,
3959                            }),
3960                            cx,
3961                        );
3962                    });
3963
3964                    let selections = this.selections.all::<usize>(cx);
3965                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3966                } else {
3967                    this.insert(&clipboard_text, cx);
3968                }
3969            }
3970        });
3971    }
3972
3973    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3974        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3975            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3976                self.change_selections(None, cx, |s| {
3977                    s.select_anchors(selections.to_vec());
3978                });
3979            }
3980            self.request_autoscroll(Autoscroll::fit(), cx);
3981            self.unmark_text(cx);
3982            cx.emit(Event::Edited);
3983        }
3984    }
3985
3986    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3987        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3988            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3989            {
3990                self.change_selections(None, cx, |s| {
3991                    s.select_anchors(selections.to_vec());
3992                });
3993            }
3994            self.request_autoscroll(Autoscroll::fit(), cx);
3995            self.unmark_text(cx);
3996            cx.emit(Event::Edited);
3997        }
3998    }
3999
4000    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4001        self.buffer
4002            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4003    }
4004
4005    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4006        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4007            let line_mode = s.line_mode;
4008            s.move_with(|map, selection| {
4009                let cursor = if selection.is_empty() && !line_mode {
4010                    movement::left(map, selection.start)
4011                } else {
4012                    selection.start
4013                };
4014                selection.collapse_to(cursor, SelectionGoal::None);
4015            });
4016        })
4017    }
4018
4019    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4020        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4021            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4022        })
4023    }
4024
4025    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4026        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4027            let line_mode = s.line_mode;
4028            s.move_with(|map, selection| {
4029                let cursor = if selection.is_empty() && !line_mode {
4030                    movement::right(map, selection.end)
4031                } else {
4032                    selection.end
4033                };
4034                selection.collapse_to(cursor, SelectionGoal::None)
4035            });
4036        })
4037    }
4038
4039    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4040        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4041            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4042        })
4043    }
4044
4045    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4046        if self.take_rename(true, cx).is_some() {
4047            return;
4048        }
4049
4050        if let Some(context_menu) = self.context_menu.as_mut() {
4051            if context_menu.select_prev(cx) {
4052                return;
4053            }
4054        }
4055
4056        if matches!(self.mode, EditorMode::SingleLine) {
4057            cx.propagate_action();
4058            return;
4059        }
4060
4061        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4062            let line_mode = s.line_mode;
4063            s.move_with(|map, selection| {
4064                if !selection.is_empty() && !line_mode {
4065                    selection.goal = SelectionGoal::None;
4066                }
4067                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4068                selection.collapse_to(cursor, goal);
4069            });
4070        })
4071    }
4072
4073    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4074        if self.take_rename(true, cx).is_some() {
4075            return;
4076        }
4077
4078        if self
4079            .context_menu
4080            .as_mut()
4081            .map(|menu| menu.select_first(cx))
4082            .unwrap_or(false)
4083        {
4084            return;
4085        }
4086
4087        if matches!(self.mode, EditorMode::SingleLine) {
4088            cx.propagate_action();
4089            return;
4090        }
4091
4092        let row_count = if let Some(row_count) = self.visible_line_count() {
4093            row_count as u32 - 1
4094        } else {
4095            return;
4096        };
4097
4098        let autoscroll = if action.center_cursor {
4099            Autoscroll::center()
4100        } else {
4101            Autoscroll::fit()
4102        };
4103
4104        self.change_selections(Some(autoscroll), cx, |s| {
4105            let line_mode = s.line_mode;
4106            s.move_with(|map, selection| {
4107                if !selection.is_empty() && !line_mode {
4108                    selection.goal = SelectionGoal::None;
4109                }
4110                let (cursor, goal) =
4111                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4112                selection.collapse_to(cursor, goal);
4113            });
4114        });
4115    }
4116
4117    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4118        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4119            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4120        })
4121    }
4122
4123    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4124        self.take_rename(true, cx);
4125
4126        if let Some(context_menu) = self.context_menu.as_mut() {
4127            if context_menu.select_next(cx) {
4128                return;
4129            }
4130        }
4131
4132        if self.mode == EditorMode::SingleLine {
4133            cx.propagate_action();
4134            return;
4135        }
4136
4137        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4138            let line_mode = s.line_mode;
4139            s.move_with(|map, selection| {
4140                if !selection.is_empty() && !line_mode {
4141                    selection.goal = SelectionGoal::None;
4142                }
4143                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4144                selection.collapse_to(cursor, goal);
4145            });
4146        });
4147    }
4148
4149    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4150        if self.take_rename(true, cx).is_some() {
4151            return;
4152        }
4153
4154        if self
4155            .context_menu
4156            .as_mut()
4157            .map(|menu| menu.select_last(cx))
4158            .unwrap_or(false)
4159        {
4160            return;
4161        }
4162
4163        if matches!(self.mode, EditorMode::SingleLine) {
4164            cx.propagate_action();
4165            return;
4166        }
4167
4168        let row_count = if let Some(row_count) = self.visible_line_count() {
4169            row_count as u32 - 1
4170        } else {
4171            return;
4172        };
4173
4174        let autoscroll = if action.center_cursor {
4175            Autoscroll::center()
4176        } else {
4177            Autoscroll::fit()
4178        };
4179
4180        self.change_selections(Some(autoscroll), cx, |s| {
4181            let line_mode = s.line_mode;
4182            s.move_with(|map, selection| {
4183                if !selection.is_empty() && !line_mode {
4184                    selection.goal = SelectionGoal::None;
4185                }
4186                let (cursor, goal) =
4187                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4188                selection.collapse_to(cursor, goal);
4189            });
4190        });
4191    }
4192
4193    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4194        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4195            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4196        });
4197    }
4198
4199    pub fn move_to_previous_word_start(
4200        &mut self,
4201        _: &MoveToPreviousWordStart,
4202        cx: &mut ViewContext<Self>,
4203    ) {
4204        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4205            s.move_cursors_with(|map, head, _| {
4206                (
4207                    movement::previous_word_start(map, head),
4208                    SelectionGoal::None,
4209                )
4210            });
4211        })
4212    }
4213
4214    pub fn move_to_previous_subword_start(
4215        &mut self,
4216        _: &MoveToPreviousSubwordStart,
4217        cx: &mut ViewContext<Self>,
4218    ) {
4219        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4220            s.move_cursors_with(|map, head, _| {
4221                (
4222                    movement::previous_subword_start(map, head),
4223                    SelectionGoal::None,
4224                )
4225            });
4226        })
4227    }
4228
4229    pub fn select_to_previous_word_start(
4230        &mut self,
4231        _: &SelectToPreviousWordStart,
4232        cx: &mut ViewContext<Self>,
4233    ) {
4234        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4235            s.move_heads_with(|map, head, _| {
4236                (
4237                    movement::previous_word_start(map, head),
4238                    SelectionGoal::None,
4239                )
4240            });
4241        })
4242    }
4243
4244    pub fn select_to_previous_subword_start(
4245        &mut self,
4246        _: &SelectToPreviousSubwordStart,
4247        cx: &mut ViewContext<Self>,
4248    ) {
4249        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4250            s.move_heads_with(|map, head, _| {
4251                (
4252                    movement::previous_subword_start(map, head),
4253                    SelectionGoal::None,
4254                )
4255            });
4256        })
4257    }
4258
4259    pub fn delete_to_previous_word_start(
4260        &mut self,
4261        _: &DeleteToPreviousWordStart,
4262        cx: &mut ViewContext<Self>,
4263    ) {
4264        self.transact(cx, |this, cx| {
4265            this.select_autoclose_pair(cx);
4266            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4267                let line_mode = s.line_mode;
4268                s.move_with(|map, selection| {
4269                    if selection.is_empty() && !line_mode {
4270                        let cursor = movement::previous_word_start(map, selection.head());
4271                        selection.set_head(cursor, SelectionGoal::None);
4272                    }
4273                });
4274            });
4275            this.insert("", cx);
4276        });
4277    }
4278
4279    pub fn delete_to_previous_subword_start(
4280        &mut self,
4281        _: &DeleteToPreviousSubwordStart,
4282        cx: &mut ViewContext<Self>,
4283    ) {
4284        self.transact(cx, |this, cx| {
4285            this.select_autoclose_pair(cx);
4286            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4287                let line_mode = s.line_mode;
4288                s.move_with(|map, selection| {
4289                    if selection.is_empty() && !line_mode {
4290                        let cursor = movement::previous_subword_start(map, selection.head());
4291                        selection.set_head(cursor, SelectionGoal::None);
4292                    }
4293                });
4294            });
4295            this.insert("", cx);
4296        });
4297    }
4298
4299    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4300        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4301            s.move_cursors_with(|map, head, _| {
4302                (movement::next_word_end(map, head), SelectionGoal::None)
4303            });
4304        })
4305    }
4306
4307    pub fn move_to_next_subword_end(
4308        &mut self,
4309        _: &MoveToNextSubwordEnd,
4310        cx: &mut ViewContext<Self>,
4311    ) {
4312        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4313            s.move_cursors_with(|map, head, _| {
4314                (movement::next_subword_end(map, head), SelectionGoal::None)
4315            });
4316        })
4317    }
4318
4319    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4320        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4321            s.move_heads_with(|map, head, _| {
4322                (movement::next_word_end(map, head), SelectionGoal::None)
4323            });
4324        })
4325    }
4326
4327    pub fn select_to_next_subword_end(
4328        &mut self,
4329        _: &SelectToNextSubwordEnd,
4330        cx: &mut ViewContext<Self>,
4331    ) {
4332        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4333            s.move_heads_with(|map, head, _| {
4334                (movement::next_subword_end(map, head), SelectionGoal::None)
4335            });
4336        })
4337    }
4338
4339    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4340        self.transact(cx, |this, cx| {
4341            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4342                let line_mode = s.line_mode;
4343                s.move_with(|map, selection| {
4344                    if selection.is_empty() && !line_mode {
4345                        let cursor = movement::next_word_end(map, selection.head());
4346                        selection.set_head(cursor, SelectionGoal::None);
4347                    }
4348                });
4349            });
4350            this.insert("", cx);
4351        });
4352    }
4353
4354    pub fn delete_to_next_subword_end(
4355        &mut self,
4356        _: &DeleteToNextSubwordEnd,
4357        cx: &mut ViewContext<Self>,
4358    ) {
4359        self.transact(cx, |this, cx| {
4360            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4361                s.move_with(|map, selection| {
4362                    if selection.is_empty() {
4363                        let cursor = movement::next_subword_end(map, selection.head());
4364                        selection.set_head(cursor, SelectionGoal::None);
4365                    }
4366                });
4367            });
4368            this.insert("", cx);
4369        });
4370    }
4371
4372    pub fn move_to_beginning_of_line(
4373        &mut self,
4374        _: &MoveToBeginningOfLine,
4375        cx: &mut ViewContext<Self>,
4376    ) {
4377        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4378            s.move_cursors_with(|map, head, _| {
4379                (
4380                    movement::indented_line_beginning(map, head, true),
4381                    SelectionGoal::None,
4382                )
4383            });
4384        })
4385    }
4386
4387    pub fn select_to_beginning_of_line(
4388        &mut self,
4389        action: &SelectToBeginningOfLine,
4390        cx: &mut ViewContext<Self>,
4391    ) {
4392        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4393            s.move_heads_with(|map, head, _| {
4394                (
4395                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4396                    SelectionGoal::None,
4397                )
4398            });
4399        });
4400    }
4401
4402    pub fn delete_to_beginning_of_line(
4403        &mut self,
4404        _: &DeleteToBeginningOfLine,
4405        cx: &mut ViewContext<Self>,
4406    ) {
4407        self.transact(cx, |this, cx| {
4408            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4409                s.move_with(|_, selection| {
4410                    selection.reversed = true;
4411                });
4412            });
4413
4414            this.select_to_beginning_of_line(
4415                &SelectToBeginningOfLine {
4416                    stop_at_soft_wraps: false,
4417                },
4418                cx,
4419            );
4420            this.backspace(&Backspace, cx);
4421        });
4422    }
4423
4424    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4425        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4426            s.move_cursors_with(|map, head, _| {
4427                (movement::line_end(map, head, true), SelectionGoal::None)
4428            });
4429        })
4430    }
4431
4432    pub fn select_to_end_of_line(
4433        &mut self,
4434        action: &SelectToEndOfLine,
4435        cx: &mut ViewContext<Self>,
4436    ) {
4437        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4438            s.move_heads_with(|map, head, _| {
4439                (
4440                    movement::line_end(map, head, action.stop_at_soft_wraps),
4441                    SelectionGoal::None,
4442                )
4443            });
4444        })
4445    }
4446
4447    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4448        self.transact(cx, |this, cx| {
4449            this.select_to_end_of_line(
4450                &SelectToEndOfLine {
4451                    stop_at_soft_wraps: false,
4452                },
4453                cx,
4454            );
4455            this.delete(&Delete, cx);
4456        });
4457    }
4458
4459    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4460        self.transact(cx, |this, cx| {
4461            this.select_to_end_of_line(
4462                &SelectToEndOfLine {
4463                    stop_at_soft_wraps: false,
4464                },
4465                cx,
4466            );
4467            this.cut(&Cut, cx);
4468        });
4469    }
4470
4471    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4472        if matches!(self.mode, EditorMode::SingleLine) {
4473            cx.propagate_action();
4474            return;
4475        }
4476
4477        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4478            s.select_ranges(vec![0..0]);
4479        });
4480    }
4481
4482    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4483        let mut selection = self.selections.last::<Point>(cx);
4484        selection.set_head(Point::zero(), SelectionGoal::None);
4485
4486        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4487            s.select(vec![selection]);
4488        });
4489    }
4490
4491    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4492        if matches!(self.mode, EditorMode::SingleLine) {
4493            cx.propagate_action();
4494            return;
4495        }
4496
4497        let cursor = self.buffer.read(cx).read(cx).len();
4498        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4499            s.select_ranges(vec![cursor..cursor])
4500        });
4501    }
4502
4503    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4504        self.nav_history = nav_history;
4505    }
4506
4507    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4508        self.nav_history.as_ref()
4509    }
4510
4511    fn push_to_nav_history(
4512        &self,
4513        cursor_anchor: Anchor,
4514        new_position: Option<Point>,
4515        cx: &mut ViewContext<Self>,
4516    ) {
4517        if let Some(nav_history) = &self.nav_history {
4518            let buffer = self.buffer.read(cx).read(cx);
4519            let cursor_position = cursor_anchor.to_point(&buffer);
4520            let scroll_state = self.scroll_manager.anchor();
4521            let scroll_top_row = scroll_state.top_row(&buffer);
4522            drop(buffer);
4523
4524            if let Some(new_position) = new_position {
4525                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4526                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4527                    return;
4528                }
4529            }
4530
4531            nav_history.push(
4532                Some(NavigationData {
4533                    cursor_anchor,
4534                    cursor_position,
4535                    scroll_anchor: scroll_state,
4536                    scroll_top_row,
4537                }),
4538                cx,
4539            );
4540        }
4541    }
4542
4543    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4544        let buffer = self.buffer.read(cx).snapshot(cx);
4545        let mut selection = self.selections.first::<usize>(cx);
4546        selection.set_head(buffer.len(), SelectionGoal::None);
4547        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4548            s.select(vec![selection]);
4549        });
4550    }
4551
4552    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4553        let end = self.buffer.read(cx).read(cx).len();
4554        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4555            s.select_ranges(vec![0..end]);
4556        });
4557    }
4558
4559    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4560        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4561        let mut selections = self.selections.all::<Point>(cx);
4562        let max_point = display_map.buffer_snapshot.max_point();
4563        for selection in &mut selections {
4564            let rows = selection.spanned_rows(true, &display_map);
4565            selection.start = Point::new(rows.start, 0);
4566            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4567            selection.reversed = false;
4568        }
4569        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4570            s.select(selections);
4571        });
4572    }
4573
4574    pub fn split_selection_into_lines(
4575        &mut self,
4576        _: &SplitSelectionIntoLines,
4577        cx: &mut ViewContext<Self>,
4578    ) {
4579        let mut to_unfold = Vec::new();
4580        let mut new_selection_ranges = Vec::new();
4581        {
4582            let selections = self.selections.all::<Point>(cx);
4583            let buffer = self.buffer.read(cx).read(cx);
4584            for selection in selections {
4585                for row in selection.start.row..selection.end.row {
4586                    let cursor = Point::new(row, buffer.line_len(row));
4587                    new_selection_ranges.push(cursor..cursor);
4588                }
4589                new_selection_ranges.push(selection.end..selection.end);
4590                to_unfold.push(selection.start..selection.end);
4591            }
4592        }
4593        self.unfold_ranges(to_unfold, true, true, cx);
4594        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4595            s.select_ranges(new_selection_ranges);
4596        });
4597    }
4598
4599    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4600        self.add_selection(true, cx);
4601    }
4602
4603    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4604        self.add_selection(false, cx);
4605    }
4606
4607    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4608        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4609        let mut selections = self.selections.all::<Point>(cx);
4610        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4611            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4612            let range = oldest_selection.display_range(&display_map).sorted();
4613            let columns = cmp::min(range.start.column(), range.end.column())
4614                ..cmp::max(range.start.column(), range.end.column());
4615
4616            selections.clear();
4617            let mut stack = Vec::new();
4618            for row in range.start.row()..=range.end.row() {
4619                if let Some(selection) = self.selections.build_columnar_selection(
4620                    &display_map,
4621                    row,
4622                    &columns,
4623                    oldest_selection.reversed,
4624                ) {
4625                    stack.push(selection.id);
4626                    selections.push(selection);
4627                }
4628            }
4629
4630            if above {
4631                stack.reverse();
4632            }
4633
4634            AddSelectionsState { above, stack }
4635        });
4636
4637        let last_added_selection = *state.stack.last().unwrap();
4638        let mut new_selections = Vec::new();
4639        if above == state.above {
4640            let end_row = if above {
4641                0
4642            } else {
4643                display_map.max_point().row()
4644            };
4645
4646            'outer: for selection in selections {
4647                if selection.id == last_added_selection {
4648                    let range = selection.display_range(&display_map).sorted();
4649                    debug_assert_eq!(range.start.row(), range.end.row());
4650                    let mut row = range.start.row();
4651                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4652                    {
4653                        start..end
4654                    } else {
4655                        cmp::min(range.start.column(), range.end.column())
4656                            ..cmp::max(range.start.column(), range.end.column())
4657                    };
4658
4659                    while row != end_row {
4660                        if above {
4661                            row -= 1;
4662                        } else {
4663                            row += 1;
4664                        }
4665
4666                        if let Some(new_selection) = self.selections.build_columnar_selection(
4667                            &display_map,
4668                            row,
4669                            &columns,
4670                            selection.reversed,
4671                        ) {
4672                            state.stack.push(new_selection.id);
4673                            if above {
4674                                new_selections.push(new_selection);
4675                                new_selections.push(selection);
4676                            } else {
4677                                new_selections.push(selection);
4678                                new_selections.push(new_selection);
4679                            }
4680
4681                            continue 'outer;
4682                        }
4683                    }
4684                }
4685
4686                new_selections.push(selection);
4687            }
4688        } else {
4689            new_selections = selections;
4690            new_selections.retain(|s| s.id != last_added_selection);
4691            state.stack.pop();
4692        }
4693
4694        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4695            s.select(new_selections);
4696        });
4697        if state.stack.len() > 1 {
4698            self.add_selections_state = Some(state);
4699        }
4700    }
4701
4702    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4703        self.push_to_selection_history();
4704        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4705        let buffer = &display_map.buffer_snapshot;
4706        let mut selections = self.selections.all::<usize>(cx);
4707        if let Some(mut select_next_state) = self.select_next_state.take() {
4708            let query = &select_next_state.query;
4709            if !select_next_state.done {
4710                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4711                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4712                let mut next_selected_range = None;
4713
4714                let bytes_after_last_selection =
4715                    buffer.bytes_in_range(last_selection.end..buffer.len());
4716                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4717                let query_matches = query
4718                    .stream_find_iter(bytes_after_last_selection)
4719                    .map(|result| (last_selection.end, result))
4720                    .chain(
4721                        query
4722                            .stream_find_iter(bytes_before_first_selection)
4723                            .map(|result| (0, result)),
4724                    );
4725                for (start_offset, query_match) in query_matches {
4726                    let query_match = query_match.unwrap(); // can only fail due to I/O
4727                    let offset_range =
4728                        start_offset + query_match.start()..start_offset + query_match.end();
4729                    let display_range = offset_range.start.to_display_point(&display_map)
4730                        ..offset_range.end.to_display_point(&display_map);
4731
4732                    if !select_next_state.wordwise
4733                        || (!movement::is_inside_word(&display_map, display_range.start)
4734                            && !movement::is_inside_word(&display_map, display_range.end))
4735                    {
4736                        next_selected_range = Some(offset_range);
4737                        break;
4738                    }
4739                }
4740
4741                if let Some(next_selected_range) = next_selected_range {
4742                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
4743                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4744                        if action.replace_newest {
4745                            s.delete(s.newest_anchor().id);
4746                        }
4747                        s.insert_range(next_selected_range);
4748                    });
4749                } else {
4750                    select_next_state.done = true;
4751                }
4752            }
4753
4754            self.select_next_state = Some(select_next_state);
4755        } else if selections.len() == 1 {
4756            let selection = selections.last_mut().unwrap();
4757            if selection.start == selection.end {
4758                let word_range = movement::surrounding_word(
4759                    &display_map,
4760                    selection.start.to_display_point(&display_map),
4761                );
4762                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4763                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4764                selection.goal = SelectionGoal::None;
4765                selection.reversed = false;
4766
4767                let query = buffer
4768                    .text_for_range(selection.start..selection.end)
4769                    .collect::<String>();
4770                let select_state = SelectNextState {
4771                    query: AhoCorasick::new_auto_configured(&[query]),
4772                    wordwise: true,
4773                    done: false,
4774                };
4775                self.unfold_ranges([selection.start..selection.end], false, true, cx);
4776                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4777                    s.select(selections);
4778                });
4779                self.select_next_state = Some(select_state);
4780            } else {
4781                let query = buffer
4782                    .text_for_range(selection.start..selection.end)
4783                    .collect::<String>();
4784                self.select_next_state = Some(SelectNextState {
4785                    query: AhoCorasick::new_auto_configured(&[query]),
4786                    wordwise: false,
4787                    done: false,
4788                });
4789                self.select_next(action, cx);
4790            }
4791        }
4792    }
4793
4794    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
4795        self.transact(cx, |this, cx| {
4796            let mut selections = this.selections.all::<Point>(cx);
4797            let mut edits = Vec::new();
4798            let mut selection_edit_ranges = Vec::new();
4799            let mut last_toggled_row = None;
4800            let snapshot = this.buffer.read(cx).read(cx);
4801            let empty_str: Arc<str> = "".into();
4802            let mut suffixes_inserted = Vec::new();
4803
4804            fn comment_prefix_range(
4805                snapshot: &MultiBufferSnapshot,
4806                row: u32,
4807                comment_prefix: &str,
4808                comment_prefix_whitespace: &str,
4809            ) -> Range<Point> {
4810                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4811
4812                let mut line_bytes = snapshot
4813                    .bytes_in_range(start..snapshot.max_point())
4814                    .flatten()
4815                    .copied();
4816
4817                // If this line currently begins with the line comment prefix, then record
4818                // the range containing the prefix.
4819                if line_bytes
4820                    .by_ref()
4821                    .take(comment_prefix.len())
4822                    .eq(comment_prefix.bytes())
4823                {
4824                    // Include any whitespace that matches the comment prefix.
4825                    let matching_whitespace_len = line_bytes
4826                        .zip(comment_prefix_whitespace.bytes())
4827                        .take_while(|(a, b)| a == b)
4828                        .count() as u32;
4829                    let end = Point::new(
4830                        start.row,
4831                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4832                    );
4833                    start..end
4834                } else {
4835                    start..start
4836                }
4837            }
4838
4839            fn comment_suffix_range(
4840                snapshot: &MultiBufferSnapshot,
4841                row: u32,
4842                comment_suffix: &str,
4843                comment_suffix_has_leading_space: bool,
4844            ) -> Range<Point> {
4845                let end = Point::new(row, snapshot.line_len(row));
4846                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4847
4848                let mut line_end_bytes = snapshot
4849                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4850                    .flatten()
4851                    .copied();
4852
4853                let leading_space_len = if suffix_start_column > 0
4854                    && line_end_bytes.next() == Some(b' ')
4855                    && comment_suffix_has_leading_space
4856                {
4857                    1
4858                } else {
4859                    0
4860                };
4861
4862                // If this line currently begins with the line comment prefix, then record
4863                // the range containing the prefix.
4864                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4865                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4866                    start..end
4867                } else {
4868                    end..end
4869                }
4870            }
4871
4872            // TODO: Handle selections that cross excerpts
4873            for selection in &mut selections {
4874                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
4875                let language = if let Some(language) =
4876                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
4877                {
4878                    language
4879                } else {
4880                    continue;
4881                };
4882
4883                selection_edit_ranges.clear();
4884
4885                // If multiple selections contain a given row, avoid processing that
4886                // row more than once.
4887                let mut start_row = selection.start.row;
4888                if last_toggled_row == Some(start_row) {
4889                    start_row += 1;
4890                }
4891                let end_row =
4892                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4893                        selection.end.row - 1
4894                    } else {
4895                        selection.end.row
4896                    };
4897                last_toggled_row = Some(end_row);
4898
4899                if start_row > end_row {
4900                    continue;
4901                }
4902
4903                // If the language has line comments, toggle those.
4904                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4905                    // Split the comment prefix's trailing whitespace into a separate string,
4906                    // as that portion won't be used for detecting if a line is a comment.
4907                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4908                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4909                    let mut all_selection_lines_are_comments = true;
4910
4911                    for row in start_row..=end_row {
4912                        if snapshot.is_line_blank(row) {
4913                            continue;
4914                        }
4915
4916                        let prefix_range = comment_prefix_range(
4917                            snapshot.deref(),
4918                            row,
4919                            comment_prefix,
4920                            comment_prefix_whitespace,
4921                        );
4922                        if prefix_range.is_empty() {
4923                            all_selection_lines_are_comments = false;
4924                        }
4925                        selection_edit_ranges.push(prefix_range);
4926                    }
4927
4928                    if all_selection_lines_are_comments {
4929                        edits.extend(
4930                            selection_edit_ranges
4931                                .iter()
4932                                .cloned()
4933                                .map(|range| (range, empty_str.clone())),
4934                        );
4935                    } else {
4936                        let min_column = selection_edit_ranges
4937                            .iter()
4938                            .map(|r| r.start.column)
4939                            .min()
4940                            .unwrap_or(0);
4941                        edits.extend(selection_edit_ranges.iter().map(|range| {
4942                            let position = Point::new(range.start.row, min_column);
4943                            (position..position, full_comment_prefix.clone())
4944                        }));
4945                    }
4946                } else if let Some((full_comment_prefix, comment_suffix)) =
4947                    language.block_comment_delimiters()
4948                {
4949                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4950                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4951                    let prefix_range = comment_prefix_range(
4952                        snapshot.deref(),
4953                        start_row,
4954                        comment_prefix,
4955                        comment_prefix_whitespace,
4956                    );
4957                    let suffix_range = comment_suffix_range(
4958                        snapshot.deref(),
4959                        end_row,
4960                        comment_suffix.trim_start_matches(' '),
4961                        comment_suffix.starts_with(' '),
4962                    );
4963
4964                    if prefix_range.is_empty() || suffix_range.is_empty() {
4965                        edits.push((
4966                            prefix_range.start..prefix_range.start,
4967                            full_comment_prefix.clone(),
4968                        ));
4969                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4970                        suffixes_inserted.push((end_row, comment_suffix.len()));
4971                    } else {
4972                        edits.push((prefix_range, empty_str.clone()));
4973                        edits.push((suffix_range, empty_str.clone()));
4974                    }
4975                } else {
4976                    continue;
4977                }
4978            }
4979
4980            drop(snapshot);
4981            this.buffer.update(cx, |buffer, cx| {
4982                buffer.edit(edits, None, cx);
4983            });
4984
4985            // Adjust selections so that they end before any comment suffixes that
4986            // were inserted.
4987            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4988            let mut selections = this.selections.all::<Point>(cx);
4989            let snapshot = this.buffer.read(cx).read(cx);
4990            for selection in &mut selections {
4991                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
4992                    match row.cmp(&selection.end.row) {
4993                        Ordering::Less => {
4994                            suffixes_inserted.next();
4995                            continue;
4996                        }
4997                        Ordering::Greater => break,
4998                        Ordering::Equal => {
4999                            if selection.end.column == snapshot.line_len(row) {
5000                                if selection.is_empty() {
5001                                    selection.start.column -= suffix_len as u32;
5002                                }
5003                                selection.end.column -= suffix_len as u32;
5004                            }
5005                            break;
5006                        }
5007                    }
5008                }
5009            }
5010
5011            drop(snapshot);
5012            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5013
5014            let selections = this.selections.all::<Point>(cx);
5015            let selections_on_single_row = selections.windows(2).all(|selections| {
5016                selections[0].start.row == selections[1].start.row
5017                    && selections[0].end.row == selections[1].end.row
5018                    && selections[0].start.row == selections[0].end.row
5019            });
5020            let selections_selecting = selections
5021                .iter()
5022                .any(|selection| selection.start != selection.end);
5023            let advance_downwards = action.advance_downwards
5024                && selections_on_single_row
5025                && !selections_selecting
5026                && this.mode != EditorMode::SingleLine;
5027
5028            if advance_downwards {
5029                let snapshot = this.buffer.read(cx).snapshot(cx);
5030
5031                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5032                    s.move_cursors_with(|display_snapshot, display_point, _| {
5033                        let mut point = display_point.to_point(display_snapshot);
5034                        point.row += 1;
5035                        point = snapshot.clip_point(point, Bias::Left);
5036                        let display_point = point.to_display_point(display_snapshot);
5037                        (display_point, SelectionGoal::Column(display_point.column()))
5038                    })
5039                });
5040            }
5041        });
5042    }
5043
5044    pub fn select_larger_syntax_node(
5045        &mut self,
5046        _: &SelectLargerSyntaxNode,
5047        cx: &mut ViewContext<Self>,
5048    ) {
5049        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5050        let buffer = self.buffer.read(cx).snapshot(cx);
5051        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5052
5053        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5054        let mut selected_larger_node = false;
5055        let new_selections = old_selections
5056            .iter()
5057            .map(|selection| {
5058                let old_range = selection.start..selection.end;
5059                let mut new_range = old_range.clone();
5060                while let Some(containing_range) =
5061                    buffer.range_for_syntax_ancestor(new_range.clone())
5062                {
5063                    new_range = containing_range;
5064                    if !display_map.intersects_fold(new_range.start)
5065                        && !display_map.intersects_fold(new_range.end)
5066                    {
5067                        break;
5068                    }
5069                }
5070
5071                selected_larger_node |= new_range != old_range;
5072                Selection {
5073                    id: selection.id,
5074                    start: new_range.start,
5075                    end: new_range.end,
5076                    goal: SelectionGoal::None,
5077                    reversed: selection.reversed,
5078                }
5079            })
5080            .collect::<Vec<_>>();
5081
5082        if selected_larger_node {
5083            stack.push(old_selections);
5084            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5085                s.select(new_selections);
5086            });
5087        }
5088        self.select_larger_syntax_node_stack = stack;
5089    }
5090
5091    pub fn select_smaller_syntax_node(
5092        &mut self,
5093        _: &SelectSmallerSyntaxNode,
5094        cx: &mut ViewContext<Self>,
5095    ) {
5096        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5097        if let Some(selections) = stack.pop() {
5098            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5099                s.select(selections.to_vec());
5100            });
5101        }
5102        self.select_larger_syntax_node_stack = stack;
5103    }
5104
5105    pub fn move_to_enclosing_bracket(
5106        &mut self,
5107        _: &MoveToEnclosingBracket,
5108        cx: &mut ViewContext<Self>,
5109    ) {
5110        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5111            s.move_offsets_with(|snapshot, selection| {
5112                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5113                    return;
5114                };
5115
5116                let mut best_length = usize::MAX;
5117                let mut best_inside = false;
5118                let mut best_in_bracket_range = false;
5119                let mut best_destination = None;
5120                for (open, close) in enclosing_bracket_ranges {
5121                    let close = close.to_inclusive();
5122                    let length = close.end() - open.start;
5123                    let inside = selection.start >= open.end && selection.end <= *close.start();
5124                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5125
5126                    // If best is next to a bracket and current isn't, skip
5127                    if !in_bracket_range && best_in_bracket_range {
5128                        continue;
5129                    }
5130
5131                    // Prefer smaller lengths unless best is inside and current isn't
5132                    if length > best_length && (best_inside || !inside) {
5133                        continue;
5134                    }
5135
5136                    best_length = length;
5137                    best_inside = inside;
5138                    best_in_bracket_range = in_bracket_range;
5139                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5140                        if inside {
5141                            open.end
5142                        } else {
5143                            open.start
5144                        }
5145                    } else {
5146                        if inside {
5147                            *close.start()
5148                        } else {
5149                            *close.end()
5150                        }
5151                    });
5152                }
5153
5154                if let Some(destination) = best_destination {
5155                    selection.collapse_to(destination, SelectionGoal::None);
5156                }
5157            })
5158        });
5159    }
5160
5161    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5162        self.end_selection(cx);
5163        self.selection_history.mode = SelectionHistoryMode::Undoing;
5164        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5165            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5166            self.select_next_state = entry.select_next_state;
5167            self.add_selections_state = entry.add_selections_state;
5168            self.request_autoscroll(Autoscroll::newest(), cx);
5169        }
5170        self.selection_history.mode = SelectionHistoryMode::Normal;
5171    }
5172
5173    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5174        self.end_selection(cx);
5175        self.selection_history.mode = SelectionHistoryMode::Redoing;
5176        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5177            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5178            self.select_next_state = entry.select_next_state;
5179            self.add_selections_state = entry.add_selections_state;
5180            self.request_autoscroll(Autoscroll::newest(), cx);
5181        }
5182        self.selection_history.mode = SelectionHistoryMode::Normal;
5183    }
5184
5185    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5186        self.go_to_diagnostic_impl(Direction::Next, cx)
5187    }
5188
5189    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5190        self.go_to_diagnostic_impl(Direction::Prev, cx)
5191    }
5192
5193    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5194        let buffer = self.buffer.read(cx).snapshot(cx);
5195        let selection = self.selections.newest::<usize>(cx);
5196
5197        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5198        if direction == Direction::Next {
5199            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5200                let (group_id, jump_to) = popover.activation_info();
5201                if self.activate_diagnostics(group_id, cx) {
5202                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5203                        let mut new_selection = s.newest_anchor().clone();
5204                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5205                        s.select_anchors(vec![new_selection.clone()]);
5206                    });
5207                }
5208                return;
5209            }
5210        }
5211
5212        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5213            active_diagnostics
5214                .primary_range
5215                .to_offset(&buffer)
5216                .to_inclusive()
5217        });
5218        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5219            if active_primary_range.contains(&selection.head()) {
5220                *active_primary_range.end()
5221            } else {
5222                selection.head()
5223            }
5224        } else {
5225            selection.head()
5226        };
5227
5228        loop {
5229            let mut diagnostics = if direction == Direction::Prev {
5230                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5231            } else {
5232                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5233            };
5234            let group = diagnostics.find_map(|entry| {
5235                if entry.diagnostic.is_primary
5236                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5237                    && !entry.range.is_empty()
5238                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5239                {
5240                    Some((entry.range, entry.diagnostic.group_id))
5241                } else {
5242                    None
5243                }
5244            });
5245
5246            if let Some((primary_range, group_id)) = group {
5247                if self.activate_diagnostics(group_id, cx) {
5248                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5249                        s.select(vec![Selection {
5250                            id: selection.id,
5251                            start: primary_range.start,
5252                            end: primary_range.start,
5253                            reversed: false,
5254                            goal: SelectionGoal::None,
5255                        }]);
5256                    });
5257                }
5258                break;
5259            } else {
5260                // Cycle around to the start of the buffer, potentially moving back to the start of
5261                // the currently active diagnostic.
5262                active_primary_range.take();
5263                if direction == Direction::Prev {
5264                    if search_start == buffer.len() {
5265                        break;
5266                    } else {
5267                        search_start = buffer.len();
5268                    }
5269                } else if search_start == 0 {
5270                    break;
5271                } else {
5272                    search_start = 0;
5273                }
5274            }
5275        }
5276    }
5277
5278    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5279        self.go_to_hunk_impl(Direction::Next, cx)
5280    }
5281
5282    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5283        self.go_to_hunk_impl(Direction::Prev, cx)
5284    }
5285
5286    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5287        let snapshot = self
5288            .display_map
5289            .update(cx, |display_map, cx| display_map.snapshot(cx));
5290        let selection = self.selections.newest::<Point>(cx);
5291
5292        fn seek_in_direction(
5293            this: &mut Editor,
5294            snapshot: &DisplaySnapshot,
5295            initial_point: Point,
5296            is_wrapped: bool,
5297            direction: Direction,
5298            cx: &mut ViewContext<Editor>,
5299        ) -> bool {
5300            let hunks = if direction == Direction::Next {
5301                snapshot
5302                    .buffer_snapshot
5303                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
5304            } else {
5305                snapshot
5306                    .buffer_snapshot
5307                    .git_diff_hunks_in_range(0..initial_point.row, true)
5308            };
5309
5310            let display_point = initial_point.to_display_point(snapshot);
5311            let mut hunks = hunks
5312                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5313                .skip_while(|hunk| {
5314                    if is_wrapped {
5315                        false
5316                    } else {
5317                        hunk.contains_display_row(display_point.row())
5318                    }
5319                })
5320                .dedup();
5321
5322            if let Some(hunk) = hunks.next() {
5323                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5324                    let row = hunk.start_display_row();
5325                    let point = DisplayPoint::new(row, 0);
5326                    s.select_display_ranges([point..point]);
5327                });
5328
5329                true
5330            } else {
5331                false
5332            }
5333        }
5334
5335        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5336            let wrapped_point = match direction {
5337                Direction::Next => Point::zero(),
5338                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5339            };
5340            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5341        }
5342    }
5343
5344    pub fn go_to_definition(
5345        workspace: &mut Workspace,
5346        _: &GoToDefinition,
5347        cx: &mut ViewContext<Workspace>,
5348    ) {
5349        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5350    }
5351
5352    pub fn go_to_type_definition(
5353        workspace: &mut Workspace,
5354        _: &GoToTypeDefinition,
5355        cx: &mut ViewContext<Workspace>,
5356    ) {
5357        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5358    }
5359
5360    fn go_to_definition_of_kind(
5361        kind: GotoDefinitionKind,
5362        workspace: &mut Workspace,
5363        cx: &mut ViewContext<Workspace>,
5364    ) {
5365        let active_item = workspace.active_item(cx);
5366        let editor_handle = if let Some(editor) = active_item
5367            .as_ref()
5368            .and_then(|item| item.act_as::<Self>(cx))
5369        {
5370            editor
5371        } else {
5372            return;
5373        };
5374
5375        let editor = editor_handle.read(cx);
5376        let buffer = editor.buffer.read(cx);
5377        let head = editor.selections.newest::<usize>(cx).head();
5378        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5379            text_anchor
5380        } else {
5381            return;
5382        };
5383
5384        let project = workspace.project().clone();
5385        let definitions = project.update(cx, |project, cx| match kind {
5386            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5387            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5388        });
5389
5390        cx.spawn_labeled("Fetching Definition...", |workspace, mut cx| async move {
5391            let definitions = definitions.await?;
5392            workspace.update(&mut cx, |workspace, cx| {
5393                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5394            });
5395
5396            Ok::<(), anyhow::Error>(())
5397        })
5398        .detach_and_log_err(cx);
5399    }
5400
5401    pub fn navigate_to_definitions(
5402        workspace: &mut Workspace,
5403        editor_handle: ViewHandle<Editor>,
5404        definitions: Vec<LocationLink>,
5405        cx: &mut ViewContext<Workspace>,
5406    ) {
5407        let pane = workspace.active_pane().clone();
5408        // If there is one definition, just open it directly
5409        if let [definition] = definitions.as_slice() {
5410            let range = definition
5411                .target
5412                .range
5413                .to_offset(definition.target.buffer.read(cx));
5414
5415            let target_editor_handle =
5416                workspace.open_project_item(definition.target.buffer.clone(), cx);
5417            target_editor_handle.update(cx, |target_editor, cx| {
5418                // When selecting a definition in a different buffer, disable the nav history
5419                // to avoid creating a history entry at the previous cursor location.
5420                if editor_handle != target_editor_handle {
5421                    pane.update(cx, |pane, _| pane.disable_history());
5422                }
5423                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5424                    s.select_ranges([range]);
5425                });
5426
5427                pane.update(cx, |pane, _| pane.enable_history());
5428            });
5429        } else if !definitions.is_empty() {
5430            let replica_id = editor_handle.read(cx).replica_id(cx);
5431            let title = definitions
5432                .iter()
5433                .find(|definition| definition.origin.is_some())
5434                .and_then(|definition| {
5435                    definition.origin.as_ref().map(|origin| {
5436                        let buffer = origin.buffer.read(cx);
5437                        format!(
5438                            "Definitions for {}",
5439                            buffer
5440                                .text_for_range(origin.range.clone())
5441                                .collect::<String>()
5442                        )
5443                    })
5444                })
5445                .unwrap_or("Definitions".to_owned());
5446            let locations = definitions
5447                .into_iter()
5448                .map(|definition| definition.target)
5449                .collect();
5450            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5451        }
5452    }
5453
5454    pub fn find_all_references(
5455        workspace: &mut Workspace,
5456        _: &FindAllReferences,
5457        cx: &mut ViewContext<Workspace>,
5458    ) -> Option<Task<Result<()>>> {
5459        let active_item = workspace.active_item(cx)?;
5460        let editor_handle = active_item.act_as::<Self>(cx)?;
5461
5462        let editor = editor_handle.read(cx);
5463        let buffer = editor.buffer.read(cx);
5464        let head = editor.selections.newest::<usize>(cx).head();
5465        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5466        let replica_id = editor.replica_id(cx);
5467
5468        let project = workspace.project().clone();
5469        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5470        Some(cx.spawn_labeled(
5471            "Finding All References...",
5472            |workspace, mut cx| async move {
5473                let locations = references.await?;
5474                if locations.is_empty() {
5475                    return Ok(());
5476                }
5477
5478                workspace.update(&mut cx, |workspace, cx| {
5479                    let title = locations
5480                        .first()
5481                        .as_ref()
5482                        .map(|location| {
5483                            let buffer = location.buffer.read(cx);
5484                            format!(
5485                                "References to `{}`",
5486                                buffer
5487                                    .text_for_range(location.range.clone())
5488                                    .collect::<String>()
5489                            )
5490                        })
5491                        .unwrap();
5492                    Self::open_locations_in_multibuffer(
5493                        workspace, locations, replica_id, title, cx,
5494                    );
5495                });
5496
5497                Ok(())
5498            },
5499        ))
5500    }
5501
5502    /// Opens a multibuffer with the given project locations in it
5503    pub fn open_locations_in_multibuffer(
5504        workspace: &mut Workspace,
5505        mut locations: Vec<Location>,
5506        replica_id: ReplicaId,
5507        title: String,
5508        cx: &mut ViewContext<Workspace>,
5509    ) {
5510        // If there are multiple definitions, open them in a multibuffer
5511        locations.sort_by_key(|location| location.buffer.id());
5512        let mut locations = locations.into_iter().peekable();
5513        let mut ranges_to_highlight = Vec::new();
5514
5515        let excerpt_buffer = cx.add_model(|cx| {
5516            let mut multibuffer = MultiBuffer::new(replica_id);
5517            while let Some(location) = locations.next() {
5518                let buffer = location.buffer.read(cx);
5519                let mut ranges_for_buffer = Vec::new();
5520                let range = location.range.to_offset(buffer);
5521                ranges_for_buffer.push(range.clone());
5522
5523                while let Some(next_location) = locations.peek() {
5524                    if next_location.buffer == location.buffer {
5525                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5526                        locations.next();
5527                    } else {
5528                        break;
5529                    }
5530                }
5531
5532                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5533                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5534                    location.buffer.clone(),
5535                    ranges_for_buffer,
5536                    1,
5537                    cx,
5538                ))
5539            }
5540
5541            multibuffer.with_title(title)
5542        });
5543
5544        let editor = cx.add_view(|cx| {
5545            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5546        });
5547        editor.update(cx, |editor, cx| {
5548            editor.highlight_background::<Self>(
5549                ranges_to_highlight,
5550                |theme| theme.editor.highlighted_line_background,
5551                cx,
5552            );
5553        });
5554        workspace.add_item(Box::new(editor), cx);
5555    }
5556
5557    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5558        use language::ToOffset as _;
5559
5560        let project = self.project.clone()?;
5561        let selection = self.selections.newest_anchor().clone();
5562        let (cursor_buffer, cursor_buffer_position) = self
5563            .buffer
5564            .read(cx)
5565            .text_anchor_for_position(selection.head(), cx)?;
5566        let (tail_buffer, _) = self
5567            .buffer
5568            .read(cx)
5569            .text_anchor_for_position(selection.tail(), cx)?;
5570        if tail_buffer != cursor_buffer {
5571            return None;
5572        }
5573
5574        let snapshot = cursor_buffer.read(cx).snapshot();
5575        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5576        let prepare_rename = project.update(cx, |project, cx| {
5577            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5578        });
5579
5580        Some(cx.spawn(|this, mut cx| async move {
5581            let rename_range = if let Some(range) = prepare_rename.await? {
5582                Some(range)
5583            } else {
5584                this.read_with(&cx, |this, cx| {
5585                    let buffer = this.buffer.read(cx).snapshot(cx);
5586                    let mut buffer_highlights = this
5587                        .document_highlights_for_position(selection.head(), &buffer)
5588                        .filter(|highlight| {
5589                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5590                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5591                        });
5592                    buffer_highlights
5593                        .next()
5594                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5595                })
5596            };
5597            if let Some(rename_range) = rename_range {
5598                let rename_buffer_range = rename_range.to_offset(&snapshot);
5599                let cursor_offset_in_rename_range =
5600                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5601
5602                this.update(&mut cx, |this, cx| {
5603                    this.take_rename(false, cx);
5604                    let style = this.style(cx);
5605                    let buffer = this.buffer.read(cx).read(cx);
5606                    let cursor_offset = selection.head().to_offset(&buffer);
5607                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5608                    let rename_end = rename_start + rename_buffer_range.len();
5609                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5610                    let mut old_highlight_id = None;
5611                    let old_name: Arc<str> = buffer
5612                        .chunks(rename_start..rename_end, true)
5613                        .map(|chunk| {
5614                            if old_highlight_id.is_none() {
5615                                old_highlight_id = chunk.syntax_highlight_id;
5616                            }
5617                            chunk.text
5618                        })
5619                        .collect::<String>()
5620                        .into();
5621
5622                    drop(buffer);
5623
5624                    // Position the selection in the rename editor so that it matches the current selection.
5625                    this.show_local_selections = false;
5626                    let rename_editor = cx.add_view(|cx| {
5627                        let mut editor = Editor::single_line(None, cx);
5628                        if let Some(old_highlight_id) = old_highlight_id {
5629                            editor.override_text_style =
5630                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5631                        }
5632                        editor.buffer.update(cx, |buffer, cx| {
5633                            buffer.edit([(0..0, old_name.clone())], None, cx)
5634                        });
5635                        editor.select_all(&SelectAll, cx);
5636                        editor
5637                    });
5638
5639                    let ranges = this
5640                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5641                        .into_iter()
5642                        .flat_map(|(_, ranges)| ranges)
5643                        .chain(
5644                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5645                                .into_iter()
5646                                .flat_map(|(_, ranges)| ranges),
5647                        )
5648                        .collect();
5649
5650                    this.highlight_text::<Rename>(
5651                        ranges,
5652                        HighlightStyle {
5653                            fade_out: Some(style.rename_fade),
5654                            ..Default::default()
5655                        },
5656                        cx,
5657                    );
5658                    cx.focus(&rename_editor);
5659                    let block_id = this.insert_blocks(
5660                        [BlockProperties {
5661                            style: BlockStyle::Flex,
5662                            position: range.start.clone(),
5663                            height: 1,
5664                            render: Arc::new({
5665                                let editor = rename_editor.clone();
5666                                move |cx: &mut BlockContext| {
5667                                    ChildView::new(&editor, cx)
5668                                        .contained()
5669                                        .with_padding_left(cx.anchor_x)
5670                                        .boxed()
5671                                }
5672                            }),
5673                            disposition: BlockDisposition::Below,
5674                        }],
5675                        cx,
5676                    )[0];
5677                    this.pending_rename = Some(RenameState {
5678                        range,
5679                        old_name,
5680                        editor: rename_editor,
5681                        block_id,
5682                    });
5683                });
5684            }
5685
5686            Ok(())
5687        }))
5688    }
5689
5690    pub fn confirm_rename(
5691        workspace: &mut Workspace,
5692        _: &ConfirmRename,
5693        cx: &mut ViewContext<Workspace>,
5694    ) -> Option<Task<Result<()>>> {
5695        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5696
5697        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5698            let rename = editor.take_rename(false, cx)?;
5699            let buffer = editor.buffer.read(cx);
5700            let (start_buffer, start) =
5701                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5702            let (end_buffer, end) =
5703                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5704            if start_buffer == end_buffer {
5705                let new_name = rename.editor.read(cx).text(cx);
5706                Some((start_buffer, start..end, rename.old_name, new_name))
5707            } else {
5708                None
5709            }
5710        })?;
5711
5712        let rename = workspace.project().clone().update(cx, |project, cx| {
5713            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5714        });
5715
5716        Some(cx.spawn(|workspace, mut cx| async move {
5717            let project_transaction = rename.await?;
5718            Self::open_project_transaction(
5719                editor.clone(),
5720                workspace,
5721                project_transaction,
5722                format!("Rename: {}{}", old_name, new_name),
5723                cx.clone(),
5724            )
5725            .await?;
5726
5727            editor.update(&mut cx, |editor, cx| {
5728                editor.refresh_document_highlights(cx);
5729            });
5730            Ok(())
5731        }))
5732    }
5733
5734    fn take_rename(
5735        &mut self,
5736        moving_cursor: bool,
5737        cx: &mut ViewContext<Self>,
5738    ) -> Option<RenameState> {
5739        let rename = self.pending_rename.take()?;
5740        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5741        self.clear_text_highlights::<Rename>(cx);
5742        self.show_local_selections = true;
5743
5744        if moving_cursor {
5745            let rename_editor = rename.editor.read(cx);
5746            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5747
5748            // Update the selection to match the position of the selection inside
5749            // the rename editor.
5750            let snapshot = self.buffer.read(cx).read(cx);
5751            let rename_range = rename.range.to_offset(&snapshot);
5752            let cursor_in_editor = snapshot
5753                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5754                .min(rename_range.end);
5755            drop(snapshot);
5756
5757            self.change_selections(None, cx, |s| {
5758                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5759            });
5760        } else {
5761            self.refresh_document_highlights(cx);
5762        }
5763
5764        Some(rename)
5765    }
5766
5767    #[cfg(any(test, feature = "test-support"))]
5768    pub fn pending_rename(&self) -> Option<&RenameState> {
5769        self.pending_rename.as_ref()
5770    }
5771
5772    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5773        let project = match &self.project {
5774            Some(project) => project.clone(),
5775            None => return None,
5776        };
5777
5778        Some(self.perform_format(project, FormatTrigger::Manual, cx))
5779    }
5780
5781    fn perform_format(
5782        &mut self,
5783        project: ModelHandle<Project>,
5784        trigger: FormatTrigger,
5785        cx: &mut ViewContext<'_, Self>,
5786    ) -> Task<Result<()>> {
5787        let buffer = self.buffer().clone();
5788        let buffers = buffer.read(cx).all_buffers();
5789
5790        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5791        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
5792
5793        cx.spawn(|_, mut cx| async move {
5794            let transaction = futures::select_biased! {
5795                _ = timeout => {
5796                    log::warn!("timed out waiting for formatting");
5797                    None
5798                }
5799                transaction = format.log_err().fuse() => transaction,
5800            };
5801
5802            buffer.update(&mut cx, |buffer, cx| {
5803                if let Some(transaction) = transaction {
5804                    if !buffer.is_singleton() {
5805                        buffer.push_transaction(&transaction.0);
5806                    }
5807                }
5808
5809                cx.notify();
5810            });
5811
5812            Ok(())
5813        })
5814    }
5815
5816    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5817        if let Some(project) = self.project.clone() {
5818            self.buffer.update(cx, |multi_buffer, cx| {
5819                project.update(cx, |project, cx| {
5820                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5821                });
5822            })
5823        }
5824    }
5825
5826    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5827        cx.show_character_palette();
5828    }
5829
5830    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5831        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5832            let buffer = self.buffer.read(cx).snapshot(cx);
5833            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5834            let is_valid = buffer
5835                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5836                .any(|entry| {
5837                    entry.diagnostic.is_primary
5838                        && !entry.range.is_empty()
5839                        && entry.range.start == primary_range_start
5840                        && entry.diagnostic.message == active_diagnostics.primary_message
5841                });
5842
5843            if is_valid != active_diagnostics.is_valid {
5844                active_diagnostics.is_valid = is_valid;
5845                let mut new_styles = HashMap::default();
5846                for (block_id, diagnostic) in &active_diagnostics.blocks {
5847                    new_styles.insert(
5848                        *block_id,
5849                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5850                    );
5851                }
5852                self.display_map
5853                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5854            }
5855        }
5856    }
5857
5858    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5859        self.dismiss_diagnostics(cx);
5860        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5861            let buffer = self.buffer.read(cx).snapshot(cx);
5862
5863            let mut primary_range = None;
5864            let mut primary_message = None;
5865            let mut group_end = Point::zero();
5866            let diagnostic_group = buffer
5867                .diagnostic_group::<Point>(group_id)
5868                .map(|entry| {
5869                    if entry.range.end > group_end {
5870                        group_end = entry.range.end;
5871                    }
5872                    if entry.diagnostic.is_primary {
5873                        primary_range = Some(entry.range.clone());
5874                        primary_message = Some(entry.diagnostic.message.clone());
5875                    }
5876                    entry
5877                })
5878                .collect::<Vec<_>>();
5879            let primary_range = primary_range?;
5880            let primary_message = primary_message?;
5881            let primary_range =
5882                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5883
5884            let blocks = display_map
5885                .insert_blocks(
5886                    diagnostic_group.iter().map(|entry| {
5887                        let diagnostic = entry.diagnostic.clone();
5888                        let message_height = diagnostic.message.lines().count() as u8;
5889                        BlockProperties {
5890                            style: BlockStyle::Fixed,
5891                            position: buffer.anchor_after(entry.range.start),
5892                            height: message_height,
5893                            render: diagnostic_block_renderer(diagnostic, true),
5894                            disposition: BlockDisposition::Below,
5895                        }
5896                    }),
5897                    cx,
5898                )
5899                .into_iter()
5900                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5901                .collect();
5902
5903            Some(ActiveDiagnosticGroup {
5904                primary_range,
5905                primary_message,
5906                blocks,
5907                is_valid: true,
5908            })
5909        });
5910        self.active_diagnostics.is_some()
5911    }
5912
5913    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5914        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5915            self.display_map.update(cx, |display_map, cx| {
5916                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5917            });
5918            cx.notify();
5919        }
5920    }
5921
5922    pub fn set_selections_from_remote(
5923        &mut self,
5924        selections: Vec<Selection<Anchor>>,
5925        pending_selection: Option<Selection<Anchor>>,
5926        cx: &mut ViewContext<Self>,
5927    ) {
5928        let old_cursor_position = self.selections.newest_anchor().head();
5929        self.selections.change_with(cx, |s| {
5930            s.select_anchors(selections);
5931            if let Some(pending_selection) = pending_selection {
5932                s.set_pending(pending_selection, SelectMode::Character);
5933            } else {
5934                s.clear_pending();
5935            }
5936        });
5937        self.selections_did_change(false, &old_cursor_position, cx);
5938    }
5939
5940    fn push_to_selection_history(&mut self) {
5941        self.selection_history.push(SelectionHistoryEntry {
5942            selections: self.selections.disjoint_anchors(),
5943            select_next_state: self.select_next_state.clone(),
5944            add_selections_state: self.add_selections_state.clone(),
5945        });
5946    }
5947
5948    pub fn transact(
5949        &mut self,
5950        cx: &mut ViewContext<Self>,
5951        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5952    ) -> Option<TransactionId> {
5953        self.start_transaction_at(Instant::now(), cx);
5954        update(self, cx);
5955        self.end_transaction_at(Instant::now(), cx)
5956    }
5957
5958    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5959        self.end_selection(cx);
5960        if let Some(tx_id) = self
5961            .buffer
5962            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5963        {
5964            self.selection_history
5965                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5966        }
5967    }
5968
5969    fn end_transaction_at(
5970        &mut self,
5971        now: Instant,
5972        cx: &mut ViewContext<Self>,
5973    ) -> Option<TransactionId> {
5974        if let Some(tx_id) = self
5975            .buffer
5976            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5977        {
5978            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5979                *end_selections = Some(self.selections.disjoint_anchors());
5980            } else {
5981                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5982            }
5983
5984            cx.emit(Event::Edited);
5985            Some(tx_id)
5986        } else {
5987            None
5988        }
5989    }
5990
5991    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5992        let mut fold_ranges = Vec::new();
5993
5994        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5995
5996        let selections = self.selections.all::<Point>(cx);
5997        for selection in selections {
5998            let range = selection.range().sorted();
5999            let buffer_start_row = range.start.row;
6000
6001            for row in (0..=range.end.row).rev() {
6002                let fold_range = display_map.foldable_range(row);
6003
6004                if let Some(fold_range) = fold_range {
6005                    if fold_range.end.row >= buffer_start_row {
6006                        fold_ranges.push(fold_range);
6007                        if row <= range.start.row {
6008                            break;
6009                        }
6010                    }
6011                }
6012            }
6013        }
6014
6015        self.fold_ranges(fold_ranges, true, cx);
6016    }
6017
6018    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6019        let buffer_row = fold_at.buffer_row;
6020        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6021
6022        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6023            let autoscroll = self
6024                .selections
6025                .all::<Point>(cx)
6026                .iter()
6027                .any(|selection| fold_range.overlaps(&selection.range()));
6028
6029            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6030        }
6031    }
6032
6033    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6034        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6035        let buffer = &display_map.buffer_snapshot;
6036        let selections = self.selections.all::<Point>(cx);
6037        let ranges = selections
6038            .iter()
6039            .map(|s| {
6040                let range = s.display_range(&display_map).sorted();
6041                let mut start = range.start.to_point(&display_map);
6042                let mut end = range.end.to_point(&display_map);
6043                start.column = 0;
6044                end.column = buffer.line_len(end.row);
6045                start..end
6046            })
6047            .collect::<Vec<_>>();
6048
6049        self.unfold_ranges(ranges, true, true, cx);
6050    }
6051
6052    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6053        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6054
6055        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6056            ..Point::new(
6057                unfold_at.buffer_row,
6058                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6059            );
6060
6061        let autoscroll = self
6062            .selections
6063            .all::<Point>(cx)
6064            .iter()
6065            .any(|selection| selection.range().overlaps(&intersection_range));
6066
6067        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6068    }
6069
6070    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6071        let selections = self.selections.all::<Point>(cx);
6072        let ranges = selections.into_iter().map(|s| s.start..s.end);
6073        self.fold_ranges(ranges, true, cx);
6074    }
6075
6076    pub fn fold_ranges<T: ToOffset + Clone>(
6077        &mut self,
6078        ranges: impl IntoIterator<Item = Range<T>>,
6079        auto_scroll: bool,
6080        cx: &mut ViewContext<Self>,
6081    ) {
6082        let mut ranges = ranges.into_iter().peekable();
6083        if ranges.peek().is_some() {
6084            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6085
6086            if auto_scroll {
6087                self.request_autoscroll(Autoscroll::fit(), cx);
6088            }
6089
6090            cx.notify();
6091        }
6092    }
6093
6094    pub fn unfold_ranges<T: ToOffset + Clone>(
6095        &mut self,
6096        ranges: impl IntoIterator<Item = Range<T>>,
6097        inclusive: bool,
6098        auto_scroll: bool,
6099        cx: &mut ViewContext<Self>,
6100    ) {
6101        let mut ranges = ranges.into_iter().peekable();
6102        if ranges.peek().is_some() {
6103            self.display_map
6104                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6105            if auto_scroll {
6106                self.request_autoscroll(Autoscroll::fit(), cx);
6107            }
6108
6109            cx.notify();
6110        }
6111    }
6112
6113    pub fn gutter_hover(
6114        &mut self,
6115        GutterHover { hovered }: &GutterHover,
6116        cx: &mut ViewContext<Self>,
6117    ) {
6118        self.gutter_hovered = *hovered;
6119        cx.notify();
6120    }
6121
6122    pub fn insert_blocks(
6123        &mut self,
6124        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6125        cx: &mut ViewContext<Self>,
6126    ) -> Vec<BlockId> {
6127        let blocks = self
6128            .display_map
6129            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6130        self.request_autoscroll(Autoscroll::fit(), cx);
6131        blocks
6132    }
6133
6134    pub fn replace_blocks(
6135        &mut self,
6136        blocks: HashMap<BlockId, RenderBlock>,
6137        cx: &mut ViewContext<Self>,
6138    ) {
6139        self.display_map
6140            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6141        self.request_autoscroll(Autoscroll::fit(), cx);
6142    }
6143
6144    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6145        self.display_map.update(cx, |display_map, cx| {
6146            display_map.remove_blocks(block_ids, cx)
6147        });
6148    }
6149
6150    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
6151        self.display_map
6152            .update(cx, |map, cx| map.snapshot(cx))
6153            .longest_row()
6154    }
6155
6156    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
6157        self.display_map
6158            .update(cx, |map, cx| map.snapshot(cx))
6159            .max_point()
6160    }
6161
6162    pub fn text(&self, cx: &AppContext) -> String {
6163        self.buffer.read(cx).read(cx).text()
6164    }
6165
6166    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6167        self.transact(cx, |this, cx| {
6168            this.buffer
6169                .read(cx)
6170                .as_singleton()
6171                .expect("you can only call set_text on editors for singleton buffers")
6172                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6173        });
6174    }
6175
6176    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
6177        self.display_map
6178            .update(cx, |map, cx| map.snapshot(cx))
6179            .text()
6180    }
6181
6182    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6183        let language_name = self
6184            .buffer
6185            .read(cx)
6186            .as_singleton()
6187            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6188            .map(|l| l.name());
6189
6190        let settings = cx.global::<Settings>();
6191        let mode = self
6192            .soft_wrap_mode_override
6193            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6194        match mode {
6195            settings::SoftWrap::None => SoftWrap::None,
6196            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6197            settings::SoftWrap::PreferredLineLength => {
6198                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6199            }
6200        }
6201    }
6202
6203    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6204        self.soft_wrap_mode_override = Some(mode);
6205        cx.notify();
6206    }
6207
6208    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
6209        self.display_map
6210            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6211    }
6212
6213    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6214        if self.soft_wrap_mode_override.is_some() {
6215            self.soft_wrap_mode_override.take();
6216        } else {
6217            let soft_wrap = match self.soft_wrap_mode(cx) {
6218                SoftWrap::None => settings::SoftWrap::EditorWidth,
6219                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
6220            };
6221            self.soft_wrap_mode_override = Some(soft_wrap);
6222        }
6223        cx.notify();
6224    }
6225
6226    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6227        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6228            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6229                cx.reveal_path(&file.abs_path(cx));
6230            }
6231        }
6232    }
6233
6234    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6235        self.highlighted_rows = rows;
6236    }
6237
6238    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6239        self.highlighted_rows.clone()
6240    }
6241
6242    pub fn highlight_background<T: 'static>(
6243        &mut self,
6244        ranges: Vec<Range<Anchor>>,
6245        color_fetcher: fn(&Theme) -> Color,
6246        cx: &mut ViewContext<Self>,
6247    ) {
6248        self.background_highlights
6249            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6250        cx.notify();
6251    }
6252
6253    #[allow(clippy::type_complexity)]
6254    pub fn clear_background_highlights<T: 'static>(
6255        &mut self,
6256        cx: &mut ViewContext<Self>,
6257    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6258        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6259        if highlights.is_some() {
6260            cx.notify();
6261        }
6262        highlights
6263    }
6264
6265    #[cfg(feature = "test-support")]
6266    pub fn all_background_highlights(
6267        &mut self,
6268        cx: &mut ViewContext<Self>,
6269    ) -> Vec<(Range<DisplayPoint>, Color)> {
6270        let snapshot = self.snapshot(cx);
6271        let buffer = &snapshot.buffer_snapshot;
6272        let start = buffer.anchor_before(0);
6273        let end = buffer.anchor_after(buffer.len());
6274        let theme = cx.global::<Settings>().theme.as_ref();
6275        self.background_highlights_in_range(start..end, &snapshot, theme)
6276    }
6277
6278    fn document_highlights_for_position<'a>(
6279        &'a self,
6280        position: Anchor,
6281        buffer: &'a MultiBufferSnapshot,
6282    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6283        let read_highlights = self
6284            .background_highlights
6285            .get(&TypeId::of::<DocumentHighlightRead>())
6286            .map(|h| &h.1);
6287        let write_highlights = self
6288            .background_highlights
6289            .get(&TypeId::of::<DocumentHighlightWrite>())
6290            .map(|h| &h.1);
6291        let left_position = position.bias_left(buffer);
6292        let right_position = position.bias_right(buffer);
6293        read_highlights
6294            .into_iter()
6295            .chain(write_highlights)
6296            .flat_map(move |ranges| {
6297                let start_ix = match ranges.binary_search_by(|probe| {
6298                    let cmp = probe.end.cmp(&left_position, buffer);
6299                    if cmp.is_ge() {
6300                        Ordering::Greater
6301                    } else {
6302                        Ordering::Less
6303                    }
6304                }) {
6305                    Ok(i) | Err(i) => i,
6306                };
6307
6308                let right_position = right_position.clone();
6309                ranges[start_ix..]
6310                    .iter()
6311                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6312            })
6313    }
6314
6315    pub fn background_highlights_in_range(
6316        &self,
6317        search_range: Range<Anchor>,
6318        display_snapshot: &DisplaySnapshot,
6319        theme: &Theme,
6320    ) -> Vec<(Range<DisplayPoint>, Color)> {
6321        let mut results = Vec::new();
6322        let buffer = &display_snapshot.buffer_snapshot;
6323        for (color_fetcher, ranges) in self.background_highlights.values() {
6324            let color = color_fetcher(theme);
6325            let start_ix = match ranges.binary_search_by(|probe| {
6326                let cmp = probe.end.cmp(&search_range.start, buffer);
6327                if cmp.is_gt() {
6328                    Ordering::Greater
6329                } else {
6330                    Ordering::Less
6331                }
6332            }) {
6333                Ok(i) | Err(i) => i,
6334            };
6335            for range in &ranges[start_ix..] {
6336                if range.start.cmp(&search_range.end, buffer).is_ge() {
6337                    break;
6338                }
6339                let start = range
6340                    .start
6341                    .to_point(buffer)
6342                    .to_display_point(display_snapshot);
6343                let end = range
6344                    .end
6345                    .to_point(buffer)
6346                    .to_display_point(display_snapshot);
6347                results.push((start..end, color))
6348            }
6349        }
6350        results
6351    }
6352
6353    pub fn highlight_text<T: 'static>(
6354        &mut self,
6355        ranges: Vec<Range<Anchor>>,
6356        style: HighlightStyle,
6357        cx: &mut ViewContext<Self>,
6358    ) {
6359        self.display_map.update(cx, |map, _| {
6360            map.highlight_text(TypeId::of::<T>(), ranges, style)
6361        });
6362        cx.notify();
6363    }
6364
6365    pub fn text_highlights<'a, T: 'static>(
6366        &'a self,
6367        cx: &'a AppContext,
6368    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6369        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6370    }
6371
6372    pub fn clear_text_highlights<T: 'static>(
6373        &mut self,
6374        cx: &mut ViewContext<Self>,
6375    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6376        let highlights = self
6377            .display_map
6378            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6379        if highlights.is_some() {
6380            cx.notify();
6381        }
6382        highlights
6383    }
6384
6385    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6386        self.blink_manager.read(cx).visible() && self.focused
6387    }
6388
6389    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6390        cx.notify();
6391    }
6392
6393    fn on_buffer_event(
6394        &mut self,
6395        _: ModelHandle<MultiBuffer>,
6396        event: &multi_buffer::Event,
6397        cx: &mut ViewContext<Self>,
6398    ) {
6399        match event {
6400            multi_buffer::Event::Edited => {
6401                self.refresh_active_diagnostics(cx);
6402                self.refresh_code_actions(cx);
6403                self.refresh_copilot_suggestions(cx);
6404                cx.emit(Event::BufferEdited);
6405            }
6406            multi_buffer::Event::ExcerptsAdded {
6407                buffer,
6408                predecessor,
6409                excerpts,
6410            } => cx.emit(Event::ExcerptsAdded {
6411                buffer: buffer.clone(),
6412                predecessor: *predecessor,
6413                excerpts: excerpts.clone(),
6414            }),
6415            multi_buffer::Event::ExcerptsRemoved { ids } => {
6416                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6417            }
6418            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6419            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6420            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6421            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6422            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6423            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6424            multi_buffer::Event::DiagnosticsUpdated => {
6425                self.refresh_active_diagnostics(cx);
6426            }
6427        }
6428    }
6429
6430    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6431        cx.notify();
6432    }
6433
6434    fn on_settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6435        self.refresh_copilot_suggestions(cx);
6436    }
6437
6438    pub fn set_searchable(&mut self, searchable: bool) {
6439        self.searchable = searchable;
6440    }
6441
6442    pub fn searchable(&self) -> bool {
6443        self.searchable
6444    }
6445
6446    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6447        let active_item = workspace.active_item(cx);
6448        let editor_handle = if let Some(editor) = active_item
6449            .as_ref()
6450            .and_then(|item| item.act_as::<Self>(cx))
6451        {
6452            editor
6453        } else {
6454            cx.propagate_action();
6455            return;
6456        };
6457
6458        let editor = editor_handle.read(cx);
6459        let buffer = editor.buffer.read(cx);
6460        if buffer.is_singleton() {
6461            cx.propagate_action();
6462            return;
6463        }
6464
6465        let mut new_selections_by_buffer = HashMap::default();
6466        for selection in editor.selections.all::<usize>(cx) {
6467            for (buffer, mut range) in
6468                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6469            {
6470                if selection.reversed {
6471                    mem::swap(&mut range.start, &mut range.end);
6472                }
6473                new_selections_by_buffer
6474                    .entry(buffer)
6475                    .or_insert(Vec::new())
6476                    .push(range)
6477            }
6478        }
6479
6480        editor_handle.update(cx, |editor, cx| {
6481            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6482        });
6483        let pane = workspace.active_pane().clone();
6484        pane.update(cx, |pane, _| pane.disable_history());
6485
6486        // We defer the pane interaction because we ourselves are a workspace item
6487        // and activating a new item causes the pane to call a method on us reentrantly,
6488        // which panics if we're on the stack.
6489        cx.defer(move |workspace, cx| {
6490            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6491                let editor = workspace.open_project_item::<Self>(buffer, cx);
6492                editor.update(cx, |editor, cx| {
6493                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6494                        s.select_ranges(ranges);
6495                    });
6496                });
6497            }
6498
6499            pane.update(cx, |pane, _| pane.enable_history());
6500        });
6501    }
6502
6503    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6504        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6505        let position = action.position;
6506        let anchor = action.anchor;
6507        cx.spawn_weak(|_, mut cx| async move {
6508            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6509            editor.update(&mut cx, |editor, cx| {
6510                let buffer = editor.buffer().read(cx).as_singleton()?;
6511                let buffer = buffer.read(cx);
6512                let cursor = if buffer.can_resolve(&anchor) {
6513                    language::ToPoint::to_point(&anchor, buffer)
6514                } else {
6515                    buffer.clip_point(position, Bias::Left)
6516                };
6517
6518                let nav_history = editor.nav_history.take();
6519                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6520                    s.select_ranges([cursor..cursor]);
6521                });
6522                editor.nav_history = nav_history;
6523
6524                Some(())
6525            })?;
6526            Some(())
6527        })
6528        .detach()
6529    }
6530
6531    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6532        let snapshot = self.buffer.read(cx).read(cx);
6533        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6534        Some(
6535            ranges
6536                .iter()
6537                .map(move |range| {
6538                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6539                })
6540                .collect(),
6541        )
6542    }
6543
6544    fn selection_replacement_ranges(
6545        &self,
6546        range: Range<OffsetUtf16>,
6547        cx: &AppContext,
6548    ) -> Vec<Range<OffsetUtf16>> {
6549        let selections = self.selections.all::<OffsetUtf16>(cx);
6550        let newest_selection = selections
6551            .iter()
6552            .max_by_key(|selection| selection.id)
6553            .unwrap();
6554        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6555        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6556        let snapshot = self.buffer.read(cx).read(cx);
6557        selections
6558            .into_iter()
6559            .map(|mut selection| {
6560                selection.start.0 =
6561                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6562                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6563                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6564                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6565            })
6566            .collect()
6567    }
6568
6569    fn report_event(&self, name: &str, cx: &AppContext) {
6570        if let Some((project, file)) = self.project.as_ref().zip(
6571            self.buffer
6572                .read(cx)
6573                .as_singleton()
6574                .and_then(|b| b.read(cx).file()),
6575        ) {
6576            let extension = Path::new(file.file_name(cx))
6577                .extension()
6578                .and_then(|e| e.to_str());
6579            project.read(cx).client().report_event(
6580                name,
6581                json!({ "File Extension": extension }),
6582                cx.global::<Settings>().telemetry(),
6583            );
6584        }
6585    }
6586
6587    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6588    /// with each line being an array of {text, highlight} objects.
6589    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6590        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6591            return;
6592        };
6593
6594        #[derive(Serialize)]
6595        struct Chunk<'a> {
6596            text: String,
6597            highlight: Option<&'a str>,
6598        }
6599
6600        let snapshot = buffer.read(cx).snapshot();
6601        let range = self
6602            .selected_text_range(cx)
6603            .and_then(|selected_range| {
6604                if selected_range.is_empty() {
6605                    None
6606                } else {
6607                    Some(selected_range)
6608                }
6609            })
6610            .unwrap_or_else(|| 0..snapshot.len());
6611
6612        let chunks = snapshot.chunks(range, true);
6613        let mut lines = Vec::new();
6614        let mut line: VecDeque<Chunk> = VecDeque::new();
6615
6616        let theme = &cx.global::<Settings>().theme.editor.syntax;
6617
6618        for chunk in chunks {
6619            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
6620            let mut chunk_lines = chunk.text.split("\n").peekable();
6621            while let Some(text) = chunk_lines.next() {
6622                let mut merged_with_last_token = false;
6623                if let Some(last_token) = line.back_mut() {
6624                    if last_token.highlight == highlight {
6625                        last_token.text.push_str(text);
6626                        merged_with_last_token = true;
6627                    }
6628                }
6629
6630                if !merged_with_last_token {
6631                    line.push_back(Chunk {
6632                        text: text.into(),
6633                        highlight,
6634                    });
6635                }
6636
6637                if chunk_lines.peek().is_some() {
6638                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
6639                        line.pop_front();
6640                    }
6641                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
6642                        line.pop_back();
6643                    }
6644
6645                    lines.push(mem::take(&mut line));
6646                }
6647            }
6648        }
6649
6650        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
6651        cx.write_to_clipboard(ClipboardItem::new(lines));
6652    }
6653}
6654
6655fn consume_contiguous_rows(
6656    contiguous_row_selections: &mut Vec<Selection<Point>>,
6657    selection: &Selection<Point>,
6658    display_map: &DisplaySnapshot,
6659    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
6660) -> (u32, u32) {
6661    contiguous_row_selections.push(selection.clone());
6662    let start_row = selection.start.row;
6663    let mut end_row = ending_row(selection, display_map);
6664
6665    while let Some(next_selection) = selections.peek() {
6666        if next_selection.start.row <= end_row {
6667            end_row = ending_row(next_selection, display_map);
6668            contiguous_row_selections.push(selections.next().unwrap().clone());
6669        } else {
6670            break;
6671        }
6672    }
6673    (start_row, end_row)
6674}
6675
6676fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
6677    if next_selection.end.column > 0 || next_selection.is_empty() {
6678        display_map.next_line_boundary(next_selection.end).0.row + 1
6679    } else {
6680        next_selection.end.row
6681    }
6682}
6683
6684impl EditorSnapshot {
6685    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6686        self.display_snapshot.buffer_snapshot.language_at(position)
6687    }
6688
6689    pub fn is_focused(&self) -> bool {
6690        self.is_focused
6691    }
6692
6693    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6694        self.placeholder_text.as_ref()
6695    }
6696
6697    pub fn scroll_position(&self) -> Vector2F {
6698        self.scroll_anchor.scroll_position(&self.display_snapshot)
6699    }
6700}
6701
6702impl Deref for EditorSnapshot {
6703    type Target = DisplaySnapshot;
6704
6705    fn deref(&self) -> &Self::Target {
6706        &self.display_snapshot
6707    }
6708}
6709
6710#[derive(Clone, Debug, PartialEq, Eq)]
6711pub enum Event {
6712    InputIgnored {
6713        text: Arc<str>,
6714    },
6715    ExcerptsAdded {
6716        buffer: ModelHandle<Buffer>,
6717        predecessor: ExcerptId,
6718        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6719    },
6720    ExcerptsRemoved {
6721        ids: Vec<ExcerptId>,
6722    },
6723    BufferEdited,
6724    Edited,
6725    Reparsed,
6726    Blurred,
6727    DirtyChanged,
6728    Saved,
6729    TitleChanged,
6730    SelectionsChanged {
6731        local: bool,
6732    },
6733    ScrollPositionChanged {
6734        local: bool,
6735    },
6736    Closed,
6737}
6738
6739pub struct EditorFocused(pub ViewHandle<Editor>);
6740pub struct EditorBlurred(pub ViewHandle<Editor>);
6741pub struct EditorReleased(pub WeakViewHandle<Editor>);
6742
6743impl Entity for Editor {
6744    type Event = Event;
6745
6746    fn release(&mut self, cx: &mut MutableAppContext) {
6747        cx.emit_global(EditorReleased(self.handle.clone()));
6748    }
6749}
6750
6751impl View for Editor {
6752    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6753        let style = self.style(cx);
6754        let font_changed = self.display_map.update(cx, |map, cx| {
6755            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
6756            map.set_font(style.text.font_id, style.text.font_size, cx)
6757        });
6758
6759        if font_changed {
6760            let handle = self.handle.clone();
6761            cx.defer(move |cx| {
6762                if let Some(editor) = handle.upgrade(cx) {
6763                    editor.update(cx, |editor, cx| {
6764                        hide_hover(editor, &HideHover, cx);
6765                        hide_link_definition(editor, cx);
6766                    })
6767                }
6768            });
6769        }
6770
6771        Stack::new()
6772            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6773            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6774            .boxed()
6775    }
6776
6777    fn ui_name() -> &'static str {
6778        "Editor"
6779    }
6780
6781    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6782        if cx.is_self_focused() {
6783            let focused_event = EditorFocused(cx.handle());
6784            cx.emit_global(focused_event);
6785        }
6786        if let Some(rename) = self.pending_rename.as_ref() {
6787            cx.focus(&rename.editor);
6788        } else {
6789            if !self.focused {
6790                self.blink_manager.update(cx, BlinkManager::enable);
6791            }
6792            self.focused = true;
6793            self.buffer.update(cx, |buffer, cx| {
6794                buffer.finalize_last_transaction(cx);
6795                if self.leader_replica_id.is_none() {
6796                    buffer.set_active_selections(
6797                        &self.selections.disjoint_anchors(),
6798                        self.selections.line_mode,
6799                        self.cursor_shape,
6800                        cx,
6801                    );
6802                }
6803            });
6804        }
6805    }
6806
6807    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6808        let blurred_event = EditorBlurred(cx.handle());
6809        cx.emit_global(blurred_event);
6810        self.focused = false;
6811        self.blink_manager.update(cx, BlinkManager::disable);
6812        self.buffer
6813            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6814        self.hide_context_menu(cx);
6815        hide_hover(self, &HideHover, cx);
6816        cx.emit(Event::Blurred);
6817        cx.notify();
6818    }
6819
6820    fn modifiers_changed(
6821        &mut self,
6822        event: &gpui::ModifiersChangedEvent,
6823        cx: &mut ViewContext<Self>,
6824    ) -> bool {
6825        let pending_selection = self.has_pending_selection();
6826
6827        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6828            if event.cmd && !pending_selection {
6829                let snapshot = self.snapshot(cx);
6830                let kind = if event.shift {
6831                    LinkDefinitionKind::Type
6832                } else {
6833                    LinkDefinitionKind::Symbol
6834                };
6835
6836                show_link_definition(kind, self, point, snapshot, cx);
6837                return false;
6838            }
6839        }
6840
6841        {
6842            if self.link_go_to_definition_state.symbol_range.is_some()
6843                || !self.link_go_to_definition_state.definitions.is_empty()
6844            {
6845                self.link_go_to_definition_state.symbol_range.take();
6846                self.link_go_to_definition_state.definitions.clear();
6847                cx.notify();
6848            }
6849
6850            self.link_go_to_definition_state.task = None;
6851
6852            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6853        }
6854
6855        false
6856    }
6857
6858    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6859        let mut context = Self::default_keymap_context();
6860        let mode = match self.mode {
6861            EditorMode::SingleLine => "single_line",
6862            EditorMode::AutoHeight { .. } => "auto_height",
6863            EditorMode::Full => "full",
6864        };
6865        context.add_key("mode", mode);
6866        if self.pending_rename.is_some() {
6867            context.add_identifier("renaming");
6868        }
6869        match self.context_menu.as_ref() {
6870            Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
6871            Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
6872            None => {}
6873        }
6874
6875        for layer in self.keymap_context_layers.values() {
6876            context.extend(layer);
6877        }
6878
6879        context
6880    }
6881
6882    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6883        Some(
6884            self.buffer
6885                .read(cx)
6886                .read(cx)
6887                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6888                .collect(),
6889        )
6890    }
6891
6892    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6893        // Prevent the IME menu from appearing when holding down an alphabetic key
6894        // while input is disabled.
6895        if !self.input_enabled {
6896            return None;
6897        }
6898
6899        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6900        Some(range.start.0..range.end.0)
6901    }
6902
6903    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6904        let snapshot = self.buffer.read(cx).read(cx);
6905        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6906        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6907    }
6908
6909    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6910        self.clear_text_highlights::<InputComposition>(cx);
6911        self.ime_transaction.take();
6912    }
6913
6914    fn replace_text_in_range(
6915        &mut self,
6916        range_utf16: Option<Range<usize>>,
6917        text: &str,
6918        cx: &mut ViewContext<Self>,
6919    ) {
6920        self.transact(cx, |this, cx| {
6921            if this.input_enabled {
6922                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6923                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6924                    Some(this.selection_replacement_ranges(range_utf16, cx))
6925                } else {
6926                    this.marked_text_ranges(cx)
6927                };
6928
6929                if let Some(new_selected_ranges) = new_selected_ranges {
6930                    this.change_selections(None, cx, |selections| {
6931                        selections.select_ranges(new_selected_ranges)
6932                    });
6933                }
6934            }
6935
6936            this.handle_input(text, cx);
6937        });
6938
6939        if !self.input_enabled {
6940            return;
6941        }
6942
6943        if let Some(transaction) = self.ime_transaction {
6944            self.buffer.update(cx, |buffer, cx| {
6945                buffer.group_until_transaction(transaction, cx);
6946            });
6947        }
6948
6949        self.unmark_text(cx);
6950    }
6951
6952    fn replace_and_mark_text_in_range(
6953        &mut self,
6954        range_utf16: Option<Range<usize>>,
6955        text: &str,
6956        new_selected_range_utf16: Option<Range<usize>>,
6957        cx: &mut ViewContext<Self>,
6958    ) {
6959        if !self.input_enabled {
6960            return;
6961        }
6962
6963        let transaction = self.transact(cx, |this, cx| {
6964            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6965                let snapshot = this.buffer.read(cx).read(cx);
6966                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6967                    for marked_range in &mut marked_ranges {
6968                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6969                        marked_range.start.0 += relative_range_utf16.start;
6970                        marked_range.start =
6971                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6972                        marked_range.end =
6973                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6974                    }
6975                }
6976                Some(marked_ranges)
6977            } else if let Some(range_utf16) = range_utf16 {
6978                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6979                Some(this.selection_replacement_ranges(range_utf16, cx))
6980            } else {
6981                None
6982            };
6983
6984            if let Some(ranges) = ranges_to_replace {
6985                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6986            }
6987
6988            let marked_ranges = {
6989                let snapshot = this.buffer.read(cx).read(cx);
6990                this.selections
6991                    .disjoint_anchors()
6992                    .iter()
6993                    .map(|selection| {
6994                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6995                    })
6996                    .collect::<Vec<_>>()
6997            };
6998
6999            if text.is_empty() {
7000                this.unmark_text(cx);
7001            } else {
7002                this.highlight_text::<InputComposition>(
7003                    marked_ranges.clone(),
7004                    this.style(cx).composition_mark,
7005                    cx,
7006                );
7007            }
7008
7009            this.handle_input(text, cx);
7010
7011            if let Some(new_selected_range) = new_selected_range_utf16 {
7012                let snapshot = this.buffer.read(cx).read(cx);
7013                let new_selected_ranges = marked_ranges
7014                    .into_iter()
7015                    .map(|marked_range| {
7016                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7017                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7018                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7019                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7020                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7021                    })
7022                    .collect::<Vec<_>>();
7023
7024                drop(snapshot);
7025                this.change_selections(None, cx, |selections| {
7026                    selections.select_ranges(new_selected_ranges)
7027                });
7028            }
7029        });
7030
7031        self.ime_transaction = self.ime_transaction.or(transaction);
7032        if let Some(transaction) = self.ime_transaction {
7033            self.buffer.update(cx, |buffer, cx| {
7034                buffer.group_until_transaction(transaction, cx);
7035            });
7036        }
7037
7038        if self.text_highlights::<InputComposition>(cx).is_none() {
7039            self.ime_transaction.take();
7040        }
7041    }
7042}
7043
7044fn build_style(
7045    settings: &Settings,
7046    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7047    override_text_style: Option<&OverrideTextStyle>,
7048    cx: &AppContext,
7049) -> EditorStyle {
7050    let font_cache = cx.font_cache();
7051
7052    let mut theme = settings.theme.editor.clone();
7053    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7054        let field_editor_theme = get_field_editor_theme(&settings.theme);
7055        theme.text_color = field_editor_theme.text.color;
7056        theme.selection = field_editor_theme.selection;
7057        theme.background = field_editor_theme
7058            .container
7059            .background_color
7060            .unwrap_or_default();
7061        EditorStyle {
7062            text: field_editor_theme.text,
7063            placeholder_text: field_editor_theme.placeholder_text,
7064            theme,
7065        }
7066    } else {
7067        let font_family_id = settings.buffer_font_family;
7068        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7069        let font_properties = Default::default();
7070        let font_id = font_cache
7071            .select_font(font_family_id, &font_properties)
7072            .unwrap();
7073        let font_size = settings.buffer_font_size;
7074        EditorStyle {
7075            text: TextStyle {
7076                color: settings.theme.editor.text_color,
7077                font_family_name,
7078                font_family_id,
7079                font_id,
7080                font_size,
7081                font_properties,
7082                underline: Default::default(),
7083            },
7084            placeholder_text: None,
7085            theme,
7086        }
7087    };
7088
7089    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7090        if let Some(highlighted) = style
7091            .text
7092            .clone()
7093            .highlight(highlight_style, font_cache)
7094            .log_err()
7095        {
7096            style.text = highlighted;
7097        }
7098    }
7099
7100    style
7101}
7102
7103trait SelectionExt {
7104    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7105    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7106    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7107    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7108        -> Range<u32>;
7109}
7110
7111impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7112    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7113        let start = self.start.to_point(buffer);
7114        let end = self.end.to_point(buffer);
7115        if self.reversed {
7116            end..start
7117        } else {
7118            start..end
7119        }
7120    }
7121
7122    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7123        let start = self.start.to_offset(buffer);
7124        let end = self.end.to_offset(buffer);
7125        if self.reversed {
7126            end..start
7127        } else {
7128            start..end
7129        }
7130    }
7131
7132    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7133        let start = self
7134            .start
7135            .to_point(&map.buffer_snapshot)
7136            .to_display_point(map);
7137        let end = self
7138            .end
7139            .to_point(&map.buffer_snapshot)
7140            .to_display_point(map);
7141        if self.reversed {
7142            end..start
7143        } else {
7144            start..end
7145        }
7146    }
7147
7148    fn spanned_rows(
7149        &self,
7150        include_end_if_at_line_start: bool,
7151        map: &DisplaySnapshot,
7152    ) -> Range<u32> {
7153        let start = self.start.to_point(&map.buffer_snapshot);
7154        let mut end = self.end.to_point(&map.buffer_snapshot);
7155        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7156            end.row -= 1;
7157        }
7158
7159        let buffer_start = map.prev_line_boundary(start).0;
7160        let buffer_end = map.next_line_boundary(end).0;
7161        buffer_start.row..buffer_end.row + 1
7162    }
7163}
7164
7165impl<T: InvalidationRegion> InvalidationStack<T> {
7166    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7167    where
7168        S: Clone + ToOffset,
7169    {
7170        while let Some(region) = self.last() {
7171            let all_selections_inside_invalidation_ranges =
7172                if selections.len() == region.ranges().len() {
7173                    selections
7174                        .iter()
7175                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7176                        .all(|(selection, invalidation_range)| {
7177                            let head = selection.head().to_offset(buffer);
7178                            invalidation_range.start <= head && invalidation_range.end >= head
7179                        })
7180                } else {
7181                    false
7182                };
7183
7184            if all_selections_inside_invalidation_ranges {
7185                break;
7186            } else {
7187                self.pop();
7188            }
7189        }
7190    }
7191}
7192
7193impl<T> Default for InvalidationStack<T> {
7194    fn default() -> Self {
7195        Self(Default::default())
7196    }
7197}
7198
7199impl<T> Deref for InvalidationStack<T> {
7200    type Target = Vec<T>;
7201
7202    fn deref(&self) -> &Self::Target {
7203        &self.0
7204    }
7205}
7206
7207impl<T> DerefMut for InvalidationStack<T> {
7208    fn deref_mut(&mut self) -> &mut Self::Target {
7209        &mut self.0
7210    }
7211}
7212
7213impl InvalidationRegion for SnippetState {
7214    fn ranges(&self) -> &[Range<Anchor>] {
7215        &self.ranges[self.active_index]
7216    }
7217}
7218
7219impl Deref for EditorStyle {
7220    type Target = theme::Editor;
7221
7222    fn deref(&self) -> &Self::Target {
7223        &self.theme
7224    }
7225}
7226
7227pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7228    let mut highlighted_lines = Vec::new();
7229    for line in diagnostic.message.lines() {
7230        highlighted_lines.push(highlight_diagnostic_message(line));
7231    }
7232
7233    Arc::new(move |cx: &mut BlockContext| {
7234        let settings = cx.global::<Settings>();
7235        let theme = &settings.theme.editor;
7236        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7237        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7238        Flex::column()
7239            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7240                Label::new(
7241                    line.clone(),
7242                    style.message.clone().with_font_size(font_size),
7243                )
7244                .with_highlights(highlights.clone())
7245                .contained()
7246                .with_margin_left(cx.anchor_x)
7247                .boxed()
7248            }))
7249            .aligned()
7250            .left()
7251            .boxed()
7252    })
7253}
7254
7255pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
7256    let mut message_without_backticks = String::new();
7257    let mut prev_offset = 0;
7258    let mut inside_block = false;
7259    let mut highlights = Vec::new();
7260    for (match_ix, (offset, _)) in message
7261        .match_indices('`')
7262        .chain([(message.len(), "")])
7263        .enumerate()
7264    {
7265        message_without_backticks.push_str(&message[prev_offset..offset]);
7266        if inside_block {
7267            highlights.extend(prev_offset - match_ix..offset - match_ix);
7268        }
7269
7270        inside_block = !inside_block;
7271        prev_offset = offset + 1;
7272    }
7273
7274    (message_without_backticks, highlights)
7275}
7276
7277pub fn diagnostic_style(
7278    severity: DiagnosticSeverity,
7279    valid: bool,
7280    theme: &theme::Editor,
7281) -> DiagnosticStyle {
7282    match (severity, valid) {
7283        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7284        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7285        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7286        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7287        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7288        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7289        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7290        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7291        _ => theme.invalid_hint_diagnostic.clone(),
7292    }
7293}
7294
7295pub fn combine_syntax_and_fuzzy_match_highlights(
7296    text: &str,
7297    default_style: HighlightStyle,
7298    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7299    match_indices: &[usize],
7300) -> Vec<(Range<usize>, HighlightStyle)> {
7301    let mut result = Vec::new();
7302    let mut match_indices = match_indices.iter().copied().peekable();
7303
7304    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7305    {
7306        syntax_highlight.weight = None;
7307
7308        // Add highlights for any fuzzy match characters before the next
7309        // syntax highlight range.
7310        while let Some(&match_index) = match_indices.peek() {
7311            if match_index >= range.start {
7312                break;
7313            }
7314            match_indices.next();
7315            let end_index = char_ix_after(match_index, text);
7316            let mut match_style = default_style;
7317            match_style.weight = Some(fonts::Weight::BOLD);
7318            result.push((match_index..end_index, match_style));
7319        }
7320
7321        if range.start == usize::MAX {
7322            break;
7323        }
7324
7325        // Add highlights for any fuzzy match characters within the
7326        // syntax highlight range.
7327        let mut offset = range.start;
7328        while let Some(&match_index) = match_indices.peek() {
7329            if match_index >= range.end {
7330                break;
7331            }
7332
7333            match_indices.next();
7334            if match_index > offset {
7335                result.push((offset..match_index, syntax_highlight));
7336            }
7337
7338            let mut end_index = char_ix_after(match_index, text);
7339            while let Some(&next_match_index) = match_indices.peek() {
7340                if next_match_index == end_index && next_match_index < range.end {
7341                    end_index = char_ix_after(next_match_index, text);
7342                    match_indices.next();
7343                } else {
7344                    break;
7345                }
7346            }
7347
7348            let mut match_style = syntax_highlight;
7349            match_style.weight = Some(fonts::Weight::BOLD);
7350            result.push((match_index..end_index, match_style));
7351            offset = end_index;
7352        }
7353
7354        if offset < range.end {
7355            result.push((offset..range.end, syntax_highlight));
7356        }
7357    }
7358
7359    fn char_ix_after(ix: usize, text: &str) -> usize {
7360        ix + text[ix..].chars().next().unwrap().len_utf8()
7361    }
7362
7363    result
7364}
7365
7366pub fn styled_runs_for_code_label<'a>(
7367    label: &'a CodeLabel,
7368    syntax_theme: &'a theme::SyntaxTheme,
7369) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7370    let fade_out = HighlightStyle {
7371        fade_out: Some(0.35),
7372        ..Default::default()
7373    };
7374
7375    let mut prev_end = label.filter_range.end;
7376    label
7377        .runs
7378        .iter()
7379        .enumerate()
7380        .flat_map(move |(ix, (range, highlight_id))| {
7381            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7382                style
7383            } else {
7384                return Default::default();
7385            };
7386            let mut muted_style = style;
7387            muted_style.highlight(fade_out);
7388
7389            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7390            if range.start >= label.filter_range.end {
7391                if range.start > prev_end {
7392                    runs.push((prev_end..range.start, fade_out));
7393                }
7394                runs.push((range.clone(), muted_style));
7395            } else if range.end <= label.filter_range.end {
7396                runs.push((range.clone(), style));
7397            } else {
7398                runs.push((range.start..label.filter_range.end, style));
7399                runs.push((label.filter_range.end..range.end, muted_style));
7400            }
7401            prev_end = cmp::max(prev_end, range.end);
7402
7403            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7404                runs.push((prev_end..label.text.len(), fade_out));
7405            }
7406
7407            runs
7408        })
7409}
7410
7411pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7412    let mut index = 0;
7413    let mut codepoints = text.char_indices().peekable();
7414
7415    std::iter::from_fn(move || {
7416        let start_index = index;
7417        while let Some((new_index, codepoint)) = codepoints.next() {
7418            index = new_index + codepoint.len_utf8();
7419            let current_upper = codepoint.is_uppercase();
7420            let next_upper = codepoints
7421                .peek()
7422                .map(|(_, c)| c.is_uppercase())
7423                .unwrap_or(false);
7424
7425            if !current_upper && next_upper {
7426                return Some(&text[start_index..index]);
7427            }
7428        }
7429
7430        index = text.len();
7431        if start_index < text.len() {
7432            return Some(&text[start_index..]);
7433        }
7434        None
7435    })
7436    .flat_map(|word| word.split_inclusive('_'))
7437}
7438
7439trait RangeToAnchorExt {
7440    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7441}
7442
7443impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7444    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7445        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7446    }
7447}