editor.rs

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