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