editor.rs

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