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