editor.rs

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