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