editor.rs

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