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