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