editor.rs

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