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