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