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