editor.rs

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