editor.rs

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