editor.rs

   1mod blink_manager;
   2pub mod display_map;
   3mod editor_settings;
   4mod element;
   5
   6mod git;
   7mod highlight_matching_bracket;
   8mod hover_popover;
   9pub mod items;
  10mod link_go_to_definition;
  11mod mouse_context_menu;
  12pub mod movement;
  13mod multi_buffer;
  14mod persistence;
  15pub mod scroll;
  16pub mod selections_collection;
  17
  18#[cfg(test)]
  19mod editor_tests;
  20#[cfg(any(test, feature = "test-support"))]
  21pub mod test;
  22
  23use ::git::diff::DiffHunk;
  24use aho_corasick::AhoCorasick;
  25use anyhow::{anyhow, Result};
  26use blink_manager::BlinkManager;
  27use client::{ClickhouseEvent, TelemetrySettings};
  28use clock::ReplicaId;
  29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  30use copilot::Copilot;
  31pub use display_map::DisplayPoint;
  32use display_map::*;
  33pub use editor_settings::EditorSettings;
  34pub use element::*;
  35use futures::FutureExt;
  36use fuzzy::{StringMatch, StringMatchCandidate};
  37use gpui::{
  38    actions,
  39    color::Color,
  40    elements::*,
  41    executor,
  42    fonts::{self, HighlightStyle, TextStyle},
  43    geometry::vector::Vector2F,
  44    impl_actions,
  45    keymap_matcher::KeymapContext,
  46    platform::{CursorStyle, MouseButton},
  47    serde_json::{self, json},
  48    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  49    ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
  50};
  51use highlight_matching_bracket::refresh_matching_bracket_highlights;
  52use hover_popover::{hide_hover, HoverState};
  53pub use items::MAX_TAB_TITLE_LEN;
  54use itertools::Itertools;
  55pub use language::{char_kind, CharKind};
  56use language::{
  57    language_settings::{self, all_language_settings},
  58    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  59    Diagnostic, DiagnosticSeverity, File, IndentKind, IndentSize, Language, OffsetRangeExt,
  60    OffsetUtf16, Point, Selection, SelectionGoal, TransactionId,
  61};
  62use link_go_to_definition::{
  63    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  64};
  65pub use multi_buffer::{
  66    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  67    ToPoint,
  68};
  69use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  70use ordered_float::OrderedFloat;
  71use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  72use scroll::{
  73    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  74};
  75use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  76use serde::{Deserialize, Serialize};
  77use settings::SettingsStore;
  78use smallvec::SmallVec;
  79use snippet::Snippet;
  80use std::{
  81    any::TypeId,
  82    borrow::Cow,
  83    cmp::{self, Ordering, Reverse},
  84    mem,
  85    num::NonZeroU32,
  86    ops::{Deref, DerefMut, Range},
  87    path::Path,
  88    sync::Arc,
  89    time::{Duration, Instant},
  90};
  91pub use sum_tree::Bias;
  92use theme::{DiagnosticStyle, Theme, ThemeSettings};
  93use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  94use workspace::{ItemNavHistory, ViewId, Workspace};
  95
  96use crate::git::diff_hunk_to_display;
  97
  98const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  99const MAX_LINE_LEN: usize = 1024;
 100const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 101const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 102const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 103
 104pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 105
 106#[derive(Clone, Deserialize, PartialEq, Default)]
 107pub struct SelectNext {
 108    #[serde(default)]
 109    pub replace_newest: bool,
 110}
 111
 112#[derive(Clone, Deserialize, PartialEq)]
 113pub struct SelectToBeginningOfLine {
 114    #[serde(default)]
 115    stop_at_soft_wraps: bool,
 116}
 117
 118#[derive(Clone, Default, Deserialize, PartialEq)]
 119pub struct MovePageUp {
 120    #[serde(default)]
 121    center_cursor: bool,
 122}
 123
 124#[derive(Clone, Default, Deserialize, PartialEq)]
 125pub struct MovePageDown {
 126    #[serde(default)]
 127    center_cursor: bool,
 128}
 129
 130#[derive(Clone, Deserialize, PartialEq)]
 131pub struct SelectToEndOfLine {
 132    #[serde(default)]
 133    stop_at_soft_wraps: bool,
 134}
 135
 136#[derive(Clone, Deserialize, PartialEq)]
 137pub struct ToggleCodeActions {
 138    #[serde(default)]
 139    pub deployed_from_indicator: bool,
 140}
 141
 142#[derive(Clone, Default, Deserialize, PartialEq)]
 143pub struct ConfirmCompletion {
 144    #[serde(default)]
 145    pub item_ix: Option<usize>,
 146}
 147
 148#[derive(Clone, Default, Deserialize, PartialEq)]
 149pub struct ConfirmCodeAction {
 150    #[serde(default)]
 151    pub item_ix: Option<usize>,
 152}
 153
 154#[derive(Clone, Default, Deserialize, PartialEq)]
 155pub struct ToggleComments {
 156    #[serde(default)]
 157    pub advance_downwards: bool,
 158}
 159
 160#[derive(Clone, Default, Deserialize, PartialEq)]
 161pub struct FoldAt {
 162    pub buffer_row: u32,
 163}
 164
 165#[derive(Clone, Default, Deserialize, PartialEq)]
 166pub struct UnfoldAt {
 167    pub buffer_row: u32,
 168}
 169
 170#[derive(Clone, Default, Deserialize, PartialEq)]
 171pub struct GutterHover {
 172    pub hovered: bool,
 173}
 174
 175actions!(
 176    editor,
 177    [
 178        Cancel,
 179        Backspace,
 180        Delete,
 181        Newline,
 182        NewlineAbove,
 183        NewlineBelow,
 184        GoToDiagnostic,
 185        GoToPrevDiagnostic,
 186        GoToHunk,
 187        GoToPrevHunk,
 188        Indent,
 189        Outdent,
 190        DeleteLine,
 191        DeleteToPreviousWordStart,
 192        DeleteToPreviousSubwordStart,
 193        DeleteToNextWordEnd,
 194        DeleteToNextSubwordEnd,
 195        DeleteToBeginningOfLine,
 196        DeleteToEndOfLine,
 197        CutToEndOfLine,
 198        DuplicateLine,
 199        MoveLineUp,
 200        MoveLineDown,
 201        Transpose,
 202        Cut,
 203        Copy,
 204        Paste,
 205        Undo,
 206        Redo,
 207        MoveUp,
 208        PageUp,
 209        MoveDown,
 210        PageDown,
 211        MoveLeft,
 212        MoveRight,
 213        MoveToPreviousWordStart,
 214        MoveToPreviousSubwordStart,
 215        MoveToNextWordEnd,
 216        MoveToNextSubwordEnd,
 217        MoveToBeginningOfLine,
 218        MoveToEndOfLine,
 219        MoveToBeginning,
 220        MoveToEnd,
 221        SelectUp,
 222        SelectDown,
 223        SelectLeft,
 224        SelectRight,
 225        SelectToPreviousWordStart,
 226        SelectToPreviousSubwordStart,
 227        SelectToNextWordEnd,
 228        SelectToNextSubwordEnd,
 229        SelectToBeginning,
 230        SelectToEnd,
 231        SelectAll,
 232        SelectLine,
 233        SplitSelectionIntoLines,
 234        AddSelectionAbove,
 235        AddSelectionBelow,
 236        Tab,
 237        TabPrev,
 238        ShowCharacterPalette,
 239        SelectLargerSyntaxNode,
 240        SelectSmallerSyntaxNode,
 241        GoToDefinition,
 242        GoToTypeDefinition,
 243        MoveToEnclosingBracket,
 244        UndoSelection,
 245        RedoSelection,
 246        FindAllReferences,
 247        Rename,
 248        ConfirmRename,
 249        Fold,
 250        UnfoldLines,
 251        FoldSelectedRanges,
 252        ShowCompletions,
 253        OpenExcerpts,
 254        RestartLanguageServer,
 255        Hover,
 256        Format,
 257        ToggleSoftWrap,
 258        RevealInFinder,
 259        CopyPath,
 260        CopyRelativePath,
 261        CopyHighlightJson
 262    ]
 263);
 264
 265impl_actions!(
 266    editor,
 267    [
 268        SelectNext,
 269        SelectToBeginningOfLine,
 270        SelectToEndOfLine,
 271        ToggleCodeActions,
 272        MovePageUp,
 273        MovePageDown,
 274        ConfirmCompletion,
 275        ConfirmCodeAction,
 276        ToggleComments,
 277        FoldAt,
 278        UnfoldAt,
 279        GutterHover
 280    ]
 281);
 282
 283enum DocumentHighlightRead {}
 284enum DocumentHighlightWrite {}
 285enum InputComposition {}
 286
 287#[derive(Copy, Clone, PartialEq, Eq)]
 288pub enum Direction {
 289    Prev,
 290    Next,
 291}
 292
 293pub fn init_settings(cx: &mut AppContext) {
 294    settings::register::<EditorSettings>(cx);
 295}
 296
 297pub fn init(cx: &mut AppContext) {
 298    init_settings(cx);
 299    cx.add_action(Editor::new_file);
 300    cx.add_action(Editor::cancel);
 301    cx.add_action(Editor::newline);
 302    cx.add_action(Editor::newline_above);
 303    cx.add_action(Editor::newline_below);
 304    cx.add_action(Editor::backspace);
 305    cx.add_action(Editor::delete);
 306    cx.add_action(Editor::tab);
 307    cx.add_action(Editor::tab_prev);
 308    cx.add_action(Editor::indent);
 309    cx.add_action(Editor::outdent);
 310    cx.add_action(Editor::delete_line);
 311    cx.add_action(Editor::delete_to_previous_word_start);
 312    cx.add_action(Editor::delete_to_previous_subword_start);
 313    cx.add_action(Editor::delete_to_next_word_end);
 314    cx.add_action(Editor::delete_to_next_subword_end);
 315    cx.add_action(Editor::delete_to_beginning_of_line);
 316    cx.add_action(Editor::delete_to_end_of_line);
 317    cx.add_action(Editor::cut_to_end_of_line);
 318    cx.add_action(Editor::duplicate_line);
 319    cx.add_action(Editor::move_line_up);
 320    cx.add_action(Editor::move_line_down);
 321    cx.add_action(Editor::transpose);
 322    cx.add_action(Editor::cut);
 323    cx.add_action(Editor::copy);
 324    cx.add_action(Editor::paste);
 325    cx.add_action(Editor::undo);
 326    cx.add_action(Editor::redo);
 327    cx.add_action(Editor::move_up);
 328    cx.add_action(Editor::move_page_up);
 329    cx.add_action(Editor::move_down);
 330    cx.add_action(Editor::move_page_down);
 331    cx.add_action(Editor::next_screen);
 332    cx.add_action(Editor::move_left);
 333    cx.add_action(Editor::move_right);
 334    cx.add_action(Editor::move_to_previous_word_start);
 335    cx.add_action(Editor::move_to_previous_subword_start);
 336    cx.add_action(Editor::move_to_next_word_end);
 337    cx.add_action(Editor::move_to_next_subword_end);
 338    cx.add_action(Editor::move_to_beginning_of_line);
 339    cx.add_action(Editor::move_to_end_of_line);
 340    cx.add_action(Editor::move_to_beginning);
 341    cx.add_action(Editor::move_to_end);
 342    cx.add_action(Editor::select_up);
 343    cx.add_action(Editor::select_down);
 344    cx.add_action(Editor::select_left);
 345    cx.add_action(Editor::select_right);
 346    cx.add_action(Editor::select_to_previous_word_start);
 347    cx.add_action(Editor::select_to_previous_subword_start);
 348    cx.add_action(Editor::select_to_next_word_end);
 349    cx.add_action(Editor::select_to_next_subword_end);
 350    cx.add_action(Editor::select_to_beginning_of_line);
 351    cx.add_action(Editor::select_to_end_of_line);
 352    cx.add_action(Editor::select_to_beginning);
 353    cx.add_action(Editor::select_to_end);
 354    cx.add_action(Editor::select_all);
 355    cx.add_action(Editor::select_line);
 356    cx.add_action(Editor::split_selection_into_lines);
 357    cx.add_action(Editor::add_selection_above);
 358    cx.add_action(Editor::add_selection_below);
 359    cx.add_action(Editor::select_next);
 360    cx.add_action(Editor::toggle_comments);
 361    cx.add_action(Editor::select_larger_syntax_node);
 362    cx.add_action(Editor::select_smaller_syntax_node);
 363    cx.add_action(Editor::move_to_enclosing_bracket);
 364    cx.add_action(Editor::undo_selection);
 365    cx.add_action(Editor::redo_selection);
 366    cx.add_action(Editor::go_to_diagnostic);
 367    cx.add_action(Editor::go_to_prev_diagnostic);
 368    cx.add_action(Editor::go_to_hunk);
 369    cx.add_action(Editor::go_to_prev_hunk);
 370    cx.add_action(Editor::go_to_definition);
 371    cx.add_action(Editor::go_to_type_definition);
 372    cx.add_action(Editor::fold);
 373    cx.add_action(Editor::fold_at);
 374    cx.add_action(Editor::unfold_lines);
 375    cx.add_action(Editor::unfold_at);
 376    cx.add_action(Editor::gutter_hover);
 377    cx.add_action(Editor::fold_selected_ranges);
 378    cx.add_action(Editor::show_completions);
 379    cx.add_action(Editor::toggle_code_actions);
 380    cx.add_action(Editor::open_excerpts);
 381    cx.add_action(Editor::toggle_soft_wrap);
 382    cx.add_action(Editor::reveal_in_finder);
 383    cx.add_action(Editor::copy_path);
 384    cx.add_action(Editor::copy_relative_path);
 385    cx.add_action(Editor::copy_highlight_json);
 386    cx.add_async_action(Editor::format);
 387    cx.add_action(Editor::restart_language_server);
 388    cx.add_action(Editor::show_character_palette);
 389    cx.add_async_action(Editor::confirm_completion);
 390    cx.add_async_action(Editor::confirm_code_action);
 391    cx.add_async_action(Editor::rename);
 392    cx.add_async_action(Editor::confirm_rename);
 393    cx.add_async_action(Editor::find_all_references);
 394    cx.add_action(Editor::next_copilot_suggestion);
 395    cx.add_action(Editor::previous_copilot_suggestion);
 396    cx.add_action(Editor::copilot_suggest);
 397
 398    hover_popover::init(cx);
 399    scroll::actions::init(cx);
 400
 401    workspace::register_project_item::<Editor>(cx);
 402    workspace::register_followable_item::<Editor>(cx);
 403    workspace::register_deserializable_item::<Editor>(cx);
 404}
 405
 406trait InvalidationRegion {
 407    fn ranges(&self) -> &[Range<Anchor>];
 408}
 409
 410#[derive(Clone, Debug, PartialEq)]
 411pub enum SelectPhase {
 412    Begin {
 413        position: DisplayPoint,
 414        add: bool,
 415        click_count: usize,
 416    },
 417    BeginColumnar {
 418        position: DisplayPoint,
 419        goal_column: u32,
 420    },
 421    Extend {
 422        position: DisplayPoint,
 423        click_count: usize,
 424    },
 425    Update {
 426        position: DisplayPoint,
 427        goal_column: u32,
 428        scroll_position: Vector2F,
 429    },
 430    End,
 431}
 432
 433#[derive(Clone, Debug)]
 434pub enum SelectMode {
 435    Character,
 436    Word(Range<Anchor>),
 437    Line(Range<Anchor>),
 438    All,
 439}
 440
 441#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 442pub enum EditorMode {
 443    SingleLine,
 444    AutoHeight { max_lines: usize },
 445    Full,
 446}
 447
 448#[derive(Clone, Debug)]
 449pub enum SoftWrap {
 450    None,
 451    EditorWidth,
 452    Column(u32),
 453}
 454
 455#[derive(Clone)]
 456pub struct EditorStyle {
 457    pub text: TextStyle,
 458    pub placeholder_text: Option<TextStyle>,
 459    pub theme: theme::Editor,
 460    pub theme_id: usize,
 461}
 462
 463type CompletionId = usize;
 464
 465type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 466type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 467
 468pub struct Editor {
 469    handle: WeakViewHandle<Self>,
 470    buffer: ModelHandle<MultiBuffer>,
 471    display_map: ModelHandle<DisplayMap>,
 472    pub selections: SelectionsCollection,
 473    pub scroll_manager: ScrollManager,
 474    columnar_selection_tail: Option<Anchor>,
 475    add_selections_state: Option<AddSelectionsState>,
 476    select_next_state: Option<SelectNextState>,
 477    selection_history: SelectionHistory,
 478    autoclose_regions: Vec<AutocloseRegion>,
 479    snippet_stack: InvalidationStack<SnippetState>,
 480    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 481    ime_transaction: Option<TransactionId>,
 482    active_diagnostics: Option<ActiveDiagnosticGroup>,
 483    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 484    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 485    override_text_style: Option<Box<OverrideTextStyle>>,
 486    project: Option<ModelHandle<Project>>,
 487    focused: bool,
 488    blink_manager: ModelHandle<BlinkManager>,
 489    show_local_selections: bool,
 490    mode: EditorMode,
 491    placeholder_text: Option<Arc<str>>,
 492    highlighted_rows: Option<Range<u32>>,
 493    #[allow(clippy::type_complexity)]
 494    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 495    nav_history: Option<ItemNavHistory>,
 496    context_menu: Option<ContextMenu>,
 497    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 498    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 499    next_completion_id: CompletionId,
 500    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 501    code_actions_task: Option<Task<()>>,
 502    document_highlights_task: Option<Task<()>>,
 503    pending_rename: Option<RenameState>,
 504    searchable: bool,
 505    cursor_shape: CursorShape,
 506    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 507    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 508    input_enabled: bool,
 509    read_only: bool,
 510    leader_replica_id: Option<u16>,
 511    remote_id: Option<ViewId>,
 512    hover_state: HoverState,
 513    gutter_hovered: bool,
 514    link_go_to_definition_state: LinkGoToDefinitionState,
 515    copilot_state: CopilotState,
 516    _subscriptions: Vec<Subscription>,
 517}
 518
 519pub struct EditorSnapshot {
 520    pub mode: EditorMode,
 521    pub display_snapshot: DisplaySnapshot,
 522    pub placeholder_text: Option<Arc<str>>,
 523    is_focused: bool,
 524    scroll_anchor: ScrollAnchor,
 525    ongoing_scroll: OngoingScroll,
 526}
 527
 528impl EditorSnapshot {
 529    fn has_scrollbar_info(&self, is_singleton: bool) -> bool {
 530        is_singleton && self.buffer_snapshot.has_git_diffs()
 531    }
 532}
 533
 534#[derive(Clone, Debug)]
 535struct SelectionHistoryEntry {
 536    selections: Arc<[Selection<Anchor>]>,
 537    select_next_state: Option<SelectNextState>,
 538    add_selections_state: Option<AddSelectionsState>,
 539}
 540
 541enum SelectionHistoryMode {
 542    Normal,
 543    Undoing,
 544    Redoing,
 545}
 546
 547impl Default for SelectionHistoryMode {
 548    fn default() -> Self {
 549        Self::Normal
 550    }
 551}
 552
 553#[derive(Default)]
 554struct SelectionHistory {
 555    #[allow(clippy::type_complexity)]
 556    selections_by_transaction:
 557        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 558    mode: SelectionHistoryMode,
 559    undo_stack: VecDeque<SelectionHistoryEntry>,
 560    redo_stack: VecDeque<SelectionHistoryEntry>,
 561}
 562
 563impl SelectionHistory {
 564    fn insert_transaction(
 565        &mut self,
 566        transaction_id: TransactionId,
 567        selections: Arc<[Selection<Anchor>]>,
 568    ) {
 569        self.selections_by_transaction
 570            .insert(transaction_id, (selections, None));
 571    }
 572
 573    #[allow(clippy::type_complexity)]
 574    fn transaction(
 575        &self,
 576        transaction_id: TransactionId,
 577    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 578        self.selections_by_transaction.get(&transaction_id)
 579    }
 580
 581    #[allow(clippy::type_complexity)]
 582    fn transaction_mut(
 583        &mut self,
 584        transaction_id: TransactionId,
 585    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 586        self.selections_by_transaction.get_mut(&transaction_id)
 587    }
 588
 589    fn push(&mut self, entry: SelectionHistoryEntry) {
 590        if !entry.selections.is_empty() {
 591            match self.mode {
 592                SelectionHistoryMode::Normal => {
 593                    self.push_undo(entry);
 594                    self.redo_stack.clear();
 595                }
 596                SelectionHistoryMode::Undoing => self.push_redo(entry),
 597                SelectionHistoryMode::Redoing => self.push_undo(entry),
 598            }
 599        }
 600    }
 601
 602    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 603        if self
 604            .undo_stack
 605            .back()
 606            .map_or(true, |e| e.selections != entry.selections)
 607        {
 608            self.undo_stack.push_back(entry);
 609            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 610                self.undo_stack.pop_front();
 611            }
 612        }
 613    }
 614
 615    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 616        if self
 617            .redo_stack
 618            .back()
 619            .map_or(true, |e| e.selections != entry.selections)
 620        {
 621            self.redo_stack.push_back(entry);
 622            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 623                self.redo_stack.pop_front();
 624            }
 625        }
 626    }
 627}
 628
 629#[derive(Clone, Debug)]
 630struct AddSelectionsState {
 631    above: bool,
 632    stack: Vec<usize>,
 633}
 634
 635#[derive(Clone, Debug)]
 636struct SelectNextState {
 637    query: AhoCorasick,
 638    wordwise: bool,
 639    done: bool,
 640}
 641
 642#[derive(Debug)]
 643struct AutocloseRegion {
 644    selection_id: usize,
 645    range: Range<Anchor>,
 646    pair: BracketPair,
 647}
 648
 649#[derive(Debug)]
 650struct SnippetState {
 651    ranges: Vec<Vec<Range<Anchor>>>,
 652    active_index: usize,
 653}
 654
 655pub struct RenameState {
 656    pub range: Range<Anchor>,
 657    pub old_name: Arc<str>,
 658    pub editor: ViewHandle<Editor>,
 659    block_id: BlockId,
 660}
 661
 662struct InvalidationStack<T>(Vec<T>);
 663
 664enum ContextMenu {
 665    Completions(CompletionsMenu),
 666    CodeActions(CodeActionsMenu),
 667}
 668
 669impl ContextMenu {
 670    fn select_first(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 671        if self.visible() {
 672            match self {
 673                ContextMenu::Completions(menu) => menu.select_first(cx),
 674                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 675            }
 676            true
 677        } else {
 678            false
 679        }
 680    }
 681
 682    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 683        if self.visible() {
 684            match self {
 685                ContextMenu::Completions(menu) => menu.select_prev(cx),
 686                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 687            }
 688            true
 689        } else {
 690            false
 691        }
 692    }
 693
 694    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 695        if self.visible() {
 696            match self {
 697                ContextMenu::Completions(menu) => menu.select_next(cx),
 698                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 699            }
 700            true
 701        } else {
 702            false
 703        }
 704    }
 705
 706    fn select_last(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 707        if self.visible() {
 708            match self {
 709                ContextMenu::Completions(menu) => menu.select_last(cx),
 710                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 711            }
 712            true
 713        } else {
 714            false
 715        }
 716    }
 717
 718    fn visible(&self) -> bool {
 719        match self {
 720            ContextMenu::Completions(menu) => menu.visible(),
 721            ContextMenu::CodeActions(menu) => menu.visible(),
 722        }
 723    }
 724
 725    fn render(
 726        &self,
 727        cursor_position: DisplayPoint,
 728        style: EditorStyle,
 729        cx: &mut ViewContext<Editor>,
 730    ) -> (DisplayPoint, AnyElement<Editor>) {
 731        match self {
 732            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 733            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 734        }
 735    }
 736}
 737
 738struct CompletionsMenu {
 739    id: CompletionId,
 740    initial_position: Anchor,
 741    buffer: ModelHandle<Buffer>,
 742    completions: Arc<[Completion]>,
 743    match_candidates: Vec<StringMatchCandidate>,
 744    matches: Arc<[StringMatch]>,
 745    selected_item: usize,
 746    list: UniformListState,
 747}
 748
 749impl CompletionsMenu {
 750    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 751        self.selected_item = 0;
 752        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 753        cx.notify();
 754    }
 755
 756    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 757        if self.selected_item > 0 {
 758            self.selected_item -= 1;
 759            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 760        }
 761        cx.notify();
 762    }
 763
 764    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 765        if self.selected_item + 1 < self.matches.len() {
 766            self.selected_item += 1;
 767            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 768        }
 769        cx.notify();
 770    }
 771
 772    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 773        self.selected_item = self.matches.len() - 1;
 774        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 775        cx.notify();
 776    }
 777
 778    fn visible(&self) -> bool {
 779        !self.matches.is_empty()
 780    }
 781
 782    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
 783        enum CompletionTag {}
 784
 785        let completions = self.completions.clone();
 786        let matches = self.matches.clone();
 787        let selected_item = self.selected_item;
 788        let container_style = style.autocomplete.container;
 789        UniformList::new(
 790            self.list.clone(),
 791            matches.len(),
 792            cx,
 793            move |_, range, items, cx| {
 794                let start_ix = range.start;
 795                for (ix, mat) in matches[range].iter().enumerate() {
 796                    let completion = &completions[mat.candidate_id];
 797                    let item_ix = start_ix + ix;
 798                    items.push(
 799                        MouseEventHandler::<CompletionTag, _>::new(
 800                            mat.candidate_id,
 801                            cx,
 802                            |state, _| {
 803                                let item_style = if item_ix == selected_item {
 804                                    style.autocomplete.selected_item
 805                                } else if state.hovered() {
 806                                    style.autocomplete.hovered_item
 807                                } else {
 808                                    style.autocomplete.item
 809                                };
 810
 811                                Text::new(completion.label.text.clone(), style.text.clone())
 812                                    .with_soft_wrap(false)
 813                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 814                                        &completion.label.text,
 815                                        style.text.color.into(),
 816                                        styled_runs_for_code_label(
 817                                            &completion.label,
 818                                            &style.syntax,
 819                                        ),
 820                                        &mat.positions,
 821                                    ))
 822                                    .contained()
 823                                    .with_style(item_style)
 824                            },
 825                        )
 826                        .with_cursor_style(CursorStyle::PointingHand)
 827                        .on_down(MouseButton::Left, move |_, this, cx| {
 828                            this.confirm_completion(
 829                                &ConfirmCompletion {
 830                                    item_ix: Some(item_ix),
 831                                },
 832                                cx,
 833                            );
 834                        })
 835                        .into_any(),
 836                    );
 837                }
 838            },
 839        )
 840        .with_width_from_item(
 841            self.matches
 842                .iter()
 843                .enumerate()
 844                .max_by_key(|(_, mat)| {
 845                    self.completions[mat.candidate_id]
 846                        .label
 847                        .text
 848                        .chars()
 849                        .count()
 850                })
 851                .map(|(ix, _)| ix),
 852        )
 853        .contained()
 854        .with_style(container_style)
 855        .into_any()
 856    }
 857
 858    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 859        let mut matches = if let Some(query) = query {
 860            fuzzy::match_strings(
 861                &self.match_candidates,
 862                query,
 863                query.chars().any(|c| c.is_uppercase()),
 864                100,
 865                &Default::default(),
 866                executor,
 867            )
 868            .await
 869        } else {
 870            self.match_candidates
 871                .iter()
 872                .enumerate()
 873                .map(|(candidate_id, candidate)| StringMatch {
 874                    candidate_id,
 875                    score: Default::default(),
 876                    positions: Default::default(),
 877                    string: candidate.string.clone(),
 878                })
 879                .collect()
 880        };
 881
 882        //Remove all candidates where the query's start does not match the start of any word in the candidate
 883        if let Some(query) = query {
 884            if let Some(query_start) = query.chars().next() {
 885                matches.retain(|string_match| {
 886                    split_words(&string_match.string).any(|word| {
 887                        //Check that the first codepoint of the word as lowercase matches the first
 888                        //codepoint of the query as lowercase
 889                        word.chars()
 890                            .flat_map(|codepoint| codepoint.to_lowercase())
 891                            .zip(query_start.to_lowercase())
 892                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 893                    })
 894                });
 895            }
 896        }
 897
 898        matches.sort_unstable_by_key(|mat| {
 899            let completion = &self.completions[mat.candidate_id];
 900            (
 901                completion.lsp_completion.sort_text.as_ref(),
 902                Reverse(OrderedFloat(mat.score)),
 903                completion.sort_key(),
 904            )
 905        });
 906
 907        for mat in &mut matches {
 908            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 909            for position in &mut mat.positions {
 910                *position += filter_start;
 911            }
 912        }
 913
 914        self.matches = matches.into();
 915    }
 916}
 917
 918#[derive(Clone)]
 919struct CodeActionsMenu {
 920    actions: Arc<[CodeAction]>,
 921    buffer: ModelHandle<Buffer>,
 922    selected_item: usize,
 923    list: UniformListState,
 924    deployed_from_indicator: bool,
 925}
 926
 927impl CodeActionsMenu {
 928    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 929        self.selected_item = 0;
 930        cx.notify()
 931    }
 932
 933    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 934        if self.selected_item > 0 {
 935            self.selected_item -= 1;
 936            cx.notify()
 937        }
 938    }
 939
 940    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 941        if self.selected_item + 1 < self.actions.len() {
 942            self.selected_item += 1;
 943            cx.notify()
 944        }
 945    }
 946
 947    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 948        self.selected_item = self.actions.len() - 1;
 949        cx.notify()
 950    }
 951
 952    fn visible(&self) -> bool {
 953        !self.actions.is_empty()
 954    }
 955
 956    fn render(
 957        &self,
 958        mut cursor_position: DisplayPoint,
 959        style: EditorStyle,
 960        cx: &mut ViewContext<Editor>,
 961    ) -> (DisplayPoint, AnyElement<Editor>) {
 962        enum ActionTag {}
 963
 964        let container_style = style.autocomplete.container;
 965        let actions = self.actions.clone();
 966        let selected_item = self.selected_item;
 967        let element = UniformList::new(
 968            self.list.clone(),
 969            actions.len(),
 970            cx,
 971            move |_, range, items, cx| {
 972                let start_ix = range.start;
 973                for (ix, action) in actions[range].iter().enumerate() {
 974                    let item_ix = start_ix + ix;
 975                    items.push(
 976                        MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| {
 977                            let item_style = if item_ix == selected_item {
 978                                style.autocomplete.selected_item
 979                            } else if state.hovered() {
 980                                style.autocomplete.hovered_item
 981                            } else {
 982                                style.autocomplete.item
 983                            };
 984
 985                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 986                                .with_soft_wrap(false)
 987                                .contained()
 988                                .with_style(item_style)
 989                        })
 990                        .with_cursor_style(CursorStyle::PointingHand)
 991                        .on_down(MouseButton::Left, move |_, this, cx| {
 992                            let workspace = this
 993                                .workspace
 994                                .as_ref()
 995                                .and_then(|(workspace, _)| workspace.upgrade(cx));
 996                            cx.window_context().defer(move |cx| {
 997                                if let Some(workspace) = workspace {
 998                                    workspace.update(cx, |workspace, cx| {
 999                                        if let Some(task) = Editor::confirm_code_action(
1000                                            workspace,
1001                                            &Default::default(),
1002                                            cx,
1003                                        ) {
1004                                            task.detach_and_log_err(cx);
1005                                        }
1006                                    });
1007                                }
1008                            });
1009                        })
1010                        .into_any(),
1011                    );
1012                }
1013            },
1014        )
1015        .with_width_from_item(
1016            self.actions
1017                .iter()
1018                .enumerate()
1019                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1020                .map(|(ix, _)| ix),
1021        )
1022        .contained()
1023        .with_style(container_style)
1024        .into_any();
1025
1026        if self.deployed_from_indicator {
1027            *cursor_position.column_mut() = 0;
1028        }
1029
1030        (cursor_position, element)
1031    }
1032}
1033
1034pub struct CopilotState {
1035    excerpt_id: Option<ExcerptId>,
1036    pending_refresh: Task<Option<()>>,
1037    pending_cycling_refresh: Task<Option<()>>,
1038    cycled: bool,
1039    completions: Vec<copilot::Completion>,
1040    active_completion_index: usize,
1041}
1042
1043impl Default for CopilotState {
1044    fn default() -> Self {
1045        Self {
1046            excerpt_id: None,
1047            pending_cycling_refresh: Task::ready(Some(())),
1048            pending_refresh: Task::ready(Some(())),
1049            completions: Default::default(),
1050            active_completion_index: 0,
1051            cycled: false,
1052        }
1053    }
1054}
1055
1056impl CopilotState {
1057    fn active_completion(&self) -> Option<&copilot::Completion> {
1058        self.completions.get(self.active_completion_index)
1059    }
1060
1061    fn text_for_active_completion(
1062        &self,
1063        cursor: Anchor,
1064        buffer: &MultiBufferSnapshot,
1065    ) -> Option<&str> {
1066        use language::ToOffset as _;
1067
1068        let completion = self.active_completion()?;
1069        let excerpt_id = self.excerpt_id?;
1070        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1071        if excerpt_id != cursor.excerpt_id
1072            || !completion.range.start.is_valid(completion_buffer)
1073            || !completion.range.end.is_valid(completion_buffer)
1074        {
1075            return None;
1076        }
1077
1078        let mut completion_range = completion.range.to_offset(&completion_buffer);
1079        let prefix_len = Self::common_prefix(
1080            completion_buffer.chars_for_range(completion_range.clone()),
1081            completion.text.chars(),
1082        );
1083        completion_range.start += prefix_len;
1084        let suffix_len = Self::common_prefix(
1085            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1086            completion.text[prefix_len..].chars().rev(),
1087        );
1088        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1089
1090        if completion_range.is_empty()
1091            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1092        {
1093            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1094        } else {
1095            None
1096        }
1097    }
1098
1099    fn cycle_completions(&mut self, direction: Direction) {
1100        match direction {
1101            Direction::Prev => {
1102                self.active_completion_index = if self.active_completion_index == 0 {
1103                    self.completions.len().saturating_sub(1)
1104                } else {
1105                    self.active_completion_index - 1
1106                };
1107            }
1108            Direction::Next => {
1109                if self.completions.len() == 0 {
1110                    self.active_completion_index = 0
1111                } else {
1112                    self.active_completion_index =
1113                        (self.active_completion_index + 1) % self.completions.len();
1114                }
1115            }
1116        }
1117    }
1118
1119    fn push_completion(&mut self, new_completion: copilot::Completion) {
1120        for completion in &self.completions {
1121            if completion.text == new_completion.text && completion.range == new_completion.range {
1122                return;
1123            }
1124        }
1125        self.completions.push(new_completion);
1126    }
1127
1128    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1129        a.zip(b)
1130            .take_while(|(a, b)| a == b)
1131            .map(|(a, _)| a.len_utf8())
1132            .sum()
1133    }
1134}
1135
1136#[derive(Debug)]
1137struct ActiveDiagnosticGroup {
1138    primary_range: Range<Anchor>,
1139    primary_message: String,
1140    blocks: HashMap<BlockId, Diagnostic>,
1141    is_valid: bool,
1142}
1143
1144#[derive(Serialize, Deserialize)]
1145pub struct ClipboardSelection {
1146    pub len: usize,
1147    pub is_entire_line: bool,
1148    pub first_line_indent: u32,
1149}
1150
1151#[derive(Debug)]
1152pub struct NavigationData {
1153    cursor_anchor: Anchor,
1154    cursor_position: Point,
1155    scroll_anchor: ScrollAnchor,
1156    scroll_top_row: u32,
1157}
1158
1159pub struct EditorCreated(pub ViewHandle<Editor>);
1160
1161enum GotoDefinitionKind {
1162    Symbol,
1163    Type,
1164}
1165
1166impl Editor {
1167    pub fn single_line(
1168        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1169        cx: &mut ViewContext<Self>,
1170    ) -> Self {
1171        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1172        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1173        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1174    }
1175
1176    pub fn multi_line(
1177        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1178        cx: &mut ViewContext<Self>,
1179    ) -> Self {
1180        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1181        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1182        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1183    }
1184
1185    pub fn auto_height(
1186        max_lines: usize,
1187        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1188        cx: &mut ViewContext<Self>,
1189    ) -> Self {
1190        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1191        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1192        Self::new(
1193            EditorMode::AutoHeight { max_lines },
1194            buffer,
1195            None,
1196            field_editor_style,
1197            cx,
1198        )
1199    }
1200
1201    pub fn for_buffer(
1202        buffer: ModelHandle<Buffer>,
1203        project: Option<ModelHandle<Project>>,
1204        cx: &mut ViewContext<Self>,
1205    ) -> Self {
1206        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1207        Self::new(EditorMode::Full, buffer, project, None, cx)
1208    }
1209
1210    pub fn for_multibuffer(
1211        buffer: ModelHandle<MultiBuffer>,
1212        project: Option<ModelHandle<Project>>,
1213        cx: &mut ViewContext<Self>,
1214    ) -> Self {
1215        Self::new(EditorMode::Full, buffer, project, None, cx)
1216    }
1217
1218    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1219        let mut clone = Self::new(
1220            self.mode,
1221            self.buffer.clone(),
1222            self.project.clone(),
1223            self.get_field_editor_theme.clone(),
1224            cx,
1225        );
1226        self.display_map.update(cx, |display_map, cx| {
1227            let snapshot = display_map.snapshot(cx);
1228            clone.display_map.update(cx, |display_map, cx| {
1229                display_map.set_state(&snapshot, cx);
1230            });
1231        });
1232        clone.selections.clone_state(&self.selections);
1233        clone.scroll_manager.clone_state(&self.scroll_manager);
1234        clone.searchable = self.searchable;
1235        clone
1236    }
1237
1238    fn new(
1239        mode: EditorMode,
1240        buffer: ModelHandle<MultiBuffer>,
1241        project: Option<ModelHandle<Project>>,
1242        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1243        cx: &mut ViewContext<Self>,
1244    ) -> Self {
1245        let editor_view_id = cx.view_id();
1246        let display_map = cx.add_model(|cx| {
1247            let settings = settings::get::<ThemeSettings>(cx);
1248            let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
1249            DisplayMap::new(
1250                buffer.clone(),
1251                style.text.font_id,
1252                style.text.font_size,
1253                None,
1254                2,
1255                1,
1256                cx,
1257            )
1258        });
1259
1260        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1261
1262        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1263
1264        let soft_wrap_mode_override =
1265            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1266
1267        let mut project_subscription = None;
1268        if mode == EditorMode::Full && buffer.read(cx).is_singleton() {
1269            if let Some(project) = project.as_ref() {
1270                project_subscription = Some(cx.observe(project, |_, _, cx| {
1271                    cx.emit(Event::TitleChanged);
1272                }))
1273            }
1274        }
1275
1276        let mut this = Self {
1277            handle: cx.weak_handle(),
1278            buffer: buffer.clone(),
1279            display_map: display_map.clone(),
1280            selections,
1281            scroll_manager: ScrollManager::new(),
1282            columnar_selection_tail: None,
1283            add_selections_state: None,
1284            select_next_state: None,
1285            selection_history: Default::default(),
1286            autoclose_regions: Default::default(),
1287            snippet_stack: Default::default(),
1288            select_larger_syntax_node_stack: Vec::new(),
1289            ime_transaction: Default::default(),
1290            active_diagnostics: None,
1291            soft_wrap_mode_override,
1292            get_field_editor_theme,
1293            project,
1294            focused: false,
1295            blink_manager: blink_manager.clone(),
1296            show_local_selections: true,
1297            mode,
1298            placeholder_text: None,
1299            highlighted_rows: None,
1300            background_highlights: Default::default(),
1301            nav_history: None,
1302            context_menu: None,
1303            mouse_context_menu: cx
1304                .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
1305            completion_tasks: Default::default(),
1306            next_completion_id: 0,
1307            available_code_actions: Default::default(),
1308            code_actions_task: Default::default(),
1309            document_highlights_task: Default::default(),
1310            pending_rename: Default::default(),
1311            searchable: true,
1312            override_text_style: None,
1313            cursor_shape: Default::default(),
1314            workspace: None,
1315            keymap_context_layers: Default::default(),
1316            input_enabled: true,
1317            read_only: false,
1318            leader_replica_id: None,
1319            remote_id: None,
1320            hover_state: Default::default(),
1321            link_go_to_definition_state: Default::default(),
1322            copilot_state: Default::default(),
1323            gutter_hovered: false,
1324            _subscriptions: vec![
1325                cx.observe(&buffer, Self::on_buffer_changed),
1326                cx.subscribe(&buffer, Self::on_buffer_event),
1327                cx.observe(&display_map, Self::on_display_map_changed),
1328                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1329                cx.observe_global::<SettingsStore, _>(Self::settings_changed),
1330            ],
1331        };
1332
1333        if let Some(project_subscription) = project_subscription {
1334            this._subscriptions.push(project_subscription);
1335        }
1336
1337        this.end_selection(cx);
1338        this.scroll_manager.show_scrollbar(cx);
1339
1340        let editor_created_event = EditorCreated(cx.handle());
1341        cx.emit_global(editor_created_event);
1342
1343        if mode == EditorMode::Full {
1344            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1345            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1346        }
1347
1348        this.report_editor_event("open", None, cx);
1349        this
1350    }
1351
1352    pub fn new_file(
1353        workspace: &mut Workspace,
1354        _: &workspace::NewFile,
1355        cx: &mut ViewContext<Workspace>,
1356    ) {
1357        let project = workspace.project().clone();
1358        if project.read(cx).is_remote() {
1359            cx.propagate_action();
1360        } else if let Some(buffer) = project
1361            .update(cx, |project, cx| project.create_buffer("", None, cx))
1362            .log_err()
1363        {
1364            workspace.add_item(
1365                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1366                cx,
1367            );
1368        }
1369    }
1370
1371    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1372        self.buffer.read(cx).replica_id()
1373    }
1374
1375    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1376        self.leader_replica_id
1377    }
1378
1379    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1380        &self.buffer
1381    }
1382
1383    fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
1384        self.workspace.as_ref()?.0.upgrade(cx)
1385    }
1386
1387    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1388        self.buffer().read(cx).title(cx)
1389    }
1390
1391    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1392        EditorSnapshot {
1393            mode: self.mode,
1394            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1395            scroll_anchor: self.scroll_manager.anchor(),
1396            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1397            placeholder_text: self.placeholder_text.clone(),
1398            is_focused: self
1399                .handle
1400                .upgrade(cx)
1401                .map_or(false, |handle| handle.is_focused(cx)),
1402        }
1403    }
1404
1405    pub fn language_at<'a, T: ToOffset>(
1406        &self,
1407        point: T,
1408        cx: &'a AppContext,
1409    ) -> Option<Arc<Language>> {
1410        self.buffer.read(cx).language_at(point, cx)
1411    }
1412
1413    pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
1414        self.buffer.read(cx).read(cx).file_at(point).cloned()
1415    }
1416
1417    pub fn active_excerpt(
1418        &self,
1419        cx: &AppContext,
1420    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1421        self.buffer
1422            .read(cx)
1423            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1424    }
1425
1426    fn style(&self, cx: &AppContext) -> EditorStyle {
1427        build_style(
1428            settings::get::<ThemeSettings>(cx),
1429            self.get_field_editor_theme.as_deref(),
1430            self.override_text_style.as_deref(),
1431            cx,
1432        )
1433    }
1434
1435    pub fn mode(&self) -> EditorMode {
1436        self.mode
1437    }
1438
1439    pub fn set_placeholder_text(
1440        &mut self,
1441        placeholder_text: impl Into<Arc<str>>,
1442        cx: &mut ViewContext<Self>,
1443    ) {
1444        self.placeholder_text = Some(placeholder_text.into());
1445        cx.notify();
1446    }
1447
1448    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1449        self.cursor_shape = cursor_shape;
1450        cx.notify();
1451    }
1452
1453    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1454        if self.display_map.read(cx).clip_at_line_ends != clip {
1455            self.display_map
1456                .update(cx, |map, _| map.clip_at_line_ends = clip);
1457        }
1458    }
1459
1460    pub fn set_keymap_context_layer<Tag: 'static>(
1461        &mut self,
1462        context: KeymapContext,
1463        cx: &mut ViewContext<Self>,
1464    ) {
1465        self.keymap_context_layers
1466            .insert(TypeId::of::<Tag>(), context);
1467        cx.notify();
1468    }
1469
1470    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1471        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1472        cx.notify();
1473    }
1474
1475    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1476        self.input_enabled = input_enabled;
1477    }
1478
1479    pub fn set_read_only(&mut self, read_only: bool) {
1480        self.read_only = read_only;
1481    }
1482
1483    fn selections_did_change(
1484        &mut self,
1485        local: bool,
1486        old_cursor_position: &Anchor,
1487        cx: &mut ViewContext<Self>,
1488    ) {
1489        if self.focused && self.leader_replica_id.is_none() {
1490            self.buffer.update(cx, |buffer, cx| {
1491                buffer.set_active_selections(
1492                    &self.selections.disjoint_anchors(),
1493                    self.selections.line_mode,
1494                    self.cursor_shape,
1495                    cx,
1496                )
1497            });
1498        }
1499
1500        let display_map = self
1501            .display_map
1502            .update(cx, |display_map, cx| display_map.snapshot(cx));
1503        let buffer = &display_map.buffer_snapshot;
1504        self.add_selections_state = None;
1505        self.select_next_state = None;
1506        self.select_larger_syntax_node_stack.clear();
1507        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1508        self.snippet_stack
1509            .invalidate(&self.selections.disjoint_anchors(), buffer);
1510        self.take_rename(false, cx);
1511
1512        let new_cursor_position = self.selections.newest_anchor().head();
1513
1514        self.push_to_nav_history(
1515            old_cursor_position.clone(),
1516            Some(new_cursor_position.to_point(buffer)),
1517            cx,
1518        );
1519
1520        if local {
1521            let new_cursor_position = self.selections.newest_anchor().head();
1522            let completion_menu = match self.context_menu.as_mut() {
1523                Some(ContextMenu::Completions(menu)) => Some(menu),
1524                _ => {
1525                    self.context_menu.take();
1526                    None
1527                }
1528            };
1529
1530            if let Some(completion_menu) = completion_menu {
1531                let cursor_position = new_cursor_position.to_offset(buffer);
1532                let (word_range, kind) =
1533                    buffer.surrounding_word(completion_menu.initial_position.clone());
1534                if kind == Some(CharKind::Word)
1535                    && word_range.to_inclusive().contains(&cursor_position)
1536                {
1537                    let query = Self::completion_query(buffer, cursor_position);
1538                    cx.background()
1539                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1540                    self.show_completions(&ShowCompletions, cx);
1541                } else {
1542                    self.hide_context_menu(cx);
1543                }
1544            }
1545
1546            hide_hover(self, cx);
1547
1548            if old_cursor_position.to_display_point(&display_map).row()
1549                != new_cursor_position.to_display_point(&display_map).row()
1550            {
1551                self.available_code_actions.take();
1552            }
1553            self.refresh_code_actions(cx);
1554            self.refresh_document_highlights(cx);
1555            refresh_matching_bracket_highlights(self, cx);
1556            self.discard_copilot_suggestion(cx);
1557        }
1558
1559        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1560        cx.emit(Event::SelectionsChanged { local });
1561        cx.notify();
1562    }
1563
1564    pub fn change_selections<R>(
1565        &mut self,
1566        autoscroll: Option<Autoscroll>,
1567        cx: &mut ViewContext<Self>,
1568        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1569    ) -> R {
1570        let old_cursor_position = self.selections.newest_anchor().head();
1571        self.push_to_selection_history();
1572
1573        let (changed, result) = self.selections.change_with(cx, change);
1574
1575        if changed {
1576            if let Some(autoscroll) = autoscroll {
1577                self.request_autoscroll(autoscroll, cx);
1578            }
1579            self.selections_did_change(true, &old_cursor_position, cx);
1580        }
1581
1582        result
1583    }
1584
1585    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1586    where
1587        I: IntoIterator<Item = (Range<S>, T)>,
1588        S: ToOffset,
1589        T: Into<Arc<str>>,
1590    {
1591        if self.read_only {
1592            return;
1593        }
1594
1595        self.buffer
1596            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1597    }
1598
1599    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1600    where
1601        I: IntoIterator<Item = (Range<S>, T)>,
1602        S: ToOffset,
1603        T: Into<Arc<str>>,
1604    {
1605        if self.read_only {
1606            return;
1607        }
1608
1609        self.buffer.update(cx, |buffer, cx| {
1610            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
1611        });
1612    }
1613
1614    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
1615        self.hide_context_menu(cx);
1616
1617        match phase {
1618            SelectPhase::Begin {
1619                position,
1620                add,
1621                click_count,
1622            } => self.begin_selection(position, add, click_count, cx),
1623            SelectPhase::BeginColumnar {
1624                position,
1625                goal_column,
1626            } => self.begin_columnar_selection(position, goal_column, cx),
1627            SelectPhase::Extend {
1628                position,
1629                click_count,
1630            } => self.extend_selection(position, click_count, cx),
1631            SelectPhase::Update {
1632                position,
1633                goal_column,
1634                scroll_position,
1635            } => self.update_selection(position, goal_column, scroll_position, cx),
1636            SelectPhase::End => self.end_selection(cx),
1637        }
1638    }
1639
1640    fn extend_selection(
1641        &mut self,
1642        position: DisplayPoint,
1643        click_count: usize,
1644        cx: &mut ViewContext<Self>,
1645    ) {
1646        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1647        let tail = self.selections.newest::<usize>(cx).tail();
1648        self.begin_selection(position, false, click_count, cx);
1649
1650        let position = position.to_offset(&display_map, Bias::Left);
1651        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1652
1653        let mut pending_selection = self
1654            .selections
1655            .pending_anchor()
1656            .expect("extend_selection not called with pending selection");
1657        if position >= tail {
1658            pending_selection.start = tail_anchor;
1659        } else {
1660            pending_selection.end = tail_anchor;
1661            pending_selection.reversed = true;
1662        }
1663
1664        let mut pending_mode = self.selections.pending_mode().unwrap();
1665        match &mut pending_mode {
1666            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1667            _ => {}
1668        }
1669
1670        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1671            s.set_pending(pending_selection, pending_mode)
1672        });
1673    }
1674
1675    fn begin_selection(
1676        &mut self,
1677        position: DisplayPoint,
1678        add: bool,
1679        click_count: usize,
1680        cx: &mut ViewContext<Self>,
1681    ) {
1682        if !self.focused {
1683            cx.focus_self();
1684        }
1685
1686        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1687        let buffer = &display_map.buffer_snapshot;
1688        let newest_selection = self.selections.newest_anchor().clone();
1689        let position = display_map.clip_point(position, Bias::Left);
1690
1691        let start;
1692        let end;
1693        let mode;
1694        let auto_scroll;
1695        match click_count {
1696            1 => {
1697                start = buffer.anchor_before(position.to_point(&display_map));
1698                end = start.clone();
1699                mode = SelectMode::Character;
1700                auto_scroll = true;
1701            }
1702            2 => {
1703                let range = movement::surrounding_word(&display_map, position);
1704                start = buffer.anchor_before(range.start.to_point(&display_map));
1705                end = buffer.anchor_before(range.end.to_point(&display_map));
1706                mode = SelectMode::Word(start.clone()..end.clone());
1707                auto_scroll = true;
1708            }
1709            3 => {
1710                let position = display_map
1711                    .clip_point(position, Bias::Left)
1712                    .to_point(&display_map);
1713                let line_start = display_map.prev_line_boundary(position).0;
1714                let next_line_start = buffer.clip_point(
1715                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1716                    Bias::Left,
1717                );
1718                start = buffer.anchor_before(line_start);
1719                end = buffer.anchor_before(next_line_start);
1720                mode = SelectMode::Line(start.clone()..end.clone());
1721                auto_scroll = true;
1722            }
1723            _ => {
1724                start = buffer.anchor_before(0);
1725                end = buffer.anchor_before(buffer.len());
1726                mode = SelectMode::All;
1727                auto_scroll = false;
1728            }
1729        }
1730
1731        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
1732            if !add {
1733                s.clear_disjoint();
1734            } else if click_count > 1 {
1735                s.delete(newest_selection.id)
1736            }
1737
1738            s.set_pending_anchor_range(start..end, mode);
1739        });
1740    }
1741
1742    fn begin_columnar_selection(
1743        &mut self,
1744        position: DisplayPoint,
1745        goal_column: u32,
1746        cx: &mut ViewContext<Self>,
1747    ) {
1748        if !self.focused {
1749            cx.focus_self();
1750        }
1751
1752        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1753        let tail = self.selections.newest::<Point>(cx).tail();
1754        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1755
1756        self.select_columns(
1757            tail.to_display_point(&display_map),
1758            position,
1759            goal_column,
1760            &display_map,
1761            cx,
1762        );
1763    }
1764
1765    fn update_selection(
1766        &mut self,
1767        position: DisplayPoint,
1768        goal_column: u32,
1769        scroll_position: Vector2F,
1770        cx: &mut ViewContext<Self>,
1771    ) {
1772        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1773
1774        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1775            let tail = tail.to_display_point(&display_map);
1776            self.select_columns(tail, position, goal_column, &display_map, cx);
1777        } else if let Some(mut pending) = self.selections.pending_anchor() {
1778            let buffer = self.buffer.read(cx).snapshot(cx);
1779            let head;
1780            let tail;
1781            let mode = self.selections.pending_mode().unwrap();
1782            match &mode {
1783                SelectMode::Character => {
1784                    head = position.to_point(&display_map);
1785                    tail = pending.tail().to_point(&buffer);
1786                }
1787                SelectMode::Word(original_range) => {
1788                    let original_display_range = original_range.start.to_display_point(&display_map)
1789                        ..original_range.end.to_display_point(&display_map);
1790                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1791                        ..original_display_range.end.to_point(&display_map);
1792                    if movement::is_inside_word(&display_map, position)
1793                        || original_display_range.contains(&position)
1794                    {
1795                        let word_range = movement::surrounding_word(&display_map, position);
1796                        if word_range.start < original_display_range.start {
1797                            head = word_range.start.to_point(&display_map);
1798                        } else {
1799                            head = word_range.end.to_point(&display_map);
1800                        }
1801                    } else {
1802                        head = position.to_point(&display_map);
1803                    }
1804
1805                    if head <= original_buffer_range.start {
1806                        tail = original_buffer_range.end;
1807                    } else {
1808                        tail = original_buffer_range.start;
1809                    }
1810                }
1811                SelectMode::Line(original_range) => {
1812                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1813
1814                    let position = display_map
1815                        .clip_point(position, Bias::Left)
1816                        .to_point(&display_map);
1817                    let line_start = display_map.prev_line_boundary(position).0;
1818                    let next_line_start = buffer.clip_point(
1819                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1820                        Bias::Left,
1821                    );
1822
1823                    if line_start < original_range.start {
1824                        head = line_start
1825                    } else {
1826                        head = next_line_start
1827                    }
1828
1829                    if head <= original_range.start {
1830                        tail = original_range.end;
1831                    } else {
1832                        tail = original_range.start;
1833                    }
1834                }
1835                SelectMode::All => {
1836                    return;
1837                }
1838            };
1839
1840            if head < tail {
1841                pending.start = buffer.anchor_before(head);
1842                pending.end = buffer.anchor_before(tail);
1843                pending.reversed = true;
1844            } else {
1845                pending.start = buffer.anchor_before(tail);
1846                pending.end = buffer.anchor_before(head);
1847                pending.reversed = false;
1848            }
1849
1850            self.change_selections(None, cx, |s| {
1851                s.set_pending(pending, mode);
1852            });
1853        } else {
1854            log::error!("update_selection dispatched with no pending selection");
1855            return;
1856        }
1857
1858        self.set_scroll_position(scroll_position, cx);
1859        cx.notify();
1860    }
1861
1862    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1863        self.columnar_selection_tail.take();
1864        if self.selections.pending_anchor().is_some() {
1865            let selections = self.selections.all::<usize>(cx);
1866            self.change_selections(None, cx, |s| {
1867                s.select(selections);
1868                s.clear_pending();
1869            });
1870        }
1871    }
1872
1873    fn select_columns(
1874        &mut self,
1875        tail: DisplayPoint,
1876        head: DisplayPoint,
1877        goal_column: u32,
1878        display_map: &DisplaySnapshot,
1879        cx: &mut ViewContext<Self>,
1880    ) {
1881        let start_row = cmp::min(tail.row(), head.row());
1882        let end_row = cmp::max(tail.row(), head.row());
1883        let start_column = cmp::min(tail.column(), goal_column);
1884        let end_column = cmp::max(tail.column(), goal_column);
1885        let reversed = start_column < tail.column();
1886
1887        let selection_ranges = (start_row..=end_row)
1888            .filter_map(|row| {
1889                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1890                    let start = display_map
1891                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1892                        .to_point(display_map);
1893                    let end = display_map
1894                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1895                        .to_point(display_map);
1896                    if reversed {
1897                        Some(end..start)
1898                    } else {
1899                        Some(start..end)
1900                    }
1901                } else {
1902                    None
1903                }
1904            })
1905            .collect::<Vec<_>>();
1906
1907        self.change_selections(None, cx, |s| {
1908            s.select_ranges(selection_ranges);
1909        });
1910        cx.notify();
1911    }
1912
1913    pub fn has_pending_nonempty_selection(&self) -> bool {
1914        let pending_nonempty_selection = match self.selections.pending_anchor() {
1915            Some(Selection { start, end, .. }) => start != end,
1916            None => false,
1917        };
1918        pending_nonempty_selection || self.columnar_selection_tail.is_some()
1919    }
1920
1921    pub fn has_pending_selection(&self) -> bool {
1922        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1923    }
1924
1925    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1926        if self.take_rename(false, cx).is_some() {
1927            return;
1928        }
1929
1930        if hide_hover(self, cx) {
1931            return;
1932        }
1933
1934        if self.hide_context_menu(cx).is_some() {
1935            return;
1936        }
1937
1938        if self.discard_copilot_suggestion(cx) {
1939            return;
1940        }
1941
1942        if self.snippet_stack.pop().is_some() {
1943            return;
1944        }
1945
1946        if self.mode == EditorMode::Full {
1947            if self.active_diagnostics.is_some() {
1948                self.dismiss_diagnostics(cx);
1949                return;
1950            }
1951
1952            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
1953                return;
1954            }
1955        }
1956
1957        cx.propagate_action();
1958    }
1959
1960    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1961        let text: Arc<str> = text.into();
1962
1963        if self.read_only {
1964            return;
1965        }
1966        if !self.input_enabled {
1967            cx.emit(Event::InputIgnored { text });
1968            return;
1969        }
1970
1971        let selections = self.selections.all_adjusted(cx);
1972        let mut edits = Vec::new();
1973        let mut new_selections = Vec::with_capacity(selections.len());
1974        let mut new_autoclose_regions = Vec::new();
1975        let snapshot = self.buffer.read(cx).read(cx);
1976
1977        for (selection, autoclose_region) in
1978            self.selections_with_autoclose_regions(selections, &snapshot)
1979        {
1980            if let Some(language) = snapshot.language_scope_at(selection.head()) {
1981                // Determine if the inserted text matches the opening or closing
1982                // bracket of any of this language's bracket pairs.
1983                let mut bracket_pair = None;
1984                let mut is_bracket_pair_start = false;
1985                for (pair, enabled) in language.brackets() {
1986                    if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
1987                        bracket_pair = Some(pair.clone());
1988                        is_bracket_pair_start = true;
1989                        break;
1990                    } else if pair.end.as_str() == text.as_ref() {
1991                        bracket_pair = Some(pair.clone());
1992                        break;
1993                    }
1994                }
1995
1996                if let Some(bracket_pair) = bracket_pair {
1997                    if selection.is_empty() {
1998                        if is_bracket_pair_start {
1999                            let prefix_len = bracket_pair.start.len() - text.len();
2000
2001                            // If the inserted text is a suffix of an opening bracket and the
2002                            // selection is preceded by the rest of the opening bracket, then
2003                            // insert the closing bracket.
2004                            let following_text_allows_autoclose = snapshot
2005                                .chars_at(selection.start)
2006                                .next()
2007                                .map_or(true, |c| language.should_autoclose_before(c));
2008                            let preceding_text_matches_prefix = prefix_len == 0
2009                                || (selection.start.column >= (prefix_len as u32)
2010                                    && snapshot.contains_str_at(
2011                                        Point::new(
2012                                            selection.start.row,
2013                                            selection.start.column - (prefix_len as u32),
2014                                        ),
2015                                        &bracket_pair.start[..prefix_len],
2016                                    ));
2017                            if following_text_allows_autoclose && preceding_text_matches_prefix {
2018                                let anchor = snapshot.anchor_before(selection.end);
2019                                new_selections.push((selection.map(|_| anchor), text.len()));
2020                                new_autoclose_regions.push((
2021                                    anchor,
2022                                    text.len(),
2023                                    selection.id,
2024                                    bracket_pair.clone(),
2025                                ));
2026                                edits.push((
2027                                    selection.range(),
2028                                    format!("{}{}", text, bracket_pair.end).into(),
2029                                ));
2030                                continue;
2031                            }
2032                        }
2033
2034                        if let Some(region) = autoclose_region {
2035                            // If the selection is followed by an auto-inserted closing bracket,
2036                            // then don't insert that closing bracket again; just move the selection
2037                            // past the closing bracket.
2038                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2039                                && text.as_ref() == region.pair.end.as_str();
2040                            if should_skip {
2041                                let anchor = snapshot.anchor_after(selection.end);
2042                                new_selections
2043                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2044                                continue;
2045                            }
2046                        }
2047                    }
2048                    // If an opening bracket is 1 character long and is typed while
2049                    // text is selected, then surround that text with the bracket pair.
2050                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2051                        edits.push((selection.start..selection.start, text.clone()));
2052                        edits.push((
2053                            selection.end..selection.end,
2054                            bracket_pair.end.as_str().into(),
2055                        ));
2056                        new_selections.push((
2057                            Selection {
2058                                id: selection.id,
2059                                start: snapshot.anchor_after(selection.start),
2060                                end: snapshot.anchor_before(selection.end),
2061                                reversed: selection.reversed,
2062                                goal: selection.goal,
2063                            },
2064                            0,
2065                        ));
2066                        continue;
2067                    }
2068                }
2069            }
2070
2071            // If not handling any auto-close operation, then just replace the selected
2072            // text with the given input and move the selection to the end of the
2073            // newly inserted text.
2074            let anchor = snapshot.anchor_after(selection.end);
2075            new_selections.push((selection.map(|_| anchor), 0));
2076            edits.push((selection.start..selection.end, text.clone()));
2077        }
2078
2079        drop(snapshot);
2080        self.transact(cx, |this, cx| {
2081            this.buffer.update(cx, |buffer, cx| {
2082                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
2083            });
2084
2085            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2086            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2087            let snapshot = this.buffer.read(cx).read(cx);
2088            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2089                .zip(new_selection_deltas)
2090                .map(|(selection, delta)| selection.map(|e| e + delta))
2091                .collect::<Vec<_>>();
2092
2093            let mut i = 0;
2094            for (position, delta, selection_id, pair) in new_autoclose_regions {
2095                let position = position.to_offset(&snapshot) + delta;
2096                let start = snapshot.anchor_before(position);
2097                let end = snapshot.anchor_after(position);
2098                while let Some(existing_state) = this.autoclose_regions.get(i) {
2099                    match existing_state.range.start.cmp(&start, &snapshot) {
2100                        Ordering::Less => i += 1,
2101                        Ordering::Greater => break,
2102                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2103                            Ordering::Less => i += 1,
2104                            Ordering::Equal => break,
2105                            Ordering::Greater => break,
2106                        },
2107                    }
2108                }
2109                this.autoclose_regions.insert(
2110                    i,
2111                    AutocloseRegion {
2112                        selection_id,
2113                        range: start..end,
2114                        pair,
2115                    },
2116                );
2117            }
2118
2119            drop(snapshot);
2120            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2121            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2122
2123            if had_active_copilot_suggestion {
2124                this.refresh_copilot_suggestions(true, cx);
2125                if !this.has_active_copilot_suggestion(cx) {
2126                    this.trigger_completion_on_input(&text, cx);
2127                }
2128            } else {
2129                this.trigger_completion_on_input(&text, cx);
2130                this.refresh_copilot_suggestions(true, cx);
2131            }
2132        });
2133    }
2134
2135    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2136        self.transact(cx, |this, cx| {
2137            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2138                let selections = this.selections.all::<usize>(cx);
2139
2140                let buffer = this.buffer.read(cx).snapshot(cx);
2141                selections
2142                    .iter()
2143                    .map(|selection| {
2144                        let start_point = selection.start.to_point(&buffer);
2145                        let mut indent = buffer.indent_size_for_line(start_point.row);
2146                        indent.len = cmp::min(indent.len, start_point.column);
2147                        let start = selection.start;
2148                        let end = selection.end;
2149
2150                        let mut insert_extra_newline = false;
2151                        if let Some(language) = buffer.language_scope_at(start) {
2152                            let leading_whitespace_len = buffer
2153                                .reversed_chars_at(start)
2154                                .take_while(|c| c.is_whitespace() && *c != '\n')
2155                                .map(|c| c.len_utf8())
2156                                .sum::<usize>();
2157
2158                            let trailing_whitespace_len = buffer
2159                                .chars_at(end)
2160                                .take_while(|c| c.is_whitespace() && *c != '\n')
2161                                .map(|c| c.len_utf8())
2162                                .sum::<usize>();
2163
2164                            insert_extra_newline = language.brackets().any(|(pair, enabled)| {
2165                                let pair_start = pair.start.trim_end();
2166                                let pair_end = pair.end.trim_start();
2167
2168                                enabled
2169                                    && pair.newline
2170                                    && buffer
2171                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
2172                                    && buffer.contains_str_at(
2173                                        (start - leading_whitespace_len)
2174                                            .saturating_sub(pair_start.len()),
2175                                        pair_start,
2176                                    )
2177                            });
2178                        }
2179
2180                        let mut new_text = String::with_capacity(1 + indent.len as usize);
2181                        new_text.push('\n');
2182                        new_text.extend(indent.chars());
2183                        if insert_extra_newline {
2184                            new_text = new_text.repeat(2);
2185                        }
2186
2187                        let anchor = buffer.anchor_after(end);
2188                        let new_selection = selection.map(|_| anchor);
2189                        (
2190                            (start..end, new_text),
2191                            (insert_extra_newline, new_selection),
2192                        )
2193                    })
2194                    .unzip()
2195            };
2196
2197            this.edit_with_autoindent(edits, cx);
2198            let buffer = this.buffer.read(cx).snapshot(cx);
2199            let new_selections = selection_fixup_info
2200                .into_iter()
2201                .map(|(extra_newline_inserted, new_selection)| {
2202                    let mut cursor = new_selection.end.to_point(&buffer);
2203                    if extra_newline_inserted {
2204                        cursor.row -= 1;
2205                        cursor.column = buffer.line_len(cursor.row);
2206                    }
2207                    new_selection.map(|_| cursor)
2208                })
2209                .collect();
2210
2211            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2212            this.refresh_copilot_suggestions(true, cx);
2213        });
2214    }
2215
2216    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2217        let buffer = self.buffer.read(cx);
2218        let snapshot = buffer.snapshot(cx);
2219
2220        let mut edits = Vec::new();
2221        let mut rows = Vec::new();
2222        let mut rows_inserted = 0;
2223
2224        for selection in self.selections.all_adjusted(cx) {
2225            let cursor = selection.head();
2226            let row = cursor.row;
2227
2228            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2229
2230            let newline = "\n".to_string();
2231            edits.push((start_of_line..start_of_line, newline));
2232
2233            rows.push(row + rows_inserted);
2234            rows_inserted += 1;
2235        }
2236
2237        self.transact(cx, |editor, cx| {
2238            editor.edit(edits, cx);
2239
2240            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2241                let mut index = 0;
2242                s.move_cursors_with(|map, _, _| {
2243                    let row = rows[index];
2244                    index += 1;
2245
2246                    let point = Point::new(row, 0);
2247                    let boundary = map.next_line_boundary(point).1;
2248                    let clipped = map.clip_point(boundary, Bias::Left);
2249
2250                    (clipped, SelectionGoal::None)
2251                });
2252            });
2253
2254            let mut indent_edits = Vec::new();
2255            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2256            for row in rows {
2257                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2258                for (row, indent) in indents {
2259                    if indent.len == 0 {
2260                        continue;
2261                    }
2262
2263                    let text = match indent.kind {
2264                        IndentKind::Space => " ".repeat(indent.len as usize),
2265                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2266                    };
2267                    let point = Point::new(row, 0);
2268                    indent_edits.push((point..point, text));
2269                }
2270            }
2271            editor.edit(indent_edits, cx);
2272        });
2273    }
2274
2275    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2276        let buffer = self.buffer.read(cx);
2277        let snapshot = buffer.snapshot(cx);
2278
2279        let mut edits = Vec::new();
2280        let mut rows = Vec::new();
2281        let mut rows_inserted = 0;
2282
2283        for selection in self.selections.all_adjusted(cx) {
2284            let cursor = selection.head();
2285            let row = cursor.row;
2286
2287            let point = Point::new(row + 1, 0);
2288            let start_of_line = snapshot.clip_point(point, Bias::Left);
2289
2290            let newline = "\n".to_string();
2291            edits.push((start_of_line..start_of_line, newline));
2292
2293            rows_inserted += 1;
2294            rows.push(row + rows_inserted);
2295        }
2296
2297        self.transact(cx, |editor, cx| {
2298            editor.edit(edits, cx);
2299
2300            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2301                let mut index = 0;
2302                s.move_cursors_with(|map, _, _| {
2303                    let row = rows[index];
2304                    index += 1;
2305
2306                    let point = Point::new(row, 0);
2307                    let boundary = map.next_line_boundary(point).1;
2308                    let clipped = map.clip_point(boundary, Bias::Left);
2309
2310                    (clipped, SelectionGoal::None)
2311                });
2312            });
2313
2314            let mut indent_edits = Vec::new();
2315            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2316            for row in rows {
2317                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2318                for (row, indent) in indents {
2319                    if indent.len == 0 {
2320                        continue;
2321                    }
2322
2323                    let text = match indent.kind {
2324                        IndentKind::Space => " ".repeat(indent.len as usize),
2325                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2326                    };
2327                    let point = Point::new(row, 0);
2328                    indent_edits.push((point..point, text));
2329                }
2330            }
2331            editor.edit(indent_edits, cx);
2332        });
2333    }
2334
2335    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2336        self.insert_with_autoindent_mode(
2337            text,
2338            Some(AutoindentMode::Block {
2339                original_indent_columns: Vec::new(),
2340            }),
2341            cx,
2342        );
2343    }
2344
2345    fn insert_with_autoindent_mode(
2346        &mut self,
2347        text: &str,
2348        autoindent_mode: Option<AutoindentMode>,
2349        cx: &mut ViewContext<Self>,
2350    ) {
2351        if self.read_only {
2352            return;
2353        }
2354
2355        let text: Arc<str> = text.into();
2356        self.transact(cx, |this, cx| {
2357            let old_selections = this.selections.all_adjusted(cx);
2358            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2359                let anchors = {
2360                    let snapshot = buffer.read(cx);
2361                    old_selections
2362                        .iter()
2363                        .map(|s| {
2364                            let anchor = snapshot.anchor_after(s.end);
2365                            s.map(|_| anchor)
2366                        })
2367                        .collect::<Vec<_>>()
2368                };
2369                buffer.edit(
2370                    old_selections
2371                        .iter()
2372                        .map(|s| (s.start..s.end, text.clone())),
2373                    autoindent_mode,
2374                    cx,
2375                );
2376                anchors
2377            });
2378
2379            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2380                s.select_anchors(selection_anchors);
2381            })
2382        });
2383    }
2384
2385    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2386        if !settings::get::<EditorSettings>(cx).show_completions_on_input {
2387            return;
2388        }
2389
2390        let selection = self.selections.newest_anchor();
2391        if self
2392            .buffer
2393            .read(cx)
2394            .is_completion_trigger(selection.head(), text, cx)
2395        {
2396            self.show_completions(&ShowCompletions, cx);
2397        } else {
2398            self.hide_context_menu(cx);
2399        }
2400    }
2401
2402    /// If any empty selections is touching the start of its innermost containing autoclose
2403    /// region, expand it to select the brackets.
2404    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2405        let selections = self.selections.all::<usize>(cx);
2406        let buffer = self.buffer.read(cx).read(cx);
2407        let mut new_selections = Vec::new();
2408        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2409            if let (Some(region), true) = (region, selection.is_empty()) {
2410                let mut range = region.range.to_offset(&buffer);
2411                if selection.start == range.start {
2412                    if range.start >= region.pair.start.len() {
2413                        range.start -= region.pair.start.len();
2414                        if buffer.contains_str_at(range.start, &region.pair.start) {
2415                            if buffer.contains_str_at(range.end, &region.pair.end) {
2416                                range.end += region.pair.end.len();
2417                                selection.start = range.start;
2418                                selection.end = range.end;
2419                            }
2420                        }
2421                    }
2422                }
2423            }
2424            new_selections.push(selection);
2425        }
2426
2427        drop(buffer);
2428        self.change_selections(None, cx, |selections| selections.select(new_selections));
2429    }
2430
2431    /// Iterate the given selections, and for each one, find the smallest surrounding
2432    /// autoclose region. This uses the ordering of the selections and the autoclose
2433    /// regions to avoid repeated comparisons.
2434    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2435        &'a self,
2436        selections: impl IntoIterator<Item = Selection<D>>,
2437        buffer: &'a MultiBufferSnapshot,
2438    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2439        let mut i = 0;
2440        let mut regions = self.autoclose_regions.as_slice();
2441        selections.into_iter().map(move |selection| {
2442            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2443
2444            let mut enclosing = None;
2445            while let Some(pair_state) = regions.get(i) {
2446                if pair_state.range.end.to_offset(buffer) < range.start {
2447                    regions = &regions[i + 1..];
2448                    i = 0;
2449                } else if pair_state.range.start.to_offset(buffer) > range.end {
2450                    break;
2451                } else if pair_state.selection_id == selection.id {
2452                    enclosing = Some(pair_state);
2453                    i += 1;
2454                }
2455            }
2456
2457            (selection.clone(), enclosing)
2458        })
2459    }
2460
2461    /// Remove any autoclose regions that no longer contain their selection.
2462    fn invalidate_autoclose_regions(
2463        &mut self,
2464        mut selections: &[Selection<Anchor>],
2465        buffer: &MultiBufferSnapshot,
2466    ) {
2467        self.autoclose_regions.retain(|state| {
2468            let mut i = 0;
2469            while let Some(selection) = selections.get(i) {
2470                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2471                    selections = &selections[1..];
2472                    continue;
2473                }
2474                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2475                    break;
2476                }
2477                if selection.id == state.selection_id {
2478                    return true;
2479                } else {
2480                    i += 1;
2481                }
2482            }
2483            false
2484        });
2485    }
2486
2487    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2488        let offset = position.to_offset(buffer);
2489        let (word_range, kind) = buffer.surrounding_word(offset);
2490        if offset > word_range.start && kind == Some(CharKind::Word) {
2491            Some(
2492                buffer
2493                    .text_for_range(word_range.start..offset)
2494                    .collect::<String>(),
2495            )
2496        } else {
2497            None
2498        }
2499    }
2500
2501    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2502        if self.pending_rename.is_some() {
2503            return;
2504        }
2505
2506        let project = if let Some(project) = self.project.clone() {
2507            project
2508        } else {
2509            return;
2510        };
2511
2512        let position = self.selections.newest_anchor().head();
2513        let (buffer, buffer_position) = if let Some(output) = self
2514            .buffer
2515            .read(cx)
2516            .text_anchor_for_position(position.clone(), cx)
2517        {
2518            output
2519        } else {
2520            return;
2521        };
2522
2523        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2524        let completions = project.update(cx, |project, cx| {
2525            project.completions(&buffer, buffer_position, cx)
2526        });
2527
2528        let id = post_inc(&mut self.next_completion_id);
2529        let task = cx.spawn(|this, mut cx| {
2530            async move {
2531                let menu = if let Some(completions) = completions.await.log_err() {
2532                    let mut menu = CompletionsMenu {
2533                        id,
2534                        initial_position: position,
2535                        match_candidates: completions
2536                            .iter()
2537                            .enumerate()
2538                            .map(|(id, completion)| {
2539                                StringMatchCandidate::new(
2540                                    id,
2541                                    completion.label.text[completion.label.filter_range.clone()]
2542                                        .into(),
2543                                )
2544                            })
2545                            .collect(),
2546                        buffer,
2547                        completions: completions.into(),
2548                        matches: Vec::new().into(),
2549                        selected_item: 0,
2550                        list: Default::default(),
2551                    };
2552                    menu.filter(query.as_deref(), cx.background()).await;
2553                    if menu.matches.is_empty() {
2554                        None
2555                    } else {
2556                        Some(menu)
2557                    }
2558                } else {
2559                    None
2560                };
2561
2562                this.update(&mut cx, |this, cx| {
2563                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2564
2565                    match this.context_menu.as_ref() {
2566                        None => {}
2567                        Some(ContextMenu::Completions(prev_menu)) => {
2568                            if prev_menu.id > id {
2569                                return;
2570                            }
2571                        }
2572                        _ => return,
2573                    }
2574
2575                    if this.focused && menu.is_some() {
2576                        let menu = menu.unwrap();
2577                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2578                    } else if this.completion_tasks.is_empty() {
2579                        // If there are no more completion tasks and the last menu was
2580                        // empty, we should hide it. If it was already hidden, we should
2581                        // also show the copilot suggestion when available.
2582                        if this.hide_context_menu(cx).is_none() {
2583                            this.update_visible_copilot_suggestion(cx);
2584                        }
2585                    }
2586                })?;
2587
2588                Ok::<_, anyhow::Error>(())
2589            }
2590            .log_err()
2591        });
2592        self.completion_tasks.push((id, task));
2593    }
2594
2595    pub fn confirm_completion(
2596        &mut self,
2597        action: &ConfirmCompletion,
2598        cx: &mut ViewContext<Self>,
2599    ) -> Option<Task<Result<()>>> {
2600        use language::ToOffset as _;
2601
2602        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2603            menu
2604        } else {
2605            return None;
2606        };
2607
2608        let mat = completions_menu
2609            .matches
2610            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2611        let buffer_handle = completions_menu.buffer;
2612        let completion = completions_menu.completions.get(mat.candidate_id)?;
2613
2614        let snippet;
2615        let text;
2616        if completion.is_snippet() {
2617            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2618            text = snippet.as_ref().unwrap().text.clone();
2619        } else {
2620            snippet = None;
2621            text = completion.new_text.clone();
2622        };
2623        let selections = self.selections.all::<usize>(cx);
2624        let buffer = buffer_handle.read(cx);
2625        let old_range = completion.old_range.to_offset(buffer);
2626        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2627
2628        let newest_selection = self.selections.newest_anchor();
2629        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2630            return None;
2631        }
2632
2633        let lookbehind = newest_selection
2634            .start
2635            .text_anchor
2636            .to_offset(buffer)
2637            .saturating_sub(old_range.start);
2638        let lookahead = old_range
2639            .end
2640            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2641        let mut common_prefix_len = old_text
2642            .bytes()
2643            .zip(text.bytes())
2644            .take_while(|(a, b)| a == b)
2645            .count();
2646
2647        let snapshot = self.buffer.read(cx).snapshot(cx);
2648        let mut ranges = Vec::new();
2649        for selection in &selections {
2650            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2651                let start = selection.start.saturating_sub(lookbehind);
2652                let end = selection.end + lookahead;
2653                ranges.push(start + common_prefix_len..end);
2654            } else {
2655                common_prefix_len = 0;
2656                ranges.clear();
2657                ranges.extend(selections.iter().map(|s| {
2658                    if s.id == newest_selection.id {
2659                        old_range.clone()
2660                    } else {
2661                        s.start..s.end
2662                    }
2663                }));
2664                break;
2665            }
2666        }
2667        let text = &text[common_prefix_len..];
2668
2669        self.transact(cx, |this, cx| {
2670            if let Some(mut snippet) = snippet {
2671                snippet.text = text.to_string();
2672                for tabstop in snippet.tabstops.iter_mut().flatten() {
2673                    tabstop.start -= common_prefix_len as isize;
2674                    tabstop.end -= common_prefix_len as isize;
2675                }
2676
2677                this.insert_snippet(&ranges, snippet, cx).log_err();
2678            } else {
2679                this.buffer.update(cx, |buffer, cx| {
2680                    buffer.edit(
2681                        ranges.iter().map(|range| (range.clone(), text)),
2682                        Some(AutoindentMode::EachLine),
2683                        cx,
2684                    );
2685                });
2686            }
2687
2688            this.refresh_copilot_suggestions(true, cx);
2689        });
2690
2691        let project = self.project.clone()?;
2692        let apply_edits = project.update(cx, |project, cx| {
2693            project.apply_additional_edits_for_completion(
2694                buffer_handle,
2695                completion.clone(),
2696                true,
2697                cx,
2698            )
2699        });
2700        Some(cx.foreground().spawn(async move {
2701            apply_edits.await?;
2702            Ok(())
2703        }))
2704    }
2705
2706    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2707        if matches!(
2708            self.context_menu.as_ref(),
2709            Some(ContextMenu::CodeActions(_))
2710        ) {
2711            self.context_menu.take();
2712            cx.notify();
2713            return;
2714        }
2715
2716        let deployed_from_indicator = action.deployed_from_indicator;
2717        let mut task = self.code_actions_task.take();
2718        cx.spawn(|this, mut cx| async move {
2719            while let Some(prev_task) = task {
2720                prev_task.await;
2721                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
2722            }
2723
2724            this.update(&mut cx, |this, cx| {
2725                if this.focused {
2726                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
2727                        this.show_context_menu(
2728                            ContextMenu::CodeActions(CodeActionsMenu {
2729                                buffer,
2730                                actions,
2731                                selected_item: Default::default(),
2732                                list: Default::default(),
2733                                deployed_from_indicator,
2734                            }),
2735                            cx,
2736                        );
2737                    }
2738                }
2739            })?;
2740
2741            Ok::<_, anyhow::Error>(())
2742        })
2743        .detach_and_log_err(cx);
2744    }
2745
2746    pub fn confirm_code_action(
2747        workspace: &mut Workspace,
2748        action: &ConfirmCodeAction,
2749        cx: &mut ViewContext<Workspace>,
2750    ) -> Option<Task<Result<()>>> {
2751        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2752        let actions_menu = if let ContextMenu::CodeActions(menu) =
2753            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2754        {
2755            menu
2756        } else {
2757            return None;
2758        };
2759        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2760        let action = actions_menu.actions.get(action_ix)?.clone();
2761        let title = action.lsp_action.title.clone();
2762        let buffer = actions_menu.buffer;
2763
2764        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2765            project.apply_code_action(buffer, action, true, cx)
2766        });
2767        let editor = editor.downgrade();
2768        Some(cx.spawn(|workspace, cx| async move {
2769            let project_transaction = apply_code_actions.await?;
2770            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
2771        }))
2772    }
2773
2774    async fn open_project_transaction(
2775        this: &WeakViewHandle<Editor>,
2776        workspace: WeakViewHandle<Workspace>,
2777        transaction: ProjectTransaction,
2778        title: String,
2779        mut cx: AsyncAppContext,
2780    ) -> Result<()> {
2781        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
2782
2783        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2784        entries.sort_unstable_by_key(|(buffer, _)| {
2785            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2786        });
2787
2788        // If the project transaction's edits are all contained within this editor, then
2789        // avoid opening a new editor to display them.
2790
2791        if let Some((buffer, transaction)) = entries.first() {
2792            if entries.len() == 1 {
2793                let excerpt = this.read_with(&cx, |editor, cx| {
2794                    editor
2795                        .buffer()
2796                        .read(cx)
2797                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2798                })?;
2799                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2800                    if excerpted_buffer == *buffer {
2801                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2802                            let excerpt_range = excerpt_range.to_offset(buffer);
2803                            buffer
2804                                .edited_ranges_for_transaction::<usize>(transaction)
2805                                .all(|range| {
2806                                    excerpt_range.start <= range.start
2807                                        && excerpt_range.end >= range.end
2808                                })
2809                        });
2810
2811                        if all_edits_within_excerpt {
2812                            return Ok(());
2813                        }
2814                    }
2815                }
2816            }
2817        } else {
2818            return Ok(());
2819        }
2820
2821        let mut ranges_to_highlight = Vec::new();
2822        let excerpt_buffer = cx.add_model(|cx| {
2823            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2824            for (buffer_handle, transaction) in &entries {
2825                let buffer = buffer_handle.read(cx);
2826                ranges_to_highlight.extend(
2827                    multibuffer.push_excerpts_with_context_lines(
2828                        buffer_handle.clone(),
2829                        buffer
2830                            .edited_ranges_for_transaction::<usize>(transaction)
2831                            .collect(),
2832                        1,
2833                        cx,
2834                    ),
2835                );
2836            }
2837            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
2838            multibuffer
2839        });
2840
2841        workspace.update(&mut cx, |workspace, cx| {
2842            let project = workspace.project().clone();
2843            let editor =
2844                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2845            workspace.add_item(Box::new(editor.clone()), cx);
2846            editor.update(cx, |editor, cx| {
2847                editor.highlight_background::<Self>(
2848                    ranges_to_highlight,
2849                    |theme| theme.editor.highlighted_line_background,
2850                    cx,
2851                );
2852            });
2853        })?;
2854
2855        Ok(())
2856    }
2857
2858    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2859        let project = self.project.as_ref()?;
2860        let buffer = self.buffer.read(cx);
2861        let newest_selection = self.selections.newest_anchor().clone();
2862        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2863        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2864        if start_buffer != end_buffer {
2865            return None;
2866        }
2867
2868        let actions = project.update(cx, |project, cx| {
2869            project.code_actions(&start_buffer, start..end, cx)
2870        });
2871        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
2872            let actions = actions.await;
2873            this.update(&mut cx, |this, cx| {
2874                this.available_code_actions = actions.log_err().and_then(|actions| {
2875                    if actions.is_empty() {
2876                        None
2877                    } else {
2878                        Some((start_buffer, actions.into()))
2879                    }
2880                });
2881                cx.notify();
2882            })
2883            .log_err();
2884        }));
2885        None
2886    }
2887
2888    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2889        if self.pending_rename.is_some() {
2890            return None;
2891        }
2892
2893        let project = self.project.as_ref()?;
2894        let buffer = self.buffer.read(cx);
2895        let newest_selection = self.selections.newest_anchor().clone();
2896        let cursor_position = newest_selection.head();
2897        let (cursor_buffer, cursor_buffer_position) =
2898            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2899        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2900        if cursor_buffer != tail_buffer {
2901            return None;
2902        }
2903
2904        let highlights = project.update(cx, |project, cx| {
2905            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2906        });
2907
2908        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
2909            if let Some(highlights) = highlights.await.log_err() {
2910                this.update(&mut cx, |this, cx| {
2911                    if this.pending_rename.is_some() {
2912                        return;
2913                    }
2914
2915                    let buffer_id = cursor_position.buffer_id;
2916                    let buffer = this.buffer.read(cx);
2917                    if !buffer
2918                        .text_anchor_for_position(cursor_position, cx)
2919                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2920                    {
2921                        return;
2922                    }
2923
2924                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2925                    let mut write_ranges = Vec::new();
2926                    let mut read_ranges = Vec::new();
2927                    for highlight in highlights {
2928                        for (excerpt_id, excerpt_range) in
2929                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2930                        {
2931                            let start = highlight
2932                                .range
2933                                .start
2934                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
2935                            let end = highlight
2936                                .range
2937                                .end
2938                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
2939                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2940                                continue;
2941                            }
2942
2943                            let range = Anchor {
2944                                buffer_id,
2945                                excerpt_id: excerpt_id.clone(),
2946                                text_anchor: start,
2947                            }..Anchor {
2948                                buffer_id,
2949                                excerpt_id,
2950                                text_anchor: end,
2951                            };
2952                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2953                                write_ranges.push(range);
2954                            } else {
2955                                read_ranges.push(range);
2956                            }
2957                        }
2958                    }
2959
2960                    this.highlight_background::<DocumentHighlightRead>(
2961                        read_ranges,
2962                        |theme| theme.editor.document_highlight_read_background,
2963                        cx,
2964                    );
2965                    this.highlight_background::<DocumentHighlightWrite>(
2966                        write_ranges,
2967                        |theme| theme.editor.document_highlight_write_background,
2968                        cx,
2969                    );
2970                    cx.notify();
2971                })
2972                .log_err();
2973            }
2974        }));
2975        None
2976    }
2977
2978    fn refresh_copilot_suggestions(
2979        &mut self,
2980        debounce: bool,
2981        cx: &mut ViewContext<Self>,
2982    ) -> Option<()> {
2983        let copilot = Copilot::global(cx)?;
2984        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
2985            self.clear_copilot_suggestions(cx);
2986            return None;
2987        }
2988        self.update_visible_copilot_suggestion(cx);
2989
2990        let snapshot = self.buffer.read(cx).snapshot(cx);
2991        let cursor = self.selections.newest_anchor().head();
2992        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
2993            self.clear_copilot_suggestions(cx);
2994            return None;
2995        }
2996
2997        let (buffer, buffer_position) =
2998            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
2999        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3000            if debounce {
3001                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3002            }
3003
3004            let completions = copilot
3005                .update(&mut cx, |copilot, cx| {
3006                    copilot.completions(&buffer, buffer_position, cx)
3007                })
3008                .await
3009                .log_err()
3010                .into_iter()
3011                .flatten()
3012                .collect_vec();
3013
3014            this.update(&mut cx, |this, cx| {
3015                if !completions.is_empty() {
3016                    this.copilot_state.cycled = false;
3017                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3018                    this.copilot_state.completions.clear();
3019                    this.copilot_state.active_completion_index = 0;
3020                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3021                    for completion in completions {
3022                        this.copilot_state.push_completion(completion);
3023                    }
3024                    this.update_visible_copilot_suggestion(cx);
3025                }
3026            })
3027            .log_err()?;
3028            Some(())
3029        });
3030
3031        Some(())
3032    }
3033
3034    fn cycle_copilot_suggestions(
3035        &mut self,
3036        direction: Direction,
3037        cx: &mut ViewContext<Self>,
3038    ) -> Option<()> {
3039        let copilot = Copilot::global(cx)?;
3040        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3041            return None;
3042        }
3043
3044        if self.copilot_state.cycled {
3045            self.copilot_state.cycle_completions(direction);
3046            self.update_visible_copilot_suggestion(cx);
3047        } else {
3048            let cursor = self.selections.newest_anchor().head();
3049            let (buffer, buffer_position) =
3050                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3051            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3052                let completions = copilot
3053                    .update(&mut cx, |copilot, cx| {
3054                        copilot.completions_cycling(&buffer, buffer_position, cx)
3055                    })
3056                    .await;
3057
3058                this.update(&mut cx, |this, cx| {
3059                    this.copilot_state.cycled = true;
3060                    for completion in completions.log_err().into_iter().flatten() {
3061                        this.copilot_state.push_completion(completion);
3062                    }
3063                    this.copilot_state.cycle_completions(direction);
3064                    this.update_visible_copilot_suggestion(cx);
3065                })
3066                .log_err()?;
3067
3068                Some(())
3069            });
3070        }
3071
3072        Some(())
3073    }
3074
3075    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3076        if !self.has_active_copilot_suggestion(cx) {
3077            self.refresh_copilot_suggestions(false, cx);
3078            return;
3079        }
3080
3081        self.update_visible_copilot_suggestion(cx);
3082    }
3083
3084    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3085        if self.has_active_copilot_suggestion(cx) {
3086            self.cycle_copilot_suggestions(Direction::Next, cx);
3087        } else {
3088            self.refresh_copilot_suggestions(false, cx);
3089        }
3090    }
3091
3092    fn previous_copilot_suggestion(
3093        &mut self,
3094        _: &copilot::PreviousSuggestion,
3095        cx: &mut ViewContext<Self>,
3096    ) {
3097        if self.has_active_copilot_suggestion(cx) {
3098            self.cycle_copilot_suggestions(Direction::Prev, cx);
3099        } else {
3100            self.refresh_copilot_suggestions(false, cx);
3101        }
3102    }
3103
3104    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3105        if let Some(suggestion) = self
3106            .display_map
3107            .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx))
3108        {
3109            if let Some((copilot, completion)) =
3110                Copilot::global(cx).zip(self.copilot_state.active_completion())
3111            {
3112                copilot
3113                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3114                    .detach_and_log_err(cx);
3115
3116                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3117            }
3118            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3119            cx.notify();
3120            true
3121        } else {
3122            false
3123        }
3124    }
3125
3126    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3127        if self.has_active_copilot_suggestion(cx) {
3128            if let Some(copilot) = Copilot::global(cx) {
3129                copilot
3130                    .update(cx, |copilot, cx| {
3131                        copilot.discard_completions(&self.copilot_state.completions, cx)
3132                    })
3133                    .detach_and_log_err(cx);
3134
3135                self.report_copilot_event(None, false, cx)
3136            }
3137
3138            self.display_map
3139                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
3140            cx.notify();
3141            true
3142        } else {
3143            false
3144        }
3145    }
3146
3147    fn is_copilot_enabled_at(
3148        &self,
3149        location: Anchor,
3150        snapshot: &MultiBufferSnapshot,
3151        cx: &mut ViewContext<Self>,
3152    ) -> bool {
3153        let path = snapshot.file_at(location).map(|file| file.path().as_ref());
3154        let language_name = snapshot
3155            .language_at(location)
3156            .map(|language| language.name());
3157        let settings = all_language_settings(cx);
3158        settings.copilot_enabled(language_name.as_deref(), path)
3159    }
3160
3161    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3162        self.display_map.read(cx).has_suggestion()
3163    }
3164
3165    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3166        let snapshot = self.buffer.read(cx).snapshot(cx);
3167        let selection = self.selections.newest_anchor();
3168        let cursor = selection.head();
3169
3170        if self.context_menu.is_some()
3171            || !self.completion_tasks.is_empty()
3172            || selection.start != selection.end
3173        {
3174            self.discard_copilot_suggestion(cx);
3175        } else if let Some(text) = self
3176            .copilot_state
3177            .text_for_active_completion(cursor, &snapshot)
3178        {
3179            self.display_map.update(cx, move |map, cx| {
3180                map.replace_suggestion(
3181                    Some(Suggestion {
3182                        position: cursor,
3183                        text: text.trim_end().into(),
3184                    }),
3185                    cx,
3186                )
3187            });
3188            cx.notify();
3189        } else {
3190            self.discard_copilot_suggestion(cx);
3191        }
3192    }
3193
3194    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3195        self.copilot_state = Default::default();
3196        self.discard_copilot_suggestion(cx);
3197    }
3198
3199    pub fn render_code_actions_indicator(
3200        &self,
3201        style: &EditorStyle,
3202        active: bool,
3203        cx: &mut ViewContext<Self>,
3204    ) -> Option<AnyElement<Self>> {
3205        if self.available_code_actions.is_some() {
3206            enum CodeActions {}
3207            Some(
3208                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3209                    Svg::new("icons/bolt_8.svg")
3210                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3211                })
3212                .with_cursor_style(CursorStyle::PointingHand)
3213                .with_padding(Padding::uniform(3.))
3214                .on_down(MouseButton::Left, |_, this, cx| {
3215                    this.toggle_code_actions(
3216                        &ToggleCodeActions {
3217                            deployed_from_indicator: true,
3218                        },
3219                        cx,
3220                    );
3221                })
3222                .into_any(),
3223            )
3224        } else {
3225            None
3226        }
3227    }
3228
3229    pub fn render_fold_indicators(
3230        &self,
3231        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3232        style: &EditorStyle,
3233        gutter_hovered: bool,
3234        line_height: f32,
3235        gutter_margin: f32,
3236        cx: &mut ViewContext<Self>,
3237    ) -> Vec<Option<AnyElement<Self>>> {
3238        enum FoldIndicators {}
3239
3240        let style = style.folds.clone();
3241
3242        fold_data
3243            .iter()
3244            .enumerate()
3245            .map(|(ix, fold_data)| {
3246                fold_data
3247                    .map(|(fold_status, buffer_row, active)| {
3248                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3249                            MouseEventHandler::<FoldIndicators, _>::new(
3250                                ix as usize,
3251                                cx,
3252                                |mouse_state, _| {
3253                                    Svg::new(match fold_status {
3254                                        FoldStatus::Folded => style.folded_icon.clone(),
3255                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3256                                    })
3257                                    .with_color(
3258                                        style
3259                                            .indicator
3260                                            .style_for(
3261                                                mouse_state,
3262                                                fold_status == FoldStatus::Folded,
3263                                            )
3264                                            .color,
3265                                    )
3266                                    .constrained()
3267                                    .with_width(gutter_margin * style.icon_margin_scale)
3268                                    .aligned()
3269                                    .constrained()
3270                                    .with_height(line_height)
3271                                    .with_width(gutter_margin)
3272                                    .aligned()
3273                                },
3274                            )
3275                            .with_cursor_style(CursorStyle::PointingHand)
3276                            .with_padding(Padding::uniform(3.))
3277                            .on_click(MouseButton::Left, {
3278                                move |_, editor, cx| match fold_status {
3279                                    FoldStatus::Folded => {
3280                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3281                                    }
3282                                    FoldStatus::Foldable => {
3283                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3284                                    }
3285                                }
3286                            })
3287                            .into_any()
3288                        })
3289                    })
3290                    .flatten()
3291            })
3292            .collect()
3293    }
3294
3295    pub fn context_menu_visible(&self) -> bool {
3296        self.context_menu
3297            .as_ref()
3298            .map_or(false, |menu| menu.visible())
3299    }
3300
3301    pub fn render_context_menu(
3302        &self,
3303        cursor_position: DisplayPoint,
3304        style: EditorStyle,
3305        cx: &mut ViewContext<Editor>,
3306    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3307        self.context_menu
3308            .as_ref()
3309            .map(|menu| menu.render(cursor_position, style, cx))
3310    }
3311
3312    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3313        if !matches!(menu, ContextMenu::Completions(_)) {
3314            self.completion_tasks.clear();
3315        }
3316        self.context_menu = Some(menu);
3317        self.discard_copilot_suggestion(cx);
3318        cx.notify();
3319    }
3320
3321    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3322        cx.notify();
3323        self.completion_tasks.clear();
3324        let context_menu = self.context_menu.take();
3325        if context_menu.is_some() {
3326            self.update_visible_copilot_suggestion(cx);
3327        }
3328        context_menu
3329    }
3330
3331    pub fn insert_snippet(
3332        &mut self,
3333        insertion_ranges: &[Range<usize>],
3334        snippet: Snippet,
3335        cx: &mut ViewContext<Self>,
3336    ) -> Result<()> {
3337        let tabstops = self.buffer.update(cx, |buffer, cx| {
3338            let snippet_text: Arc<str> = snippet.text.clone().into();
3339            buffer.edit(
3340                insertion_ranges
3341                    .iter()
3342                    .cloned()
3343                    .map(|range| (range, snippet_text.clone())),
3344                Some(AutoindentMode::EachLine),
3345                cx,
3346            );
3347
3348            let snapshot = &*buffer.read(cx);
3349            let snippet = &snippet;
3350            snippet
3351                .tabstops
3352                .iter()
3353                .map(|tabstop| {
3354                    let mut tabstop_ranges = tabstop
3355                        .iter()
3356                        .flat_map(|tabstop_range| {
3357                            let mut delta = 0_isize;
3358                            insertion_ranges.iter().map(move |insertion_range| {
3359                                let insertion_start = insertion_range.start as isize + delta;
3360                                delta +=
3361                                    snippet.text.len() as isize - insertion_range.len() as isize;
3362
3363                                let start = snapshot.anchor_before(
3364                                    (insertion_start + tabstop_range.start) as usize,
3365                                );
3366                                let end = snapshot
3367                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3368                                start..end
3369                            })
3370                        })
3371                        .collect::<Vec<_>>();
3372                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3373                    tabstop_ranges
3374                })
3375                .collect::<Vec<_>>()
3376        });
3377
3378        if let Some(tabstop) = tabstops.first() {
3379            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3380                s.select_ranges(tabstop.iter().cloned());
3381            });
3382            self.snippet_stack.push(SnippetState {
3383                active_index: 0,
3384                ranges: tabstops,
3385            });
3386        }
3387
3388        Ok(())
3389    }
3390
3391    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3392        self.move_to_snippet_tabstop(Bias::Right, cx)
3393    }
3394
3395    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3396        self.move_to_snippet_tabstop(Bias::Left, cx)
3397    }
3398
3399    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3400        if let Some(mut snippet) = self.snippet_stack.pop() {
3401            match bias {
3402                Bias::Left => {
3403                    if snippet.active_index > 0 {
3404                        snippet.active_index -= 1;
3405                    } else {
3406                        self.snippet_stack.push(snippet);
3407                        return false;
3408                    }
3409                }
3410                Bias::Right => {
3411                    if snippet.active_index + 1 < snippet.ranges.len() {
3412                        snippet.active_index += 1;
3413                    } else {
3414                        self.snippet_stack.push(snippet);
3415                        return false;
3416                    }
3417                }
3418            }
3419            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3420                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3421                    s.select_anchor_ranges(current_ranges.iter().cloned())
3422                });
3423                // If snippet state is not at the last tabstop, push it back on the stack
3424                if snippet.active_index + 1 < snippet.ranges.len() {
3425                    self.snippet_stack.push(snippet);
3426                }
3427                return true;
3428            }
3429        }
3430
3431        false
3432    }
3433
3434    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3435        self.transact(cx, |this, cx| {
3436            this.select_all(&SelectAll, cx);
3437            this.insert("", cx);
3438        });
3439    }
3440
3441    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3442        self.transact(cx, |this, cx| {
3443            this.select_autoclose_pair(cx);
3444            let mut selections = this.selections.all::<Point>(cx);
3445            if !this.selections.line_mode {
3446                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3447                for selection in &mut selections {
3448                    if selection.is_empty() {
3449                        let old_head = selection.head();
3450                        let mut new_head =
3451                            movement::left(&display_map, old_head.to_display_point(&display_map))
3452                                .to_point(&display_map);
3453                        if let Some((buffer, line_buffer_range)) = display_map
3454                            .buffer_snapshot
3455                            .buffer_line_for_row(old_head.row)
3456                        {
3457                            let indent_size =
3458                                buffer.indent_size_for_line(line_buffer_range.start.row);
3459                            let indent_len = match indent_size.kind {
3460                                IndentKind::Space => {
3461                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3462                                }
3463                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3464                            };
3465                            if old_head.column <= indent_size.len && old_head.column > 0 {
3466                                let indent_len = indent_len.get();
3467                                new_head = cmp::min(
3468                                    new_head,
3469                                    Point::new(
3470                                        old_head.row,
3471                                        ((old_head.column - 1) / indent_len) * indent_len,
3472                                    ),
3473                                );
3474                            }
3475                        }
3476
3477                        selection.set_head(new_head, SelectionGoal::None);
3478                    }
3479                }
3480            }
3481
3482            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3483            this.insert("", cx);
3484            this.refresh_copilot_suggestions(true, cx);
3485        });
3486    }
3487
3488    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3489        self.transact(cx, |this, cx| {
3490            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3491                let line_mode = s.line_mode;
3492                s.move_with(|map, selection| {
3493                    if selection.is_empty() && !line_mode {
3494                        let cursor = movement::right(map, selection.head());
3495                        selection.set_head(cursor, SelectionGoal::None);
3496                    }
3497                })
3498            });
3499            this.insert("", cx);
3500            this.refresh_copilot_suggestions(true, cx);
3501        });
3502    }
3503
3504    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3505        if self.move_to_prev_snippet_tabstop(cx) {
3506            return;
3507        }
3508
3509        self.outdent(&Outdent, cx);
3510    }
3511
3512    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3513        if self.move_to_next_snippet_tabstop(cx) {
3514            return;
3515        }
3516
3517        let mut selections = self.selections.all_adjusted(cx);
3518        let buffer = self.buffer.read(cx);
3519        let snapshot = buffer.snapshot(cx);
3520        let rows_iter = selections.iter().map(|s| s.head().row);
3521        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3522
3523        let mut edits = Vec::new();
3524        let mut prev_edited_row = 0;
3525        let mut row_delta = 0;
3526        for selection in &mut selections {
3527            if selection.start.row != prev_edited_row {
3528                row_delta = 0;
3529            }
3530            prev_edited_row = selection.end.row;
3531
3532            // If the selection is non-empty, then increase the indentation of the selected lines.
3533            if !selection.is_empty() {
3534                row_delta =
3535                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3536                continue;
3537            }
3538
3539            // If the selection is empty and the cursor is in the leading whitespace before the
3540            // suggested indentation, then auto-indent the line.
3541            let cursor = selection.head();
3542            let current_indent = snapshot.indent_size_for_line(cursor.row);
3543            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3544                if cursor.column < suggested_indent.len
3545                    && cursor.column <= current_indent.len
3546                    && current_indent.len <= suggested_indent.len
3547                {
3548                    selection.start = Point::new(cursor.row, suggested_indent.len);
3549                    selection.end = selection.start;
3550                    if row_delta == 0 {
3551                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3552                            cursor.row,
3553                            current_indent,
3554                            suggested_indent,
3555                        ));
3556                        row_delta = suggested_indent.len - current_indent.len;
3557                    }
3558                    continue;
3559                }
3560            }
3561
3562            // Accept copilot suggestion if there is only one selection and the cursor is not
3563            // in the leading whitespace.
3564            if self.selections.count() == 1
3565                && cursor.column >= current_indent.len
3566                && self.has_active_copilot_suggestion(cx)
3567            {
3568                self.accept_copilot_suggestion(cx);
3569                return;
3570            }
3571
3572            // Otherwise, insert a hard or soft tab.
3573            let settings = buffer.settings_at(cursor, cx);
3574            let tab_size = if settings.hard_tabs {
3575                IndentSize::tab()
3576            } else {
3577                let tab_size = settings.tab_size.get();
3578                let char_column = snapshot
3579                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3580                    .flat_map(str::chars)
3581                    .count()
3582                    + row_delta as usize;
3583                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3584                IndentSize::spaces(chars_to_next_tab_stop)
3585            };
3586            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3587            selection.end = selection.start;
3588            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3589            row_delta += tab_size.len;
3590        }
3591
3592        self.transact(cx, |this, cx| {
3593            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3594            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3595            this.refresh_copilot_suggestions(true, cx);
3596        });
3597    }
3598
3599    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3600        let mut selections = self.selections.all::<Point>(cx);
3601        let mut prev_edited_row = 0;
3602        let mut row_delta = 0;
3603        let mut edits = Vec::new();
3604        let buffer = self.buffer.read(cx);
3605        let snapshot = buffer.snapshot(cx);
3606        for selection in &mut selections {
3607            if selection.start.row != prev_edited_row {
3608                row_delta = 0;
3609            }
3610            prev_edited_row = selection.end.row;
3611
3612            row_delta =
3613                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3614        }
3615
3616        self.transact(cx, |this, cx| {
3617            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3618            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3619        });
3620    }
3621
3622    fn indent_selection(
3623        buffer: &MultiBuffer,
3624        snapshot: &MultiBufferSnapshot,
3625        selection: &mut Selection<Point>,
3626        edits: &mut Vec<(Range<Point>, String)>,
3627        delta_for_start_row: u32,
3628        cx: &AppContext,
3629    ) -> u32 {
3630        let settings = buffer.settings_at(selection.start, cx);
3631        let tab_size = settings.tab_size.get();
3632        let indent_kind = if settings.hard_tabs {
3633            IndentKind::Tab
3634        } else {
3635            IndentKind::Space
3636        };
3637        let mut start_row = selection.start.row;
3638        let mut end_row = selection.end.row + 1;
3639
3640        // If a selection ends at the beginning of a line, don't indent
3641        // that last line.
3642        if selection.end.column == 0 {
3643            end_row -= 1;
3644        }
3645
3646        // Avoid re-indenting a row that has already been indented by a
3647        // previous selection, but still update this selection's column
3648        // to reflect that indentation.
3649        if delta_for_start_row > 0 {
3650            start_row += 1;
3651            selection.start.column += delta_for_start_row;
3652            if selection.end.row == selection.start.row {
3653                selection.end.column += delta_for_start_row;
3654            }
3655        }
3656
3657        let mut delta_for_end_row = 0;
3658        for row in start_row..end_row {
3659            let current_indent = snapshot.indent_size_for_line(row);
3660            let indent_delta = match (current_indent.kind, indent_kind) {
3661                (IndentKind::Space, IndentKind::Space) => {
3662                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3663                    IndentSize::spaces(columns_to_next_tab_stop)
3664                }
3665                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3666                (_, IndentKind::Tab) => IndentSize::tab(),
3667            };
3668
3669            let row_start = Point::new(row, 0);
3670            edits.push((
3671                row_start..row_start,
3672                indent_delta.chars().collect::<String>(),
3673            ));
3674
3675            // Update this selection's endpoints to reflect the indentation.
3676            if row == selection.start.row {
3677                selection.start.column += indent_delta.len;
3678            }
3679            if row == selection.end.row {
3680                selection.end.column += indent_delta.len;
3681                delta_for_end_row = indent_delta.len;
3682            }
3683        }
3684
3685        if selection.start.row == selection.end.row {
3686            delta_for_start_row + delta_for_end_row
3687        } else {
3688            delta_for_end_row
3689        }
3690    }
3691
3692    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3693        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3694        let selections = self.selections.all::<Point>(cx);
3695        let mut deletion_ranges = Vec::new();
3696        let mut last_outdent = None;
3697        {
3698            let buffer = self.buffer.read(cx);
3699            let snapshot = buffer.snapshot(cx);
3700            for selection in &selections {
3701                let settings = buffer.settings_at(selection.start, cx);
3702                let tab_size = settings.tab_size.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        let snapshot = self
5571            .display_map
5572            .update(cx, |display_map, cx| display_map.snapshot(cx));
5573        let selection = self.selections.newest::<Point>(cx);
5574
5575        if !self.seek_in_direction(
5576            &snapshot,
5577            selection.head(),
5578            false,
5579            snapshot
5580                .buffer_snapshot
5581                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5582            cx,
5583        ) {
5584            let wrapped_point = Point::zero();
5585            self.seek_in_direction(
5586                &snapshot,
5587                wrapped_point,
5588                true,
5589                snapshot
5590                    .buffer_snapshot
5591                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5592                cx,
5593            );
5594        }
5595    }
5596
5597    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5598        let snapshot = self
5599            .display_map
5600            .update(cx, |display_map, cx| display_map.snapshot(cx));
5601        let selection = self.selections.newest::<Point>(cx);
5602
5603        if !self.seek_in_direction(
5604            &snapshot,
5605            selection.head(),
5606            false,
5607            snapshot
5608                .buffer_snapshot
5609                .git_diff_hunks_in_range_rev(0..selection.head().row),
5610            cx,
5611        ) {
5612            let wrapped_point = snapshot.buffer_snapshot.max_point();
5613            self.seek_in_direction(
5614                &snapshot,
5615                wrapped_point,
5616                true,
5617                snapshot
5618                    .buffer_snapshot
5619                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5620                cx,
5621            );
5622        }
5623    }
5624
5625    fn seek_in_direction(
5626        &mut self,
5627        snapshot: &DisplaySnapshot,
5628        initial_point: Point,
5629        is_wrapped: bool,
5630        hunks: impl Iterator<Item = DiffHunk<u32>>,
5631        cx: &mut ViewContext<Editor>,
5632    ) -> bool {
5633        let display_point = initial_point.to_display_point(snapshot);
5634        let mut hunks = hunks
5635            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5636            .skip_while(|hunk| {
5637                if is_wrapped {
5638                    false
5639                } else {
5640                    hunk.contains_display_row(display_point.row())
5641                }
5642            })
5643            .dedup();
5644
5645        if let Some(hunk) = hunks.next() {
5646            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5647                let row = hunk.start_display_row();
5648                let point = DisplayPoint::new(row, 0);
5649                s.select_display_ranges([point..point]);
5650            });
5651
5652            true
5653        } else {
5654            false
5655        }
5656    }
5657
5658    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5659        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5660    }
5661
5662    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5663        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5664    }
5665
5666    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5667        let Some(workspace) = self.workspace(cx) else { return };
5668        let buffer = self.buffer.read(cx);
5669        let head = self.selections.newest::<usize>(cx).head();
5670        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5671            text_anchor
5672        } else {
5673            return;
5674        };
5675
5676        let project = workspace.read(cx).project().clone();
5677        let definitions = project.update(cx, |project, cx| match kind {
5678            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5679            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5680        });
5681
5682        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5683            let definitions = definitions.await?;
5684            editor.update(&mut cx, |editor, cx| {
5685                editor.navigate_to_definitions(definitions, cx);
5686            })?;
5687            Ok::<(), anyhow::Error>(())
5688        })
5689        .detach_and_log_err(cx);
5690    }
5691
5692    pub fn navigate_to_definitions(
5693        &mut self,
5694        mut definitions: Vec<LocationLink>,
5695        cx: &mut ViewContext<Editor>,
5696    ) {
5697        let Some(workspace) = self.workspace(cx) else { return };
5698        let pane = workspace.read(cx).active_pane().clone();
5699        // If there is one definition, just open it directly
5700        if definitions.len() == 1 {
5701            let definition = definitions.pop().unwrap();
5702            let range = definition
5703                .target
5704                .range
5705                .to_offset(definition.target.buffer.read(cx));
5706
5707            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
5708                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5709                    s.select_ranges([range]);
5710                });
5711            } else {
5712                cx.window_context().defer(move |cx| {
5713                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
5714                        workspace.open_project_item(definition.target.buffer.clone(), cx)
5715                    });
5716                    target_editor.update(cx, |target_editor, cx| {
5717                        // When selecting a definition in a different buffer, disable the nav history
5718                        // to avoid creating a history entry at the previous cursor location.
5719                        pane.update(cx, |pane, _| pane.disable_history());
5720                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5721                            s.select_ranges([range]);
5722                        });
5723                        pane.update(cx, |pane, _| pane.enable_history());
5724                    });
5725                });
5726            }
5727        } else if !definitions.is_empty() {
5728            let replica_id = self.replica_id(cx);
5729            cx.window_context().defer(move |cx| {
5730                let title = definitions
5731                    .iter()
5732                    .find(|definition| definition.origin.is_some())
5733                    .and_then(|definition| {
5734                        definition.origin.as_ref().map(|origin| {
5735                            let buffer = origin.buffer.read(cx);
5736                            format!(
5737                                "Definitions for {}",
5738                                buffer
5739                                    .text_for_range(origin.range.clone())
5740                                    .collect::<String>()
5741                            )
5742                        })
5743                    })
5744                    .unwrap_or("Definitions".to_owned());
5745                let locations = definitions
5746                    .into_iter()
5747                    .map(|definition| definition.target)
5748                    .collect();
5749                workspace.update(cx, |workspace, cx| {
5750                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5751                });
5752            });
5753        }
5754    }
5755
5756    pub fn find_all_references(
5757        workspace: &mut Workspace,
5758        _: &FindAllReferences,
5759        cx: &mut ViewContext<Workspace>,
5760    ) -> Option<Task<Result<()>>> {
5761        let active_item = workspace.active_item(cx)?;
5762        let editor_handle = active_item.act_as::<Self>(cx)?;
5763
5764        let editor = editor_handle.read(cx);
5765        let buffer = editor.buffer.read(cx);
5766        let head = editor.selections.newest::<usize>(cx).head();
5767        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5768        let replica_id = editor.replica_id(cx);
5769
5770        let project = workspace.project().clone();
5771        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5772        Some(cx.spawn_labeled(
5773            "Finding All References...",
5774            |workspace, mut cx| async move {
5775                let locations = references.await?;
5776                if locations.is_empty() {
5777                    return Ok(());
5778                }
5779
5780                workspace.update(&mut cx, |workspace, cx| {
5781                    let title = locations
5782                        .first()
5783                        .as_ref()
5784                        .map(|location| {
5785                            let buffer = location.buffer.read(cx);
5786                            format!(
5787                                "References to `{}`",
5788                                buffer
5789                                    .text_for_range(location.range.clone())
5790                                    .collect::<String>()
5791                            )
5792                        })
5793                        .unwrap();
5794                    Self::open_locations_in_multibuffer(
5795                        workspace, locations, replica_id, title, cx,
5796                    );
5797                })?;
5798
5799                Ok(())
5800            },
5801        ))
5802    }
5803
5804    /// Opens a multibuffer with the given project locations in it
5805    pub fn open_locations_in_multibuffer(
5806        workspace: &mut Workspace,
5807        mut locations: Vec<Location>,
5808        replica_id: ReplicaId,
5809        title: String,
5810        cx: &mut ViewContext<Workspace>,
5811    ) {
5812        // If there are multiple definitions, open them in a multibuffer
5813        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
5814        let mut locations = locations.into_iter().peekable();
5815        let mut ranges_to_highlight = Vec::new();
5816
5817        let excerpt_buffer = cx.add_model(|cx| {
5818            let mut multibuffer = MultiBuffer::new(replica_id);
5819            while let Some(location) = locations.next() {
5820                let buffer = location.buffer.read(cx);
5821                let mut ranges_for_buffer = Vec::new();
5822                let range = location.range.to_offset(buffer);
5823                ranges_for_buffer.push(range.clone());
5824
5825                while let Some(next_location) = locations.peek() {
5826                    if next_location.buffer == location.buffer {
5827                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5828                        locations.next();
5829                    } else {
5830                        break;
5831                    }
5832                }
5833
5834                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5835                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5836                    location.buffer.clone(),
5837                    ranges_for_buffer,
5838                    1,
5839                    cx,
5840                ))
5841            }
5842
5843            multibuffer.with_title(title)
5844        });
5845
5846        let editor = cx.add_view(|cx| {
5847            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5848        });
5849        editor.update(cx, |editor, cx| {
5850            editor.highlight_background::<Self>(
5851                ranges_to_highlight,
5852                |theme| theme.editor.highlighted_line_background,
5853                cx,
5854            );
5855        });
5856        workspace.add_item(Box::new(editor), cx);
5857    }
5858
5859    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5860        use language::ToOffset as _;
5861
5862        let project = self.project.clone()?;
5863        let selection = self.selections.newest_anchor().clone();
5864        let (cursor_buffer, cursor_buffer_position) = self
5865            .buffer
5866            .read(cx)
5867            .text_anchor_for_position(selection.head(), cx)?;
5868        let (tail_buffer, _) = self
5869            .buffer
5870            .read(cx)
5871            .text_anchor_for_position(selection.tail(), cx)?;
5872        if tail_buffer != cursor_buffer {
5873            return None;
5874        }
5875
5876        let snapshot = cursor_buffer.read(cx).snapshot();
5877        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5878        let prepare_rename = project.update(cx, |project, cx| {
5879            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5880        });
5881
5882        Some(cx.spawn(|this, mut cx| async move {
5883            let rename_range = if let Some(range) = prepare_rename.await? {
5884                Some(range)
5885            } else {
5886                this.read_with(&cx, |this, cx| {
5887                    let buffer = this.buffer.read(cx).snapshot(cx);
5888                    let mut buffer_highlights = this
5889                        .document_highlights_for_position(selection.head(), &buffer)
5890                        .filter(|highlight| {
5891                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5892                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5893                        });
5894                    buffer_highlights
5895                        .next()
5896                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5897                })?
5898            };
5899            if let Some(rename_range) = rename_range {
5900                let rename_buffer_range = rename_range.to_offset(&snapshot);
5901                let cursor_offset_in_rename_range =
5902                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5903
5904                this.update(&mut cx, |this, cx| {
5905                    this.take_rename(false, cx);
5906                    let style = this.style(cx);
5907                    let buffer = this.buffer.read(cx).read(cx);
5908                    let cursor_offset = selection.head().to_offset(&buffer);
5909                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5910                    let rename_end = rename_start + rename_buffer_range.len();
5911                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5912                    let mut old_highlight_id = None;
5913                    let old_name: Arc<str> = buffer
5914                        .chunks(rename_start..rename_end, true)
5915                        .map(|chunk| {
5916                            if old_highlight_id.is_none() {
5917                                old_highlight_id = chunk.syntax_highlight_id;
5918                            }
5919                            chunk.text
5920                        })
5921                        .collect::<String>()
5922                        .into();
5923
5924                    drop(buffer);
5925
5926                    // Position the selection in the rename editor so that it matches the current selection.
5927                    this.show_local_selections = false;
5928                    let rename_editor = cx.add_view(|cx| {
5929                        let mut editor = Editor::single_line(None, cx);
5930                        if let Some(old_highlight_id) = old_highlight_id {
5931                            editor.override_text_style =
5932                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5933                        }
5934                        editor.buffer.update(cx, |buffer, cx| {
5935                            buffer.edit([(0..0, old_name.clone())], None, cx)
5936                        });
5937                        editor.select_all(&SelectAll, cx);
5938                        editor
5939                    });
5940
5941                    let ranges = this
5942                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5943                        .into_iter()
5944                        .flat_map(|(_, ranges)| ranges)
5945                        .chain(
5946                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5947                                .into_iter()
5948                                .flat_map(|(_, ranges)| ranges),
5949                        )
5950                        .collect();
5951
5952                    this.highlight_text::<Rename>(
5953                        ranges,
5954                        HighlightStyle {
5955                            fade_out: Some(style.rename_fade),
5956                            ..Default::default()
5957                        },
5958                        cx,
5959                    );
5960                    cx.focus(&rename_editor);
5961                    let block_id = this.insert_blocks(
5962                        [BlockProperties {
5963                            style: BlockStyle::Flex,
5964                            position: range.start.clone(),
5965                            height: 1,
5966                            render: Arc::new({
5967                                let editor = rename_editor.clone();
5968                                move |cx: &mut BlockContext| {
5969                                    ChildView::new(&editor, cx)
5970                                        .contained()
5971                                        .with_padding_left(cx.anchor_x)
5972                                        .into_any()
5973                                }
5974                            }),
5975                            disposition: BlockDisposition::Below,
5976                        }],
5977                        cx,
5978                    )[0];
5979                    this.pending_rename = Some(RenameState {
5980                        range,
5981                        old_name,
5982                        editor: rename_editor,
5983                        block_id,
5984                    });
5985                })?;
5986            }
5987
5988            Ok(())
5989        }))
5990    }
5991
5992    pub fn confirm_rename(
5993        workspace: &mut Workspace,
5994        _: &ConfirmRename,
5995        cx: &mut ViewContext<Workspace>,
5996    ) -> Option<Task<Result<()>>> {
5997        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5998
5999        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6000            let rename = editor.take_rename(false, cx)?;
6001            let buffer = editor.buffer.read(cx);
6002            let (start_buffer, start) =
6003                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6004            let (end_buffer, end) =
6005                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6006            if start_buffer == end_buffer {
6007                let new_name = rename.editor.read(cx).text(cx);
6008                Some((start_buffer, start..end, rename.old_name, new_name))
6009            } else {
6010                None
6011            }
6012        })?;
6013
6014        let rename = workspace.project().clone().update(cx, |project, cx| {
6015            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6016        });
6017
6018        let editor = editor.downgrade();
6019        Some(cx.spawn(|workspace, mut cx| async move {
6020            let project_transaction = rename.await?;
6021            Self::open_project_transaction(
6022                &editor,
6023                workspace,
6024                project_transaction,
6025                format!("Rename: {}{}", old_name, new_name),
6026                cx.clone(),
6027            )
6028            .await?;
6029
6030            editor.update(&mut cx, |editor, cx| {
6031                editor.refresh_document_highlights(cx);
6032            })?;
6033            Ok(())
6034        }))
6035    }
6036
6037    fn take_rename(
6038        &mut self,
6039        moving_cursor: bool,
6040        cx: &mut ViewContext<Self>,
6041    ) -> Option<RenameState> {
6042        let rename = self.pending_rename.take()?;
6043        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
6044        self.clear_text_highlights::<Rename>(cx);
6045        self.show_local_selections = true;
6046
6047        if moving_cursor {
6048            let rename_editor = rename.editor.read(cx);
6049            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6050
6051            // Update the selection to match the position of the selection inside
6052            // the rename editor.
6053            let snapshot = self.buffer.read(cx).read(cx);
6054            let rename_range = rename.range.to_offset(&snapshot);
6055            let cursor_in_editor = snapshot
6056                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6057                .min(rename_range.end);
6058            drop(snapshot);
6059
6060            self.change_selections(None, cx, |s| {
6061                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6062            });
6063        } else {
6064            self.refresh_document_highlights(cx);
6065        }
6066
6067        Some(rename)
6068    }
6069
6070    #[cfg(any(test, feature = "test-support"))]
6071    pub fn pending_rename(&self) -> Option<&RenameState> {
6072        self.pending_rename.as_ref()
6073    }
6074
6075    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6076        let project = match &self.project {
6077            Some(project) => project.clone(),
6078            None => return None,
6079        };
6080
6081        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6082    }
6083
6084    fn perform_format(
6085        &mut self,
6086        project: ModelHandle<Project>,
6087        trigger: FormatTrigger,
6088        cx: &mut ViewContext<Self>,
6089    ) -> Task<Result<()>> {
6090        let buffer = self.buffer().clone();
6091        let buffers = buffer.read(cx).all_buffers();
6092
6093        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6094        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6095
6096        cx.spawn(|_, mut cx| async move {
6097            let transaction = futures::select_biased! {
6098                _ = timeout => {
6099                    log::warn!("timed out waiting for formatting");
6100                    None
6101                }
6102                transaction = format.log_err().fuse() => transaction,
6103            };
6104
6105            buffer.update(&mut cx, |buffer, cx| {
6106                if let Some(transaction) = transaction {
6107                    if !buffer.is_singleton() {
6108                        buffer.push_transaction(&transaction.0, cx);
6109                    }
6110                }
6111
6112                cx.notify();
6113            });
6114
6115            Ok(())
6116        })
6117    }
6118
6119    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6120        if let Some(project) = self.project.clone() {
6121            self.buffer.update(cx, |multi_buffer, cx| {
6122                project.update(cx, |project, cx| {
6123                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6124                });
6125            })
6126        }
6127    }
6128
6129    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6130        cx.show_character_palette();
6131    }
6132
6133    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6134        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6135            let buffer = self.buffer.read(cx).snapshot(cx);
6136            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6137            let is_valid = buffer
6138                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6139                .any(|entry| {
6140                    entry.diagnostic.is_primary
6141                        && !entry.range.is_empty()
6142                        && entry.range.start == primary_range_start
6143                        && entry.diagnostic.message == active_diagnostics.primary_message
6144                });
6145
6146            if is_valid != active_diagnostics.is_valid {
6147                active_diagnostics.is_valid = is_valid;
6148                let mut new_styles = HashMap::default();
6149                for (block_id, diagnostic) in &active_diagnostics.blocks {
6150                    new_styles.insert(
6151                        *block_id,
6152                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6153                    );
6154                }
6155                self.display_map
6156                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6157            }
6158        }
6159    }
6160
6161    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6162        self.dismiss_diagnostics(cx);
6163        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6164            let buffer = self.buffer.read(cx).snapshot(cx);
6165
6166            let mut primary_range = None;
6167            let mut primary_message = None;
6168            let mut group_end = Point::zero();
6169            let diagnostic_group = buffer
6170                .diagnostic_group::<Point>(group_id)
6171                .map(|entry| {
6172                    if entry.range.end > group_end {
6173                        group_end = entry.range.end;
6174                    }
6175                    if entry.diagnostic.is_primary {
6176                        primary_range = Some(entry.range.clone());
6177                        primary_message = Some(entry.diagnostic.message.clone());
6178                    }
6179                    entry
6180                })
6181                .collect::<Vec<_>>();
6182            let primary_range = primary_range?;
6183            let primary_message = primary_message?;
6184            let primary_range =
6185                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6186
6187            let blocks = display_map
6188                .insert_blocks(
6189                    diagnostic_group.iter().map(|entry| {
6190                        let diagnostic = entry.diagnostic.clone();
6191                        let message_height = diagnostic.message.lines().count() as u8;
6192                        BlockProperties {
6193                            style: BlockStyle::Fixed,
6194                            position: buffer.anchor_after(entry.range.start),
6195                            height: message_height,
6196                            render: diagnostic_block_renderer(diagnostic, true),
6197                            disposition: BlockDisposition::Below,
6198                        }
6199                    }),
6200                    cx,
6201                )
6202                .into_iter()
6203                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6204                .collect();
6205
6206            Some(ActiveDiagnosticGroup {
6207                primary_range,
6208                primary_message,
6209                blocks,
6210                is_valid: true,
6211            })
6212        });
6213        self.active_diagnostics.is_some()
6214    }
6215
6216    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6217        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6218            self.display_map.update(cx, |display_map, cx| {
6219                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6220            });
6221            cx.notify();
6222        }
6223    }
6224
6225    pub fn set_selections_from_remote(
6226        &mut self,
6227        selections: Vec<Selection<Anchor>>,
6228        pending_selection: Option<Selection<Anchor>>,
6229        cx: &mut ViewContext<Self>,
6230    ) {
6231        let old_cursor_position = self.selections.newest_anchor().head();
6232        self.selections.change_with(cx, |s| {
6233            s.select_anchors(selections);
6234            if let Some(pending_selection) = pending_selection {
6235                s.set_pending(pending_selection, SelectMode::Character);
6236            } else {
6237                s.clear_pending();
6238            }
6239        });
6240        self.selections_did_change(false, &old_cursor_position, cx);
6241    }
6242
6243    fn push_to_selection_history(&mut self) {
6244        self.selection_history.push(SelectionHistoryEntry {
6245            selections: self.selections.disjoint_anchors(),
6246            select_next_state: self.select_next_state.clone(),
6247            add_selections_state: self.add_selections_state.clone(),
6248        });
6249    }
6250
6251    pub fn transact(
6252        &mut self,
6253        cx: &mut ViewContext<Self>,
6254        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6255    ) -> Option<TransactionId> {
6256        self.start_transaction_at(Instant::now(), cx);
6257        update(self, cx);
6258        self.end_transaction_at(Instant::now(), cx)
6259    }
6260
6261    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6262        self.end_selection(cx);
6263        if let Some(tx_id) = self
6264            .buffer
6265            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6266        {
6267            self.selection_history
6268                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6269        }
6270    }
6271
6272    fn end_transaction_at(
6273        &mut self,
6274        now: Instant,
6275        cx: &mut ViewContext<Self>,
6276    ) -> Option<TransactionId> {
6277        if let Some(tx_id) = self
6278            .buffer
6279            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6280        {
6281            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6282                *end_selections = Some(self.selections.disjoint_anchors());
6283            } else {
6284                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6285            }
6286
6287            cx.emit(Event::Edited);
6288            Some(tx_id)
6289        } else {
6290            None
6291        }
6292    }
6293
6294    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6295        let mut fold_ranges = Vec::new();
6296
6297        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6298
6299        let selections = self.selections.all::<Point>(cx);
6300        for selection in selections {
6301            let range = selection.range().sorted();
6302            let buffer_start_row = range.start.row;
6303
6304            for row in (0..=range.end.row).rev() {
6305                let fold_range = display_map.foldable_range(row);
6306
6307                if let Some(fold_range) = fold_range {
6308                    if fold_range.end.row >= buffer_start_row {
6309                        fold_ranges.push(fold_range);
6310                        if row <= range.start.row {
6311                            break;
6312                        }
6313                    }
6314                }
6315            }
6316        }
6317
6318        self.fold_ranges(fold_ranges, true, cx);
6319    }
6320
6321    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6322        let buffer_row = fold_at.buffer_row;
6323        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6324
6325        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6326            let autoscroll = self
6327                .selections
6328                .all::<Point>(cx)
6329                .iter()
6330                .any(|selection| fold_range.overlaps(&selection.range()));
6331
6332            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6333        }
6334    }
6335
6336    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6337        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6338        let buffer = &display_map.buffer_snapshot;
6339        let selections = self.selections.all::<Point>(cx);
6340        let ranges = selections
6341            .iter()
6342            .map(|s| {
6343                let range = s.display_range(&display_map).sorted();
6344                let mut start = range.start.to_point(&display_map);
6345                let mut end = range.end.to_point(&display_map);
6346                start.column = 0;
6347                end.column = buffer.line_len(end.row);
6348                start..end
6349            })
6350            .collect::<Vec<_>>();
6351
6352        self.unfold_ranges(ranges, true, true, cx);
6353    }
6354
6355    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6356        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6357
6358        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6359            ..Point::new(
6360                unfold_at.buffer_row,
6361                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6362            );
6363
6364        let autoscroll = self
6365            .selections
6366            .all::<Point>(cx)
6367            .iter()
6368            .any(|selection| selection.range().overlaps(&intersection_range));
6369
6370        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6371    }
6372
6373    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6374        let selections = self.selections.all::<Point>(cx);
6375        let ranges = selections.into_iter().map(|s| s.start..s.end);
6376        self.fold_ranges(ranges, true, cx);
6377    }
6378
6379    pub fn fold_ranges<T: ToOffset + Clone>(
6380        &mut self,
6381        ranges: impl IntoIterator<Item = Range<T>>,
6382        auto_scroll: bool,
6383        cx: &mut ViewContext<Self>,
6384    ) {
6385        let mut ranges = ranges.into_iter().peekable();
6386        if ranges.peek().is_some() {
6387            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6388
6389            if auto_scroll {
6390                self.request_autoscroll(Autoscroll::fit(), cx);
6391            }
6392
6393            cx.notify();
6394        }
6395    }
6396
6397    pub fn unfold_ranges<T: ToOffset + Clone>(
6398        &mut self,
6399        ranges: impl IntoIterator<Item = Range<T>>,
6400        inclusive: bool,
6401        auto_scroll: bool,
6402        cx: &mut ViewContext<Self>,
6403    ) {
6404        let mut ranges = ranges.into_iter().peekable();
6405        if ranges.peek().is_some() {
6406            self.display_map
6407                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6408            if auto_scroll {
6409                self.request_autoscroll(Autoscroll::fit(), cx);
6410            }
6411
6412            cx.notify();
6413        }
6414    }
6415
6416    pub fn gutter_hover(
6417        &mut self,
6418        GutterHover { hovered }: &GutterHover,
6419        cx: &mut ViewContext<Self>,
6420    ) {
6421        self.gutter_hovered = *hovered;
6422        cx.notify();
6423    }
6424
6425    pub fn insert_blocks(
6426        &mut self,
6427        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6428        cx: &mut ViewContext<Self>,
6429    ) -> Vec<BlockId> {
6430        let blocks = self
6431            .display_map
6432            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6433        self.request_autoscroll(Autoscroll::fit(), cx);
6434        blocks
6435    }
6436
6437    pub fn replace_blocks(
6438        &mut self,
6439        blocks: HashMap<BlockId, RenderBlock>,
6440        cx: &mut ViewContext<Self>,
6441    ) {
6442        self.display_map
6443            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6444        self.request_autoscroll(Autoscroll::fit(), cx);
6445    }
6446
6447    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6448        self.display_map.update(cx, |display_map, cx| {
6449            display_map.remove_blocks(block_ids, cx)
6450        });
6451    }
6452
6453    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6454        self.display_map
6455            .update(cx, |map, cx| map.snapshot(cx))
6456            .longest_row()
6457    }
6458
6459    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6460        self.display_map
6461            .update(cx, |map, cx| map.snapshot(cx))
6462            .max_point()
6463    }
6464
6465    pub fn text(&self, cx: &AppContext) -> String {
6466        self.buffer.read(cx).read(cx).text()
6467    }
6468
6469    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6470        self.transact(cx, |this, cx| {
6471            this.buffer
6472                .read(cx)
6473                .as_singleton()
6474                .expect("you can only call set_text on editors for singleton buffers")
6475                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6476        });
6477    }
6478
6479    pub fn display_text(&self, cx: &mut AppContext) -> String {
6480        self.display_map
6481            .update(cx, |map, cx| map.snapshot(cx))
6482            .text()
6483    }
6484
6485    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6486        let settings = self.buffer.read(cx).settings_at(0, cx);
6487        let mode = self
6488            .soft_wrap_mode_override
6489            .unwrap_or_else(|| settings.soft_wrap);
6490        match mode {
6491            language_settings::SoftWrap::None => SoftWrap::None,
6492            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6493            language_settings::SoftWrap::PreferredLineLength => {
6494                SoftWrap::Column(settings.preferred_line_length)
6495            }
6496        }
6497    }
6498
6499    pub fn set_soft_wrap_mode(
6500        &mut self,
6501        mode: language_settings::SoftWrap,
6502        cx: &mut ViewContext<Self>,
6503    ) {
6504        self.soft_wrap_mode_override = Some(mode);
6505        cx.notify();
6506    }
6507
6508    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6509        self.display_map
6510            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6511    }
6512
6513    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6514        if self.soft_wrap_mode_override.is_some() {
6515            self.soft_wrap_mode_override.take();
6516        } else {
6517            let soft_wrap = match self.soft_wrap_mode(cx) {
6518                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
6519                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
6520            };
6521            self.soft_wrap_mode_override = Some(soft_wrap);
6522        }
6523        cx.notify();
6524    }
6525
6526    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6527        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6528            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6529                cx.reveal_path(&file.abs_path(cx));
6530            }
6531        }
6532    }
6533
6534    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6535        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6536            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6537                if let Some(path) = file.abs_path(cx).to_str() {
6538                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6539                }
6540            }
6541        }
6542    }
6543
6544    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6545        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6546            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6547                if let Some(path) = file.path().to_str() {
6548                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6549                }
6550            }
6551        }
6552    }
6553
6554    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6555        self.highlighted_rows = rows;
6556    }
6557
6558    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6559        self.highlighted_rows.clone()
6560    }
6561
6562    pub fn highlight_background<T: 'static>(
6563        &mut self,
6564        ranges: Vec<Range<Anchor>>,
6565        color_fetcher: fn(&Theme) -> Color,
6566        cx: &mut ViewContext<Self>,
6567    ) {
6568        self.background_highlights
6569            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6570        cx.notify();
6571    }
6572
6573    #[allow(clippy::type_complexity)]
6574    pub fn clear_background_highlights<T: 'static>(
6575        &mut self,
6576        cx: &mut ViewContext<Self>,
6577    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6578        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6579        if highlights.is_some() {
6580            cx.notify();
6581        }
6582        highlights
6583    }
6584
6585    #[cfg(feature = "test-support")]
6586    pub fn all_background_highlights(
6587        &mut self,
6588        cx: &mut ViewContext<Self>,
6589    ) -> Vec<(Range<DisplayPoint>, Color)> {
6590        let snapshot = self.snapshot(cx);
6591        let buffer = &snapshot.buffer_snapshot;
6592        let start = buffer.anchor_before(0);
6593        let end = buffer.anchor_after(buffer.len());
6594        let theme = theme::current(cx);
6595        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
6596    }
6597
6598    fn document_highlights_for_position<'a>(
6599        &'a self,
6600        position: Anchor,
6601        buffer: &'a MultiBufferSnapshot,
6602    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6603        let read_highlights = self
6604            .background_highlights
6605            .get(&TypeId::of::<DocumentHighlightRead>())
6606            .map(|h| &h.1);
6607        let write_highlights = self
6608            .background_highlights
6609            .get(&TypeId::of::<DocumentHighlightWrite>())
6610            .map(|h| &h.1);
6611        let left_position = position.bias_left(buffer);
6612        let right_position = position.bias_right(buffer);
6613        read_highlights
6614            .into_iter()
6615            .chain(write_highlights)
6616            .flat_map(move |ranges| {
6617                let start_ix = match ranges.binary_search_by(|probe| {
6618                    let cmp = probe.end.cmp(&left_position, buffer);
6619                    if cmp.is_ge() {
6620                        Ordering::Greater
6621                    } else {
6622                        Ordering::Less
6623                    }
6624                }) {
6625                    Ok(i) | Err(i) => i,
6626                };
6627
6628                let right_position = right_position.clone();
6629                ranges[start_ix..]
6630                    .iter()
6631                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6632            })
6633    }
6634
6635    pub fn background_highlights_in_range(
6636        &self,
6637        search_range: Range<Anchor>,
6638        display_snapshot: &DisplaySnapshot,
6639        theme: &Theme,
6640    ) -> Vec<(Range<DisplayPoint>, Color)> {
6641        let mut results = Vec::new();
6642        let buffer = &display_snapshot.buffer_snapshot;
6643        for (color_fetcher, ranges) in self.background_highlights.values() {
6644            let color = color_fetcher(theme);
6645            let start_ix = match ranges.binary_search_by(|probe| {
6646                let cmp = probe.end.cmp(&search_range.start, buffer);
6647                if cmp.is_gt() {
6648                    Ordering::Greater
6649                } else {
6650                    Ordering::Less
6651                }
6652            }) {
6653                Ok(i) | Err(i) => i,
6654            };
6655            for range in &ranges[start_ix..] {
6656                if range.start.cmp(&search_range.end, buffer).is_ge() {
6657                    break;
6658                }
6659                let start = range
6660                    .start
6661                    .to_point(buffer)
6662                    .to_display_point(display_snapshot);
6663                let end = range
6664                    .end
6665                    .to_point(buffer)
6666                    .to_display_point(display_snapshot);
6667                results.push((start..end, color))
6668            }
6669        }
6670        results
6671    }
6672
6673    pub fn highlight_text<T: 'static>(
6674        &mut self,
6675        ranges: Vec<Range<Anchor>>,
6676        style: HighlightStyle,
6677        cx: &mut ViewContext<Self>,
6678    ) {
6679        self.display_map.update(cx, |map, _| {
6680            map.highlight_text(TypeId::of::<T>(), ranges, style)
6681        });
6682        cx.notify();
6683    }
6684
6685    pub fn text_highlights<'a, T: 'static>(
6686        &'a self,
6687        cx: &'a AppContext,
6688    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6689        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6690    }
6691
6692    pub fn clear_text_highlights<T: 'static>(
6693        &mut self,
6694        cx: &mut ViewContext<Self>,
6695    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6696        let highlights = self
6697            .display_map
6698            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6699        if highlights.is_some() {
6700            cx.notify();
6701        }
6702        highlights
6703    }
6704
6705    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6706        self.blink_manager.read(cx).visible() && self.focused
6707    }
6708
6709    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6710        cx.notify();
6711    }
6712
6713    fn on_buffer_event(
6714        &mut self,
6715        _: ModelHandle<MultiBuffer>,
6716        event: &multi_buffer::Event,
6717        cx: &mut ViewContext<Self>,
6718    ) {
6719        match event {
6720            multi_buffer::Event::Edited => {
6721                self.refresh_active_diagnostics(cx);
6722                self.refresh_code_actions(cx);
6723                if self.has_active_copilot_suggestion(cx) {
6724                    self.update_visible_copilot_suggestion(cx);
6725                }
6726                cx.emit(Event::BufferEdited);
6727            }
6728            multi_buffer::Event::ExcerptsAdded {
6729                buffer,
6730                predecessor,
6731                excerpts,
6732            } => cx.emit(Event::ExcerptsAdded {
6733                buffer: buffer.clone(),
6734                predecessor: *predecessor,
6735                excerpts: excerpts.clone(),
6736            }),
6737            multi_buffer::Event::ExcerptsRemoved { ids } => {
6738                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6739            }
6740            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6741            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6742            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6743            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6744            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6745            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6746            multi_buffer::Event::DiagnosticsUpdated => {
6747                self.refresh_active_diagnostics(cx);
6748            }
6749            multi_buffer::Event::LanguageChanged => {}
6750        }
6751    }
6752
6753    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6754        cx.notify();
6755    }
6756
6757    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6758        self.refresh_copilot_suggestions(true, cx);
6759    }
6760
6761    pub fn set_searchable(&mut self, searchable: bool) {
6762        self.searchable = searchable;
6763    }
6764
6765    pub fn searchable(&self) -> bool {
6766        self.searchable
6767    }
6768
6769    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6770        let active_item = workspace.active_item(cx);
6771        let editor_handle = if let Some(editor) = active_item
6772            .as_ref()
6773            .and_then(|item| item.act_as::<Self>(cx))
6774        {
6775            editor
6776        } else {
6777            cx.propagate_action();
6778            return;
6779        };
6780
6781        let editor = editor_handle.read(cx);
6782        let buffer = editor.buffer.read(cx);
6783        if buffer.is_singleton() {
6784            cx.propagate_action();
6785            return;
6786        }
6787
6788        let mut new_selections_by_buffer = HashMap::default();
6789        for selection in editor.selections.all::<usize>(cx) {
6790            for (buffer, mut range) in
6791                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6792            {
6793                if selection.reversed {
6794                    mem::swap(&mut range.start, &mut range.end);
6795                }
6796                new_selections_by_buffer
6797                    .entry(buffer)
6798                    .or_insert(Vec::new())
6799                    .push(range)
6800            }
6801        }
6802
6803        editor_handle.update(cx, |editor, cx| {
6804            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6805        });
6806        let pane = workspace.active_pane().clone();
6807        pane.update(cx, |pane, _| pane.disable_history());
6808
6809        // We defer the pane interaction because we ourselves are a workspace item
6810        // and activating a new item causes the pane to call a method on us reentrantly,
6811        // which panics if we're on the stack.
6812        cx.defer(move |workspace, cx| {
6813            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6814                let editor = workspace.open_project_item::<Self>(buffer, cx);
6815                editor.update(cx, |editor, cx| {
6816                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6817                        s.select_ranges(ranges);
6818                    });
6819                });
6820            }
6821
6822            pane.update(cx, |pane, _| pane.enable_history());
6823        });
6824    }
6825
6826    fn jump(
6827        workspace: &mut Workspace,
6828        path: ProjectPath,
6829        position: Point,
6830        anchor: language::Anchor,
6831        cx: &mut ViewContext<Workspace>,
6832    ) {
6833        let editor = workspace.open_path(path, None, true, cx);
6834        cx.spawn(|_, mut cx| async move {
6835            let editor = editor
6836                .await?
6837                .downcast::<Editor>()
6838                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6839                .downgrade();
6840            editor.update(&mut cx, |editor, cx| {
6841                let buffer = editor
6842                    .buffer()
6843                    .read(cx)
6844                    .as_singleton()
6845                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6846                let buffer = buffer.read(cx);
6847                let cursor = if buffer.can_resolve(&anchor) {
6848                    language::ToPoint::to_point(&anchor, buffer)
6849                } else {
6850                    buffer.clip_point(position, Bias::Left)
6851                };
6852
6853                let nav_history = editor.nav_history.take();
6854                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6855                    s.select_ranges([cursor..cursor]);
6856                });
6857                editor.nav_history = nav_history;
6858
6859                anyhow::Ok(())
6860            })??;
6861
6862            anyhow::Ok(())
6863        })
6864        .detach_and_log_err(cx);
6865    }
6866
6867    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6868        let snapshot = self.buffer.read(cx).read(cx);
6869        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6870        Some(
6871            ranges
6872                .iter()
6873                .map(move |range| {
6874                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6875                })
6876                .collect(),
6877        )
6878    }
6879
6880    fn selection_replacement_ranges(
6881        &self,
6882        range: Range<OffsetUtf16>,
6883        cx: &AppContext,
6884    ) -> Vec<Range<OffsetUtf16>> {
6885        let selections = self.selections.all::<OffsetUtf16>(cx);
6886        let newest_selection = selections
6887            .iter()
6888            .max_by_key(|selection| selection.id)
6889            .unwrap();
6890        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6891        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6892        let snapshot = self.buffer.read(cx).read(cx);
6893        selections
6894            .into_iter()
6895            .map(|mut selection| {
6896                selection.start.0 =
6897                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6898                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6899                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6900                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6901            })
6902            .collect()
6903    }
6904
6905    fn report_copilot_event(
6906        &self,
6907        suggestion_id: Option<String>,
6908        suggestion_accepted: bool,
6909        cx: &AppContext,
6910    ) {
6911        let Some(project) = &self.project else {
6912            return
6913        };
6914
6915        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
6916        let file_extension = self
6917            .buffer
6918            .read(cx)
6919            .as_singleton()
6920            .and_then(|b| b.read(cx).file())
6921            .and_then(|file| Path::new(file.file_name(cx)).extension())
6922            .and_then(|e| e.to_str())
6923            .map(|a| a.to_string());
6924
6925        let telemetry = project.read(cx).client().telemetry().clone();
6926        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
6927
6928        let event = ClickhouseEvent::Copilot {
6929            suggestion_id,
6930            suggestion_accepted,
6931            file_extension,
6932        };
6933        telemetry.report_clickhouse_event(event, telemetry_settings);
6934    }
6935
6936    fn report_editor_event(
6937        &self,
6938        name: &'static str,
6939        file_extension: Option<String>,
6940        cx: &AppContext,
6941    ) {
6942        let Some(project) = &self.project else {
6943            return
6944        };
6945
6946        // If None, we are in a file without an extension
6947        let file_extension = file_extension.or(self
6948            .buffer
6949            .read(cx)
6950            .as_singleton()
6951            .and_then(|b| b.read(cx).file())
6952            .and_then(|file| Path::new(file.file_name(cx)).extension())
6953            .and_then(|e| e.to_str())
6954            .map(|a| a.to_string()));
6955
6956        let vim_mode = cx
6957            .global::<SettingsStore>()
6958            .untyped_user_settings()
6959            .get("vim_mode")
6960            == Some(&serde_json::Value::Bool(true));
6961        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
6962        let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None);
6963        let copilot_enabled_for_language = self
6964            .buffer
6965            .read(cx)
6966            .settings_at(0, cx)
6967            .show_copilot_suggestions;
6968
6969        let telemetry = project.read(cx).client().telemetry().clone();
6970        telemetry.report_mixpanel_event(
6971            match name {
6972                "open" => "open editor",
6973                "save" => "save editor",
6974                _ => name,
6975            },
6976            json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true  }),
6977            telemetry_settings,
6978        );
6979        let event = ClickhouseEvent::Editor {
6980            file_extension,
6981            vim_mode,
6982            operation: name,
6983            copilot_enabled,
6984            copilot_enabled_for_language,
6985        };
6986        telemetry.report_clickhouse_event(event, telemetry_settings)
6987    }
6988
6989    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6990    /// with each line being an array of {text, highlight} objects.
6991    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6992        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6993            return;
6994        };
6995
6996        #[derive(Serialize)]
6997        struct Chunk<'a> {
6998            text: String,
6999            highlight: Option<&'a str>,
7000        }
7001
7002        let snapshot = buffer.read(cx).snapshot();
7003        let range = self
7004            .selected_text_range(cx)
7005            .and_then(|selected_range| {
7006                if selected_range.is_empty() {
7007                    None
7008                } else {
7009                    Some(selected_range)
7010                }
7011            })
7012            .unwrap_or_else(|| 0..snapshot.len());
7013
7014        let chunks = snapshot.chunks(range, true);
7015        let mut lines = Vec::new();
7016        let mut line: VecDeque<Chunk> = VecDeque::new();
7017
7018        let theme = &theme::current(cx).editor.syntax;
7019
7020        for chunk in chunks {
7021            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7022            let mut chunk_lines = chunk.text.split("\n").peekable();
7023            while let Some(text) = chunk_lines.next() {
7024                let mut merged_with_last_token = false;
7025                if let Some(last_token) = line.back_mut() {
7026                    if last_token.highlight == highlight {
7027                        last_token.text.push_str(text);
7028                        merged_with_last_token = true;
7029                    }
7030                }
7031
7032                if !merged_with_last_token {
7033                    line.push_back(Chunk {
7034                        text: text.into(),
7035                        highlight,
7036                    });
7037                }
7038
7039                if chunk_lines.peek().is_some() {
7040                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7041                        line.pop_front();
7042                    }
7043                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7044                        line.pop_back();
7045                    }
7046
7047                    lines.push(mem::take(&mut line));
7048                }
7049            }
7050        }
7051
7052        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7053        cx.write_to_clipboard(ClipboardItem::new(lines));
7054    }
7055}
7056
7057fn consume_contiguous_rows(
7058    contiguous_row_selections: &mut Vec<Selection<Point>>,
7059    selection: &Selection<Point>,
7060    display_map: &DisplaySnapshot,
7061    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7062) -> (u32, u32) {
7063    contiguous_row_selections.push(selection.clone());
7064    let start_row = selection.start.row;
7065    let mut end_row = ending_row(selection, display_map);
7066
7067    while let Some(next_selection) = selections.peek() {
7068        if next_selection.start.row <= end_row {
7069            end_row = ending_row(next_selection, display_map);
7070            contiguous_row_selections.push(selections.next().unwrap().clone());
7071        } else {
7072            break;
7073        }
7074    }
7075    (start_row, end_row)
7076}
7077
7078fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7079    if next_selection.end.column > 0 || next_selection.is_empty() {
7080        display_map.next_line_boundary(next_selection.end).0.row + 1
7081    } else {
7082        next_selection.end.row
7083    }
7084}
7085
7086impl EditorSnapshot {
7087    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7088        self.display_snapshot.buffer_snapshot.language_at(position)
7089    }
7090
7091    pub fn is_focused(&self) -> bool {
7092        self.is_focused
7093    }
7094
7095    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7096        self.placeholder_text.as_ref()
7097    }
7098
7099    pub fn scroll_position(&self) -> Vector2F {
7100        self.scroll_anchor.scroll_position(&self.display_snapshot)
7101    }
7102}
7103
7104impl Deref for EditorSnapshot {
7105    type Target = DisplaySnapshot;
7106
7107    fn deref(&self) -> &Self::Target {
7108        &self.display_snapshot
7109    }
7110}
7111
7112#[derive(Clone, Debug, PartialEq, Eq)]
7113pub enum Event {
7114    InputIgnored {
7115        text: Arc<str>,
7116    },
7117    ExcerptsAdded {
7118        buffer: ModelHandle<Buffer>,
7119        predecessor: ExcerptId,
7120        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7121    },
7122    ExcerptsRemoved {
7123        ids: Vec<ExcerptId>,
7124    },
7125    BufferEdited,
7126    Edited,
7127    Reparsed,
7128    Blurred,
7129    DirtyChanged,
7130    Saved,
7131    TitleChanged,
7132    SelectionsChanged {
7133        local: bool,
7134    },
7135    ScrollPositionChanged {
7136        local: bool,
7137    },
7138    Closed,
7139}
7140
7141pub struct EditorFocused(pub ViewHandle<Editor>);
7142pub struct EditorBlurred(pub ViewHandle<Editor>);
7143pub struct EditorReleased(pub WeakViewHandle<Editor>);
7144
7145impl Entity for Editor {
7146    type Event = Event;
7147
7148    fn release(&mut self, cx: &mut AppContext) {
7149        cx.emit_global(EditorReleased(self.handle.clone()));
7150    }
7151}
7152
7153impl View for Editor {
7154    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7155        let style = self.style(cx);
7156        let font_changed = self.display_map.update(cx, |map, cx| {
7157            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7158            map.set_font(style.text.font_id, style.text.font_size, cx)
7159        });
7160
7161        if font_changed {
7162            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7163                hide_hover(editor, cx);
7164                hide_link_definition(editor, cx);
7165            });
7166        }
7167
7168        Stack::new()
7169            .with_child(EditorElement::new(style.clone()))
7170            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7171            .into_any()
7172    }
7173
7174    fn ui_name() -> &'static str {
7175        "Editor"
7176    }
7177
7178    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7179        if cx.is_self_focused() {
7180            let focused_event = EditorFocused(cx.handle());
7181            cx.emit_global(focused_event);
7182        }
7183        if let Some(rename) = self.pending_rename.as_ref() {
7184            cx.focus(&rename.editor);
7185        } else {
7186            if !self.focused {
7187                self.blink_manager.update(cx, BlinkManager::enable);
7188            }
7189            self.focused = true;
7190            self.buffer.update(cx, |buffer, cx| {
7191                buffer.finalize_last_transaction(cx);
7192                if self.leader_replica_id.is_none() {
7193                    buffer.set_active_selections(
7194                        &self.selections.disjoint_anchors(),
7195                        self.selections.line_mode,
7196                        self.cursor_shape,
7197                        cx,
7198                    );
7199                }
7200            });
7201        }
7202    }
7203
7204    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7205        let blurred_event = EditorBlurred(cx.handle());
7206        cx.emit_global(blurred_event);
7207        self.focused = false;
7208        self.blink_manager.update(cx, BlinkManager::disable);
7209        self.buffer
7210            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7211        self.hide_context_menu(cx);
7212        hide_hover(self, cx);
7213        cx.emit(Event::Blurred);
7214        cx.notify();
7215    }
7216
7217    fn modifiers_changed(
7218        &mut self,
7219        event: &gpui::platform::ModifiersChangedEvent,
7220        cx: &mut ViewContext<Self>,
7221    ) -> bool {
7222        let pending_selection = self.has_pending_selection();
7223
7224        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7225            if event.cmd && !pending_selection {
7226                let snapshot = self.snapshot(cx);
7227                let kind = if event.shift {
7228                    LinkDefinitionKind::Type
7229                } else {
7230                    LinkDefinitionKind::Symbol
7231                };
7232
7233                show_link_definition(kind, self, point, snapshot, cx);
7234                return false;
7235            }
7236        }
7237
7238        {
7239            if self.link_go_to_definition_state.symbol_range.is_some()
7240                || !self.link_go_to_definition_state.definitions.is_empty()
7241            {
7242                self.link_go_to_definition_state.symbol_range.take();
7243                self.link_go_to_definition_state.definitions.clear();
7244                cx.notify();
7245            }
7246
7247            self.link_go_to_definition_state.task = None;
7248
7249            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7250        }
7251
7252        false
7253    }
7254
7255    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
7256        Self::reset_to_default_keymap_context(keymap);
7257        let mode = match self.mode {
7258            EditorMode::SingleLine => "single_line",
7259            EditorMode::AutoHeight { .. } => "auto_height",
7260            EditorMode::Full => "full",
7261        };
7262        keymap.add_key("mode", mode);
7263        if self.pending_rename.is_some() {
7264            keymap.add_identifier("renaming");
7265        }
7266        match self.context_menu.as_ref() {
7267            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7268            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7269            None => {}
7270        }
7271
7272        for layer in self.keymap_context_layers.values() {
7273            keymap.extend(layer);
7274        }
7275    }
7276
7277    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7278        Some(
7279            self.buffer
7280                .read(cx)
7281                .read(cx)
7282                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7283                .collect(),
7284        )
7285    }
7286
7287    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7288        // Prevent the IME menu from appearing when holding down an alphabetic key
7289        // while input is disabled.
7290        if !self.input_enabled {
7291            return None;
7292        }
7293
7294        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7295        Some(range.start.0..range.end.0)
7296    }
7297
7298    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7299        let snapshot = self.buffer.read(cx).read(cx);
7300        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7301        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7302    }
7303
7304    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7305        self.clear_text_highlights::<InputComposition>(cx);
7306        self.ime_transaction.take();
7307    }
7308
7309    fn replace_text_in_range(
7310        &mut self,
7311        range_utf16: Option<Range<usize>>,
7312        text: &str,
7313        cx: &mut ViewContext<Self>,
7314    ) {
7315        self.transact(cx, |this, cx| {
7316            if this.input_enabled {
7317                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7318                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7319                    Some(this.selection_replacement_ranges(range_utf16, cx))
7320                } else {
7321                    this.marked_text_ranges(cx)
7322                };
7323
7324                if let Some(new_selected_ranges) = new_selected_ranges {
7325                    this.change_selections(None, cx, |selections| {
7326                        selections.select_ranges(new_selected_ranges)
7327                    });
7328                }
7329            }
7330
7331            this.handle_input(text, cx);
7332        });
7333
7334        if !self.input_enabled {
7335            return;
7336        }
7337
7338        if let Some(transaction) = self.ime_transaction {
7339            self.buffer.update(cx, |buffer, cx| {
7340                buffer.group_until_transaction(transaction, cx);
7341            });
7342        }
7343
7344        self.unmark_text(cx);
7345    }
7346
7347    fn replace_and_mark_text_in_range(
7348        &mut self,
7349        range_utf16: Option<Range<usize>>,
7350        text: &str,
7351        new_selected_range_utf16: Option<Range<usize>>,
7352        cx: &mut ViewContext<Self>,
7353    ) {
7354        if !self.input_enabled {
7355            return;
7356        }
7357
7358        let transaction = self.transact(cx, |this, cx| {
7359            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7360                let snapshot = this.buffer.read(cx).read(cx);
7361                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7362                    for marked_range in &mut marked_ranges {
7363                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7364                        marked_range.start.0 += relative_range_utf16.start;
7365                        marked_range.start =
7366                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7367                        marked_range.end =
7368                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7369                    }
7370                }
7371                Some(marked_ranges)
7372            } else if let Some(range_utf16) = range_utf16 {
7373                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7374                Some(this.selection_replacement_ranges(range_utf16, cx))
7375            } else {
7376                None
7377            };
7378
7379            if let Some(ranges) = ranges_to_replace {
7380                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7381            }
7382
7383            let marked_ranges = {
7384                let snapshot = this.buffer.read(cx).read(cx);
7385                this.selections
7386                    .disjoint_anchors()
7387                    .iter()
7388                    .map(|selection| {
7389                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7390                    })
7391                    .collect::<Vec<_>>()
7392            };
7393
7394            if text.is_empty() {
7395                this.unmark_text(cx);
7396            } else {
7397                this.highlight_text::<InputComposition>(
7398                    marked_ranges.clone(),
7399                    this.style(cx).composition_mark,
7400                    cx,
7401                );
7402            }
7403
7404            this.handle_input(text, cx);
7405
7406            if let Some(new_selected_range) = new_selected_range_utf16 {
7407                let snapshot = this.buffer.read(cx).read(cx);
7408                let new_selected_ranges = marked_ranges
7409                    .into_iter()
7410                    .map(|marked_range| {
7411                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7412                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7413                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7414                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7415                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7416                    })
7417                    .collect::<Vec<_>>();
7418
7419                drop(snapshot);
7420                this.change_selections(None, cx, |selections| {
7421                    selections.select_ranges(new_selected_ranges)
7422                });
7423            }
7424        });
7425
7426        self.ime_transaction = self.ime_transaction.or(transaction);
7427        if let Some(transaction) = self.ime_transaction {
7428            self.buffer.update(cx, |buffer, cx| {
7429                buffer.group_until_transaction(transaction, cx);
7430            });
7431        }
7432
7433        if self.text_highlights::<InputComposition>(cx).is_none() {
7434            self.ime_transaction.take();
7435        }
7436    }
7437}
7438
7439fn build_style(
7440    settings: &ThemeSettings,
7441    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7442    override_text_style: Option<&OverrideTextStyle>,
7443    cx: &AppContext,
7444) -> EditorStyle {
7445    let font_cache = cx.font_cache();
7446
7447    let theme_id = settings.theme.meta.id;
7448    let mut theme = settings.theme.editor.clone();
7449    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7450        let field_editor_theme = get_field_editor_theme(&settings.theme);
7451        theme.text_color = field_editor_theme.text.color;
7452        theme.selection = field_editor_theme.selection;
7453        theme.background = field_editor_theme
7454            .container
7455            .background_color
7456            .unwrap_or_default();
7457        EditorStyle {
7458            text: field_editor_theme.text,
7459            placeholder_text: field_editor_theme.placeholder_text,
7460            theme,
7461            theme_id,
7462        }
7463    } else {
7464        let font_family_id = settings.buffer_font_family;
7465        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7466        let font_properties = Default::default();
7467        let font_id = font_cache
7468            .select_font(font_family_id, &font_properties)
7469            .unwrap();
7470        let font_size = settings.buffer_font_size(cx);
7471        EditorStyle {
7472            text: TextStyle {
7473                color: settings.theme.editor.text_color,
7474                font_family_name,
7475                font_family_id,
7476                font_id,
7477                font_size,
7478                font_properties,
7479                underline: Default::default(),
7480            },
7481            placeholder_text: None,
7482            theme,
7483            theme_id,
7484        }
7485    };
7486
7487    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7488        if let Some(highlighted) = style
7489            .text
7490            .clone()
7491            .highlight(highlight_style, font_cache)
7492            .log_err()
7493        {
7494            style.text = highlighted;
7495        }
7496    }
7497
7498    style
7499}
7500
7501trait SelectionExt {
7502    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7503    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7504    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7505    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7506        -> Range<u32>;
7507}
7508
7509impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7510    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7511        let start = self.start.to_point(buffer);
7512        let end = self.end.to_point(buffer);
7513        if self.reversed {
7514            end..start
7515        } else {
7516            start..end
7517        }
7518    }
7519
7520    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7521        let start = self.start.to_offset(buffer);
7522        let end = self.end.to_offset(buffer);
7523        if self.reversed {
7524            end..start
7525        } else {
7526            start..end
7527        }
7528    }
7529
7530    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7531        let start = self
7532            .start
7533            .to_point(&map.buffer_snapshot)
7534            .to_display_point(map);
7535        let end = self
7536            .end
7537            .to_point(&map.buffer_snapshot)
7538            .to_display_point(map);
7539        if self.reversed {
7540            end..start
7541        } else {
7542            start..end
7543        }
7544    }
7545
7546    fn spanned_rows(
7547        &self,
7548        include_end_if_at_line_start: bool,
7549        map: &DisplaySnapshot,
7550    ) -> Range<u32> {
7551        let start = self.start.to_point(&map.buffer_snapshot);
7552        let mut end = self.end.to_point(&map.buffer_snapshot);
7553        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7554            end.row -= 1;
7555        }
7556
7557        let buffer_start = map.prev_line_boundary(start).0;
7558        let buffer_end = map.next_line_boundary(end).0;
7559        buffer_start.row..buffer_end.row + 1
7560    }
7561}
7562
7563impl<T: InvalidationRegion> InvalidationStack<T> {
7564    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7565    where
7566        S: Clone + ToOffset,
7567    {
7568        while let Some(region) = self.last() {
7569            let all_selections_inside_invalidation_ranges =
7570                if selections.len() == region.ranges().len() {
7571                    selections
7572                        .iter()
7573                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7574                        .all(|(selection, invalidation_range)| {
7575                            let head = selection.head().to_offset(buffer);
7576                            invalidation_range.start <= head && invalidation_range.end >= head
7577                        })
7578                } else {
7579                    false
7580                };
7581
7582            if all_selections_inside_invalidation_ranges {
7583                break;
7584            } else {
7585                self.pop();
7586            }
7587        }
7588    }
7589}
7590
7591impl<T> Default for InvalidationStack<T> {
7592    fn default() -> Self {
7593        Self(Default::default())
7594    }
7595}
7596
7597impl<T> Deref for InvalidationStack<T> {
7598    type Target = Vec<T>;
7599
7600    fn deref(&self) -> &Self::Target {
7601        &self.0
7602    }
7603}
7604
7605impl<T> DerefMut for InvalidationStack<T> {
7606    fn deref_mut(&mut self) -> &mut Self::Target {
7607        &mut self.0
7608    }
7609}
7610
7611impl InvalidationRegion for SnippetState {
7612    fn ranges(&self) -> &[Range<Anchor>] {
7613        &self.ranges[self.active_index]
7614    }
7615}
7616
7617impl Deref for EditorStyle {
7618    type Target = theme::Editor;
7619
7620    fn deref(&self) -> &Self::Target {
7621        &self.theme
7622    }
7623}
7624
7625pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7626    let mut highlighted_lines = Vec::new();
7627    for (index, line) in diagnostic.message.lines().enumerate() {
7628        let line = match &diagnostic.source {
7629            Some(source) if index == 0 => {
7630                let source_highlight = Vec::from_iter(0..source.len());
7631                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7632            }
7633
7634            _ => highlight_diagnostic_message(Vec::new(), line),
7635        };
7636        highlighted_lines.push(line);
7637    }
7638
7639    Arc::new(move |cx: &mut BlockContext| {
7640        let settings = settings::get::<ThemeSettings>(cx);
7641        let theme = &settings.theme.editor;
7642        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7643        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7644        Flex::column()
7645            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7646                Label::new(
7647                    line.clone(),
7648                    style.message.clone().with_font_size(font_size),
7649                )
7650                .with_highlights(highlights.clone())
7651                .contained()
7652                .with_margin_left(cx.anchor_x)
7653            }))
7654            .aligned()
7655            .left()
7656            .into_any()
7657    })
7658}
7659
7660pub fn highlight_diagnostic_message(
7661    inital_highlights: Vec<usize>,
7662    message: &str,
7663) -> (String, Vec<usize>) {
7664    let mut message_without_backticks = String::new();
7665    let mut prev_offset = 0;
7666    let mut inside_block = false;
7667    let mut highlights = inital_highlights;
7668    for (match_ix, (offset, _)) in message
7669        .match_indices('`')
7670        .chain([(message.len(), "")])
7671        .enumerate()
7672    {
7673        message_without_backticks.push_str(&message[prev_offset..offset]);
7674        if inside_block {
7675            highlights.extend(prev_offset - match_ix..offset - match_ix);
7676        }
7677
7678        inside_block = !inside_block;
7679        prev_offset = offset + 1;
7680    }
7681
7682    (message_without_backticks, highlights)
7683}
7684
7685pub fn diagnostic_style(
7686    severity: DiagnosticSeverity,
7687    valid: bool,
7688    theme: &theme::Editor,
7689) -> DiagnosticStyle {
7690    match (severity, valid) {
7691        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7692        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7693        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7694        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7695        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7696        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7697        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7698        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7699        _ => theme.invalid_hint_diagnostic.clone(),
7700    }
7701}
7702
7703pub fn combine_syntax_and_fuzzy_match_highlights(
7704    text: &str,
7705    default_style: HighlightStyle,
7706    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7707    match_indices: &[usize],
7708) -> Vec<(Range<usize>, HighlightStyle)> {
7709    let mut result = Vec::new();
7710    let mut match_indices = match_indices.iter().copied().peekable();
7711
7712    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7713    {
7714        syntax_highlight.weight = None;
7715
7716        // Add highlights for any fuzzy match characters before the next
7717        // syntax highlight range.
7718        while let Some(&match_index) = match_indices.peek() {
7719            if match_index >= range.start {
7720                break;
7721            }
7722            match_indices.next();
7723            let end_index = char_ix_after(match_index, text);
7724            let mut match_style = default_style;
7725            match_style.weight = Some(fonts::Weight::BOLD);
7726            result.push((match_index..end_index, match_style));
7727        }
7728
7729        if range.start == usize::MAX {
7730            break;
7731        }
7732
7733        // Add highlights for any fuzzy match characters within the
7734        // syntax highlight range.
7735        let mut offset = range.start;
7736        while let Some(&match_index) = match_indices.peek() {
7737            if match_index >= range.end {
7738                break;
7739            }
7740
7741            match_indices.next();
7742            if match_index > offset {
7743                result.push((offset..match_index, syntax_highlight));
7744            }
7745
7746            let mut end_index = char_ix_after(match_index, text);
7747            while let Some(&next_match_index) = match_indices.peek() {
7748                if next_match_index == end_index && next_match_index < range.end {
7749                    end_index = char_ix_after(next_match_index, text);
7750                    match_indices.next();
7751                } else {
7752                    break;
7753                }
7754            }
7755
7756            let mut match_style = syntax_highlight;
7757            match_style.weight = Some(fonts::Weight::BOLD);
7758            result.push((match_index..end_index, match_style));
7759            offset = end_index;
7760        }
7761
7762        if offset < range.end {
7763            result.push((offset..range.end, syntax_highlight));
7764        }
7765    }
7766
7767    fn char_ix_after(ix: usize, text: &str) -> usize {
7768        ix + text[ix..].chars().next().unwrap().len_utf8()
7769    }
7770
7771    result
7772}
7773
7774pub fn styled_runs_for_code_label<'a>(
7775    label: &'a CodeLabel,
7776    syntax_theme: &'a theme::SyntaxTheme,
7777) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7778    let fade_out = HighlightStyle {
7779        fade_out: Some(0.35),
7780        ..Default::default()
7781    };
7782
7783    let mut prev_end = label.filter_range.end;
7784    label
7785        .runs
7786        .iter()
7787        .enumerate()
7788        .flat_map(move |(ix, (range, highlight_id))| {
7789            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7790                style
7791            } else {
7792                return Default::default();
7793            };
7794            let mut muted_style = style;
7795            muted_style.highlight(fade_out);
7796
7797            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7798            if range.start >= label.filter_range.end {
7799                if range.start > prev_end {
7800                    runs.push((prev_end..range.start, fade_out));
7801                }
7802                runs.push((range.clone(), muted_style));
7803            } else if range.end <= label.filter_range.end {
7804                runs.push((range.clone(), style));
7805            } else {
7806                runs.push((range.start..label.filter_range.end, style));
7807                runs.push((label.filter_range.end..range.end, muted_style));
7808            }
7809            prev_end = cmp::max(prev_end, range.end);
7810
7811            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7812                runs.push((prev_end..label.text.len(), fade_out));
7813            }
7814
7815            runs
7816        })
7817}
7818
7819pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7820    let mut index = 0;
7821    let mut codepoints = text.char_indices().peekable();
7822
7823    std::iter::from_fn(move || {
7824        let start_index = index;
7825        while let Some((new_index, codepoint)) = codepoints.next() {
7826            index = new_index + codepoint.len_utf8();
7827            let current_upper = codepoint.is_uppercase();
7828            let next_upper = codepoints
7829                .peek()
7830                .map(|(_, c)| c.is_uppercase())
7831                .unwrap_or(false);
7832
7833            if !current_upper && next_upper {
7834                return Some(&text[start_index..index]);
7835            }
7836        }
7837
7838        index = text.len();
7839        if start_index < text.len() {
7840            return Some(&text[start_index..]);
7841        }
7842        None
7843    })
7844    .flat_map(|word| word.split_inclusive('_'))
7845}
7846
7847trait RangeToAnchorExt {
7848    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7849}
7850
7851impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7852    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7853        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7854    }
7855}