editor.rs

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