editor.rs

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