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(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(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(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(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(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2834        let copilot = Copilot::global(cx)?;
2835        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
2836            self.clear_copilot_suggestions(cx);
2837            return None;
2838        }
2839        self.update_visible_copilot_suggestion(cx);
2840
2841        let snapshot = self.buffer.read(cx).snapshot(cx);
2842        let cursor = self.selections.newest_anchor().head();
2843        let language_name = snapshot.language_at(cursor).map(|language| language.name());
2844        if !cx
2845            .global::<Settings>()
2846            .show_copilot_suggestions(language_name.as_deref())
2847        {
2848            self.clear_copilot_suggestions(cx);
2849            return None;
2850        }
2851
2852        let (buffer, buffer_position) =
2853            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
2854        self.copilot_state.pending_refresh = cx.spawn_weak(|this, mut cx| async move {
2855            cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
2856
2857            let completions = copilot
2858                .update(&mut cx, |copilot, cx| {
2859                    copilot.completions(&buffer, buffer_position, cx)
2860                })
2861                .await
2862                .log_err()
2863                .into_iter()
2864                .flatten()
2865                .collect_vec();
2866
2867            this.upgrade(&cx)?.update(&mut cx, |this, cx| {
2868                if !completions.is_empty() {
2869                    this.copilot_state.cycled = false;
2870                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
2871                    this.copilot_state.completions.clear();
2872                    this.copilot_state.active_completion_index = 0;
2873                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
2874                    for completion in completions {
2875                        this.copilot_state.push_completion(completion);
2876                    }
2877                    this.update_visible_copilot_suggestion(cx);
2878                }
2879            });
2880
2881            Some(())
2882        });
2883
2884        Some(())
2885    }
2886
2887    fn cycle_suggestions(
2888        &mut self,
2889        direction: Direction,
2890        cx: &mut ViewContext<Self>,
2891    ) -> Option<()> {
2892        let copilot = Copilot::global(cx)?;
2893        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
2894            return None;
2895        }
2896
2897        if self.copilot_state.cycled {
2898            self.copilot_state.cycle_completions(direction);
2899            self.update_visible_copilot_suggestion(cx);
2900        } else {
2901            let cursor = self.selections.newest_anchor().head();
2902            let (buffer, buffer_position) =
2903                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
2904            self.copilot_state.pending_cycling_refresh = cx.spawn_weak(|this, mut cx| async move {
2905                let completions = copilot
2906                    .update(&mut cx, |copilot, cx| {
2907                        copilot.completions_cycling(&buffer, buffer_position, cx)
2908                    })
2909                    .await;
2910
2911                this.upgrade(&cx)?.update(&mut cx, |this, cx| {
2912                    this.copilot_state.cycled = true;
2913                    for completion in completions.log_err().into_iter().flatten() {
2914                        this.copilot_state.push_completion(completion);
2915                    }
2916                    this.copilot_state.cycle_completions(direction);
2917                    this.update_visible_copilot_suggestion(cx);
2918                });
2919
2920                Some(())
2921            });
2922        }
2923
2924        Some(())
2925    }
2926
2927    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
2928        if !self.has_active_copilot_suggestion(cx) {
2929            self.refresh_copilot_suggestions(cx);
2930            return;
2931        }
2932
2933        self.update_visible_copilot_suggestion(cx);
2934    }
2935
2936    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
2937        // if self.has_active_copilot_suggestion(cx) {
2938        self.cycle_suggestions(Direction::Next, cx);
2939        // } else {
2940        // self.refresh_copilot_suggestions(cx);
2941        // }
2942    }
2943
2944    fn previous_copilot_suggestion(
2945        &mut self,
2946        _: &copilot::PreviousSuggestion,
2947        cx: &mut ViewContext<Self>,
2948    ) {
2949        // if self.has_active_copilot_suggestion(cx) {
2950        self.cycle_suggestions(Direction::Prev, cx);
2951        // } else {
2952        // self.refresh_copilot_suggestions(cx);
2953        // }
2954    }
2955
2956    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
2957        if let Some(text) = self.hide_copilot_suggestion(cx) {
2958            self.insert_with_autoindent_mode(&text.to_string(), None, cx);
2959            true
2960        } else {
2961            false
2962        }
2963    }
2964
2965    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
2966        self.display_map.read(cx).has_suggestion()
2967    }
2968
2969    fn hide_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Rope> {
2970        if self.has_active_copilot_suggestion(cx) {
2971            let old_suggestion = self
2972                .display_map
2973                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
2974            cx.notify();
2975            old_suggestion.map(|suggestion| suggestion.text)
2976        } else {
2977            None
2978        }
2979    }
2980
2981    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
2982        let snapshot = self.buffer.read(cx).snapshot(cx);
2983        let selection = self.selections.newest_anchor();
2984        let cursor = selection.head();
2985
2986        if self.context_menu.is_some()
2987            || !self.completion_tasks.is_empty()
2988            || selection.start != selection.end
2989        {
2990            self.hide_copilot_suggestion(cx);
2991        } else if let Some(text) = self
2992            .copilot_state
2993            .text_for_active_completion(cursor, &snapshot)
2994        {
2995            self.display_map.update(cx, move |map, cx| {
2996                map.replace_suggestion(
2997                    Some(Suggestion {
2998                        position: cursor,
2999                        text: text.trim_end().into(),
3000                    }),
3001                    cx,
3002                )
3003            });
3004            cx.notify();
3005        } else {
3006            self.hide_copilot_suggestion(cx);
3007        }
3008    }
3009
3010    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3011        self.copilot_state = Default::default();
3012        self.hide_copilot_suggestion(cx);
3013    }
3014
3015    pub fn render_code_actions_indicator(
3016        &self,
3017        style: &EditorStyle,
3018        active: bool,
3019        cx: &mut RenderContext<Self>,
3020    ) -> Option<ElementBox> {
3021        if self.available_code_actions.is_some() {
3022            enum CodeActions {}
3023            Some(
3024                MouseEventHandler::<CodeActions>::new(0, cx, |state, _| {
3025                    Svg::new("icons/bolt_8.svg")
3026                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3027                        .boxed()
3028                })
3029                .with_cursor_style(CursorStyle::PointingHand)
3030                .with_padding(Padding::uniform(3.))
3031                .on_down(MouseButton::Left, |_, cx| {
3032                    cx.dispatch_action(ToggleCodeActions {
3033                        deployed_from_indicator: true,
3034                    });
3035                })
3036                .boxed(),
3037            )
3038        } else {
3039            None
3040        }
3041    }
3042
3043    pub fn render_fold_indicators(
3044        &self,
3045        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3046        style: &EditorStyle,
3047        gutter_hovered: bool,
3048        line_height: f32,
3049        gutter_margin: f32,
3050        cx: &mut RenderContext<Self>,
3051    ) -> Vec<Option<ElementBox>> {
3052        enum FoldIndicators {}
3053
3054        let style = style.folds.clone();
3055
3056        fold_data
3057            .iter()
3058            .enumerate()
3059            .map(|(ix, fold_data)| {
3060                fold_data
3061                    .map(|(fold_status, buffer_row, active)| {
3062                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3063                            MouseEventHandler::<FoldIndicators>::new(
3064                                ix as usize,
3065                                cx,
3066                                |mouse_state, _| -> ElementBox {
3067                                    Svg::new(match fold_status {
3068                                        FoldStatus::Folded => style.folded_icon.clone(),
3069                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3070                                    })
3071                                    .with_color(
3072                                        style
3073                                            .indicator
3074                                            .style_for(
3075                                                mouse_state,
3076                                                fold_status == FoldStatus::Folded,
3077                                            )
3078                                            .color,
3079                                    )
3080                                    .constrained()
3081                                    .with_width(gutter_margin * style.icon_margin_scale)
3082                                    .aligned()
3083                                    .constrained()
3084                                    .with_height(line_height)
3085                                    .with_width(gutter_margin)
3086                                    .aligned()
3087                                    .boxed()
3088                                },
3089                            )
3090                            .with_cursor_style(CursorStyle::PointingHand)
3091                            .with_padding(Padding::uniform(3.))
3092                            .on_click(MouseButton::Left, {
3093                                move |_, cx| {
3094                                    cx.dispatch_any_action(match fold_status {
3095                                        FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
3096                                        FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
3097                                    });
3098                                }
3099                            })
3100                            .boxed()
3101                        })
3102                    })
3103                    .flatten()
3104            })
3105            .collect()
3106    }
3107
3108    pub fn context_menu_visible(&self) -> bool {
3109        self.context_menu
3110            .as_ref()
3111            .map_or(false, |menu| menu.visible())
3112    }
3113
3114    pub fn render_context_menu(
3115        &self,
3116        cursor_position: DisplayPoint,
3117        style: EditorStyle,
3118        cx: &mut RenderContext<Editor>,
3119    ) -> Option<(DisplayPoint, ElementBox)> {
3120        self.context_menu
3121            .as_ref()
3122            .map(|menu| menu.render(cursor_position, style, cx))
3123    }
3124
3125    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3126        if !matches!(menu, ContextMenu::Completions(_)) {
3127            self.completion_tasks.clear();
3128        }
3129        self.context_menu = Some(menu);
3130        self.hide_copilot_suggestion(cx);
3131        cx.notify();
3132    }
3133
3134    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3135        cx.notify();
3136        self.completion_tasks.clear();
3137        let context_menu = self.context_menu.take();
3138        if context_menu.is_some() {
3139            self.update_visible_copilot_suggestion(cx);
3140        }
3141        context_menu
3142    }
3143
3144    pub fn insert_snippet(
3145        &mut self,
3146        insertion_ranges: &[Range<usize>],
3147        snippet: Snippet,
3148        cx: &mut ViewContext<Self>,
3149    ) -> Result<()> {
3150        let tabstops = self.buffer.update(cx, |buffer, cx| {
3151            let snippet_text: Arc<str> = snippet.text.clone().into();
3152            buffer.edit(
3153                insertion_ranges
3154                    .iter()
3155                    .cloned()
3156                    .map(|range| (range, snippet_text.clone())),
3157                Some(AutoindentMode::EachLine),
3158                cx,
3159            );
3160
3161            let snapshot = &*buffer.read(cx);
3162            let snippet = &snippet;
3163            snippet
3164                .tabstops
3165                .iter()
3166                .map(|tabstop| {
3167                    let mut tabstop_ranges = tabstop
3168                        .iter()
3169                        .flat_map(|tabstop_range| {
3170                            let mut delta = 0_isize;
3171                            insertion_ranges.iter().map(move |insertion_range| {
3172                                let insertion_start = insertion_range.start as isize + delta;
3173                                delta +=
3174                                    snippet.text.len() as isize - insertion_range.len() as isize;
3175
3176                                let start = snapshot.anchor_before(
3177                                    (insertion_start + tabstop_range.start) as usize,
3178                                );
3179                                let end = snapshot
3180                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3181                                start..end
3182                            })
3183                        })
3184                        .collect::<Vec<_>>();
3185                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3186                    tabstop_ranges
3187                })
3188                .collect::<Vec<_>>()
3189        });
3190
3191        if let Some(tabstop) = tabstops.first() {
3192            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3193                s.select_ranges(tabstop.iter().cloned());
3194            });
3195            self.snippet_stack.push(SnippetState {
3196                active_index: 0,
3197                ranges: tabstops,
3198            });
3199        }
3200
3201        Ok(())
3202    }
3203
3204    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3205        self.move_to_snippet_tabstop(Bias::Right, cx)
3206    }
3207
3208    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3209        self.move_to_snippet_tabstop(Bias::Left, cx)
3210    }
3211
3212    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3213        if let Some(mut snippet) = self.snippet_stack.pop() {
3214            match bias {
3215                Bias::Left => {
3216                    if snippet.active_index > 0 {
3217                        snippet.active_index -= 1;
3218                    } else {
3219                        self.snippet_stack.push(snippet);
3220                        return false;
3221                    }
3222                }
3223                Bias::Right => {
3224                    if snippet.active_index + 1 < snippet.ranges.len() {
3225                        snippet.active_index += 1;
3226                    } else {
3227                        self.snippet_stack.push(snippet);
3228                        return false;
3229                    }
3230                }
3231            }
3232            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3233                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3234                    s.select_anchor_ranges(current_ranges.iter().cloned())
3235                });
3236                // If snippet state is not at the last tabstop, push it back on the stack
3237                if snippet.active_index + 1 < snippet.ranges.len() {
3238                    self.snippet_stack.push(snippet);
3239                }
3240                return true;
3241            }
3242        }
3243
3244        false
3245    }
3246
3247    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3248        self.transact(cx, |this, cx| {
3249            this.select_all(&SelectAll, cx);
3250            this.insert("", cx);
3251        });
3252    }
3253
3254    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3255        self.transact(cx, |this, cx| {
3256            this.select_autoclose_pair(cx);
3257            let mut selections = this.selections.all::<Point>(cx);
3258            if !this.selections.line_mode {
3259                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3260                for selection in &mut selections {
3261                    if selection.is_empty() {
3262                        let old_head = selection.head();
3263                        let mut new_head =
3264                            movement::left(&display_map, old_head.to_display_point(&display_map))
3265                                .to_point(&display_map);
3266                        if let Some((buffer, line_buffer_range)) = display_map
3267                            .buffer_snapshot
3268                            .buffer_line_for_row(old_head.row)
3269                        {
3270                            let indent_size =
3271                                buffer.indent_size_for_line(line_buffer_range.start.row);
3272                            let language_name = buffer
3273                                .language_at(line_buffer_range.start)
3274                                .map(|language| language.name());
3275                            let indent_len = match indent_size.kind {
3276                                IndentKind::Space => {
3277                                    cx.global::<Settings>().tab_size(language_name.as_deref())
3278                                }
3279                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3280                            };
3281                            if old_head.column <= indent_size.len && old_head.column > 0 {
3282                                let indent_len = indent_len.get();
3283                                new_head = cmp::min(
3284                                    new_head,
3285                                    Point::new(
3286                                        old_head.row,
3287                                        ((old_head.column - 1) / indent_len) * indent_len,
3288                                    ),
3289                                );
3290                            }
3291                        }
3292
3293                        selection.set_head(new_head, SelectionGoal::None);
3294                    }
3295                }
3296            }
3297
3298            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3299            this.insert("", cx);
3300            this.refresh_copilot_suggestions(cx);
3301        });
3302    }
3303
3304    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3305        self.transact(cx, |this, cx| {
3306            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3307                let line_mode = s.line_mode;
3308                s.move_with(|map, selection| {
3309                    if selection.is_empty() && !line_mode {
3310                        let cursor = movement::right(map, selection.head());
3311                        selection.set_head(cursor, SelectionGoal::None);
3312                    }
3313                })
3314            });
3315            this.insert("", cx);
3316            this.refresh_copilot_suggestions(cx);
3317        });
3318    }
3319
3320    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3321        if self.move_to_prev_snippet_tabstop(cx) {
3322            return;
3323        }
3324
3325        self.outdent(&Outdent, cx);
3326    }
3327
3328    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3329        if self.move_to_next_snippet_tabstop(cx) {
3330            return;
3331        }
3332
3333        let mut selections = self.selections.all_adjusted(cx);
3334        let buffer = self.buffer.read(cx);
3335        let snapshot = buffer.snapshot(cx);
3336        let rows_iter = selections.iter().map(|s| s.head().row);
3337        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3338
3339        let mut edits = Vec::new();
3340        let mut prev_edited_row = 0;
3341        let mut row_delta = 0;
3342        for selection in &mut selections {
3343            if selection.start.row != prev_edited_row {
3344                row_delta = 0;
3345            }
3346            prev_edited_row = selection.end.row;
3347
3348            // If the selection is non-empty, then increase the indentation of the selected lines.
3349            if !selection.is_empty() {
3350                row_delta =
3351                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3352                continue;
3353            }
3354
3355            // If the selection is empty and the cursor is in the leading whitespace before the
3356            // suggested indentation, then auto-indent the line.
3357            let cursor = selection.head();
3358            let current_indent = snapshot.indent_size_for_line(cursor.row);
3359            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3360                if cursor.column < suggested_indent.len
3361                    && cursor.column <= current_indent.len
3362                    && current_indent.len <= suggested_indent.len
3363                {
3364                    selection.start = Point::new(cursor.row, suggested_indent.len);
3365                    selection.end = selection.start;
3366                    if row_delta == 0 {
3367                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3368                            cursor.row,
3369                            current_indent,
3370                            suggested_indent,
3371                        ));
3372                        row_delta = suggested_indent.len - current_indent.len;
3373                    }
3374                    continue;
3375                }
3376            }
3377
3378            // Accept copilot suggestion if there is only one selection and the cursor is not
3379            // in the leading whitespace.
3380            if self.selections.count() == 1
3381                && cursor.column >= current_indent.len
3382                && self.has_active_copilot_suggestion(cx)
3383            {
3384                self.accept_copilot_suggestion(cx);
3385                return;
3386            }
3387
3388            // Otherwise, insert a hard or soft tab.
3389            let settings = cx.global::<Settings>();
3390            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3391            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3392                IndentSize::tab()
3393            } else {
3394                let tab_size = settings.tab_size(language_name.as_deref()).get();
3395                let char_column = snapshot
3396                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3397                    .flat_map(str::chars)
3398                    .count()
3399                    + row_delta as usize;
3400                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3401                IndentSize::spaces(chars_to_next_tab_stop)
3402            };
3403            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3404            selection.end = selection.start;
3405            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3406            row_delta += tab_size.len;
3407        }
3408
3409        self.transact(cx, |this, cx| {
3410            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3411            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3412            this.refresh_copilot_suggestions(cx);
3413        });
3414    }
3415
3416    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3417        let mut selections = self.selections.all::<Point>(cx);
3418        let mut prev_edited_row = 0;
3419        let mut row_delta = 0;
3420        let mut edits = Vec::new();
3421        let buffer = self.buffer.read(cx);
3422        let snapshot = buffer.snapshot(cx);
3423        for selection in &mut selections {
3424            if selection.start.row != prev_edited_row {
3425                row_delta = 0;
3426            }
3427            prev_edited_row = selection.end.row;
3428
3429            row_delta =
3430                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3431        }
3432
3433        self.transact(cx, |this, cx| {
3434            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3435            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3436        });
3437    }
3438
3439    fn indent_selection(
3440        buffer: &MultiBuffer,
3441        snapshot: &MultiBufferSnapshot,
3442        selection: &mut Selection<Point>,
3443        edits: &mut Vec<(Range<Point>, String)>,
3444        delta_for_start_row: u32,
3445        cx: &AppContext,
3446    ) -> u32 {
3447        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3448        let settings = cx.global::<Settings>();
3449        let tab_size = settings.tab_size(language_name.as_deref()).get();
3450        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3451            IndentKind::Tab
3452        } else {
3453            IndentKind::Space
3454        };
3455        let mut start_row = selection.start.row;
3456        let mut end_row = selection.end.row + 1;
3457
3458        // If a selection ends at the beginning of a line, don't indent
3459        // that last line.
3460        if selection.end.column == 0 {
3461            end_row -= 1;
3462        }
3463
3464        // Avoid re-indenting a row that has already been indented by a
3465        // previous selection, but still update this selection's column
3466        // to reflect that indentation.
3467        if delta_for_start_row > 0 {
3468            start_row += 1;
3469            selection.start.column += delta_for_start_row;
3470            if selection.end.row == selection.start.row {
3471                selection.end.column += delta_for_start_row;
3472            }
3473        }
3474
3475        let mut delta_for_end_row = 0;
3476        for row in start_row..end_row {
3477            let current_indent = snapshot.indent_size_for_line(row);
3478            let indent_delta = match (current_indent.kind, indent_kind) {
3479                (IndentKind::Space, IndentKind::Space) => {
3480                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3481                    IndentSize::spaces(columns_to_next_tab_stop)
3482                }
3483                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3484                (_, IndentKind::Tab) => IndentSize::tab(),
3485            };
3486
3487            let row_start = Point::new(row, 0);
3488            edits.push((
3489                row_start..row_start,
3490                indent_delta.chars().collect::<String>(),
3491            ));
3492
3493            // Update this selection's endpoints to reflect the indentation.
3494            if row == selection.start.row {
3495                selection.start.column += indent_delta.len;
3496            }
3497            if row == selection.end.row {
3498                selection.end.column += indent_delta.len;
3499                delta_for_end_row = indent_delta.len;
3500            }
3501        }
3502
3503        if selection.start.row == selection.end.row {
3504            delta_for_start_row + delta_for_end_row
3505        } else {
3506            delta_for_end_row
3507        }
3508    }
3509
3510    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3511        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3512        let selections = self.selections.all::<Point>(cx);
3513        let mut deletion_ranges = Vec::new();
3514        let mut last_outdent = None;
3515        {
3516            let buffer = self.buffer.read(cx);
3517            let snapshot = buffer.snapshot(cx);
3518            for selection in &selections {
3519                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3520                let tab_size = cx
3521                    .global::<Settings>()
3522                    .tab_size(language_name.as_deref())
3523                    .get();
3524                let mut rows = selection.spanned_rows(false, &display_map);
3525
3526                // Avoid re-outdenting a row that has already been outdented by a
3527                // previous selection.
3528                if let Some(last_row) = last_outdent {
3529                    if last_row == rows.start {
3530                        rows.start += 1;
3531                    }
3532                }
3533
3534                for row in rows {
3535                    let indent_size = snapshot.indent_size_for_line(row);
3536                    if indent_size.len > 0 {
3537                        let deletion_len = match indent_size.kind {
3538                            IndentKind::Space => {
3539                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3540                                if columns_to_prev_tab_stop == 0 {
3541                                    tab_size
3542                                } else {
3543                                    columns_to_prev_tab_stop
3544                                }
3545                            }
3546                            IndentKind::Tab => 1,
3547                        };
3548                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3549                        last_outdent = Some(row);
3550                    }
3551                }
3552            }
3553        }
3554
3555        self.transact(cx, |this, cx| {
3556            this.buffer.update(cx, |buffer, cx| {
3557                let empty_str: Arc<str> = "".into();
3558                buffer.edit(
3559                    deletion_ranges
3560                        .into_iter()
3561                        .map(|range| (range, empty_str.clone())),
3562                    None,
3563                    cx,
3564                );
3565            });
3566            let selections = this.selections.all::<usize>(cx);
3567            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3568        });
3569    }
3570
3571    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3572        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3573        let selections = self.selections.all::<Point>(cx);
3574
3575        let mut new_cursors = Vec::new();
3576        let mut edit_ranges = Vec::new();
3577        let mut selections = selections.iter().peekable();
3578        while let Some(selection) = selections.next() {
3579            let mut rows = selection.spanned_rows(false, &display_map);
3580            let goal_display_column = selection.head().to_display_point(&display_map).column();
3581
3582            // Accumulate contiguous regions of rows that we want to delete.
3583            while let Some(next_selection) = selections.peek() {
3584                let next_rows = next_selection.spanned_rows(false, &display_map);
3585                if next_rows.start <= rows.end {
3586                    rows.end = next_rows.end;
3587                    selections.next().unwrap();
3588                } else {
3589                    break;
3590                }
3591            }
3592
3593            let buffer = &display_map.buffer_snapshot;
3594            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3595            let edit_end;
3596            let cursor_buffer_row;
3597            if buffer.max_point().row >= rows.end {
3598                // If there's a line after the range, delete the \n from the end of the row range
3599                // and position the cursor on the next line.
3600                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3601                cursor_buffer_row = rows.end;
3602            } else {
3603                // If there isn't a line after the range, delete the \n from the line before the
3604                // start of the row range and position the cursor there.
3605                edit_start = edit_start.saturating_sub(1);
3606                edit_end = buffer.len();
3607                cursor_buffer_row = rows.start.saturating_sub(1);
3608            }
3609
3610            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3611            *cursor.column_mut() =
3612                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3613
3614            new_cursors.push((
3615                selection.id,
3616                buffer.anchor_after(cursor.to_point(&display_map)),
3617            ));
3618            edit_ranges.push(edit_start..edit_end);
3619        }
3620
3621        self.transact(cx, |this, cx| {
3622            let buffer = this.buffer.update(cx, |buffer, cx| {
3623                let empty_str: Arc<str> = "".into();
3624                buffer.edit(
3625                    edit_ranges
3626                        .into_iter()
3627                        .map(|range| (range, empty_str.clone())),
3628                    None,
3629                    cx,
3630                );
3631                buffer.snapshot(cx)
3632            });
3633            let new_selections = new_cursors
3634                .into_iter()
3635                .map(|(id, cursor)| {
3636                    let cursor = cursor.to_point(&buffer);
3637                    Selection {
3638                        id,
3639                        start: cursor,
3640                        end: cursor,
3641                        reversed: false,
3642                        goal: SelectionGoal::None,
3643                    }
3644                })
3645                .collect();
3646
3647            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3648                s.select(new_selections);
3649            });
3650        });
3651    }
3652
3653    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3654        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3655        let buffer = &display_map.buffer_snapshot;
3656        let selections = self.selections.all::<Point>(cx);
3657
3658        let mut edits = Vec::new();
3659        let mut selections_iter = selections.iter().peekable();
3660        while let Some(selection) = selections_iter.next() {
3661            // Avoid duplicating the same lines twice.
3662            let mut rows = selection.spanned_rows(false, &display_map);
3663
3664            while let Some(next_selection) = selections_iter.peek() {
3665                let next_rows = next_selection.spanned_rows(false, &display_map);
3666                if next_rows.start < rows.end {
3667                    rows.end = next_rows.end;
3668                    selections_iter.next().unwrap();
3669                } else {
3670                    break;
3671                }
3672            }
3673
3674            // Copy the text from the selected row region and splice it at the start of the region.
3675            let start = Point::new(rows.start, 0);
3676            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3677            let text = buffer
3678                .text_for_range(start..end)
3679                .chain(Some("\n"))
3680                .collect::<String>();
3681            edits.push((start..start, text));
3682        }
3683
3684        self.transact(cx, |this, cx| {
3685            this.buffer.update(cx, |buffer, cx| {
3686                buffer.edit(edits, None, cx);
3687            });
3688
3689            this.request_autoscroll(Autoscroll::fit(), cx);
3690        });
3691    }
3692
3693    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3694        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3695        let buffer = self.buffer.read(cx).snapshot(cx);
3696
3697        let mut edits = Vec::new();
3698        let mut unfold_ranges = Vec::new();
3699        let mut refold_ranges = Vec::new();
3700
3701        let selections = self.selections.all::<Point>(cx);
3702        let mut selections = selections.iter().peekable();
3703        let mut contiguous_row_selections = Vec::new();
3704        let mut new_selections = Vec::new();
3705
3706        while let Some(selection) = selections.next() {
3707            // Find all the selections that span a contiguous row range
3708            let (start_row, end_row) = consume_contiguous_rows(
3709                &mut contiguous_row_selections,
3710                selection,
3711                &display_map,
3712                &mut selections,
3713            );
3714
3715            // Move the text spanned by the row range to be before the line preceding the row range
3716            if start_row > 0 {
3717                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3718                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3719                let insertion_point = display_map
3720                    .prev_line_boundary(Point::new(start_row - 1, 0))
3721                    .0;
3722
3723                // Don't move lines across excerpts
3724                if buffer
3725                    .excerpt_boundaries_in_range((
3726                        Bound::Excluded(insertion_point),
3727                        Bound::Included(range_to_move.end),
3728                    ))
3729                    .next()
3730                    .is_none()
3731                {
3732                    let text = buffer
3733                        .text_for_range(range_to_move.clone())
3734                        .flat_map(|s| s.chars())
3735                        .skip(1)
3736                        .chain(['\n'])
3737                        .collect::<String>();
3738
3739                    edits.push((
3740                        buffer.anchor_after(range_to_move.start)
3741                            ..buffer.anchor_before(range_to_move.end),
3742                        String::new(),
3743                    ));
3744                    let insertion_anchor = buffer.anchor_after(insertion_point);
3745                    edits.push((insertion_anchor..insertion_anchor, text));
3746
3747                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3748
3749                    // Move selections up
3750                    new_selections.extend(contiguous_row_selections.drain(..).map(
3751                        |mut selection| {
3752                            selection.start.row -= row_delta;
3753                            selection.end.row -= row_delta;
3754                            selection
3755                        },
3756                    ));
3757
3758                    // Move folds up
3759                    unfold_ranges.push(range_to_move.clone());
3760                    for fold in display_map.folds_in_range(
3761                        buffer.anchor_before(range_to_move.start)
3762                            ..buffer.anchor_after(range_to_move.end),
3763                    ) {
3764                        let mut start = fold.start.to_point(&buffer);
3765                        let mut end = fold.end.to_point(&buffer);
3766                        start.row -= row_delta;
3767                        end.row -= row_delta;
3768                        refold_ranges.push(start..end);
3769                    }
3770                }
3771            }
3772
3773            // If we didn't move line(s), preserve the existing selections
3774            new_selections.append(&mut contiguous_row_selections);
3775        }
3776
3777        self.transact(cx, |this, cx| {
3778            this.unfold_ranges(unfold_ranges, true, true, cx);
3779            this.buffer.update(cx, |buffer, cx| {
3780                for (range, text) in edits {
3781                    buffer.edit([(range, text)], None, cx);
3782                }
3783            });
3784            this.fold_ranges(refold_ranges, true, cx);
3785            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3786                s.select(new_selections);
3787            })
3788        });
3789    }
3790
3791    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3792        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3793        let buffer = self.buffer.read(cx).snapshot(cx);
3794
3795        let mut edits = Vec::new();
3796        let mut unfold_ranges = Vec::new();
3797        let mut refold_ranges = Vec::new();
3798
3799        let selections = self.selections.all::<Point>(cx);
3800        let mut selections = selections.iter().peekable();
3801        let mut contiguous_row_selections = Vec::new();
3802        let mut new_selections = Vec::new();
3803
3804        while let Some(selection) = selections.next() {
3805            // Find all the selections that span a contiguous row range
3806            let (start_row, end_row) = consume_contiguous_rows(
3807                &mut contiguous_row_selections,
3808                selection,
3809                &display_map,
3810                &mut selections,
3811            );
3812
3813            // Move the text spanned by the row range to be after the last line of the row range
3814            if end_row <= buffer.max_point().row {
3815                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3816                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3817
3818                // Don't move lines across excerpt boundaries
3819                if buffer
3820                    .excerpt_boundaries_in_range((
3821                        Bound::Excluded(range_to_move.start),
3822                        Bound::Included(insertion_point),
3823                    ))
3824                    .next()
3825                    .is_none()
3826                {
3827                    let mut text = String::from("\n");
3828                    text.extend(buffer.text_for_range(range_to_move.clone()));
3829                    text.pop(); // Drop trailing newline
3830                    edits.push((
3831                        buffer.anchor_after(range_to_move.start)
3832                            ..buffer.anchor_before(range_to_move.end),
3833                        String::new(),
3834                    ));
3835                    let insertion_anchor = buffer.anchor_after(insertion_point);
3836                    edits.push((insertion_anchor..insertion_anchor, text));
3837
3838                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3839
3840                    // Move selections down
3841                    new_selections.extend(contiguous_row_selections.drain(..).map(
3842                        |mut selection| {
3843                            selection.start.row += row_delta;
3844                            selection.end.row += row_delta;
3845                            selection
3846                        },
3847                    ));
3848
3849                    // Move folds down
3850                    unfold_ranges.push(range_to_move.clone());
3851                    for fold in display_map.folds_in_range(
3852                        buffer.anchor_before(range_to_move.start)
3853                            ..buffer.anchor_after(range_to_move.end),
3854                    ) {
3855                        let mut start = fold.start.to_point(&buffer);
3856                        let mut end = fold.end.to_point(&buffer);
3857                        start.row += row_delta;
3858                        end.row += row_delta;
3859                        refold_ranges.push(start..end);
3860                    }
3861                }
3862            }
3863
3864            // If we didn't move line(s), preserve the existing selections
3865            new_selections.append(&mut contiguous_row_selections);
3866        }
3867
3868        self.transact(cx, |this, cx| {
3869            this.unfold_ranges(unfold_ranges, true, true, cx);
3870            this.buffer.update(cx, |buffer, cx| {
3871                for (range, text) in edits {
3872                    buffer.edit([(range, text)], None, cx);
3873                }
3874            });
3875            this.fold_ranges(refold_ranges, true, cx);
3876            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
3877        });
3878    }
3879
3880    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3881        self.transact(cx, |this, cx| {
3882            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3883                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3884                let line_mode = s.line_mode;
3885                s.move_with(|display_map, selection| {
3886                    if !selection.is_empty() || line_mode {
3887                        return;
3888                    }
3889
3890                    let mut head = selection.head();
3891                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3892                    if head.column() == display_map.line_len(head.row()) {
3893                        transpose_offset = display_map
3894                            .buffer_snapshot
3895                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3896                    }
3897
3898                    if transpose_offset == 0 {
3899                        return;
3900                    }
3901
3902                    *head.column_mut() += 1;
3903                    head = display_map.clip_point(head, Bias::Right);
3904                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3905
3906                    let transpose_start = display_map
3907                        .buffer_snapshot
3908                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3909                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3910                        let transpose_end = display_map
3911                            .buffer_snapshot
3912                            .clip_offset(transpose_offset + 1, Bias::Right);
3913                        if let Some(ch) =
3914                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3915                        {
3916                            edits.push((transpose_start..transpose_offset, String::new()));
3917                            edits.push((transpose_end..transpose_end, ch.to_string()));
3918                        }
3919                    }
3920                });
3921                edits
3922            });
3923            this.buffer
3924                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3925            let selections = this.selections.all::<usize>(cx);
3926            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3927                s.select(selections);
3928            });
3929        });
3930    }
3931
3932    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3933        let mut text = String::new();
3934        let buffer = self.buffer.read(cx).snapshot(cx);
3935        let mut selections = self.selections.all::<Point>(cx);
3936        let mut clipboard_selections = Vec::with_capacity(selections.len());
3937        {
3938            let max_point = buffer.max_point();
3939            for selection in &mut selections {
3940                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3941                if is_entire_line {
3942                    selection.start = Point::new(selection.start.row, 0);
3943                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3944                    selection.goal = SelectionGoal::None;
3945                }
3946                let mut len = 0;
3947                for chunk in buffer.text_for_range(selection.start..selection.end) {
3948                    text.push_str(chunk);
3949                    len += chunk.len();
3950                }
3951                clipboard_selections.push(ClipboardSelection {
3952                    len,
3953                    is_entire_line,
3954                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3955                });
3956            }
3957        }
3958
3959        self.transact(cx, |this, cx| {
3960            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3961                s.select(selections);
3962            });
3963            this.insert("", cx);
3964            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3965        });
3966    }
3967
3968    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3969        let selections = self.selections.all::<Point>(cx);
3970        let buffer = self.buffer.read(cx).read(cx);
3971        let mut text = String::new();
3972
3973        let mut clipboard_selections = Vec::with_capacity(selections.len());
3974        {
3975            let max_point = buffer.max_point();
3976            for selection in selections.iter() {
3977                let mut start = selection.start;
3978                let mut end = selection.end;
3979                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3980                if is_entire_line {
3981                    start = Point::new(start.row, 0);
3982                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3983                }
3984                let mut len = 0;
3985                for chunk in buffer.text_for_range(start..end) {
3986                    text.push_str(chunk);
3987                    len += chunk.len();
3988                }
3989                clipboard_selections.push(ClipboardSelection {
3990                    len,
3991                    is_entire_line,
3992                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3993                });
3994            }
3995        }
3996
3997        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3998    }
3999
4000    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4001        self.transact(cx, |this, cx| {
4002            if let Some(item) = cx.as_mut().read_from_clipboard() {
4003                let mut clipboard_text = Cow::Borrowed(item.text());
4004                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4005                    let old_selections = this.selections.all::<usize>(cx);
4006                    let all_selections_were_entire_line =
4007                        clipboard_selections.iter().all(|s| s.is_entire_line);
4008                    let first_selection_indent_column =
4009                        clipboard_selections.first().map(|s| s.first_line_indent);
4010                    if clipboard_selections.len() != old_selections.len() {
4011                        let mut newline_separated_text = String::new();
4012                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4013                        let mut ix = 0;
4014                        while let Some(clipboard_selection) = clipboard_selections.next() {
4015                            newline_separated_text
4016                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4017                            ix += clipboard_selection.len;
4018                            if clipboard_selections.peek().is_some() {
4019                                newline_separated_text.push('\n');
4020                            }
4021                        }
4022                        clipboard_text = Cow::Owned(newline_separated_text);
4023                    }
4024
4025                    this.buffer.update(cx, |buffer, cx| {
4026                        let snapshot = buffer.read(cx);
4027                        let mut start_offset = 0;
4028                        let mut edits = Vec::new();
4029                        let mut original_indent_columns = Vec::new();
4030                        let line_mode = this.selections.line_mode;
4031                        for (ix, selection) in old_selections.iter().enumerate() {
4032                            let to_insert;
4033                            let entire_line;
4034                            let original_indent_column;
4035                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4036                                let end_offset = start_offset + clipboard_selection.len;
4037                                to_insert = &clipboard_text[start_offset..end_offset];
4038                                entire_line = clipboard_selection.is_entire_line;
4039                                start_offset = end_offset;
4040                                original_indent_column =
4041                                    Some(clipboard_selection.first_line_indent);
4042                            } else {
4043                                to_insert = clipboard_text.as_str();
4044                                entire_line = all_selections_were_entire_line;
4045                                original_indent_column = first_selection_indent_column
4046                            }
4047
4048                            // If the corresponding selection was empty when this slice of the
4049                            // clipboard text was written, then the entire line containing the
4050                            // selection was copied. If this selection is also currently empty,
4051                            // then paste the line before the current line of the buffer.
4052                            let range = if selection.is_empty() && !line_mode && entire_line {
4053                                let column = selection.start.to_point(&snapshot).column as usize;
4054                                let line_start = selection.start - column;
4055                                line_start..line_start
4056                            } else {
4057                                selection.range()
4058                            };
4059
4060                            edits.push((range, to_insert));
4061                            original_indent_columns.extend(original_indent_column);
4062                        }
4063                        drop(snapshot);
4064
4065                        buffer.edit(
4066                            edits,
4067                            Some(AutoindentMode::Block {
4068                                original_indent_columns,
4069                            }),
4070                            cx,
4071                        );
4072                    });
4073
4074                    let selections = this.selections.all::<usize>(cx);
4075                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4076                } else {
4077                    this.insert(&clipboard_text, cx);
4078                }
4079            }
4080        });
4081    }
4082
4083    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4084        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4085            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4086                self.change_selections(None, cx, |s| {
4087                    s.select_anchors(selections.to_vec());
4088                });
4089            }
4090            self.request_autoscroll(Autoscroll::fit(), cx);
4091            self.unmark_text(cx);
4092            self.refresh_copilot_suggestions(cx);
4093            cx.emit(Event::Edited);
4094        }
4095    }
4096
4097    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4098        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4099            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4100            {
4101                self.change_selections(None, cx, |s| {
4102                    s.select_anchors(selections.to_vec());
4103                });
4104            }
4105            self.request_autoscroll(Autoscroll::fit(), cx);
4106            self.unmark_text(cx);
4107            self.refresh_copilot_suggestions(cx);
4108            cx.emit(Event::Edited);
4109        }
4110    }
4111
4112    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4113        self.buffer
4114            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4115    }
4116
4117    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4118        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4119            let line_mode = s.line_mode;
4120            s.move_with(|map, selection| {
4121                let cursor = if selection.is_empty() && !line_mode {
4122                    movement::left(map, selection.start)
4123                } else {
4124                    selection.start
4125                };
4126                selection.collapse_to(cursor, SelectionGoal::None);
4127            });
4128        })
4129    }
4130
4131    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4132        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4133            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4134        })
4135    }
4136
4137    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4138        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4139            let line_mode = s.line_mode;
4140            s.move_with(|map, selection| {
4141                let cursor = if selection.is_empty() && !line_mode {
4142                    movement::right(map, selection.end)
4143                } else {
4144                    selection.end
4145                };
4146                selection.collapse_to(cursor, SelectionGoal::None)
4147            });
4148        })
4149    }
4150
4151    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4152        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4153            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4154        })
4155    }
4156
4157    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4158        if self.take_rename(true, cx).is_some() {
4159            return;
4160        }
4161
4162        if let Some(context_menu) = self.context_menu.as_mut() {
4163            if context_menu.select_prev(cx) {
4164                return;
4165            }
4166        }
4167
4168        if matches!(self.mode, EditorMode::SingleLine) {
4169            cx.propagate_action();
4170            return;
4171        }
4172
4173        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4174            let line_mode = s.line_mode;
4175            s.move_with(|map, selection| {
4176                if !selection.is_empty() && !line_mode {
4177                    selection.goal = SelectionGoal::None;
4178                }
4179                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4180                selection.collapse_to(cursor, goal);
4181            });
4182        })
4183    }
4184
4185    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4186        if self.take_rename(true, cx).is_some() {
4187            return;
4188        }
4189
4190        if self
4191            .context_menu
4192            .as_mut()
4193            .map(|menu| menu.select_first(cx))
4194            .unwrap_or(false)
4195        {
4196            return;
4197        }
4198
4199        if matches!(self.mode, EditorMode::SingleLine) {
4200            cx.propagate_action();
4201            return;
4202        }
4203
4204        let row_count = if let Some(row_count) = self.visible_line_count() {
4205            row_count as u32 - 1
4206        } else {
4207            return;
4208        };
4209
4210        let autoscroll = if action.center_cursor {
4211            Autoscroll::center()
4212        } else {
4213            Autoscroll::fit()
4214        };
4215
4216        self.change_selections(Some(autoscroll), cx, |s| {
4217            let line_mode = s.line_mode;
4218            s.move_with(|map, selection| {
4219                if !selection.is_empty() && !line_mode {
4220                    selection.goal = SelectionGoal::None;
4221                }
4222                let (cursor, goal) =
4223                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4224                selection.collapse_to(cursor, goal);
4225            });
4226        });
4227    }
4228
4229    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4230        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4231            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4232        })
4233    }
4234
4235    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4236        self.take_rename(true, cx);
4237
4238        if let Some(context_menu) = self.context_menu.as_mut() {
4239            if context_menu.select_next(cx) {
4240                return;
4241            }
4242        }
4243
4244        if self.mode == EditorMode::SingleLine {
4245            cx.propagate_action();
4246            return;
4247        }
4248
4249        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4250            let line_mode = s.line_mode;
4251            s.move_with(|map, selection| {
4252                if !selection.is_empty() && !line_mode {
4253                    selection.goal = SelectionGoal::None;
4254                }
4255                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4256                selection.collapse_to(cursor, goal);
4257            });
4258        });
4259    }
4260
4261    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4262        if self.take_rename(true, cx).is_some() {
4263            return;
4264        }
4265
4266        if self
4267            .context_menu
4268            .as_mut()
4269            .map(|menu| menu.select_last(cx))
4270            .unwrap_or(false)
4271        {
4272            return;
4273        }
4274
4275        if matches!(self.mode, EditorMode::SingleLine) {
4276            cx.propagate_action();
4277            return;
4278        }
4279
4280        let row_count = if let Some(row_count) = self.visible_line_count() {
4281            row_count as u32 - 1
4282        } else {
4283            return;
4284        };
4285
4286        let autoscroll = if action.center_cursor {
4287            Autoscroll::center()
4288        } else {
4289            Autoscroll::fit()
4290        };
4291
4292        self.change_selections(Some(autoscroll), cx, |s| {
4293            let line_mode = s.line_mode;
4294            s.move_with(|map, selection| {
4295                if !selection.is_empty() && !line_mode {
4296                    selection.goal = SelectionGoal::None;
4297                }
4298                let (cursor, goal) =
4299                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4300                selection.collapse_to(cursor, goal);
4301            });
4302        });
4303    }
4304
4305    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4306        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4307            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4308        });
4309    }
4310
4311    pub fn move_to_previous_word_start(
4312        &mut self,
4313        _: &MoveToPreviousWordStart,
4314        cx: &mut ViewContext<Self>,
4315    ) {
4316        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4317            s.move_cursors_with(|map, head, _| {
4318                (
4319                    movement::previous_word_start(map, head),
4320                    SelectionGoal::None,
4321                )
4322            });
4323        })
4324    }
4325
4326    pub fn move_to_previous_subword_start(
4327        &mut self,
4328        _: &MoveToPreviousSubwordStart,
4329        cx: &mut ViewContext<Self>,
4330    ) {
4331        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4332            s.move_cursors_with(|map, head, _| {
4333                (
4334                    movement::previous_subword_start(map, head),
4335                    SelectionGoal::None,
4336                )
4337            });
4338        })
4339    }
4340
4341    pub fn select_to_previous_word_start(
4342        &mut self,
4343        _: &SelectToPreviousWordStart,
4344        cx: &mut ViewContext<Self>,
4345    ) {
4346        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4347            s.move_heads_with(|map, head, _| {
4348                (
4349                    movement::previous_word_start(map, head),
4350                    SelectionGoal::None,
4351                )
4352            });
4353        })
4354    }
4355
4356    pub fn select_to_previous_subword_start(
4357        &mut self,
4358        _: &SelectToPreviousSubwordStart,
4359        cx: &mut ViewContext<Self>,
4360    ) {
4361        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4362            s.move_heads_with(|map, head, _| {
4363                (
4364                    movement::previous_subword_start(map, head),
4365                    SelectionGoal::None,
4366                )
4367            });
4368        })
4369    }
4370
4371    pub fn delete_to_previous_word_start(
4372        &mut self,
4373        _: &DeleteToPreviousWordStart,
4374        cx: &mut ViewContext<Self>,
4375    ) {
4376        self.transact(cx, |this, cx| {
4377            this.select_autoclose_pair(cx);
4378            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4379                let line_mode = s.line_mode;
4380                s.move_with(|map, selection| {
4381                    if selection.is_empty() && !line_mode {
4382                        let cursor = movement::previous_word_start(map, selection.head());
4383                        selection.set_head(cursor, SelectionGoal::None);
4384                    }
4385                });
4386            });
4387            this.insert("", cx);
4388        });
4389    }
4390
4391    pub fn delete_to_previous_subword_start(
4392        &mut self,
4393        _: &DeleteToPreviousSubwordStart,
4394        cx: &mut ViewContext<Self>,
4395    ) {
4396        self.transact(cx, |this, cx| {
4397            this.select_autoclose_pair(cx);
4398            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4399                let line_mode = s.line_mode;
4400                s.move_with(|map, selection| {
4401                    if selection.is_empty() && !line_mode {
4402                        let cursor = movement::previous_subword_start(map, selection.head());
4403                        selection.set_head(cursor, SelectionGoal::None);
4404                    }
4405                });
4406            });
4407            this.insert("", cx);
4408        });
4409    }
4410
4411    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4412        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4413            s.move_cursors_with(|map, head, _| {
4414                (movement::next_word_end(map, head), SelectionGoal::None)
4415            });
4416        })
4417    }
4418
4419    pub fn move_to_next_subword_end(
4420        &mut self,
4421        _: &MoveToNextSubwordEnd,
4422        cx: &mut ViewContext<Self>,
4423    ) {
4424        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4425            s.move_cursors_with(|map, head, _| {
4426                (movement::next_subword_end(map, head), SelectionGoal::None)
4427            });
4428        })
4429    }
4430
4431    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4432        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4433            s.move_heads_with(|map, head, _| {
4434                (movement::next_word_end(map, head), SelectionGoal::None)
4435            });
4436        })
4437    }
4438
4439    pub fn select_to_next_subword_end(
4440        &mut self,
4441        _: &SelectToNextSubwordEnd,
4442        cx: &mut ViewContext<Self>,
4443    ) {
4444        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4445            s.move_heads_with(|map, head, _| {
4446                (movement::next_subword_end(map, head), SelectionGoal::None)
4447            });
4448        })
4449    }
4450
4451    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4452        self.transact(cx, |this, cx| {
4453            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4454                let line_mode = s.line_mode;
4455                s.move_with(|map, selection| {
4456                    if selection.is_empty() && !line_mode {
4457                        let cursor = movement::next_word_end(map, selection.head());
4458                        selection.set_head(cursor, SelectionGoal::None);
4459                    }
4460                });
4461            });
4462            this.insert("", cx);
4463        });
4464    }
4465
4466    pub fn delete_to_next_subword_end(
4467        &mut self,
4468        _: &DeleteToNextSubwordEnd,
4469        cx: &mut ViewContext<Self>,
4470    ) {
4471        self.transact(cx, |this, cx| {
4472            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4473                s.move_with(|map, selection| {
4474                    if selection.is_empty() {
4475                        let cursor = movement::next_subword_end(map, selection.head());
4476                        selection.set_head(cursor, SelectionGoal::None);
4477                    }
4478                });
4479            });
4480            this.insert("", cx);
4481        });
4482    }
4483
4484    pub fn move_to_beginning_of_line(
4485        &mut self,
4486        _: &MoveToBeginningOfLine,
4487        cx: &mut ViewContext<Self>,
4488    ) {
4489        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4490            s.move_cursors_with(|map, head, _| {
4491                (
4492                    movement::indented_line_beginning(map, head, true),
4493                    SelectionGoal::None,
4494                )
4495            });
4496        })
4497    }
4498
4499    pub fn select_to_beginning_of_line(
4500        &mut self,
4501        action: &SelectToBeginningOfLine,
4502        cx: &mut ViewContext<Self>,
4503    ) {
4504        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4505            s.move_heads_with(|map, head, _| {
4506                (
4507                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4508                    SelectionGoal::None,
4509                )
4510            });
4511        });
4512    }
4513
4514    pub fn delete_to_beginning_of_line(
4515        &mut self,
4516        _: &DeleteToBeginningOfLine,
4517        cx: &mut ViewContext<Self>,
4518    ) {
4519        self.transact(cx, |this, cx| {
4520            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4521                s.move_with(|_, selection| {
4522                    selection.reversed = true;
4523                });
4524            });
4525
4526            this.select_to_beginning_of_line(
4527                &SelectToBeginningOfLine {
4528                    stop_at_soft_wraps: false,
4529                },
4530                cx,
4531            );
4532            this.backspace(&Backspace, cx);
4533        });
4534    }
4535
4536    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4537        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4538            s.move_cursors_with(|map, head, _| {
4539                (movement::line_end(map, head, true), SelectionGoal::None)
4540            });
4541        })
4542    }
4543
4544    pub fn select_to_end_of_line(
4545        &mut self,
4546        action: &SelectToEndOfLine,
4547        cx: &mut ViewContext<Self>,
4548    ) {
4549        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4550            s.move_heads_with(|map, head, _| {
4551                (
4552                    movement::line_end(map, head, action.stop_at_soft_wraps),
4553                    SelectionGoal::None,
4554                )
4555            });
4556        })
4557    }
4558
4559    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4560        self.transact(cx, |this, cx| {
4561            this.select_to_end_of_line(
4562                &SelectToEndOfLine {
4563                    stop_at_soft_wraps: false,
4564                },
4565                cx,
4566            );
4567            this.delete(&Delete, cx);
4568        });
4569    }
4570
4571    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4572        self.transact(cx, |this, cx| {
4573            this.select_to_end_of_line(
4574                &SelectToEndOfLine {
4575                    stop_at_soft_wraps: false,
4576                },
4577                cx,
4578            );
4579            this.cut(&Cut, cx);
4580        });
4581    }
4582
4583    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4584        if matches!(self.mode, EditorMode::SingleLine) {
4585            cx.propagate_action();
4586            return;
4587        }
4588
4589        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4590            s.select_ranges(vec![0..0]);
4591        });
4592    }
4593
4594    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4595        let mut selection = self.selections.last::<Point>(cx);
4596        selection.set_head(Point::zero(), SelectionGoal::None);
4597
4598        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4599            s.select(vec![selection]);
4600        });
4601    }
4602
4603    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4604        if matches!(self.mode, EditorMode::SingleLine) {
4605            cx.propagate_action();
4606            return;
4607        }
4608
4609        let cursor = self.buffer.read(cx).read(cx).len();
4610        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4611            s.select_ranges(vec![cursor..cursor])
4612        });
4613    }
4614
4615    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4616        self.nav_history = nav_history;
4617    }
4618
4619    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4620        self.nav_history.as_ref()
4621    }
4622
4623    fn push_to_nav_history(
4624        &self,
4625        cursor_anchor: Anchor,
4626        new_position: Option<Point>,
4627        cx: &mut ViewContext<Self>,
4628    ) {
4629        if let Some(nav_history) = &self.nav_history {
4630            let buffer = self.buffer.read(cx).read(cx);
4631            let cursor_position = cursor_anchor.to_point(&buffer);
4632            let scroll_state = self.scroll_manager.anchor();
4633            let scroll_top_row = scroll_state.top_row(&buffer);
4634            drop(buffer);
4635
4636            if let Some(new_position) = new_position {
4637                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4638                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4639                    return;
4640                }
4641            }
4642
4643            nav_history.push(
4644                Some(NavigationData {
4645                    cursor_anchor,
4646                    cursor_position,
4647                    scroll_anchor: scroll_state,
4648                    scroll_top_row,
4649                }),
4650                cx,
4651            );
4652        }
4653    }
4654
4655    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4656        let buffer = self.buffer.read(cx).snapshot(cx);
4657        let mut selection = self.selections.first::<usize>(cx);
4658        selection.set_head(buffer.len(), SelectionGoal::None);
4659        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4660            s.select(vec![selection]);
4661        });
4662    }
4663
4664    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4665        let end = self.buffer.read(cx).read(cx).len();
4666        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4667            s.select_ranges(vec![0..end]);
4668        });
4669    }
4670
4671    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4672        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4673        let mut selections = self.selections.all::<Point>(cx);
4674        let max_point = display_map.buffer_snapshot.max_point();
4675        for selection in &mut selections {
4676            let rows = selection.spanned_rows(true, &display_map);
4677            selection.start = Point::new(rows.start, 0);
4678            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4679            selection.reversed = false;
4680        }
4681        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4682            s.select(selections);
4683        });
4684    }
4685
4686    pub fn split_selection_into_lines(
4687        &mut self,
4688        _: &SplitSelectionIntoLines,
4689        cx: &mut ViewContext<Self>,
4690    ) {
4691        let mut to_unfold = Vec::new();
4692        let mut new_selection_ranges = Vec::new();
4693        {
4694            let selections = self.selections.all::<Point>(cx);
4695            let buffer = self.buffer.read(cx).read(cx);
4696            for selection in selections {
4697                for row in selection.start.row..selection.end.row {
4698                    let cursor = Point::new(row, buffer.line_len(row));
4699                    new_selection_ranges.push(cursor..cursor);
4700                }
4701                new_selection_ranges.push(selection.end..selection.end);
4702                to_unfold.push(selection.start..selection.end);
4703            }
4704        }
4705        self.unfold_ranges(to_unfold, true, true, cx);
4706        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4707            s.select_ranges(new_selection_ranges);
4708        });
4709    }
4710
4711    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4712        self.add_selection(true, cx);
4713    }
4714
4715    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4716        self.add_selection(false, cx);
4717    }
4718
4719    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4720        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4721        let mut selections = self.selections.all::<Point>(cx);
4722        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4723            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4724            let range = oldest_selection.display_range(&display_map).sorted();
4725            let columns = cmp::min(range.start.column(), range.end.column())
4726                ..cmp::max(range.start.column(), range.end.column());
4727
4728            selections.clear();
4729            let mut stack = Vec::new();
4730            for row in range.start.row()..=range.end.row() {
4731                if let Some(selection) = self.selections.build_columnar_selection(
4732                    &display_map,
4733                    row,
4734                    &columns,
4735                    oldest_selection.reversed,
4736                ) {
4737                    stack.push(selection.id);
4738                    selections.push(selection);
4739                }
4740            }
4741
4742            if above {
4743                stack.reverse();
4744            }
4745
4746            AddSelectionsState { above, stack }
4747        });
4748
4749        let last_added_selection = *state.stack.last().unwrap();
4750        let mut new_selections = Vec::new();
4751        if above == state.above {
4752            let end_row = if above {
4753                0
4754            } else {
4755                display_map.max_point().row()
4756            };
4757
4758            'outer: for selection in selections {
4759                if selection.id == last_added_selection {
4760                    let range = selection.display_range(&display_map).sorted();
4761                    debug_assert_eq!(range.start.row(), range.end.row());
4762                    let mut row = range.start.row();
4763                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4764                    {
4765                        start..end
4766                    } else {
4767                        cmp::min(range.start.column(), range.end.column())
4768                            ..cmp::max(range.start.column(), range.end.column())
4769                    };
4770
4771                    while row != end_row {
4772                        if above {
4773                            row -= 1;
4774                        } else {
4775                            row += 1;
4776                        }
4777
4778                        if let Some(new_selection) = self.selections.build_columnar_selection(
4779                            &display_map,
4780                            row,
4781                            &columns,
4782                            selection.reversed,
4783                        ) {
4784                            state.stack.push(new_selection.id);
4785                            if above {
4786                                new_selections.push(new_selection);
4787                                new_selections.push(selection);
4788                            } else {
4789                                new_selections.push(selection);
4790                                new_selections.push(new_selection);
4791                            }
4792
4793                            continue 'outer;
4794                        }
4795                    }
4796                }
4797
4798                new_selections.push(selection);
4799            }
4800        } else {
4801            new_selections = selections;
4802            new_selections.retain(|s| s.id != last_added_selection);
4803            state.stack.pop();
4804        }
4805
4806        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4807            s.select(new_selections);
4808        });
4809        if state.stack.len() > 1 {
4810            self.add_selections_state = Some(state);
4811        }
4812    }
4813
4814    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4815        self.push_to_selection_history();
4816        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4817        let buffer = &display_map.buffer_snapshot;
4818        let mut selections = self.selections.all::<usize>(cx);
4819        if let Some(mut select_next_state) = self.select_next_state.take() {
4820            let query = &select_next_state.query;
4821            if !select_next_state.done {
4822                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4823                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4824                let mut next_selected_range = None;
4825
4826                let bytes_after_last_selection =
4827                    buffer.bytes_in_range(last_selection.end..buffer.len());
4828                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4829                let query_matches = query
4830                    .stream_find_iter(bytes_after_last_selection)
4831                    .map(|result| (last_selection.end, result))
4832                    .chain(
4833                        query
4834                            .stream_find_iter(bytes_before_first_selection)
4835                            .map(|result| (0, result)),
4836                    );
4837                for (start_offset, query_match) in query_matches {
4838                    let query_match = query_match.unwrap(); // can only fail due to I/O
4839                    let offset_range =
4840                        start_offset + query_match.start()..start_offset + query_match.end();
4841                    let display_range = offset_range.start.to_display_point(&display_map)
4842                        ..offset_range.end.to_display_point(&display_map);
4843
4844                    if !select_next_state.wordwise
4845                        || (!movement::is_inside_word(&display_map, display_range.start)
4846                            && !movement::is_inside_word(&display_map, display_range.end))
4847                    {
4848                        next_selected_range = Some(offset_range);
4849                        break;
4850                    }
4851                }
4852
4853                if let Some(next_selected_range) = next_selected_range {
4854                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
4855                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4856                        if action.replace_newest {
4857                            s.delete(s.newest_anchor().id);
4858                        }
4859                        s.insert_range(next_selected_range);
4860                    });
4861                } else {
4862                    select_next_state.done = true;
4863                }
4864            }
4865
4866            self.select_next_state = Some(select_next_state);
4867        } else if selections.len() == 1 {
4868            let selection = selections.last_mut().unwrap();
4869            if selection.start == selection.end {
4870                let word_range = movement::surrounding_word(
4871                    &display_map,
4872                    selection.start.to_display_point(&display_map),
4873                );
4874                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4875                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4876                selection.goal = SelectionGoal::None;
4877                selection.reversed = false;
4878
4879                let query = buffer
4880                    .text_for_range(selection.start..selection.end)
4881                    .collect::<String>();
4882                let select_state = SelectNextState {
4883                    query: AhoCorasick::new_auto_configured(&[query]),
4884                    wordwise: true,
4885                    done: false,
4886                };
4887                self.unfold_ranges([selection.start..selection.end], false, true, cx);
4888                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4889                    s.select(selections);
4890                });
4891                self.select_next_state = Some(select_state);
4892            } else {
4893                let query = buffer
4894                    .text_for_range(selection.start..selection.end)
4895                    .collect::<String>();
4896                self.select_next_state = Some(SelectNextState {
4897                    query: AhoCorasick::new_auto_configured(&[query]),
4898                    wordwise: false,
4899                    done: false,
4900                });
4901                self.select_next(action, cx);
4902            }
4903        }
4904    }
4905
4906    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
4907        self.transact(cx, |this, cx| {
4908            let mut selections = this.selections.all::<Point>(cx);
4909            let mut edits = Vec::new();
4910            let mut selection_edit_ranges = Vec::new();
4911            let mut last_toggled_row = None;
4912            let snapshot = this.buffer.read(cx).read(cx);
4913            let empty_str: Arc<str> = "".into();
4914            let mut suffixes_inserted = Vec::new();
4915
4916            fn comment_prefix_range(
4917                snapshot: &MultiBufferSnapshot,
4918                row: u32,
4919                comment_prefix: &str,
4920                comment_prefix_whitespace: &str,
4921            ) -> Range<Point> {
4922                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4923
4924                let mut line_bytes = snapshot
4925                    .bytes_in_range(start..snapshot.max_point())
4926                    .flatten()
4927                    .copied();
4928
4929                // If this line currently begins with the line comment prefix, then record
4930                // the range containing the prefix.
4931                if line_bytes
4932                    .by_ref()
4933                    .take(comment_prefix.len())
4934                    .eq(comment_prefix.bytes())
4935                {
4936                    // Include any whitespace that matches the comment prefix.
4937                    let matching_whitespace_len = line_bytes
4938                        .zip(comment_prefix_whitespace.bytes())
4939                        .take_while(|(a, b)| a == b)
4940                        .count() as u32;
4941                    let end = Point::new(
4942                        start.row,
4943                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4944                    );
4945                    start..end
4946                } else {
4947                    start..start
4948                }
4949            }
4950
4951            fn comment_suffix_range(
4952                snapshot: &MultiBufferSnapshot,
4953                row: u32,
4954                comment_suffix: &str,
4955                comment_suffix_has_leading_space: bool,
4956            ) -> Range<Point> {
4957                let end = Point::new(row, snapshot.line_len(row));
4958                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4959
4960                let mut line_end_bytes = snapshot
4961                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4962                    .flatten()
4963                    .copied();
4964
4965                let leading_space_len = if suffix_start_column > 0
4966                    && line_end_bytes.next() == Some(b' ')
4967                    && comment_suffix_has_leading_space
4968                {
4969                    1
4970                } else {
4971                    0
4972                };
4973
4974                // If this line currently begins with the line comment prefix, then record
4975                // the range containing the prefix.
4976                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4977                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4978                    start..end
4979                } else {
4980                    end..end
4981                }
4982            }
4983
4984            // TODO: Handle selections that cross excerpts
4985            for selection in &mut selections {
4986                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
4987                let language = if let Some(language) =
4988                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
4989                {
4990                    language
4991                } else {
4992                    continue;
4993                };
4994
4995                selection_edit_ranges.clear();
4996
4997                // If multiple selections contain a given row, avoid processing that
4998                // row more than once.
4999                let mut start_row = selection.start.row;
5000                if last_toggled_row == Some(start_row) {
5001                    start_row += 1;
5002                }
5003                let end_row =
5004                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5005                        selection.end.row - 1
5006                    } else {
5007                        selection.end.row
5008                    };
5009                last_toggled_row = Some(end_row);
5010
5011                if start_row > end_row {
5012                    continue;
5013                }
5014
5015                // If the language has line comments, toggle those.
5016                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5017                    // Split the comment prefix's trailing whitespace into a separate string,
5018                    // as that portion won't be used for detecting if a line is a comment.
5019                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5020                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5021                    let mut all_selection_lines_are_comments = true;
5022
5023                    for row in start_row..=end_row {
5024                        if snapshot.is_line_blank(row) {
5025                            continue;
5026                        }
5027
5028                        let prefix_range = comment_prefix_range(
5029                            snapshot.deref(),
5030                            row,
5031                            comment_prefix,
5032                            comment_prefix_whitespace,
5033                        );
5034                        if prefix_range.is_empty() {
5035                            all_selection_lines_are_comments = false;
5036                        }
5037                        selection_edit_ranges.push(prefix_range);
5038                    }
5039
5040                    if all_selection_lines_are_comments {
5041                        edits.extend(
5042                            selection_edit_ranges
5043                                .iter()
5044                                .cloned()
5045                                .map(|range| (range, empty_str.clone())),
5046                        );
5047                    } else {
5048                        let min_column = selection_edit_ranges
5049                            .iter()
5050                            .map(|r| r.start.column)
5051                            .min()
5052                            .unwrap_or(0);
5053                        edits.extend(selection_edit_ranges.iter().map(|range| {
5054                            let position = Point::new(range.start.row, min_column);
5055                            (position..position, full_comment_prefix.clone())
5056                        }));
5057                    }
5058                } else if let Some((full_comment_prefix, comment_suffix)) =
5059                    language.block_comment_delimiters()
5060                {
5061                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5062                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5063                    let prefix_range = comment_prefix_range(
5064                        snapshot.deref(),
5065                        start_row,
5066                        comment_prefix,
5067                        comment_prefix_whitespace,
5068                    );
5069                    let suffix_range = comment_suffix_range(
5070                        snapshot.deref(),
5071                        end_row,
5072                        comment_suffix.trim_start_matches(' '),
5073                        comment_suffix.starts_with(' '),
5074                    );
5075
5076                    if prefix_range.is_empty() || suffix_range.is_empty() {
5077                        edits.push((
5078                            prefix_range.start..prefix_range.start,
5079                            full_comment_prefix.clone(),
5080                        ));
5081                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5082                        suffixes_inserted.push((end_row, comment_suffix.len()));
5083                    } else {
5084                        edits.push((prefix_range, empty_str.clone()));
5085                        edits.push((suffix_range, empty_str.clone()));
5086                    }
5087                } else {
5088                    continue;
5089                }
5090            }
5091
5092            drop(snapshot);
5093            this.buffer.update(cx, |buffer, cx| {
5094                buffer.edit(edits, None, cx);
5095            });
5096
5097            // Adjust selections so that they end before any comment suffixes that
5098            // were inserted.
5099            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5100            let mut selections = this.selections.all::<Point>(cx);
5101            let snapshot = this.buffer.read(cx).read(cx);
5102            for selection in &mut selections {
5103                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5104                    match row.cmp(&selection.end.row) {
5105                        Ordering::Less => {
5106                            suffixes_inserted.next();
5107                            continue;
5108                        }
5109                        Ordering::Greater => break,
5110                        Ordering::Equal => {
5111                            if selection.end.column == snapshot.line_len(row) {
5112                                if selection.is_empty() {
5113                                    selection.start.column -= suffix_len as u32;
5114                                }
5115                                selection.end.column -= suffix_len as u32;
5116                            }
5117                            break;
5118                        }
5119                    }
5120                }
5121            }
5122
5123            drop(snapshot);
5124            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5125
5126            let selections = this.selections.all::<Point>(cx);
5127            let selections_on_single_row = selections.windows(2).all(|selections| {
5128                selections[0].start.row == selections[1].start.row
5129                    && selections[0].end.row == selections[1].end.row
5130                    && selections[0].start.row == selections[0].end.row
5131            });
5132            let selections_selecting = selections
5133                .iter()
5134                .any(|selection| selection.start != selection.end);
5135            let advance_downwards = action.advance_downwards
5136                && selections_on_single_row
5137                && !selections_selecting
5138                && this.mode != EditorMode::SingleLine;
5139
5140            if advance_downwards {
5141                let snapshot = this.buffer.read(cx).snapshot(cx);
5142
5143                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5144                    s.move_cursors_with(|display_snapshot, display_point, _| {
5145                        let mut point = display_point.to_point(display_snapshot);
5146                        point.row += 1;
5147                        point = snapshot.clip_point(point, Bias::Left);
5148                        let display_point = point.to_display_point(display_snapshot);
5149                        (display_point, SelectionGoal::Column(display_point.column()))
5150                    })
5151                });
5152            }
5153        });
5154    }
5155
5156    pub fn select_larger_syntax_node(
5157        &mut self,
5158        _: &SelectLargerSyntaxNode,
5159        cx: &mut ViewContext<Self>,
5160    ) {
5161        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5162        let buffer = self.buffer.read(cx).snapshot(cx);
5163        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5164
5165        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5166        let mut selected_larger_node = false;
5167        let new_selections = old_selections
5168            .iter()
5169            .map(|selection| {
5170                let old_range = selection.start..selection.end;
5171                let mut new_range = old_range.clone();
5172                while let Some(containing_range) =
5173                    buffer.range_for_syntax_ancestor(new_range.clone())
5174                {
5175                    new_range = containing_range;
5176                    if !display_map.intersects_fold(new_range.start)
5177                        && !display_map.intersects_fold(new_range.end)
5178                    {
5179                        break;
5180                    }
5181                }
5182
5183                selected_larger_node |= new_range != old_range;
5184                Selection {
5185                    id: selection.id,
5186                    start: new_range.start,
5187                    end: new_range.end,
5188                    goal: SelectionGoal::None,
5189                    reversed: selection.reversed,
5190                }
5191            })
5192            .collect::<Vec<_>>();
5193
5194        if selected_larger_node {
5195            stack.push(old_selections);
5196            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5197                s.select(new_selections);
5198            });
5199        }
5200        self.select_larger_syntax_node_stack = stack;
5201    }
5202
5203    pub fn select_smaller_syntax_node(
5204        &mut self,
5205        _: &SelectSmallerSyntaxNode,
5206        cx: &mut ViewContext<Self>,
5207    ) {
5208        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5209        if let Some(selections) = stack.pop() {
5210            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5211                s.select(selections.to_vec());
5212            });
5213        }
5214        self.select_larger_syntax_node_stack = stack;
5215    }
5216
5217    pub fn move_to_enclosing_bracket(
5218        &mut self,
5219        _: &MoveToEnclosingBracket,
5220        cx: &mut ViewContext<Self>,
5221    ) {
5222        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5223            s.move_offsets_with(|snapshot, selection| {
5224                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5225                    return;
5226                };
5227
5228                let mut best_length = usize::MAX;
5229                let mut best_inside = false;
5230                let mut best_in_bracket_range = false;
5231                let mut best_destination = None;
5232                for (open, close) in enclosing_bracket_ranges {
5233                    let close = close.to_inclusive();
5234                    let length = close.end() - open.start;
5235                    let inside = selection.start >= open.end && selection.end <= *close.start();
5236                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5237
5238                    // If best is next to a bracket and current isn't, skip
5239                    if !in_bracket_range && best_in_bracket_range {
5240                        continue;
5241                    }
5242
5243                    // Prefer smaller lengths unless best is inside and current isn't
5244                    if length > best_length && (best_inside || !inside) {
5245                        continue;
5246                    }
5247
5248                    best_length = length;
5249                    best_inside = inside;
5250                    best_in_bracket_range = in_bracket_range;
5251                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5252                        if inside {
5253                            open.end
5254                        } else {
5255                            open.start
5256                        }
5257                    } else {
5258                        if inside {
5259                            *close.start()
5260                        } else {
5261                            *close.end()
5262                        }
5263                    });
5264                }
5265
5266                if let Some(destination) = best_destination {
5267                    selection.collapse_to(destination, SelectionGoal::None);
5268                }
5269            })
5270        });
5271    }
5272
5273    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5274        self.end_selection(cx);
5275        self.selection_history.mode = SelectionHistoryMode::Undoing;
5276        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5277            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5278            self.select_next_state = entry.select_next_state;
5279            self.add_selections_state = entry.add_selections_state;
5280            self.request_autoscroll(Autoscroll::newest(), cx);
5281        }
5282        self.selection_history.mode = SelectionHistoryMode::Normal;
5283    }
5284
5285    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5286        self.end_selection(cx);
5287        self.selection_history.mode = SelectionHistoryMode::Redoing;
5288        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5289            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5290            self.select_next_state = entry.select_next_state;
5291            self.add_selections_state = entry.add_selections_state;
5292            self.request_autoscroll(Autoscroll::newest(), cx);
5293        }
5294        self.selection_history.mode = SelectionHistoryMode::Normal;
5295    }
5296
5297    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5298        self.go_to_diagnostic_impl(Direction::Next, cx)
5299    }
5300
5301    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5302        self.go_to_diagnostic_impl(Direction::Prev, cx)
5303    }
5304
5305    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5306        let buffer = self.buffer.read(cx).snapshot(cx);
5307        let selection = self.selections.newest::<usize>(cx);
5308
5309        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5310        if direction == Direction::Next {
5311            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5312                let (group_id, jump_to) = popover.activation_info();
5313                if self.activate_diagnostics(group_id, cx) {
5314                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5315                        let mut new_selection = s.newest_anchor().clone();
5316                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5317                        s.select_anchors(vec![new_selection.clone()]);
5318                    });
5319                }
5320                return;
5321            }
5322        }
5323
5324        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5325            active_diagnostics
5326                .primary_range
5327                .to_offset(&buffer)
5328                .to_inclusive()
5329        });
5330        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5331            if active_primary_range.contains(&selection.head()) {
5332                *active_primary_range.end()
5333            } else {
5334                selection.head()
5335            }
5336        } else {
5337            selection.head()
5338        };
5339
5340        loop {
5341            let mut diagnostics = if direction == Direction::Prev {
5342                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5343            } else {
5344                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5345            };
5346            let group = diagnostics.find_map(|entry| {
5347                if entry.diagnostic.is_primary
5348                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5349                    && !entry.range.is_empty()
5350                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5351                {
5352                    Some((entry.range, entry.diagnostic.group_id))
5353                } else {
5354                    None
5355                }
5356            });
5357
5358            if let Some((primary_range, group_id)) = group {
5359                if self.activate_diagnostics(group_id, cx) {
5360                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5361                        s.select(vec![Selection {
5362                            id: selection.id,
5363                            start: primary_range.start,
5364                            end: primary_range.start,
5365                            reversed: false,
5366                            goal: SelectionGoal::None,
5367                        }]);
5368                    });
5369                }
5370                break;
5371            } else {
5372                // Cycle around to the start of the buffer, potentially moving back to the start of
5373                // the currently active diagnostic.
5374                active_primary_range.take();
5375                if direction == Direction::Prev {
5376                    if search_start == buffer.len() {
5377                        break;
5378                    } else {
5379                        search_start = buffer.len();
5380                    }
5381                } else if search_start == 0 {
5382                    break;
5383                } else {
5384                    search_start = 0;
5385                }
5386            }
5387        }
5388    }
5389
5390    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5391        self.go_to_hunk_impl(Direction::Next, cx)
5392    }
5393
5394    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5395        self.go_to_hunk_impl(Direction::Prev, cx)
5396    }
5397
5398    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5399        let snapshot = self
5400            .display_map
5401            .update(cx, |display_map, cx| display_map.snapshot(cx));
5402        let selection = self.selections.newest::<Point>(cx);
5403
5404        fn seek_in_direction(
5405            this: &mut Editor,
5406            snapshot: &DisplaySnapshot,
5407            initial_point: Point,
5408            is_wrapped: bool,
5409            direction: Direction,
5410            cx: &mut ViewContext<Editor>,
5411        ) -> bool {
5412            let hunks = if direction == Direction::Next {
5413                snapshot
5414                    .buffer_snapshot
5415                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
5416            } else {
5417                snapshot
5418                    .buffer_snapshot
5419                    .git_diff_hunks_in_range(0..initial_point.row, true)
5420            };
5421
5422            let display_point = initial_point.to_display_point(snapshot);
5423            let mut hunks = hunks
5424                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5425                .skip_while(|hunk| {
5426                    if is_wrapped {
5427                        false
5428                    } else {
5429                        hunk.contains_display_row(display_point.row())
5430                    }
5431                })
5432                .dedup();
5433
5434            if let Some(hunk) = hunks.next() {
5435                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5436                    let row = hunk.start_display_row();
5437                    let point = DisplayPoint::new(row, 0);
5438                    s.select_display_ranges([point..point]);
5439                });
5440
5441                true
5442            } else {
5443                false
5444            }
5445        }
5446
5447        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5448            let wrapped_point = match direction {
5449                Direction::Next => Point::zero(),
5450                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5451            };
5452            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5453        }
5454    }
5455
5456    pub fn go_to_definition(
5457        workspace: &mut Workspace,
5458        _: &GoToDefinition,
5459        cx: &mut ViewContext<Workspace>,
5460    ) {
5461        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5462    }
5463
5464    pub fn go_to_type_definition(
5465        workspace: &mut Workspace,
5466        _: &GoToTypeDefinition,
5467        cx: &mut ViewContext<Workspace>,
5468    ) {
5469        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5470    }
5471
5472    fn go_to_definition_of_kind(
5473        kind: GotoDefinitionKind,
5474        workspace: &mut Workspace,
5475        cx: &mut ViewContext<Workspace>,
5476    ) {
5477        let active_item = workspace.active_item(cx);
5478        let editor_handle = if let Some(editor) = active_item
5479            .as_ref()
5480            .and_then(|item| item.act_as::<Self>(cx))
5481        {
5482            editor
5483        } else {
5484            return;
5485        };
5486
5487        let editor = editor_handle.read(cx);
5488        let buffer = editor.buffer.read(cx);
5489        let head = editor.selections.newest::<usize>(cx).head();
5490        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5491            text_anchor
5492        } else {
5493            return;
5494        };
5495
5496        let project = workspace.project().clone();
5497        let definitions = project.update(cx, |project, cx| match kind {
5498            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5499            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5500        });
5501
5502        cx.spawn_labeled("Fetching Definition...", |workspace, mut cx| async move {
5503            let definitions = definitions.await?;
5504            workspace.update(&mut cx, |workspace, cx| {
5505                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5506            });
5507
5508            Ok::<(), anyhow::Error>(())
5509        })
5510        .detach_and_log_err(cx);
5511    }
5512
5513    pub fn navigate_to_definitions(
5514        workspace: &mut Workspace,
5515        editor_handle: ViewHandle<Editor>,
5516        definitions: Vec<LocationLink>,
5517        cx: &mut ViewContext<Workspace>,
5518    ) {
5519        let pane = workspace.active_pane().clone();
5520        // If there is one definition, just open it directly
5521        if let [definition] = definitions.as_slice() {
5522            let range = definition
5523                .target
5524                .range
5525                .to_offset(definition.target.buffer.read(cx));
5526
5527            let target_editor_handle =
5528                workspace.open_project_item(definition.target.buffer.clone(), cx);
5529            target_editor_handle.update(cx, |target_editor, cx| {
5530                // When selecting a definition in a different buffer, disable the nav history
5531                // to avoid creating a history entry at the previous cursor location.
5532                if editor_handle != target_editor_handle {
5533                    pane.update(cx, |pane, _| pane.disable_history());
5534                }
5535                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5536                    s.select_ranges([range]);
5537                });
5538
5539                pane.update(cx, |pane, _| pane.enable_history());
5540            });
5541        } else if !definitions.is_empty() {
5542            let replica_id = editor_handle.read(cx).replica_id(cx);
5543            let title = definitions
5544                .iter()
5545                .find(|definition| definition.origin.is_some())
5546                .and_then(|definition| {
5547                    definition.origin.as_ref().map(|origin| {
5548                        let buffer = origin.buffer.read(cx);
5549                        format!(
5550                            "Definitions for {}",
5551                            buffer
5552                                .text_for_range(origin.range.clone())
5553                                .collect::<String>()
5554                        )
5555                    })
5556                })
5557                .unwrap_or("Definitions".to_owned());
5558            let locations = definitions
5559                .into_iter()
5560                .map(|definition| definition.target)
5561                .collect();
5562            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5563        }
5564    }
5565
5566    pub fn find_all_references(
5567        workspace: &mut Workspace,
5568        _: &FindAllReferences,
5569        cx: &mut ViewContext<Workspace>,
5570    ) -> Option<Task<Result<()>>> {
5571        let active_item = workspace.active_item(cx)?;
5572        let editor_handle = active_item.act_as::<Self>(cx)?;
5573
5574        let editor = editor_handle.read(cx);
5575        let buffer = editor.buffer.read(cx);
5576        let head = editor.selections.newest::<usize>(cx).head();
5577        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5578        let replica_id = editor.replica_id(cx);
5579
5580        let project = workspace.project().clone();
5581        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5582        Some(cx.spawn_labeled(
5583            "Finding All References...",
5584            |workspace, mut cx| async move {
5585                let locations = references.await?;
5586                if locations.is_empty() {
5587                    return Ok(());
5588                }
5589
5590                workspace.update(&mut cx, |workspace, cx| {
5591                    let title = locations
5592                        .first()
5593                        .as_ref()
5594                        .map(|location| {
5595                            let buffer = location.buffer.read(cx);
5596                            format!(
5597                                "References to `{}`",
5598                                buffer
5599                                    .text_for_range(location.range.clone())
5600                                    .collect::<String>()
5601                            )
5602                        })
5603                        .unwrap();
5604                    Self::open_locations_in_multibuffer(
5605                        workspace, locations, replica_id, title, cx,
5606                    );
5607                });
5608
5609                Ok(())
5610            },
5611        ))
5612    }
5613
5614    /// Opens a multibuffer with the given project locations in it
5615    pub fn open_locations_in_multibuffer(
5616        workspace: &mut Workspace,
5617        mut locations: Vec<Location>,
5618        replica_id: ReplicaId,
5619        title: String,
5620        cx: &mut ViewContext<Workspace>,
5621    ) {
5622        // If there are multiple definitions, open them in a multibuffer
5623        locations.sort_by_key(|location| location.buffer.id());
5624        let mut locations = locations.into_iter().peekable();
5625        let mut ranges_to_highlight = Vec::new();
5626
5627        let excerpt_buffer = cx.add_model(|cx| {
5628            let mut multibuffer = MultiBuffer::new(replica_id);
5629            while let Some(location) = locations.next() {
5630                let buffer = location.buffer.read(cx);
5631                let mut ranges_for_buffer = Vec::new();
5632                let range = location.range.to_offset(buffer);
5633                ranges_for_buffer.push(range.clone());
5634
5635                while let Some(next_location) = locations.peek() {
5636                    if next_location.buffer == location.buffer {
5637                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5638                        locations.next();
5639                    } else {
5640                        break;
5641                    }
5642                }
5643
5644                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5645                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5646                    location.buffer.clone(),
5647                    ranges_for_buffer,
5648                    1,
5649                    cx,
5650                ))
5651            }
5652
5653            multibuffer.with_title(title)
5654        });
5655
5656        let editor = cx.add_view(|cx| {
5657            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5658        });
5659        editor.update(cx, |editor, cx| {
5660            editor.highlight_background::<Self>(
5661                ranges_to_highlight,
5662                |theme| theme.editor.highlighted_line_background,
5663                cx,
5664            );
5665        });
5666        workspace.add_item(Box::new(editor), cx);
5667    }
5668
5669    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5670        use language::ToOffset as _;
5671
5672        let project = self.project.clone()?;
5673        let selection = self.selections.newest_anchor().clone();
5674        let (cursor_buffer, cursor_buffer_position) = self
5675            .buffer
5676            .read(cx)
5677            .text_anchor_for_position(selection.head(), cx)?;
5678        let (tail_buffer, _) = self
5679            .buffer
5680            .read(cx)
5681            .text_anchor_for_position(selection.tail(), cx)?;
5682        if tail_buffer != cursor_buffer {
5683            return None;
5684        }
5685
5686        let snapshot = cursor_buffer.read(cx).snapshot();
5687        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5688        let prepare_rename = project.update(cx, |project, cx| {
5689            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5690        });
5691
5692        Some(cx.spawn(|this, mut cx| async move {
5693            let rename_range = if let Some(range) = prepare_rename.await? {
5694                Some(range)
5695            } else {
5696                this.read_with(&cx, |this, cx| {
5697                    let buffer = this.buffer.read(cx).snapshot(cx);
5698                    let mut buffer_highlights = this
5699                        .document_highlights_for_position(selection.head(), &buffer)
5700                        .filter(|highlight| {
5701                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5702                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5703                        });
5704                    buffer_highlights
5705                        .next()
5706                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5707                })
5708            };
5709            if let Some(rename_range) = rename_range {
5710                let rename_buffer_range = rename_range.to_offset(&snapshot);
5711                let cursor_offset_in_rename_range =
5712                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5713
5714                this.update(&mut cx, |this, cx| {
5715                    this.take_rename(false, cx);
5716                    let style = this.style(cx);
5717                    let buffer = this.buffer.read(cx).read(cx);
5718                    let cursor_offset = selection.head().to_offset(&buffer);
5719                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5720                    let rename_end = rename_start + rename_buffer_range.len();
5721                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5722                    let mut old_highlight_id = None;
5723                    let old_name: Arc<str> = buffer
5724                        .chunks(rename_start..rename_end, true)
5725                        .map(|chunk| {
5726                            if old_highlight_id.is_none() {
5727                                old_highlight_id = chunk.syntax_highlight_id;
5728                            }
5729                            chunk.text
5730                        })
5731                        .collect::<String>()
5732                        .into();
5733
5734                    drop(buffer);
5735
5736                    // Position the selection in the rename editor so that it matches the current selection.
5737                    this.show_local_selections = false;
5738                    let rename_editor = cx.add_view(|cx| {
5739                        let mut editor = Editor::single_line(None, cx);
5740                        if let Some(old_highlight_id) = old_highlight_id {
5741                            editor.override_text_style =
5742                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5743                        }
5744                        editor.buffer.update(cx, |buffer, cx| {
5745                            buffer.edit([(0..0, old_name.clone())], None, cx)
5746                        });
5747                        editor.select_all(&SelectAll, cx);
5748                        editor
5749                    });
5750
5751                    let ranges = this
5752                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5753                        .into_iter()
5754                        .flat_map(|(_, ranges)| ranges)
5755                        .chain(
5756                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5757                                .into_iter()
5758                                .flat_map(|(_, ranges)| ranges),
5759                        )
5760                        .collect();
5761
5762                    this.highlight_text::<Rename>(
5763                        ranges,
5764                        HighlightStyle {
5765                            fade_out: Some(style.rename_fade),
5766                            ..Default::default()
5767                        },
5768                        cx,
5769                    );
5770                    cx.focus(&rename_editor);
5771                    let block_id = this.insert_blocks(
5772                        [BlockProperties {
5773                            style: BlockStyle::Flex,
5774                            position: range.start.clone(),
5775                            height: 1,
5776                            render: Arc::new({
5777                                let editor = rename_editor.clone();
5778                                move |cx: &mut BlockContext| {
5779                                    ChildView::new(&editor, cx)
5780                                        .contained()
5781                                        .with_padding_left(cx.anchor_x)
5782                                        .boxed()
5783                                }
5784                            }),
5785                            disposition: BlockDisposition::Below,
5786                        }],
5787                        cx,
5788                    )[0];
5789                    this.pending_rename = Some(RenameState {
5790                        range,
5791                        old_name,
5792                        editor: rename_editor,
5793                        block_id,
5794                    });
5795                });
5796            }
5797
5798            Ok(())
5799        }))
5800    }
5801
5802    pub fn confirm_rename(
5803        workspace: &mut Workspace,
5804        _: &ConfirmRename,
5805        cx: &mut ViewContext<Workspace>,
5806    ) -> Option<Task<Result<()>>> {
5807        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5808
5809        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5810            let rename = editor.take_rename(false, cx)?;
5811            let buffer = editor.buffer.read(cx);
5812            let (start_buffer, start) =
5813                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5814            let (end_buffer, end) =
5815                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5816            if start_buffer == end_buffer {
5817                let new_name = rename.editor.read(cx).text(cx);
5818                Some((start_buffer, start..end, rename.old_name, new_name))
5819            } else {
5820                None
5821            }
5822        })?;
5823
5824        let rename = workspace.project().clone().update(cx, |project, cx| {
5825            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5826        });
5827
5828        Some(cx.spawn(|workspace, mut cx| async move {
5829            let project_transaction = rename.await?;
5830            Self::open_project_transaction(
5831                editor.clone(),
5832                workspace,
5833                project_transaction,
5834                format!("Rename: {}{}", old_name, new_name),
5835                cx.clone(),
5836            )
5837            .await?;
5838
5839            editor.update(&mut cx, |editor, cx| {
5840                editor.refresh_document_highlights(cx);
5841            });
5842            Ok(())
5843        }))
5844    }
5845
5846    fn take_rename(
5847        &mut self,
5848        moving_cursor: bool,
5849        cx: &mut ViewContext<Self>,
5850    ) -> Option<RenameState> {
5851        let rename = self.pending_rename.take()?;
5852        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5853        self.clear_text_highlights::<Rename>(cx);
5854        self.show_local_selections = true;
5855
5856        if moving_cursor {
5857            let rename_editor = rename.editor.read(cx);
5858            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5859
5860            // Update the selection to match the position of the selection inside
5861            // the rename editor.
5862            let snapshot = self.buffer.read(cx).read(cx);
5863            let rename_range = rename.range.to_offset(&snapshot);
5864            let cursor_in_editor = snapshot
5865                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5866                .min(rename_range.end);
5867            drop(snapshot);
5868
5869            self.change_selections(None, cx, |s| {
5870                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5871            });
5872        } else {
5873            self.refresh_document_highlights(cx);
5874        }
5875
5876        Some(rename)
5877    }
5878
5879    #[cfg(any(test, feature = "test-support"))]
5880    pub fn pending_rename(&self) -> Option<&RenameState> {
5881        self.pending_rename.as_ref()
5882    }
5883
5884    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5885        let project = match &self.project {
5886            Some(project) => project.clone(),
5887            None => return None,
5888        };
5889
5890        Some(self.perform_format(project, FormatTrigger::Manual, cx))
5891    }
5892
5893    fn perform_format(
5894        &mut self,
5895        project: ModelHandle<Project>,
5896        trigger: FormatTrigger,
5897        cx: &mut ViewContext<'_, Self>,
5898    ) -> Task<Result<()>> {
5899        let buffer = self.buffer().clone();
5900        let buffers = buffer.read(cx).all_buffers();
5901
5902        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5903        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
5904
5905        cx.spawn(|_, mut cx| async move {
5906            let transaction = futures::select_biased! {
5907                _ = timeout => {
5908                    log::warn!("timed out waiting for formatting");
5909                    None
5910                }
5911                transaction = format.log_err().fuse() => transaction,
5912            };
5913
5914            buffer.update(&mut cx, |buffer, cx| {
5915                if let Some(transaction) = transaction {
5916                    if !buffer.is_singleton() {
5917                        buffer.push_transaction(&transaction.0);
5918                    }
5919                }
5920
5921                cx.notify();
5922            });
5923
5924            Ok(())
5925        })
5926    }
5927
5928    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5929        if let Some(project) = self.project.clone() {
5930            self.buffer.update(cx, |multi_buffer, cx| {
5931                project.update(cx, |project, cx| {
5932                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5933                });
5934            })
5935        }
5936    }
5937
5938    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5939        cx.show_character_palette();
5940    }
5941
5942    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5943        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5944            let buffer = self.buffer.read(cx).snapshot(cx);
5945            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5946            let is_valid = buffer
5947                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5948                .any(|entry| {
5949                    entry.diagnostic.is_primary
5950                        && !entry.range.is_empty()
5951                        && entry.range.start == primary_range_start
5952                        && entry.diagnostic.message == active_diagnostics.primary_message
5953                });
5954
5955            if is_valid != active_diagnostics.is_valid {
5956                active_diagnostics.is_valid = is_valid;
5957                let mut new_styles = HashMap::default();
5958                for (block_id, diagnostic) in &active_diagnostics.blocks {
5959                    new_styles.insert(
5960                        *block_id,
5961                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5962                    );
5963                }
5964                self.display_map
5965                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5966            }
5967        }
5968    }
5969
5970    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5971        self.dismiss_diagnostics(cx);
5972        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5973            let buffer = self.buffer.read(cx).snapshot(cx);
5974
5975            let mut primary_range = None;
5976            let mut primary_message = None;
5977            let mut group_end = Point::zero();
5978            let diagnostic_group = buffer
5979                .diagnostic_group::<Point>(group_id)
5980                .map(|entry| {
5981                    if entry.range.end > group_end {
5982                        group_end = entry.range.end;
5983                    }
5984                    if entry.diagnostic.is_primary {
5985                        primary_range = Some(entry.range.clone());
5986                        primary_message = Some(entry.diagnostic.message.clone());
5987                    }
5988                    entry
5989                })
5990                .collect::<Vec<_>>();
5991            let primary_range = primary_range?;
5992            let primary_message = primary_message?;
5993            let primary_range =
5994                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5995
5996            let blocks = display_map
5997                .insert_blocks(
5998                    diagnostic_group.iter().map(|entry| {
5999                        let diagnostic = entry.diagnostic.clone();
6000                        let message_height = diagnostic.message.lines().count() as u8;
6001                        BlockProperties {
6002                            style: BlockStyle::Fixed,
6003                            position: buffer.anchor_after(entry.range.start),
6004                            height: message_height,
6005                            render: diagnostic_block_renderer(diagnostic, true),
6006                            disposition: BlockDisposition::Below,
6007                        }
6008                    }),
6009                    cx,
6010                )
6011                .into_iter()
6012                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6013                .collect();
6014
6015            Some(ActiveDiagnosticGroup {
6016                primary_range,
6017                primary_message,
6018                blocks,
6019                is_valid: true,
6020            })
6021        });
6022        self.active_diagnostics.is_some()
6023    }
6024
6025    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6026        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6027            self.display_map.update(cx, |display_map, cx| {
6028                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6029            });
6030            cx.notify();
6031        }
6032    }
6033
6034    pub fn set_selections_from_remote(
6035        &mut self,
6036        selections: Vec<Selection<Anchor>>,
6037        pending_selection: Option<Selection<Anchor>>,
6038        cx: &mut ViewContext<Self>,
6039    ) {
6040        let old_cursor_position = self.selections.newest_anchor().head();
6041        self.selections.change_with(cx, |s| {
6042            s.select_anchors(selections);
6043            if let Some(pending_selection) = pending_selection {
6044                s.set_pending(pending_selection, SelectMode::Character);
6045            } else {
6046                s.clear_pending();
6047            }
6048        });
6049        self.selections_did_change(false, &old_cursor_position, cx);
6050    }
6051
6052    fn push_to_selection_history(&mut self) {
6053        self.selection_history.push(SelectionHistoryEntry {
6054            selections: self.selections.disjoint_anchors(),
6055            select_next_state: self.select_next_state.clone(),
6056            add_selections_state: self.add_selections_state.clone(),
6057        });
6058    }
6059
6060    pub fn transact(
6061        &mut self,
6062        cx: &mut ViewContext<Self>,
6063        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6064    ) -> Option<TransactionId> {
6065        self.start_transaction_at(Instant::now(), cx);
6066        update(self, cx);
6067        self.end_transaction_at(Instant::now(), cx)
6068    }
6069
6070    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6071        self.end_selection(cx);
6072        if let Some(tx_id) = self
6073            .buffer
6074            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6075        {
6076            self.selection_history
6077                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6078        }
6079    }
6080
6081    fn end_transaction_at(
6082        &mut self,
6083        now: Instant,
6084        cx: &mut ViewContext<Self>,
6085    ) -> Option<TransactionId> {
6086        if let Some(tx_id) = self
6087            .buffer
6088            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6089        {
6090            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6091                *end_selections = Some(self.selections.disjoint_anchors());
6092            } else {
6093                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6094            }
6095
6096            cx.emit(Event::Edited);
6097            Some(tx_id)
6098        } else {
6099            None
6100        }
6101    }
6102
6103    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6104        let mut fold_ranges = Vec::new();
6105
6106        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6107
6108        let selections = self.selections.all::<Point>(cx);
6109        for selection in selections {
6110            let range = selection.range().sorted();
6111            let buffer_start_row = range.start.row;
6112
6113            for row in (0..=range.end.row).rev() {
6114                let fold_range = display_map.foldable_range(row);
6115
6116                if let Some(fold_range) = fold_range {
6117                    if fold_range.end.row >= buffer_start_row {
6118                        fold_ranges.push(fold_range);
6119                        if row <= range.start.row {
6120                            break;
6121                        }
6122                    }
6123                }
6124            }
6125        }
6126
6127        self.fold_ranges(fold_ranges, true, cx);
6128    }
6129
6130    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6131        let buffer_row = fold_at.buffer_row;
6132        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6133
6134        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6135            let autoscroll = self
6136                .selections
6137                .all::<Point>(cx)
6138                .iter()
6139                .any(|selection| fold_range.overlaps(&selection.range()));
6140
6141            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6142        }
6143    }
6144
6145    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6146        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6147        let buffer = &display_map.buffer_snapshot;
6148        let selections = self.selections.all::<Point>(cx);
6149        let ranges = selections
6150            .iter()
6151            .map(|s| {
6152                let range = s.display_range(&display_map).sorted();
6153                let mut start = range.start.to_point(&display_map);
6154                let mut end = range.end.to_point(&display_map);
6155                start.column = 0;
6156                end.column = buffer.line_len(end.row);
6157                start..end
6158            })
6159            .collect::<Vec<_>>();
6160
6161        self.unfold_ranges(ranges, true, true, cx);
6162    }
6163
6164    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6165        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6166
6167        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6168            ..Point::new(
6169                unfold_at.buffer_row,
6170                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6171            );
6172
6173        let autoscroll = self
6174            .selections
6175            .all::<Point>(cx)
6176            .iter()
6177            .any(|selection| selection.range().overlaps(&intersection_range));
6178
6179        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6180    }
6181
6182    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6183        let selections = self.selections.all::<Point>(cx);
6184        let ranges = selections.into_iter().map(|s| s.start..s.end);
6185        self.fold_ranges(ranges, true, cx);
6186    }
6187
6188    pub fn fold_ranges<T: ToOffset + Clone>(
6189        &mut self,
6190        ranges: impl IntoIterator<Item = Range<T>>,
6191        auto_scroll: bool,
6192        cx: &mut ViewContext<Self>,
6193    ) {
6194        let mut ranges = ranges.into_iter().peekable();
6195        if ranges.peek().is_some() {
6196            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6197
6198            if auto_scroll {
6199                self.request_autoscroll(Autoscroll::fit(), cx);
6200            }
6201
6202            cx.notify();
6203        }
6204    }
6205
6206    pub fn unfold_ranges<T: ToOffset + Clone>(
6207        &mut self,
6208        ranges: impl IntoIterator<Item = Range<T>>,
6209        inclusive: bool,
6210        auto_scroll: bool,
6211        cx: &mut ViewContext<Self>,
6212    ) {
6213        let mut ranges = ranges.into_iter().peekable();
6214        if ranges.peek().is_some() {
6215            self.display_map
6216                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6217            if auto_scroll {
6218                self.request_autoscroll(Autoscroll::fit(), cx);
6219            }
6220
6221            cx.notify();
6222        }
6223    }
6224
6225    pub fn gutter_hover(
6226        &mut self,
6227        GutterHover { hovered }: &GutterHover,
6228        cx: &mut ViewContext<Self>,
6229    ) {
6230        self.gutter_hovered = *hovered;
6231        cx.notify();
6232    }
6233
6234    pub fn insert_blocks(
6235        &mut self,
6236        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6237        cx: &mut ViewContext<Self>,
6238    ) -> Vec<BlockId> {
6239        let blocks = self
6240            .display_map
6241            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6242        self.request_autoscroll(Autoscroll::fit(), cx);
6243        blocks
6244    }
6245
6246    pub fn replace_blocks(
6247        &mut self,
6248        blocks: HashMap<BlockId, RenderBlock>,
6249        cx: &mut ViewContext<Self>,
6250    ) {
6251        self.display_map
6252            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6253        self.request_autoscroll(Autoscroll::fit(), cx);
6254    }
6255
6256    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6257        self.display_map.update(cx, |display_map, cx| {
6258            display_map.remove_blocks(block_ids, cx)
6259        });
6260    }
6261
6262    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6263        self.display_map
6264            .update(cx, |map, cx| map.snapshot(cx))
6265            .longest_row()
6266    }
6267
6268    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6269        self.display_map
6270            .update(cx, |map, cx| map.snapshot(cx))
6271            .max_point()
6272    }
6273
6274    pub fn text(&self, cx: &AppContext) -> String {
6275        self.buffer.read(cx).read(cx).text()
6276    }
6277
6278    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6279        self.transact(cx, |this, cx| {
6280            this.buffer
6281                .read(cx)
6282                .as_singleton()
6283                .expect("you can only call set_text on editors for singleton buffers")
6284                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6285        });
6286    }
6287
6288    pub fn display_text(&self, cx: &mut AppContext) -> String {
6289        self.display_map
6290            .update(cx, |map, cx| map.snapshot(cx))
6291            .text()
6292    }
6293
6294    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6295        let language_name = self
6296            .buffer
6297            .read(cx)
6298            .as_singleton()
6299            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6300            .map(|l| l.name());
6301
6302        let settings = cx.global::<Settings>();
6303        let mode = self
6304            .soft_wrap_mode_override
6305            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6306        match mode {
6307            settings::SoftWrap::None => SoftWrap::None,
6308            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6309            settings::SoftWrap::PreferredLineLength => {
6310                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6311            }
6312        }
6313    }
6314
6315    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6316        self.soft_wrap_mode_override = Some(mode);
6317        cx.notify();
6318    }
6319
6320    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6321        self.display_map
6322            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6323    }
6324
6325    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6326        if self.soft_wrap_mode_override.is_some() {
6327            self.soft_wrap_mode_override.take();
6328        } else {
6329            let soft_wrap = match self.soft_wrap_mode(cx) {
6330                SoftWrap::None => settings::SoftWrap::EditorWidth,
6331                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
6332            };
6333            self.soft_wrap_mode_override = Some(soft_wrap);
6334        }
6335        cx.notify();
6336    }
6337
6338    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6339        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6340            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6341                cx.reveal_path(&file.abs_path(cx));
6342            }
6343        }
6344    }
6345
6346    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6347        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6348            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6349                if let Some(path) = file.abs_path(cx).to_str() {
6350                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6351                }
6352            }
6353        }
6354    }
6355
6356    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6357        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6358            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6359                if let Some(path) = file.path().to_str() {
6360                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6361                }
6362            }
6363        }
6364    }
6365
6366    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6367        self.highlighted_rows = rows;
6368    }
6369
6370    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6371        self.highlighted_rows.clone()
6372    }
6373
6374    pub fn highlight_background<T: 'static>(
6375        &mut self,
6376        ranges: Vec<Range<Anchor>>,
6377        color_fetcher: fn(&Theme) -> Color,
6378        cx: &mut ViewContext<Self>,
6379    ) {
6380        self.background_highlights
6381            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6382        cx.notify();
6383    }
6384
6385    #[allow(clippy::type_complexity)]
6386    pub fn clear_background_highlights<T: 'static>(
6387        &mut self,
6388        cx: &mut ViewContext<Self>,
6389    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6390        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6391        if highlights.is_some() {
6392            cx.notify();
6393        }
6394        highlights
6395    }
6396
6397    #[cfg(feature = "test-support")]
6398    pub fn all_background_highlights(
6399        &mut self,
6400        cx: &mut ViewContext<Self>,
6401    ) -> Vec<(Range<DisplayPoint>, Color)> {
6402        let snapshot = self.snapshot(cx);
6403        let buffer = &snapshot.buffer_snapshot;
6404        let start = buffer.anchor_before(0);
6405        let end = buffer.anchor_after(buffer.len());
6406        let theme = cx.global::<Settings>().theme.as_ref();
6407        self.background_highlights_in_range(start..end, &snapshot, theme)
6408    }
6409
6410    fn document_highlights_for_position<'a>(
6411        &'a self,
6412        position: Anchor,
6413        buffer: &'a MultiBufferSnapshot,
6414    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6415        let read_highlights = self
6416            .background_highlights
6417            .get(&TypeId::of::<DocumentHighlightRead>())
6418            .map(|h| &h.1);
6419        let write_highlights = self
6420            .background_highlights
6421            .get(&TypeId::of::<DocumentHighlightWrite>())
6422            .map(|h| &h.1);
6423        let left_position = position.bias_left(buffer);
6424        let right_position = position.bias_right(buffer);
6425        read_highlights
6426            .into_iter()
6427            .chain(write_highlights)
6428            .flat_map(move |ranges| {
6429                let start_ix = match ranges.binary_search_by(|probe| {
6430                    let cmp = probe.end.cmp(&left_position, buffer);
6431                    if cmp.is_ge() {
6432                        Ordering::Greater
6433                    } else {
6434                        Ordering::Less
6435                    }
6436                }) {
6437                    Ok(i) | Err(i) => i,
6438                };
6439
6440                let right_position = right_position.clone();
6441                ranges[start_ix..]
6442                    .iter()
6443                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6444            })
6445    }
6446
6447    pub fn background_highlights_in_range(
6448        &self,
6449        search_range: Range<Anchor>,
6450        display_snapshot: &DisplaySnapshot,
6451        theme: &Theme,
6452    ) -> Vec<(Range<DisplayPoint>, Color)> {
6453        let mut results = Vec::new();
6454        let buffer = &display_snapshot.buffer_snapshot;
6455        for (color_fetcher, ranges) in self.background_highlights.values() {
6456            let color = color_fetcher(theme);
6457            let start_ix = match ranges.binary_search_by(|probe| {
6458                let cmp = probe.end.cmp(&search_range.start, buffer);
6459                if cmp.is_gt() {
6460                    Ordering::Greater
6461                } else {
6462                    Ordering::Less
6463                }
6464            }) {
6465                Ok(i) | Err(i) => i,
6466            };
6467            for range in &ranges[start_ix..] {
6468                if range.start.cmp(&search_range.end, buffer).is_ge() {
6469                    break;
6470                }
6471                let start = range
6472                    .start
6473                    .to_point(buffer)
6474                    .to_display_point(display_snapshot);
6475                let end = range
6476                    .end
6477                    .to_point(buffer)
6478                    .to_display_point(display_snapshot);
6479                results.push((start..end, color))
6480            }
6481        }
6482        results
6483    }
6484
6485    pub fn highlight_text<T: 'static>(
6486        &mut self,
6487        ranges: Vec<Range<Anchor>>,
6488        style: HighlightStyle,
6489        cx: &mut ViewContext<Self>,
6490    ) {
6491        self.display_map.update(cx, |map, _| {
6492            map.highlight_text(TypeId::of::<T>(), ranges, style)
6493        });
6494        cx.notify();
6495    }
6496
6497    pub fn text_highlights<'a, T: 'static>(
6498        &'a self,
6499        cx: &'a AppContext,
6500    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6501        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6502    }
6503
6504    pub fn clear_text_highlights<T: 'static>(
6505        &mut self,
6506        cx: &mut ViewContext<Self>,
6507    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6508        let highlights = self
6509            .display_map
6510            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6511        if highlights.is_some() {
6512            cx.notify();
6513        }
6514        highlights
6515    }
6516
6517    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6518        self.blink_manager.read(cx).visible() && self.focused
6519    }
6520
6521    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6522        cx.notify();
6523    }
6524
6525    fn on_buffer_event(
6526        &mut self,
6527        _: ModelHandle<MultiBuffer>,
6528        event: &multi_buffer::Event,
6529        cx: &mut ViewContext<Self>,
6530    ) {
6531        match event {
6532            multi_buffer::Event::Edited => {
6533                self.refresh_active_diagnostics(cx);
6534                self.refresh_code_actions(cx);
6535                if self.has_active_copilot_suggestion(cx) {
6536                    self.update_visible_copilot_suggestion(cx);
6537                }
6538                cx.emit(Event::BufferEdited);
6539            }
6540            multi_buffer::Event::ExcerptsAdded {
6541                buffer,
6542                predecessor,
6543                excerpts,
6544            } => cx.emit(Event::ExcerptsAdded {
6545                buffer: buffer.clone(),
6546                predecessor: *predecessor,
6547                excerpts: excerpts.clone(),
6548            }),
6549            multi_buffer::Event::ExcerptsRemoved { ids } => {
6550                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6551            }
6552            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6553            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6554            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6555            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6556            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6557            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6558            multi_buffer::Event::DiagnosticsUpdated => {
6559                self.refresh_active_diagnostics(cx);
6560            }
6561        }
6562    }
6563
6564    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6565        cx.notify();
6566    }
6567
6568    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6569        self.refresh_copilot_suggestions(cx);
6570    }
6571
6572    pub fn set_searchable(&mut self, searchable: bool) {
6573        self.searchable = searchable;
6574    }
6575
6576    pub fn searchable(&self) -> bool {
6577        self.searchable
6578    }
6579
6580    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6581        let active_item = workspace.active_item(cx);
6582        let editor_handle = if let Some(editor) = active_item
6583            .as_ref()
6584            .and_then(|item| item.act_as::<Self>(cx))
6585        {
6586            editor
6587        } else {
6588            cx.propagate_action();
6589            return;
6590        };
6591
6592        let editor = editor_handle.read(cx);
6593        let buffer = editor.buffer.read(cx);
6594        if buffer.is_singleton() {
6595            cx.propagate_action();
6596            return;
6597        }
6598
6599        let mut new_selections_by_buffer = HashMap::default();
6600        for selection in editor.selections.all::<usize>(cx) {
6601            for (buffer, mut range) in
6602                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6603            {
6604                if selection.reversed {
6605                    mem::swap(&mut range.start, &mut range.end);
6606                }
6607                new_selections_by_buffer
6608                    .entry(buffer)
6609                    .or_insert(Vec::new())
6610                    .push(range)
6611            }
6612        }
6613
6614        editor_handle.update(cx, |editor, cx| {
6615            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6616        });
6617        let pane = workspace.active_pane().clone();
6618        pane.update(cx, |pane, _| pane.disable_history());
6619
6620        // We defer the pane interaction because we ourselves are a workspace item
6621        // and activating a new item causes the pane to call a method on us reentrantly,
6622        // which panics if we're on the stack.
6623        cx.defer(move |workspace, cx| {
6624            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6625                let editor = workspace.open_project_item::<Self>(buffer, cx);
6626                editor.update(cx, |editor, cx| {
6627                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6628                        s.select_ranges(ranges);
6629                    });
6630                });
6631            }
6632
6633            pane.update(cx, |pane, _| pane.enable_history());
6634        });
6635    }
6636
6637    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6638        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6639        let position = action.position;
6640        let anchor = action.anchor;
6641        cx.spawn_weak(|_, mut cx| async move {
6642            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6643            editor.update(&mut cx, |editor, cx| {
6644                let buffer = editor.buffer().read(cx).as_singleton()?;
6645                let buffer = buffer.read(cx);
6646                let cursor = if buffer.can_resolve(&anchor) {
6647                    language::ToPoint::to_point(&anchor, buffer)
6648                } else {
6649                    buffer.clip_point(position, Bias::Left)
6650                };
6651
6652                let nav_history = editor.nav_history.take();
6653                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6654                    s.select_ranges([cursor..cursor]);
6655                });
6656                editor.nav_history = nav_history;
6657
6658                Some(())
6659            })?;
6660            Some(())
6661        })
6662        .detach()
6663    }
6664
6665    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6666        let snapshot = self.buffer.read(cx).read(cx);
6667        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6668        Some(
6669            ranges
6670                .iter()
6671                .map(move |range| {
6672                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6673                })
6674                .collect(),
6675        )
6676    }
6677
6678    fn selection_replacement_ranges(
6679        &self,
6680        range: Range<OffsetUtf16>,
6681        cx: &AppContext,
6682    ) -> Vec<Range<OffsetUtf16>> {
6683        let selections = self.selections.all::<OffsetUtf16>(cx);
6684        let newest_selection = selections
6685            .iter()
6686            .max_by_key(|selection| selection.id)
6687            .unwrap();
6688        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6689        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6690        let snapshot = self.buffer.read(cx).read(cx);
6691        selections
6692            .into_iter()
6693            .map(|mut selection| {
6694                selection.start.0 =
6695                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6696                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6697                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6698                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6699            })
6700            .collect()
6701    }
6702
6703    fn report_event(&self, name: &str, cx: &AppContext) {
6704        if let Some((project, file)) = self.project.as_ref().zip(
6705            self.buffer
6706                .read(cx)
6707                .as_singleton()
6708                .and_then(|b| b.read(cx).file()),
6709        ) {
6710            let settings = cx.global::<Settings>();
6711
6712            let extension = Path::new(file.file_name(cx))
6713                .extension()
6714                .and_then(|e| e.to_str());
6715            project.read(cx).client().report_event(
6716                name,
6717                json!({ "File Extension": extension, "Vim Mode": settings.vim_mode  }),
6718                settings.telemetry(),
6719            );
6720        }
6721    }
6722
6723    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6724    /// with each line being an array of {text, highlight} objects.
6725    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6726        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6727            return;
6728        };
6729
6730        #[derive(Serialize)]
6731        struct Chunk<'a> {
6732            text: String,
6733            highlight: Option<&'a str>,
6734        }
6735
6736        let snapshot = buffer.read(cx).snapshot();
6737        let range = self
6738            .selected_text_range(cx)
6739            .and_then(|selected_range| {
6740                if selected_range.is_empty() {
6741                    None
6742                } else {
6743                    Some(selected_range)
6744                }
6745            })
6746            .unwrap_or_else(|| 0..snapshot.len());
6747
6748        let chunks = snapshot.chunks(range, true);
6749        let mut lines = Vec::new();
6750        let mut line: VecDeque<Chunk> = VecDeque::new();
6751
6752        let theme = &cx.global::<Settings>().theme.editor.syntax;
6753
6754        for chunk in chunks {
6755            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
6756            let mut chunk_lines = chunk.text.split("\n").peekable();
6757            while let Some(text) = chunk_lines.next() {
6758                let mut merged_with_last_token = false;
6759                if let Some(last_token) = line.back_mut() {
6760                    if last_token.highlight == highlight {
6761                        last_token.text.push_str(text);
6762                        merged_with_last_token = true;
6763                    }
6764                }
6765
6766                if !merged_with_last_token {
6767                    line.push_back(Chunk {
6768                        text: text.into(),
6769                        highlight,
6770                    });
6771                }
6772
6773                if chunk_lines.peek().is_some() {
6774                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
6775                        line.pop_front();
6776                    }
6777                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
6778                        line.pop_back();
6779                    }
6780
6781                    lines.push(mem::take(&mut line));
6782                }
6783            }
6784        }
6785
6786        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
6787        cx.write_to_clipboard(ClipboardItem::new(lines));
6788    }
6789}
6790
6791fn consume_contiguous_rows(
6792    contiguous_row_selections: &mut Vec<Selection<Point>>,
6793    selection: &Selection<Point>,
6794    display_map: &DisplaySnapshot,
6795    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
6796) -> (u32, u32) {
6797    contiguous_row_selections.push(selection.clone());
6798    let start_row = selection.start.row;
6799    let mut end_row = ending_row(selection, display_map);
6800
6801    while let Some(next_selection) = selections.peek() {
6802        if next_selection.start.row <= end_row {
6803            end_row = ending_row(next_selection, display_map);
6804            contiguous_row_selections.push(selections.next().unwrap().clone());
6805        } else {
6806            break;
6807        }
6808    }
6809    (start_row, end_row)
6810}
6811
6812fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
6813    if next_selection.end.column > 0 || next_selection.is_empty() {
6814        display_map.next_line_boundary(next_selection.end).0.row + 1
6815    } else {
6816        next_selection.end.row
6817    }
6818}
6819
6820impl EditorSnapshot {
6821    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6822        self.display_snapshot.buffer_snapshot.language_at(position)
6823    }
6824
6825    pub fn is_focused(&self) -> bool {
6826        self.is_focused
6827    }
6828
6829    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6830        self.placeholder_text.as_ref()
6831    }
6832
6833    pub fn scroll_position(&self) -> Vector2F {
6834        self.scroll_anchor.scroll_position(&self.display_snapshot)
6835    }
6836}
6837
6838impl Deref for EditorSnapshot {
6839    type Target = DisplaySnapshot;
6840
6841    fn deref(&self) -> &Self::Target {
6842        &self.display_snapshot
6843    }
6844}
6845
6846#[derive(Clone, Debug, PartialEq, Eq)]
6847pub enum Event {
6848    InputIgnored {
6849        text: Arc<str>,
6850    },
6851    ExcerptsAdded {
6852        buffer: ModelHandle<Buffer>,
6853        predecessor: ExcerptId,
6854        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6855    },
6856    ExcerptsRemoved {
6857        ids: Vec<ExcerptId>,
6858    },
6859    BufferEdited,
6860    Edited,
6861    Reparsed,
6862    Blurred,
6863    DirtyChanged,
6864    Saved,
6865    TitleChanged,
6866    SelectionsChanged {
6867        local: bool,
6868    },
6869    ScrollPositionChanged {
6870        local: bool,
6871    },
6872    Closed,
6873}
6874
6875pub struct EditorFocused(pub ViewHandle<Editor>);
6876pub struct EditorBlurred(pub ViewHandle<Editor>);
6877pub struct EditorReleased(pub WeakViewHandle<Editor>);
6878
6879impl Entity for Editor {
6880    type Event = Event;
6881
6882    fn release(&mut self, cx: &mut AppContext) {
6883        cx.emit_global(EditorReleased(self.handle.clone()));
6884    }
6885}
6886
6887impl View for Editor {
6888    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6889        let style = self.style(cx);
6890        let font_changed = self.display_map.update(cx, |map, cx| {
6891            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
6892            map.set_font(style.text.font_id, style.text.font_size, cx)
6893        });
6894
6895        if font_changed {
6896            let handle = self.handle.clone();
6897            cx.defer(move |cx| {
6898                if let Some(editor) = handle.upgrade(cx) {
6899                    editor.update(cx, |editor, cx| {
6900                        hide_hover(editor, &HideHover, cx);
6901                        hide_link_definition(editor, cx);
6902                    })
6903                }
6904            });
6905        }
6906
6907        Stack::new()
6908            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6909            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6910            .boxed()
6911    }
6912
6913    fn ui_name() -> &'static str {
6914        "Editor"
6915    }
6916
6917    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6918        if cx.is_self_focused() {
6919            let focused_event = EditorFocused(cx.handle());
6920            cx.emit_global(focused_event);
6921        }
6922        if let Some(rename) = self.pending_rename.as_ref() {
6923            cx.focus(&rename.editor);
6924        } else {
6925            if !self.focused {
6926                self.blink_manager.update(cx, BlinkManager::enable);
6927            }
6928            self.focused = true;
6929            self.buffer.update(cx, |buffer, cx| {
6930                buffer.finalize_last_transaction(cx);
6931                if self.leader_replica_id.is_none() {
6932                    buffer.set_active_selections(
6933                        &self.selections.disjoint_anchors(),
6934                        self.selections.line_mode,
6935                        self.cursor_shape,
6936                        cx,
6937                    );
6938                }
6939            });
6940        }
6941    }
6942
6943    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6944        let blurred_event = EditorBlurred(cx.handle());
6945        cx.emit_global(blurred_event);
6946        self.focused = false;
6947        self.blink_manager.update(cx, BlinkManager::disable);
6948        self.buffer
6949            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6950        self.hide_context_menu(cx);
6951        hide_hover(self, &HideHover, cx);
6952        cx.emit(Event::Blurred);
6953        cx.notify();
6954    }
6955
6956    fn modifiers_changed(
6957        &mut self,
6958        event: &gpui::platform::ModifiersChangedEvent,
6959        cx: &mut ViewContext<Self>,
6960    ) -> bool {
6961        let pending_selection = self.has_pending_selection();
6962
6963        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6964            if event.cmd && !pending_selection {
6965                let snapshot = self.snapshot(cx);
6966                let kind = if event.shift {
6967                    LinkDefinitionKind::Type
6968                } else {
6969                    LinkDefinitionKind::Symbol
6970                };
6971
6972                show_link_definition(kind, self, point, snapshot, cx);
6973                return false;
6974            }
6975        }
6976
6977        {
6978            if self.link_go_to_definition_state.symbol_range.is_some()
6979                || !self.link_go_to_definition_state.definitions.is_empty()
6980            {
6981                self.link_go_to_definition_state.symbol_range.take();
6982                self.link_go_to_definition_state.definitions.clear();
6983                cx.notify();
6984            }
6985
6986            self.link_go_to_definition_state.task = None;
6987
6988            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6989        }
6990
6991        false
6992    }
6993
6994    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6995        let mut context = Self::default_keymap_context();
6996        let mode = match self.mode {
6997            EditorMode::SingleLine => "single_line",
6998            EditorMode::AutoHeight { .. } => "auto_height",
6999            EditorMode::Full => "full",
7000        };
7001        context.add_key("mode", mode);
7002        if self.pending_rename.is_some() {
7003            context.add_identifier("renaming");
7004        }
7005        match self.context_menu.as_ref() {
7006            Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
7007            Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
7008            None => {}
7009        }
7010
7011        for layer in self.keymap_context_layers.values() {
7012            context.extend(layer);
7013        }
7014
7015        context
7016    }
7017
7018    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7019        Some(
7020            self.buffer
7021                .read(cx)
7022                .read(cx)
7023                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7024                .collect(),
7025        )
7026    }
7027
7028    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7029        // Prevent the IME menu from appearing when holding down an alphabetic key
7030        // while input is disabled.
7031        if !self.input_enabled {
7032            return None;
7033        }
7034
7035        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7036        Some(range.start.0..range.end.0)
7037    }
7038
7039    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7040        let snapshot = self.buffer.read(cx).read(cx);
7041        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7042        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7043    }
7044
7045    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7046        self.clear_text_highlights::<InputComposition>(cx);
7047        self.ime_transaction.take();
7048    }
7049
7050    fn replace_text_in_range(
7051        &mut self,
7052        range_utf16: Option<Range<usize>>,
7053        text: &str,
7054        cx: &mut ViewContext<Self>,
7055    ) {
7056        self.transact(cx, |this, cx| {
7057            if this.input_enabled {
7058                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7059                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7060                    Some(this.selection_replacement_ranges(range_utf16, cx))
7061                } else {
7062                    this.marked_text_ranges(cx)
7063                };
7064
7065                if let Some(new_selected_ranges) = new_selected_ranges {
7066                    this.change_selections(None, cx, |selections| {
7067                        selections.select_ranges(new_selected_ranges)
7068                    });
7069                }
7070            }
7071
7072            this.handle_input(text, cx);
7073        });
7074
7075        if !self.input_enabled {
7076            return;
7077        }
7078
7079        if let Some(transaction) = self.ime_transaction {
7080            self.buffer.update(cx, |buffer, cx| {
7081                buffer.group_until_transaction(transaction, cx);
7082            });
7083        }
7084
7085        self.unmark_text(cx);
7086    }
7087
7088    fn replace_and_mark_text_in_range(
7089        &mut self,
7090        range_utf16: Option<Range<usize>>,
7091        text: &str,
7092        new_selected_range_utf16: Option<Range<usize>>,
7093        cx: &mut ViewContext<Self>,
7094    ) {
7095        if !self.input_enabled {
7096            return;
7097        }
7098
7099        let transaction = self.transact(cx, |this, cx| {
7100            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7101                let snapshot = this.buffer.read(cx).read(cx);
7102                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7103                    for marked_range in &mut marked_ranges {
7104                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7105                        marked_range.start.0 += relative_range_utf16.start;
7106                        marked_range.start =
7107                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7108                        marked_range.end =
7109                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7110                    }
7111                }
7112                Some(marked_ranges)
7113            } else if let Some(range_utf16) = range_utf16 {
7114                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7115                Some(this.selection_replacement_ranges(range_utf16, cx))
7116            } else {
7117                None
7118            };
7119
7120            if let Some(ranges) = ranges_to_replace {
7121                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7122            }
7123
7124            let marked_ranges = {
7125                let snapshot = this.buffer.read(cx).read(cx);
7126                this.selections
7127                    .disjoint_anchors()
7128                    .iter()
7129                    .map(|selection| {
7130                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7131                    })
7132                    .collect::<Vec<_>>()
7133            };
7134
7135            if text.is_empty() {
7136                this.unmark_text(cx);
7137            } else {
7138                this.highlight_text::<InputComposition>(
7139                    marked_ranges.clone(),
7140                    this.style(cx).composition_mark,
7141                    cx,
7142                );
7143            }
7144
7145            this.handle_input(text, cx);
7146
7147            if let Some(new_selected_range) = new_selected_range_utf16 {
7148                let snapshot = this.buffer.read(cx).read(cx);
7149                let new_selected_ranges = marked_ranges
7150                    .into_iter()
7151                    .map(|marked_range| {
7152                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7153                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7154                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7155                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7156                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7157                    })
7158                    .collect::<Vec<_>>();
7159
7160                drop(snapshot);
7161                this.change_selections(None, cx, |selections| {
7162                    selections.select_ranges(new_selected_ranges)
7163                });
7164            }
7165        });
7166
7167        self.ime_transaction = self.ime_transaction.or(transaction);
7168        if let Some(transaction) = self.ime_transaction {
7169            self.buffer.update(cx, |buffer, cx| {
7170                buffer.group_until_transaction(transaction, cx);
7171            });
7172        }
7173
7174        if self.text_highlights::<InputComposition>(cx).is_none() {
7175            self.ime_transaction.take();
7176        }
7177    }
7178}
7179
7180fn build_style(
7181    settings: &Settings,
7182    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7183    override_text_style: Option<&OverrideTextStyle>,
7184    cx: &AppContext,
7185) -> EditorStyle {
7186    let font_cache = cx.font_cache();
7187
7188    let mut theme = settings.theme.editor.clone();
7189    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7190        let field_editor_theme = get_field_editor_theme(&settings.theme);
7191        theme.text_color = field_editor_theme.text.color;
7192        theme.selection = field_editor_theme.selection;
7193        theme.background = field_editor_theme
7194            .container
7195            .background_color
7196            .unwrap_or_default();
7197        EditorStyle {
7198            text: field_editor_theme.text,
7199            placeholder_text: field_editor_theme.placeholder_text,
7200            theme,
7201        }
7202    } else {
7203        let font_family_id = settings.buffer_font_family;
7204        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7205        let font_properties = Default::default();
7206        let font_id = font_cache
7207            .select_font(font_family_id, &font_properties)
7208            .unwrap();
7209        let font_size = settings.buffer_font_size;
7210        EditorStyle {
7211            text: TextStyle {
7212                color: settings.theme.editor.text_color,
7213                font_family_name,
7214                font_family_id,
7215                font_id,
7216                font_size,
7217                font_properties,
7218                underline: Default::default(),
7219            },
7220            placeholder_text: None,
7221            theme,
7222        }
7223    };
7224
7225    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7226        if let Some(highlighted) = style
7227            .text
7228            .clone()
7229            .highlight(highlight_style, font_cache)
7230            .log_err()
7231        {
7232            style.text = highlighted;
7233        }
7234    }
7235
7236    style
7237}
7238
7239trait SelectionExt {
7240    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7241    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7242    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7243    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7244        -> Range<u32>;
7245}
7246
7247impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7248    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7249        let start = self.start.to_point(buffer);
7250        let end = self.end.to_point(buffer);
7251        if self.reversed {
7252            end..start
7253        } else {
7254            start..end
7255        }
7256    }
7257
7258    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7259        let start = self.start.to_offset(buffer);
7260        let end = self.end.to_offset(buffer);
7261        if self.reversed {
7262            end..start
7263        } else {
7264            start..end
7265        }
7266    }
7267
7268    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7269        let start = self
7270            .start
7271            .to_point(&map.buffer_snapshot)
7272            .to_display_point(map);
7273        let end = self
7274            .end
7275            .to_point(&map.buffer_snapshot)
7276            .to_display_point(map);
7277        if self.reversed {
7278            end..start
7279        } else {
7280            start..end
7281        }
7282    }
7283
7284    fn spanned_rows(
7285        &self,
7286        include_end_if_at_line_start: bool,
7287        map: &DisplaySnapshot,
7288    ) -> Range<u32> {
7289        let start = self.start.to_point(&map.buffer_snapshot);
7290        let mut end = self.end.to_point(&map.buffer_snapshot);
7291        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7292            end.row -= 1;
7293        }
7294
7295        let buffer_start = map.prev_line_boundary(start).0;
7296        let buffer_end = map.next_line_boundary(end).0;
7297        buffer_start.row..buffer_end.row + 1
7298    }
7299}
7300
7301impl<T: InvalidationRegion> InvalidationStack<T> {
7302    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7303    where
7304        S: Clone + ToOffset,
7305    {
7306        while let Some(region) = self.last() {
7307            let all_selections_inside_invalidation_ranges =
7308                if selections.len() == region.ranges().len() {
7309                    selections
7310                        .iter()
7311                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7312                        .all(|(selection, invalidation_range)| {
7313                            let head = selection.head().to_offset(buffer);
7314                            invalidation_range.start <= head && invalidation_range.end >= head
7315                        })
7316                } else {
7317                    false
7318                };
7319
7320            if all_selections_inside_invalidation_ranges {
7321                break;
7322            } else {
7323                self.pop();
7324            }
7325        }
7326    }
7327}
7328
7329impl<T> Default for InvalidationStack<T> {
7330    fn default() -> Self {
7331        Self(Default::default())
7332    }
7333}
7334
7335impl<T> Deref for InvalidationStack<T> {
7336    type Target = Vec<T>;
7337
7338    fn deref(&self) -> &Self::Target {
7339        &self.0
7340    }
7341}
7342
7343impl<T> DerefMut for InvalidationStack<T> {
7344    fn deref_mut(&mut self) -> &mut Self::Target {
7345        &mut self.0
7346    }
7347}
7348
7349impl InvalidationRegion for SnippetState {
7350    fn ranges(&self) -> &[Range<Anchor>] {
7351        &self.ranges[self.active_index]
7352    }
7353}
7354
7355impl Deref for EditorStyle {
7356    type Target = theme::Editor;
7357
7358    fn deref(&self) -> &Self::Target {
7359        &self.theme
7360    }
7361}
7362
7363pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7364    let mut highlighted_lines = Vec::new();
7365    for line in diagnostic.message.lines() {
7366        highlighted_lines.push(highlight_diagnostic_message(line));
7367    }
7368
7369    Arc::new(move |cx: &mut BlockContext| {
7370        let settings = cx.global::<Settings>();
7371        let theme = &settings.theme.editor;
7372        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7373        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7374        Flex::column()
7375            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7376                Label::new(
7377                    line.clone(),
7378                    style.message.clone().with_font_size(font_size),
7379                )
7380                .with_highlights(highlights.clone())
7381                .contained()
7382                .with_margin_left(cx.anchor_x)
7383                .boxed()
7384            }))
7385            .aligned()
7386            .left()
7387            .boxed()
7388    })
7389}
7390
7391pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
7392    let mut message_without_backticks = String::new();
7393    let mut prev_offset = 0;
7394    let mut inside_block = false;
7395    let mut highlights = Vec::new();
7396    for (match_ix, (offset, _)) in message
7397        .match_indices('`')
7398        .chain([(message.len(), "")])
7399        .enumerate()
7400    {
7401        message_without_backticks.push_str(&message[prev_offset..offset]);
7402        if inside_block {
7403            highlights.extend(prev_offset - match_ix..offset - match_ix);
7404        }
7405
7406        inside_block = !inside_block;
7407        prev_offset = offset + 1;
7408    }
7409
7410    (message_without_backticks, highlights)
7411}
7412
7413pub fn diagnostic_style(
7414    severity: DiagnosticSeverity,
7415    valid: bool,
7416    theme: &theme::Editor,
7417) -> DiagnosticStyle {
7418    match (severity, valid) {
7419        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7420        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7421        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7422        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7423        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7424        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7425        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7426        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7427        _ => theme.invalid_hint_diagnostic.clone(),
7428    }
7429}
7430
7431pub fn combine_syntax_and_fuzzy_match_highlights(
7432    text: &str,
7433    default_style: HighlightStyle,
7434    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7435    match_indices: &[usize],
7436) -> Vec<(Range<usize>, HighlightStyle)> {
7437    let mut result = Vec::new();
7438    let mut match_indices = match_indices.iter().copied().peekable();
7439
7440    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7441    {
7442        syntax_highlight.weight = None;
7443
7444        // Add highlights for any fuzzy match characters before the next
7445        // syntax highlight range.
7446        while let Some(&match_index) = match_indices.peek() {
7447            if match_index >= range.start {
7448                break;
7449            }
7450            match_indices.next();
7451            let end_index = char_ix_after(match_index, text);
7452            let mut match_style = default_style;
7453            match_style.weight = Some(fonts::Weight::BOLD);
7454            result.push((match_index..end_index, match_style));
7455        }
7456
7457        if range.start == usize::MAX {
7458            break;
7459        }
7460
7461        // Add highlights for any fuzzy match characters within the
7462        // syntax highlight range.
7463        let mut offset = range.start;
7464        while let Some(&match_index) = match_indices.peek() {
7465            if match_index >= range.end {
7466                break;
7467            }
7468
7469            match_indices.next();
7470            if match_index > offset {
7471                result.push((offset..match_index, syntax_highlight));
7472            }
7473
7474            let mut end_index = char_ix_after(match_index, text);
7475            while let Some(&next_match_index) = match_indices.peek() {
7476                if next_match_index == end_index && next_match_index < range.end {
7477                    end_index = char_ix_after(next_match_index, text);
7478                    match_indices.next();
7479                } else {
7480                    break;
7481                }
7482            }
7483
7484            let mut match_style = syntax_highlight;
7485            match_style.weight = Some(fonts::Weight::BOLD);
7486            result.push((match_index..end_index, match_style));
7487            offset = end_index;
7488        }
7489
7490        if offset < range.end {
7491            result.push((offset..range.end, syntax_highlight));
7492        }
7493    }
7494
7495    fn char_ix_after(ix: usize, text: &str) -> usize {
7496        ix + text[ix..].chars().next().unwrap().len_utf8()
7497    }
7498
7499    result
7500}
7501
7502pub fn styled_runs_for_code_label<'a>(
7503    label: &'a CodeLabel,
7504    syntax_theme: &'a theme::SyntaxTheme,
7505) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7506    let fade_out = HighlightStyle {
7507        fade_out: Some(0.35),
7508        ..Default::default()
7509    };
7510
7511    let mut prev_end = label.filter_range.end;
7512    label
7513        .runs
7514        .iter()
7515        .enumerate()
7516        .flat_map(move |(ix, (range, highlight_id))| {
7517            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7518                style
7519            } else {
7520                return Default::default();
7521            };
7522            let mut muted_style = style;
7523            muted_style.highlight(fade_out);
7524
7525            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7526            if range.start >= label.filter_range.end {
7527                if range.start > prev_end {
7528                    runs.push((prev_end..range.start, fade_out));
7529                }
7530                runs.push((range.clone(), muted_style));
7531            } else if range.end <= label.filter_range.end {
7532                runs.push((range.clone(), style));
7533            } else {
7534                runs.push((range.start..label.filter_range.end, style));
7535                runs.push((label.filter_range.end..range.end, muted_style));
7536            }
7537            prev_end = cmp::max(prev_end, range.end);
7538
7539            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7540                runs.push((prev_end..label.text.len(), fade_out));
7541            }
7542
7543            runs
7544        })
7545}
7546
7547pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7548    let mut index = 0;
7549    let mut codepoints = text.char_indices().peekable();
7550
7551    std::iter::from_fn(move || {
7552        let start_index = index;
7553        while let Some((new_index, codepoint)) = codepoints.next() {
7554            index = new_index + codepoint.len_utf8();
7555            let current_upper = codepoint.is_uppercase();
7556            let next_upper = codepoints
7557                .peek()
7558                .map(|(_, c)| c.is_uppercase())
7559                .unwrap_or(false);
7560
7561            if !current_upper && next_upper {
7562                return Some(&text[start_index..index]);
7563            }
7564        }
7565
7566        index = text.len();
7567        if start_index < text.len() {
7568            return Some(&text[start_index..]);
7569        }
7570        None
7571    })
7572    .flat_map(|word| word.split_inclusive('_'))
7573}
7574
7575trait RangeToAnchorExt {
7576    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7577}
7578
7579impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7580    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7581        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7582    }
7583}