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