editor.rs

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