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