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