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