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    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2658        let offset = position.to_offset(buffer);
2659        let (word_range, kind) = buffer.surrounding_word(offset);
2660        if offset > word_range.start && kind == Some(CharKind::Word) {
2661            Some(
2662                buffer
2663                    .text_for_range(word_range.start..offset)
2664                    .collect::<String>(),
2665            )
2666        } else {
2667            None
2668        }
2669    }
2670
2671    fn refresh_inlays(&mut self, reason: InlayRefreshReason, cx: &mut ViewContext<Self>) {
2672        if self.project.is_none() || self.mode != EditorMode::Full {
2673            return;
2674        }
2675
2676        let (invalidate_cache, required_languages) = match reason {
2677            InlayRefreshReason::SettingsChange(new_settings) => {
2678                match self.inlay_hint_cache.update_settings(
2679                    &self.buffer,
2680                    new_settings,
2681                    self.visible_inlay_hints(cx),
2682                    cx,
2683                ) {
2684                    ControlFlow::Break(Some(InlaySplice {
2685                        to_remove,
2686                        to_insert,
2687                    })) => {
2688                        self.splice_inlay_hints(to_remove, to_insert, cx);
2689                        return;
2690                    }
2691                    ControlFlow::Break(None) => return,
2692                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
2693                }
2694            }
2695            InlayRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
2696            InlayRefreshReason::BufferEdited(buffer_languages) => {
2697                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
2698            }
2699            InlayRefreshReason::RefreshRequested => (InvalidationStrategy::RefreshRequested, None),
2700        };
2701
2702        if let Some(InlaySplice {
2703            to_remove,
2704            to_insert,
2705        }) = self.inlay_hint_cache.spawn_hint_refresh(
2706            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
2707            invalidate_cache,
2708            cx,
2709        ) {
2710            self.splice_inlay_hints(to_remove, to_insert, cx);
2711        }
2712    }
2713
2714    fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> {
2715        self.display_map
2716            .read(cx)
2717            .current_inlays()
2718            .filter(move |inlay| {
2719                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
2720            })
2721            .cloned()
2722            .collect()
2723    }
2724
2725    pub fn excerpt_visible_offsets(
2726        &self,
2727        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
2728        cx: &mut ViewContext<'_, '_, Editor>,
2729    ) -> HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)> {
2730        let multi_buffer = self.buffer().read(cx);
2731        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
2732        let multi_buffer_visible_start = self
2733            .scroll_manager
2734            .anchor()
2735            .anchor
2736            .to_point(&multi_buffer_snapshot);
2737        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
2738            multi_buffer_visible_start
2739                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
2740            Bias::Left,
2741        );
2742        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
2743        multi_buffer
2744            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
2745            .into_iter()
2746            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
2747            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
2748                let buffer = buffer_handle.read(cx);
2749                let language = buffer.language()?;
2750                if let Some(restrict_to_languages) = restrict_to_languages {
2751                    if !restrict_to_languages.contains(language) {
2752                        return None;
2753                    }
2754                }
2755                Some((
2756                    excerpt_id,
2757                    (
2758                        buffer_handle,
2759                        buffer.version().clone(),
2760                        excerpt_visible_range,
2761                    ),
2762                ))
2763            })
2764            .collect()
2765    }
2766
2767    fn splice_inlay_hints(
2768        &self,
2769        to_remove: Vec<InlayId>,
2770        to_insert: Vec<Inlay>,
2771        cx: &mut ViewContext<Self>,
2772    ) {
2773        self.display_map.update(cx, |display_map, cx| {
2774            display_map.splice_inlays(to_remove, to_insert, cx);
2775        });
2776    }
2777
2778    fn trigger_on_type_formatting(
2779        &self,
2780        input: String,
2781        cx: &mut ViewContext<Self>,
2782    ) -> Option<Task<Result<()>>> {
2783        if input.len() != 1 {
2784            return None;
2785        }
2786
2787        let project = self.project.as_ref()?;
2788        let position = self.selections.newest_anchor().head();
2789        let (buffer, buffer_position) = self
2790            .buffer
2791            .read(cx)
2792            .text_anchor_for_position(position.clone(), cx)?;
2793
2794        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
2795        // hence we do LSP request & edit on host side only — add formats to host's history.
2796        let push_to_lsp_host_history = true;
2797        // If this is not the host, append its history with new edits.
2798        let push_to_client_history = project.read(cx).is_remote();
2799
2800        let on_type_formatting = project.update(cx, |project, cx| {
2801            project.on_type_format(
2802                buffer.clone(),
2803                buffer_position,
2804                input,
2805                push_to_lsp_host_history,
2806                cx,
2807            )
2808        });
2809        Some(cx.spawn(|editor, mut cx| async move {
2810            if let Some(transaction) = on_type_formatting.await? {
2811                if push_to_client_history {
2812                    buffer.update(&mut cx, |buffer, _| {
2813                        buffer.push_transaction(transaction, Instant::now());
2814                    });
2815                }
2816                editor.update(&mut cx, |editor, cx| {
2817                    editor.refresh_document_highlights(cx);
2818                })?;
2819            }
2820            Ok(())
2821        }))
2822    }
2823
2824    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2825        if self.pending_rename.is_some() {
2826            return;
2827        }
2828
2829        let project = if let Some(project) = self.project.clone() {
2830            project
2831        } else {
2832            return;
2833        };
2834
2835        let position = self.selections.newest_anchor().head();
2836        let (buffer, buffer_position) = if let Some(output) = self
2837            .buffer
2838            .read(cx)
2839            .text_anchor_for_position(position.clone(), cx)
2840        {
2841            output
2842        } else {
2843            return;
2844        };
2845
2846        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2847        let completions = project.update(cx, |project, cx| {
2848            project.completions(&buffer, buffer_position, cx)
2849        });
2850
2851        let id = post_inc(&mut self.next_completion_id);
2852        let task = cx.spawn(|this, mut cx| {
2853            async move {
2854                let menu = if let Some(completions) = completions.await.log_err() {
2855                    let mut menu = CompletionsMenu {
2856                        id,
2857                        initial_position: position,
2858                        match_candidates: completions
2859                            .iter()
2860                            .enumerate()
2861                            .map(|(id, completion)| {
2862                                StringMatchCandidate::new(
2863                                    id,
2864                                    completion.label.text[completion.label.filter_range.clone()]
2865                                        .into(),
2866                                )
2867                            })
2868                            .collect(),
2869                        buffer,
2870                        completions: completions.into(),
2871                        matches: Vec::new().into(),
2872                        selected_item: 0,
2873                        list: Default::default(),
2874                    };
2875                    menu.filter(query.as_deref(), cx.background()).await;
2876                    if menu.matches.is_empty() {
2877                        None
2878                    } else {
2879                        Some(menu)
2880                    }
2881                } else {
2882                    None
2883                };
2884
2885                this.update(&mut cx, |this, cx| {
2886                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2887
2888                    match this.context_menu.as_ref() {
2889                        None => {}
2890                        Some(ContextMenu::Completions(prev_menu)) => {
2891                            if prev_menu.id > id {
2892                                return;
2893                            }
2894                        }
2895                        _ => return,
2896                    }
2897
2898                    if this.focused && menu.is_some() {
2899                        let menu = menu.unwrap();
2900                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2901                    } else if this.completion_tasks.is_empty() {
2902                        // If there are no more completion tasks and the last menu was
2903                        // empty, we should hide it. If it was already hidden, we should
2904                        // also show the copilot suggestion when available.
2905                        if this.hide_context_menu(cx).is_none() {
2906                            this.update_visible_copilot_suggestion(cx);
2907                        }
2908                    }
2909                })?;
2910
2911                Ok::<_, anyhow::Error>(())
2912            }
2913            .log_err()
2914        });
2915        self.completion_tasks.push((id, task));
2916    }
2917
2918    pub fn confirm_completion(
2919        &mut self,
2920        action: &ConfirmCompletion,
2921        cx: &mut ViewContext<Self>,
2922    ) -> Option<Task<Result<()>>> {
2923        use language::ToOffset as _;
2924
2925        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2926            menu
2927        } else {
2928            return None;
2929        };
2930
2931        let mat = completions_menu
2932            .matches
2933            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2934        let buffer_handle = completions_menu.buffer;
2935        let completion = completions_menu.completions.get(mat.candidate_id)?;
2936
2937        let snippet;
2938        let text;
2939        if completion.is_snippet() {
2940            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2941            text = snippet.as_ref().unwrap().text.clone();
2942        } else {
2943            snippet = None;
2944            text = completion.new_text.clone();
2945        };
2946        let selections = self.selections.all::<usize>(cx);
2947        let buffer = buffer_handle.read(cx);
2948        let old_range = completion.old_range.to_offset(buffer);
2949        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2950
2951        let newest_selection = self.selections.newest_anchor();
2952        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2953            return None;
2954        }
2955
2956        let lookbehind = newest_selection
2957            .start
2958            .text_anchor
2959            .to_offset(buffer)
2960            .saturating_sub(old_range.start);
2961        let lookahead = old_range
2962            .end
2963            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2964        let mut common_prefix_len = old_text
2965            .bytes()
2966            .zip(text.bytes())
2967            .take_while(|(a, b)| a == b)
2968            .count();
2969
2970        let snapshot = self.buffer.read(cx).snapshot(cx);
2971        let mut ranges = Vec::new();
2972        for selection in &selections {
2973            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2974                let start = selection.start.saturating_sub(lookbehind);
2975                let end = selection.end + lookahead;
2976                ranges.push(start + common_prefix_len..end);
2977            } else {
2978                common_prefix_len = 0;
2979                ranges.clear();
2980                ranges.extend(selections.iter().map(|s| {
2981                    if s.id == newest_selection.id {
2982                        old_range.clone()
2983                    } else {
2984                        s.start..s.end
2985                    }
2986                }));
2987                break;
2988            }
2989        }
2990        let text = &text[common_prefix_len..];
2991
2992        self.transact(cx, |this, cx| {
2993            if let Some(mut snippet) = snippet {
2994                snippet.text = text.to_string();
2995                for tabstop in snippet.tabstops.iter_mut().flatten() {
2996                    tabstop.start -= common_prefix_len as isize;
2997                    tabstop.end -= common_prefix_len as isize;
2998                }
2999
3000                this.insert_snippet(&ranges, snippet, cx).log_err();
3001            } else {
3002                this.buffer.update(cx, |buffer, cx| {
3003                    buffer.edit(
3004                        ranges.iter().map(|range| (range.clone(), text)),
3005                        Some(AutoindentMode::EachLine),
3006                        cx,
3007                    );
3008                });
3009            }
3010
3011            this.refresh_copilot_suggestions(true, cx);
3012        });
3013
3014        let project = self.project.clone()?;
3015        let apply_edits = project.update(cx, |project, cx| {
3016            project.apply_additional_edits_for_completion(
3017                buffer_handle,
3018                completion.clone(),
3019                true,
3020                cx,
3021            )
3022        });
3023        Some(cx.foreground().spawn(async move {
3024            apply_edits.await?;
3025            Ok(())
3026        }))
3027    }
3028
3029    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3030        if matches!(
3031            self.context_menu.as_ref(),
3032            Some(ContextMenu::CodeActions(_))
3033        ) {
3034            self.context_menu.take();
3035            cx.notify();
3036            return;
3037        }
3038
3039        let deployed_from_indicator = action.deployed_from_indicator;
3040        let mut task = self.code_actions_task.take();
3041        cx.spawn(|this, mut cx| async move {
3042            while let Some(prev_task) = task {
3043                prev_task.await;
3044                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3045            }
3046
3047            this.update(&mut cx, |this, cx| {
3048                if this.focused {
3049                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3050                        this.show_context_menu(
3051                            ContextMenu::CodeActions(CodeActionsMenu {
3052                                buffer,
3053                                actions,
3054                                selected_item: Default::default(),
3055                                list: Default::default(),
3056                                deployed_from_indicator,
3057                            }),
3058                            cx,
3059                        );
3060                    }
3061                }
3062            })?;
3063
3064            Ok::<_, anyhow::Error>(())
3065        })
3066        .detach_and_log_err(cx);
3067    }
3068
3069    pub fn confirm_code_action(
3070        workspace: &mut Workspace,
3071        action: &ConfirmCodeAction,
3072        cx: &mut ViewContext<Workspace>,
3073    ) -> Option<Task<Result<()>>> {
3074        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3075        let actions_menu = if let ContextMenu::CodeActions(menu) =
3076            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3077        {
3078            menu
3079        } else {
3080            return None;
3081        };
3082        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3083        let action = actions_menu.actions.get(action_ix)?.clone();
3084        let title = action.lsp_action.title.clone();
3085        let buffer = actions_menu.buffer;
3086
3087        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3088            project.apply_code_action(buffer, action, true, cx)
3089        });
3090        let editor = editor.downgrade();
3091        Some(cx.spawn(|workspace, cx| async move {
3092            let project_transaction = apply_code_actions.await?;
3093            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3094        }))
3095    }
3096
3097    async fn open_project_transaction(
3098        this: &WeakViewHandle<Editor>,
3099        workspace: WeakViewHandle<Workspace>,
3100        transaction: ProjectTransaction,
3101        title: String,
3102        mut cx: AsyncAppContext,
3103    ) -> Result<()> {
3104        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3105
3106        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3107        entries.sort_unstable_by_key(|(buffer, _)| {
3108            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3109        });
3110
3111        // If the project transaction's edits are all contained within this editor, then
3112        // avoid opening a new editor to display them.
3113
3114        if let Some((buffer, transaction)) = entries.first() {
3115            if entries.len() == 1 {
3116                let excerpt = this.read_with(&cx, |editor, cx| {
3117                    editor
3118                        .buffer()
3119                        .read(cx)
3120                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3121                })?;
3122                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3123                    if excerpted_buffer == *buffer {
3124                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3125                            let excerpt_range = excerpt_range.to_offset(buffer);
3126                            buffer
3127                                .edited_ranges_for_transaction::<usize>(transaction)
3128                                .all(|range| {
3129                                    excerpt_range.start <= range.start
3130                                        && excerpt_range.end >= range.end
3131                                })
3132                        });
3133
3134                        if all_edits_within_excerpt {
3135                            return Ok(());
3136                        }
3137                    }
3138                }
3139            }
3140        } else {
3141            return Ok(());
3142        }
3143
3144        let mut ranges_to_highlight = Vec::new();
3145        let excerpt_buffer = cx.add_model(|cx| {
3146            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3147            for (buffer_handle, transaction) in &entries {
3148                let buffer = buffer_handle.read(cx);
3149                ranges_to_highlight.extend(
3150                    multibuffer.push_excerpts_with_context_lines(
3151                        buffer_handle.clone(),
3152                        buffer
3153                            .edited_ranges_for_transaction::<usize>(transaction)
3154                            .collect(),
3155                        1,
3156                        cx,
3157                    ),
3158                );
3159            }
3160            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3161            multibuffer
3162        });
3163
3164        workspace.update(&mut cx, |workspace, cx| {
3165            let project = workspace.project().clone();
3166            let editor =
3167                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3168            workspace.add_item(Box::new(editor.clone()), cx);
3169            editor.update(cx, |editor, cx| {
3170                editor.highlight_background::<Self>(
3171                    ranges_to_highlight,
3172                    |theme| theme.editor.highlighted_line_background,
3173                    cx,
3174                );
3175            });
3176        })?;
3177
3178        Ok(())
3179    }
3180
3181    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3182        let project = self.project.as_ref()?;
3183        let buffer = self.buffer.read(cx);
3184        let newest_selection = self.selections.newest_anchor().clone();
3185        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3186        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3187        if start_buffer != end_buffer {
3188            return None;
3189        }
3190
3191        let actions = project.update(cx, |project, cx| {
3192            project.code_actions(&start_buffer, start..end, cx)
3193        });
3194        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3195            let actions = actions.await;
3196            this.update(&mut cx, |this, cx| {
3197                this.available_code_actions = actions.log_err().and_then(|actions| {
3198                    if actions.is_empty() {
3199                        None
3200                    } else {
3201                        Some((start_buffer, actions.into()))
3202                    }
3203                });
3204                cx.notify();
3205            })
3206            .log_err();
3207        }));
3208        None
3209    }
3210
3211    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3212        if self.pending_rename.is_some() {
3213            return None;
3214        }
3215
3216        let project = self.project.as_ref()?;
3217        let buffer = self.buffer.read(cx);
3218        let newest_selection = self.selections.newest_anchor().clone();
3219        let cursor_position = newest_selection.head();
3220        let (cursor_buffer, cursor_buffer_position) =
3221            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3222        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3223        if cursor_buffer != tail_buffer {
3224            return None;
3225        }
3226
3227        let highlights = project.update(cx, |project, cx| {
3228            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3229        });
3230
3231        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3232            if let Some(highlights) = highlights.await.log_err() {
3233                this.update(&mut cx, |this, cx| {
3234                    if this.pending_rename.is_some() {
3235                        return;
3236                    }
3237
3238                    let buffer_id = cursor_position.buffer_id;
3239                    let buffer = this.buffer.read(cx);
3240                    if !buffer
3241                        .text_anchor_for_position(cursor_position, cx)
3242                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3243                    {
3244                        return;
3245                    }
3246
3247                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3248                    let mut write_ranges = Vec::new();
3249                    let mut read_ranges = Vec::new();
3250                    for highlight in highlights {
3251                        for (excerpt_id, excerpt_range) in
3252                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3253                        {
3254                            let start = highlight
3255                                .range
3256                                .start
3257                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3258                            let end = highlight
3259                                .range
3260                                .end
3261                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3262                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3263                                continue;
3264                            }
3265
3266                            let range = Anchor {
3267                                buffer_id,
3268                                excerpt_id: excerpt_id.clone(),
3269                                text_anchor: start,
3270                            }..Anchor {
3271                                buffer_id,
3272                                excerpt_id,
3273                                text_anchor: end,
3274                            };
3275                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3276                                write_ranges.push(range);
3277                            } else {
3278                                read_ranges.push(range);
3279                            }
3280                        }
3281                    }
3282
3283                    this.highlight_background::<DocumentHighlightRead>(
3284                        read_ranges,
3285                        |theme| theme.editor.document_highlight_read_background,
3286                        cx,
3287                    );
3288                    this.highlight_background::<DocumentHighlightWrite>(
3289                        write_ranges,
3290                        |theme| theme.editor.document_highlight_write_background,
3291                        cx,
3292                    );
3293                    cx.notify();
3294                })
3295                .log_err();
3296            }
3297        }));
3298        None
3299    }
3300
3301    fn refresh_copilot_suggestions(
3302        &mut self,
3303        debounce: bool,
3304        cx: &mut ViewContext<Self>,
3305    ) -> Option<()> {
3306        let copilot = Copilot::global(cx)?;
3307        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3308            self.clear_copilot_suggestions(cx);
3309            return None;
3310        }
3311        self.update_visible_copilot_suggestion(cx);
3312
3313        let snapshot = self.buffer.read(cx).snapshot(cx);
3314        let cursor = self.selections.newest_anchor().head();
3315        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3316            self.clear_copilot_suggestions(cx);
3317            return None;
3318        }
3319
3320        let (buffer, buffer_position) =
3321            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3322        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3323            if debounce {
3324                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3325            }
3326
3327            let completions = copilot
3328                .update(&mut cx, |copilot, cx| {
3329                    copilot.completions(&buffer, buffer_position, cx)
3330                })
3331                .await
3332                .log_err()
3333                .into_iter()
3334                .flatten()
3335                .collect_vec();
3336
3337            this.update(&mut cx, |this, cx| {
3338                if !completions.is_empty() {
3339                    this.copilot_state.cycled = false;
3340                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3341                    this.copilot_state.completions.clear();
3342                    this.copilot_state.active_completion_index = 0;
3343                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3344                    for completion in completions {
3345                        this.copilot_state.push_completion(completion);
3346                    }
3347                    this.update_visible_copilot_suggestion(cx);
3348                }
3349            })
3350            .log_err()?;
3351            Some(())
3352        });
3353
3354        Some(())
3355    }
3356
3357    fn cycle_copilot_suggestions(
3358        &mut self,
3359        direction: Direction,
3360        cx: &mut ViewContext<Self>,
3361    ) -> Option<()> {
3362        let copilot = Copilot::global(cx)?;
3363        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3364            return None;
3365        }
3366
3367        if self.copilot_state.cycled {
3368            self.copilot_state.cycle_completions(direction);
3369            self.update_visible_copilot_suggestion(cx);
3370        } else {
3371            let cursor = self.selections.newest_anchor().head();
3372            let (buffer, buffer_position) =
3373                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3374            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3375                let completions = copilot
3376                    .update(&mut cx, |copilot, cx| {
3377                        copilot.completions_cycling(&buffer, buffer_position, cx)
3378                    })
3379                    .await;
3380
3381                this.update(&mut cx, |this, cx| {
3382                    this.copilot_state.cycled = true;
3383                    for completion in completions.log_err().into_iter().flatten() {
3384                        this.copilot_state.push_completion(completion);
3385                    }
3386                    this.copilot_state.cycle_completions(direction);
3387                    this.update_visible_copilot_suggestion(cx);
3388                })
3389                .log_err()?;
3390
3391                Some(())
3392            });
3393        }
3394
3395        Some(())
3396    }
3397
3398    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3399        if !self.has_active_copilot_suggestion(cx) {
3400            self.refresh_copilot_suggestions(false, cx);
3401            return;
3402        }
3403
3404        self.update_visible_copilot_suggestion(cx);
3405    }
3406
3407    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3408        if self.has_active_copilot_suggestion(cx) {
3409            self.cycle_copilot_suggestions(Direction::Next, cx);
3410        } else {
3411            self.refresh_copilot_suggestions(false, cx);
3412        }
3413    }
3414
3415    fn previous_copilot_suggestion(
3416        &mut self,
3417        _: &copilot::PreviousSuggestion,
3418        cx: &mut ViewContext<Self>,
3419    ) {
3420        if self.has_active_copilot_suggestion(cx) {
3421            self.cycle_copilot_suggestions(Direction::Prev, cx);
3422        } else {
3423            self.refresh_copilot_suggestions(false, cx);
3424        }
3425    }
3426
3427    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3428        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3429            if let Some((copilot, completion)) =
3430                Copilot::global(cx).zip(self.copilot_state.active_completion())
3431            {
3432                copilot
3433                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3434                    .detach_and_log_err(cx);
3435
3436                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3437            }
3438            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3439            cx.notify();
3440            true
3441        } else {
3442            false
3443        }
3444    }
3445
3446    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3447        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3448            if let Some(copilot) = Copilot::global(cx) {
3449                copilot
3450                    .update(cx, |copilot, cx| {
3451                        copilot.discard_completions(&self.copilot_state.completions, cx)
3452                    })
3453                    .detach_and_log_err(cx);
3454
3455                self.report_copilot_event(None, false, cx)
3456            }
3457
3458            self.display_map.update(cx, |map, cx| {
3459                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
3460            });
3461            cx.notify();
3462            true
3463        } else {
3464            false
3465        }
3466    }
3467
3468    fn is_copilot_enabled_at(
3469        &self,
3470        location: Anchor,
3471        snapshot: &MultiBufferSnapshot,
3472        cx: &mut ViewContext<Self>,
3473    ) -> bool {
3474        let file = snapshot.file_at(location);
3475        let language = snapshot.language_at(location);
3476        let settings = all_language_settings(file, cx);
3477        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3478    }
3479
3480    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3481        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3482            let buffer = self.buffer.read(cx).read(cx);
3483            suggestion.position.is_valid(&buffer)
3484        } else {
3485            false
3486        }
3487    }
3488
3489    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3490        let suggestion = self.copilot_state.suggestion.take()?;
3491        self.display_map.update(cx, |map, cx| {
3492            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
3493        });
3494        let buffer = self.buffer.read(cx).read(cx);
3495
3496        if suggestion.position.is_valid(&buffer) {
3497            Some(suggestion)
3498        } else {
3499            None
3500        }
3501    }
3502
3503    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3504        let snapshot = self.buffer.read(cx).snapshot(cx);
3505        let selection = self.selections.newest_anchor();
3506        let cursor = selection.head();
3507
3508        if self.context_menu.is_some()
3509            || !self.completion_tasks.is_empty()
3510            || selection.start != selection.end
3511        {
3512            self.discard_copilot_suggestion(cx);
3513        } else if let Some(text) = self
3514            .copilot_state
3515            .text_for_active_completion(cursor, &snapshot)
3516        {
3517            let text = Rope::from(text);
3518            let mut to_remove = Vec::new();
3519            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3520                to_remove.push(suggestion.id);
3521            }
3522
3523            let suggestion_inlay =
3524                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
3525            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
3526            self.display_map.update(cx, move |map, cx| {
3527                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
3528            });
3529            cx.notify();
3530        } else {
3531            self.discard_copilot_suggestion(cx);
3532        }
3533    }
3534
3535    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3536        self.copilot_state = Default::default();
3537        self.discard_copilot_suggestion(cx);
3538    }
3539
3540    pub fn render_code_actions_indicator(
3541        &self,
3542        style: &EditorStyle,
3543        is_active: bool,
3544        cx: &mut ViewContext<Self>,
3545    ) -> Option<AnyElement<Self>> {
3546        if self.available_code_actions.is_some() {
3547            enum CodeActions {}
3548            Some(
3549                MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
3550                    Svg::new("icons/bolt_8.svg").with_color(
3551                        style
3552                            .code_actions
3553                            .indicator
3554                            .in_state(is_active)
3555                            .style_for(state)
3556                            .color,
3557                    )
3558                })
3559                .with_cursor_style(CursorStyle::PointingHand)
3560                .with_padding(Padding::uniform(3.))
3561                .on_down(MouseButton::Left, |_, this, cx| {
3562                    this.toggle_code_actions(
3563                        &ToggleCodeActions {
3564                            deployed_from_indicator: true,
3565                        },
3566                        cx,
3567                    );
3568                })
3569                .into_any(),
3570            )
3571        } else {
3572            None
3573        }
3574    }
3575
3576    pub fn render_fold_indicators(
3577        &self,
3578        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3579        style: &EditorStyle,
3580        gutter_hovered: bool,
3581        line_height: f32,
3582        gutter_margin: f32,
3583        cx: &mut ViewContext<Self>,
3584    ) -> Vec<Option<AnyElement<Self>>> {
3585        enum FoldIndicators {}
3586
3587        let style = style.folds.clone();
3588
3589        fold_data
3590            .iter()
3591            .enumerate()
3592            .map(|(ix, fold_data)| {
3593                fold_data
3594                    .map(|(fold_status, buffer_row, active)| {
3595                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3596                            MouseEventHandler::new::<FoldIndicators, _>(
3597                                ix as usize,
3598                                cx,
3599                                |mouse_state, _| {
3600                                    Svg::new(match fold_status {
3601                                        FoldStatus::Folded => style.folded_icon.clone(),
3602                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3603                                    })
3604                                    .with_color(
3605                                        style
3606                                            .indicator
3607                                            .in_state(fold_status == FoldStatus::Folded)
3608                                            .style_for(mouse_state)
3609                                            .color,
3610                                    )
3611                                    .constrained()
3612                                    .with_width(gutter_margin * style.icon_margin_scale)
3613                                    .aligned()
3614                                    .constrained()
3615                                    .with_height(line_height)
3616                                    .with_width(gutter_margin)
3617                                    .aligned()
3618                                },
3619                            )
3620                            .with_cursor_style(CursorStyle::PointingHand)
3621                            .with_padding(Padding::uniform(3.))
3622                            .on_click(MouseButton::Left, {
3623                                move |_, editor, cx| match fold_status {
3624                                    FoldStatus::Folded => {
3625                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3626                                    }
3627                                    FoldStatus::Foldable => {
3628                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3629                                    }
3630                                }
3631                            })
3632                            .into_any()
3633                        })
3634                    })
3635                    .flatten()
3636            })
3637            .collect()
3638    }
3639
3640    pub fn context_menu_visible(&self) -> bool {
3641        self.context_menu
3642            .as_ref()
3643            .map_or(false, |menu| menu.visible())
3644    }
3645
3646    pub fn render_context_menu(
3647        &self,
3648        cursor_position: DisplayPoint,
3649        style: EditorStyle,
3650        cx: &mut ViewContext<Editor>,
3651    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3652        self.context_menu
3653            .as_ref()
3654            .map(|menu| menu.render(cursor_position, style, cx))
3655    }
3656
3657    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3658        if !matches!(menu, ContextMenu::Completions(_)) {
3659            self.completion_tasks.clear();
3660        }
3661        self.context_menu = Some(menu);
3662        self.discard_copilot_suggestion(cx);
3663        cx.notify();
3664    }
3665
3666    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3667        cx.notify();
3668        self.completion_tasks.clear();
3669        let context_menu = self.context_menu.take();
3670        if context_menu.is_some() {
3671            self.update_visible_copilot_suggestion(cx);
3672        }
3673        context_menu
3674    }
3675
3676    pub fn insert_snippet(
3677        &mut self,
3678        insertion_ranges: &[Range<usize>],
3679        snippet: Snippet,
3680        cx: &mut ViewContext<Self>,
3681    ) -> Result<()> {
3682        let tabstops = self.buffer.update(cx, |buffer, cx| {
3683            let snippet_text: Arc<str> = snippet.text.clone().into();
3684            buffer.edit(
3685                insertion_ranges
3686                    .iter()
3687                    .cloned()
3688                    .map(|range| (range, snippet_text.clone())),
3689                Some(AutoindentMode::EachLine),
3690                cx,
3691            );
3692
3693            let snapshot = &*buffer.read(cx);
3694            let snippet = &snippet;
3695            snippet
3696                .tabstops
3697                .iter()
3698                .map(|tabstop| {
3699                    let mut tabstop_ranges = tabstop
3700                        .iter()
3701                        .flat_map(|tabstop_range| {
3702                            let mut delta = 0_isize;
3703                            insertion_ranges.iter().map(move |insertion_range| {
3704                                let insertion_start = insertion_range.start as isize + delta;
3705                                delta +=
3706                                    snippet.text.len() as isize - insertion_range.len() as isize;
3707
3708                                let start = snapshot.anchor_before(
3709                                    (insertion_start + tabstop_range.start) as usize,
3710                                );
3711                                let end = snapshot
3712                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3713                                start..end
3714                            })
3715                        })
3716                        .collect::<Vec<_>>();
3717                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3718                    tabstop_ranges
3719                })
3720                .collect::<Vec<_>>()
3721        });
3722
3723        if let Some(tabstop) = tabstops.first() {
3724            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3725                s.select_ranges(tabstop.iter().cloned());
3726            });
3727            self.snippet_stack.push(SnippetState {
3728                active_index: 0,
3729                ranges: tabstops,
3730            });
3731        }
3732
3733        Ok(())
3734    }
3735
3736    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3737        self.move_to_snippet_tabstop(Bias::Right, cx)
3738    }
3739
3740    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3741        self.move_to_snippet_tabstop(Bias::Left, cx)
3742    }
3743
3744    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3745        if let Some(mut snippet) = self.snippet_stack.pop() {
3746            match bias {
3747                Bias::Left => {
3748                    if snippet.active_index > 0 {
3749                        snippet.active_index -= 1;
3750                    } else {
3751                        self.snippet_stack.push(snippet);
3752                        return false;
3753                    }
3754                }
3755                Bias::Right => {
3756                    if snippet.active_index + 1 < snippet.ranges.len() {
3757                        snippet.active_index += 1;
3758                    } else {
3759                        self.snippet_stack.push(snippet);
3760                        return false;
3761                    }
3762                }
3763            }
3764            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3765                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3766                    s.select_anchor_ranges(current_ranges.iter().cloned())
3767                });
3768                // If snippet state is not at the last tabstop, push it back on the stack
3769                if snippet.active_index + 1 < snippet.ranges.len() {
3770                    self.snippet_stack.push(snippet);
3771                }
3772                return true;
3773            }
3774        }
3775
3776        false
3777    }
3778
3779    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3780        self.transact(cx, |this, cx| {
3781            this.select_all(&SelectAll, cx);
3782            this.insert("", cx);
3783        });
3784    }
3785
3786    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3787        self.transact(cx, |this, cx| {
3788            this.select_autoclose_pair(cx);
3789            let mut selections = this.selections.all::<Point>(cx);
3790            if !this.selections.line_mode {
3791                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3792                for selection in &mut selections {
3793                    if selection.is_empty() {
3794                        let old_head = selection.head();
3795                        let mut new_head =
3796                            movement::left(&display_map, old_head.to_display_point(&display_map))
3797                                .to_point(&display_map);
3798                        if let Some((buffer, line_buffer_range)) = display_map
3799                            .buffer_snapshot
3800                            .buffer_line_for_row(old_head.row)
3801                        {
3802                            let indent_size =
3803                                buffer.indent_size_for_line(line_buffer_range.start.row);
3804                            let indent_len = match indent_size.kind {
3805                                IndentKind::Space => {
3806                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3807                                }
3808                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3809                            };
3810                            if old_head.column <= indent_size.len && old_head.column > 0 {
3811                                let indent_len = indent_len.get();
3812                                new_head = cmp::min(
3813                                    new_head,
3814                                    Point::new(
3815                                        old_head.row,
3816                                        ((old_head.column - 1) / indent_len) * indent_len,
3817                                    ),
3818                                );
3819                            }
3820                        }
3821
3822                        selection.set_head(new_head, SelectionGoal::None);
3823                    }
3824                }
3825            }
3826
3827            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3828            this.insert("", cx);
3829            this.refresh_copilot_suggestions(true, cx);
3830        });
3831    }
3832
3833    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3834        self.transact(cx, |this, cx| {
3835            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3836                let line_mode = s.line_mode;
3837                s.move_with(|map, selection| {
3838                    if selection.is_empty() && !line_mode {
3839                        let cursor = movement::right(map, selection.head());
3840                        selection.end = cursor;
3841                        selection.reversed = true;
3842                        selection.goal = SelectionGoal::None;
3843                    }
3844                })
3845            });
3846            this.insert("", cx);
3847            this.refresh_copilot_suggestions(true, cx);
3848        });
3849    }
3850
3851    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3852        if self.move_to_prev_snippet_tabstop(cx) {
3853            return;
3854        }
3855
3856        self.outdent(&Outdent, cx);
3857    }
3858
3859    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3860        if self.move_to_next_snippet_tabstop(cx) {
3861            return;
3862        }
3863
3864        let mut selections = self.selections.all_adjusted(cx);
3865        let buffer = self.buffer.read(cx);
3866        let snapshot = buffer.snapshot(cx);
3867        let rows_iter = selections.iter().map(|s| s.head().row);
3868        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3869
3870        let mut edits = Vec::new();
3871        let mut prev_edited_row = 0;
3872        let mut row_delta = 0;
3873        for selection in &mut selections {
3874            if selection.start.row != prev_edited_row {
3875                row_delta = 0;
3876            }
3877            prev_edited_row = selection.end.row;
3878
3879            // If the selection is non-empty, then increase the indentation of the selected lines.
3880            if !selection.is_empty() {
3881                row_delta =
3882                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3883                continue;
3884            }
3885
3886            // If the selection is empty and the cursor is in the leading whitespace before the
3887            // suggested indentation, then auto-indent the line.
3888            let cursor = selection.head();
3889            let current_indent = snapshot.indent_size_for_line(cursor.row);
3890            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3891                if cursor.column < suggested_indent.len
3892                    && cursor.column <= current_indent.len
3893                    && current_indent.len <= suggested_indent.len
3894                {
3895                    selection.start = Point::new(cursor.row, suggested_indent.len);
3896                    selection.end = selection.start;
3897                    if row_delta == 0 {
3898                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3899                            cursor.row,
3900                            current_indent,
3901                            suggested_indent,
3902                        ));
3903                        row_delta = suggested_indent.len - current_indent.len;
3904                    }
3905                    continue;
3906                }
3907            }
3908
3909            // Accept copilot suggestion if there is only one selection and the cursor is not
3910            // in the leading whitespace.
3911            if self.selections.count() == 1
3912                && cursor.column >= current_indent.len
3913                && self.has_active_copilot_suggestion(cx)
3914            {
3915                self.accept_copilot_suggestion(cx);
3916                return;
3917            }
3918
3919            // Otherwise, insert a hard or soft tab.
3920            let settings = buffer.settings_at(cursor, cx);
3921            let tab_size = if settings.hard_tabs {
3922                IndentSize::tab()
3923            } else {
3924                let tab_size = settings.tab_size.get();
3925                let char_column = snapshot
3926                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3927                    .flat_map(str::chars)
3928                    .count()
3929                    + row_delta as usize;
3930                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3931                IndentSize::spaces(chars_to_next_tab_stop)
3932            };
3933            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3934            selection.end = selection.start;
3935            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3936            row_delta += tab_size.len;
3937        }
3938
3939        self.transact(cx, |this, cx| {
3940            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3941            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3942            this.refresh_copilot_suggestions(true, cx);
3943        });
3944    }
3945
3946    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3947        let mut selections = self.selections.all::<Point>(cx);
3948        let mut prev_edited_row = 0;
3949        let mut row_delta = 0;
3950        let mut edits = Vec::new();
3951        let buffer = self.buffer.read(cx);
3952        let snapshot = buffer.snapshot(cx);
3953        for selection in &mut selections {
3954            if selection.start.row != prev_edited_row {
3955                row_delta = 0;
3956            }
3957            prev_edited_row = selection.end.row;
3958
3959            row_delta =
3960                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3961        }
3962
3963        self.transact(cx, |this, cx| {
3964            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3965            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3966        });
3967    }
3968
3969    fn indent_selection(
3970        buffer: &MultiBuffer,
3971        snapshot: &MultiBufferSnapshot,
3972        selection: &mut Selection<Point>,
3973        edits: &mut Vec<(Range<Point>, String)>,
3974        delta_for_start_row: u32,
3975        cx: &AppContext,
3976    ) -> u32 {
3977        let settings = buffer.settings_at(selection.start, cx);
3978        let tab_size = settings.tab_size.get();
3979        let indent_kind = if settings.hard_tabs {
3980            IndentKind::Tab
3981        } else {
3982            IndentKind::Space
3983        };
3984        let mut start_row = selection.start.row;
3985        let mut end_row = selection.end.row + 1;
3986
3987        // If a selection ends at the beginning of a line, don't indent
3988        // that last line.
3989        if selection.end.column == 0 {
3990            end_row -= 1;
3991        }
3992
3993        // Avoid re-indenting a row that has already been indented by a
3994        // previous selection, but still update this selection's column
3995        // to reflect that indentation.
3996        if delta_for_start_row > 0 {
3997            start_row += 1;
3998            selection.start.column += delta_for_start_row;
3999            if selection.end.row == selection.start.row {
4000                selection.end.column += delta_for_start_row;
4001            }
4002        }
4003
4004        let mut delta_for_end_row = 0;
4005        for row in start_row..end_row {
4006            let current_indent = snapshot.indent_size_for_line(row);
4007            let indent_delta = match (current_indent.kind, indent_kind) {
4008                (IndentKind::Space, IndentKind::Space) => {
4009                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4010                    IndentSize::spaces(columns_to_next_tab_stop)
4011                }
4012                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4013                (_, IndentKind::Tab) => IndentSize::tab(),
4014            };
4015
4016            let row_start = Point::new(row, 0);
4017            edits.push((
4018                row_start..row_start,
4019                indent_delta.chars().collect::<String>(),
4020            ));
4021
4022            // Update this selection's endpoints to reflect the indentation.
4023            if row == selection.start.row {
4024                selection.start.column += indent_delta.len;
4025            }
4026            if row == selection.end.row {
4027                selection.end.column += indent_delta.len;
4028                delta_for_end_row = indent_delta.len;
4029            }
4030        }
4031
4032        if selection.start.row == selection.end.row {
4033            delta_for_start_row + delta_for_end_row
4034        } else {
4035            delta_for_end_row
4036        }
4037    }
4038
4039    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4040        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4041        let selections = self.selections.all::<Point>(cx);
4042        let mut deletion_ranges = Vec::new();
4043        let mut last_outdent = None;
4044        {
4045            let buffer = self.buffer.read(cx);
4046            let snapshot = buffer.snapshot(cx);
4047            for selection in &selections {
4048                let settings = buffer.settings_at(selection.start, cx);
4049                let tab_size = settings.tab_size.get();
4050                let mut rows = selection.spanned_rows(false, &display_map);
4051
4052                // Avoid re-outdenting a row that has already been outdented by a
4053                // previous selection.
4054                if let Some(last_row) = last_outdent {
4055                    if last_row == rows.start {
4056                        rows.start += 1;
4057                    }
4058                }
4059
4060                for row in rows {
4061                    let indent_size = snapshot.indent_size_for_line(row);
4062                    if indent_size.len > 0 {
4063                        let deletion_len = match indent_size.kind {
4064                            IndentKind::Space => {
4065                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4066                                if columns_to_prev_tab_stop == 0 {
4067                                    tab_size
4068                                } else {
4069                                    columns_to_prev_tab_stop
4070                                }
4071                            }
4072                            IndentKind::Tab => 1,
4073                        };
4074                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4075                        last_outdent = Some(row);
4076                    }
4077                }
4078            }
4079        }
4080
4081        self.transact(cx, |this, cx| {
4082            this.buffer.update(cx, |buffer, cx| {
4083                let empty_str: Arc<str> = "".into();
4084                buffer.edit(
4085                    deletion_ranges
4086                        .into_iter()
4087                        .map(|range| (range, empty_str.clone())),
4088                    None,
4089                    cx,
4090                );
4091            });
4092            let selections = this.selections.all::<usize>(cx);
4093            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4094        });
4095    }
4096
4097    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4098        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4099        let selections = self.selections.all::<Point>(cx);
4100
4101        let mut new_cursors = Vec::new();
4102        let mut edit_ranges = Vec::new();
4103        let mut selections = selections.iter().peekable();
4104        while let Some(selection) = selections.next() {
4105            let mut rows = selection.spanned_rows(false, &display_map);
4106            let goal_display_column = selection.head().to_display_point(&display_map).column();
4107
4108            // Accumulate contiguous regions of rows that we want to delete.
4109            while let Some(next_selection) = selections.peek() {
4110                let next_rows = next_selection.spanned_rows(false, &display_map);
4111                if next_rows.start <= rows.end {
4112                    rows.end = next_rows.end;
4113                    selections.next().unwrap();
4114                } else {
4115                    break;
4116                }
4117            }
4118
4119            let buffer = &display_map.buffer_snapshot;
4120            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4121            let edit_end;
4122            let cursor_buffer_row;
4123            if buffer.max_point().row >= rows.end {
4124                // If there's a line after the range, delete the \n from the end of the row range
4125                // and position the cursor on the next line.
4126                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4127                cursor_buffer_row = rows.end;
4128            } else {
4129                // If there isn't a line after the range, delete the \n from the line before the
4130                // start of the row range and position the cursor there.
4131                edit_start = edit_start.saturating_sub(1);
4132                edit_end = buffer.len();
4133                cursor_buffer_row = rows.start.saturating_sub(1);
4134            }
4135
4136            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4137            *cursor.column_mut() =
4138                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4139
4140            new_cursors.push((
4141                selection.id,
4142                buffer.anchor_after(cursor.to_point(&display_map)),
4143            ));
4144            edit_ranges.push(edit_start..edit_end);
4145        }
4146
4147        self.transact(cx, |this, cx| {
4148            let buffer = this.buffer.update(cx, |buffer, cx| {
4149                let empty_str: Arc<str> = "".into();
4150                buffer.edit(
4151                    edit_ranges
4152                        .into_iter()
4153                        .map(|range| (range, empty_str.clone())),
4154                    None,
4155                    cx,
4156                );
4157                buffer.snapshot(cx)
4158            });
4159            let new_selections = new_cursors
4160                .into_iter()
4161                .map(|(id, cursor)| {
4162                    let cursor = cursor.to_point(&buffer);
4163                    Selection {
4164                        id,
4165                        start: cursor,
4166                        end: cursor,
4167                        reversed: false,
4168                        goal: SelectionGoal::None,
4169                    }
4170                })
4171                .collect();
4172
4173            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4174                s.select(new_selections);
4175            });
4176        });
4177    }
4178
4179    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4180        let mut row_ranges = Vec::<Range<u32>>::new();
4181        for selection in self.selections.all::<Point>(cx) {
4182            let start = selection.start.row;
4183            let end = if selection.start.row == selection.end.row {
4184                selection.start.row + 1
4185            } else {
4186                selection.end.row
4187            };
4188
4189            if let Some(last_row_range) = row_ranges.last_mut() {
4190                if start <= last_row_range.end {
4191                    last_row_range.end = end;
4192                    continue;
4193                }
4194            }
4195            row_ranges.push(start..end);
4196        }
4197
4198        let snapshot = self.buffer.read(cx).snapshot(cx);
4199        let mut cursor_positions = Vec::new();
4200        for row_range in &row_ranges {
4201            let anchor = snapshot.anchor_before(Point::new(
4202                row_range.end - 1,
4203                snapshot.line_len(row_range.end - 1),
4204            ));
4205            cursor_positions.push(anchor.clone()..anchor);
4206        }
4207
4208        self.transact(cx, |this, cx| {
4209            for row_range in row_ranges.into_iter().rev() {
4210                for row in row_range.rev() {
4211                    let end_of_line = Point::new(row, snapshot.line_len(row));
4212                    let indent = snapshot.indent_size_for_line(row + 1);
4213                    let start_of_next_line = Point::new(row + 1, indent.len);
4214
4215                    let replace = if snapshot.line_len(row + 1) > indent.len {
4216                        " "
4217                    } else {
4218                        ""
4219                    };
4220
4221                    this.buffer.update(cx, |buffer, cx| {
4222                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4223                    });
4224                }
4225            }
4226
4227            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4228                s.select_anchor_ranges(cursor_positions)
4229            });
4230        });
4231    }
4232
4233    pub fn sort_lines_case_sensitive(
4234        &mut self,
4235        _: &SortLinesCaseSensitive,
4236        cx: &mut ViewContext<Self>,
4237    ) {
4238        self.manipulate_lines(cx, |lines| lines.sort())
4239    }
4240
4241    pub fn sort_lines_case_insensitive(
4242        &mut self,
4243        _: &SortLinesCaseInsensitive,
4244        cx: &mut ViewContext<Self>,
4245    ) {
4246        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4247    }
4248
4249    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4250        self.manipulate_lines(cx, |lines| lines.reverse())
4251    }
4252
4253    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4254        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4255    }
4256
4257    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4258    where
4259        Fn: FnMut(&mut [&str]),
4260    {
4261        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4262        let buffer = self.buffer.read(cx).snapshot(cx);
4263
4264        let mut edits = Vec::new();
4265
4266        let selections = self.selections.all::<Point>(cx);
4267        let mut selections = selections.iter().peekable();
4268        let mut contiguous_row_selections = Vec::new();
4269        let mut new_selections = Vec::new();
4270
4271        while let Some(selection) = selections.next() {
4272            let (start_row, end_row) = consume_contiguous_rows(
4273                &mut contiguous_row_selections,
4274                selection,
4275                &display_map,
4276                &mut selections,
4277            );
4278
4279            let start_point = Point::new(start_row, 0);
4280            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4281            let text = buffer
4282                .text_for_range(start_point..end_point)
4283                .collect::<String>();
4284            let mut lines = text.split("\n").collect_vec();
4285
4286            let lines_len = lines.len();
4287            callback(&mut lines);
4288
4289            // This is a current limitation with selections.
4290            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4291            debug_assert!(
4292                lines.len() == lines_len,
4293                "callback should not change the number of lines"
4294            );
4295
4296            edits.push((start_point..end_point, lines.join("\n")));
4297            let start_anchor = buffer.anchor_after(start_point);
4298            let end_anchor = buffer.anchor_before(end_point);
4299
4300            // Make selection and push
4301            new_selections.push(Selection {
4302                id: selection.id,
4303                start: start_anchor.to_offset(&buffer),
4304                end: end_anchor.to_offset(&buffer),
4305                goal: SelectionGoal::None,
4306                reversed: selection.reversed,
4307            });
4308        }
4309
4310        self.transact(cx, |this, cx| {
4311            this.buffer.update(cx, |buffer, cx| {
4312                buffer.edit(edits, None, cx);
4313            });
4314
4315            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4316                s.select(new_selections);
4317            });
4318
4319            this.request_autoscroll(Autoscroll::fit(), cx);
4320        });
4321    }
4322
4323    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
4324        self.manipulate_text(cx, |text| text.to_uppercase())
4325    }
4326
4327    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
4328        self.manipulate_text(cx, |text| text.to_lowercase())
4329    }
4330
4331    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
4332        self.manipulate_text(cx, |text| text.to_case(Case::Title))
4333    }
4334
4335    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
4336        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
4337    }
4338
4339    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
4340        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
4341    }
4342
4343    pub fn convert_to_upper_camel_case(
4344        &mut self,
4345        _: &ConvertToUpperCamelCase,
4346        cx: &mut ViewContext<Self>,
4347    ) {
4348        self.manipulate_text(cx, |text| text.to_case(Case::UpperCamel))
4349    }
4350
4351    pub fn convert_to_lower_camel_case(
4352        &mut self,
4353        _: &ConvertToLowerCamelCase,
4354        cx: &mut ViewContext<Self>,
4355    ) {
4356        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
4357    }
4358
4359    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4360    where
4361        Fn: FnMut(&str) -> String,
4362    {
4363        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4364        let buffer = self.buffer.read(cx).snapshot(cx);
4365
4366        let mut new_selections = Vec::new();
4367        let mut edits = Vec::new();
4368        let mut selection_adjustment = 0i32;
4369
4370        for selection in self.selections.all::<usize>(cx) {
4371            let selection_is_empty = selection.is_empty();
4372
4373            let (start, end) = if selection_is_empty {
4374                let word_range = movement::surrounding_word(
4375                    &display_map,
4376                    selection.start.to_display_point(&display_map),
4377                );
4378                let start = word_range.start.to_offset(&display_map, Bias::Left);
4379                let end = word_range.end.to_offset(&display_map, Bias::Left);
4380                (start, end)
4381            } else {
4382                (selection.start, selection.end)
4383            };
4384
4385            let text = buffer.text_for_range(start..end).collect::<String>();
4386            let old_length = text.len() as i32;
4387            let text = callback(&text);
4388
4389            new_selections.push(Selection {
4390                start: (start as i32 - selection_adjustment) as usize,
4391                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
4392                goal: SelectionGoal::None,
4393                ..selection
4394            });
4395
4396            selection_adjustment += old_length - text.len() as i32;
4397
4398            edits.push((start..end, text));
4399        }
4400
4401        self.transact(cx, |this, cx| {
4402            this.buffer.update(cx, |buffer, cx| {
4403                buffer.edit(edits, None, cx);
4404            });
4405
4406            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4407                s.select(new_selections);
4408            });
4409
4410            this.request_autoscroll(Autoscroll::fit(), cx);
4411        });
4412    }
4413
4414    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4415        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4416        let buffer = &display_map.buffer_snapshot;
4417        let selections = self.selections.all::<Point>(cx);
4418
4419        let mut edits = Vec::new();
4420        let mut selections_iter = selections.iter().peekable();
4421        while let Some(selection) = selections_iter.next() {
4422            // Avoid duplicating the same lines twice.
4423            let mut rows = selection.spanned_rows(false, &display_map);
4424
4425            while let Some(next_selection) = selections_iter.peek() {
4426                let next_rows = next_selection.spanned_rows(false, &display_map);
4427                if next_rows.start < rows.end {
4428                    rows.end = next_rows.end;
4429                    selections_iter.next().unwrap();
4430                } else {
4431                    break;
4432                }
4433            }
4434
4435            // Copy the text from the selected row region and splice it at the start of the region.
4436            let start = Point::new(rows.start, 0);
4437            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4438            let text = buffer
4439                .text_for_range(start..end)
4440                .chain(Some("\n"))
4441                .collect::<String>();
4442            edits.push((start..start, text));
4443        }
4444
4445        self.transact(cx, |this, cx| {
4446            this.buffer.update(cx, |buffer, cx| {
4447                buffer.edit(edits, None, cx);
4448            });
4449
4450            this.request_autoscroll(Autoscroll::fit(), cx);
4451        });
4452    }
4453
4454    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4455        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4456        let buffer = self.buffer.read(cx).snapshot(cx);
4457
4458        let mut edits = Vec::new();
4459        let mut unfold_ranges = Vec::new();
4460        let mut refold_ranges = Vec::new();
4461
4462        let selections = self.selections.all::<Point>(cx);
4463        let mut selections = selections.iter().peekable();
4464        let mut contiguous_row_selections = Vec::new();
4465        let mut new_selections = Vec::new();
4466
4467        while let Some(selection) = selections.next() {
4468            // Find all the selections that span a contiguous row range
4469            let (start_row, end_row) = consume_contiguous_rows(
4470                &mut contiguous_row_selections,
4471                selection,
4472                &display_map,
4473                &mut selections,
4474            );
4475
4476            // Move the text spanned by the row range to be before the line preceding the row range
4477            if start_row > 0 {
4478                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4479                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4480                let insertion_point = display_map
4481                    .prev_line_boundary(Point::new(start_row - 1, 0))
4482                    .0;
4483
4484                // Don't move lines across excerpts
4485                if buffer
4486                    .excerpt_boundaries_in_range((
4487                        Bound::Excluded(insertion_point),
4488                        Bound::Included(range_to_move.end),
4489                    ))
4490                    .next()
4491                    .is_none()
4492                {
4493                    let text = buffer
4494                        .text_for_range(range_to_move.clone())
4495                        .flat_map(|s| s.chars())
4496                        .skip(1)
4497                        .chain(['\n'])
4498                        .collect::<String>();
4499
4500                    edits.push((
4501                        buffer.anchor_after(range_to_move.start)
4502                            ..buffer.anchor_before(range_to_move.end),
4503                        String::new(),
4504                    ));
4505                    let insertion_anchor = buffer.anchor_after(insertion_point);
4506                    edits.push((insertion_anchor..insertion_anchor, text));
4507
4508                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4509
4510                    // Move selections up
4511                    new_selections.extend(contiguous_row_selections.drain(..).map(
4512                        |mut selection| {
4513                            selection.start.row -= row_delta;
4514                            selection.end.row -= row_delta;
4515                            selection
4516                        },
4517                    ));
4518
4519                    // Move folds up
4520                    unfold_ranges.push(range_to_move.clone());
4521                    for fold in display_map.folds_in_range(
4522                        buffer.anchor_before(range_to_move.start)
4523                            ..buffer.anchor_after(range_to_move.end),
4524                    ) {
4525                        let mut start = fold.start.to_point(&buffer);
4526                        let mut end = fold.end.to_point(&buffer);
4527                        start.row -= row_delta;
4528                        end.row -= row_delta;
4529                        refold_ranges.push(start..end);
4530                    }
4531                }
4532            }
4533
4534            // If we didn't move line(s), preserve the existing selections
4535            new_selections.append(&mut contiguous_row_selections);
4536        }
4537
4538        self.transact(cx, |this, cx| {
4539            this.unfold_ranges(unfold_ranges, true, true, cx);
4540            this.buffer.update(cx, |buffer, cx| {
4541                for (range, text) in edits {
4542                    buffer.edit([(range, text)], None, cx);
4543                }
4544            });
4545            this.fold_ranges(refold_ranges, true, cx);
4546            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4547                s.select(new_selections);
4548            })
4549        });
4550    }
4551
4552    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4553        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4554        let buffer = self.buffer.read(cx).snapshot(cx);
4555
4556        let mut edits = Vec::new();
4557        let mut unfold_ranges = Vec::new();
4558        let mut refold_ranges = Vec::new();
4559
4560        let selections = self.selections.all::<Point>(cx);
4561        let mut selections = selections.iter().peekable();
4562        let mut contiguous_row_selections = Vec::new();
4563        let mut new_selections = Vec::new();
4564
4565        while let Some(selection) = selections.next() {
4566            // Find all the selections that span a contiguous row range
4567            let (start_row, end_row) = consume_contiguous_rows(
4568                &mut contiguous_row_selections,
4569                selection,
4570                &display_map,
4571                &mut selections,
4572            );
4573
4574            // Move the text spanned by the row range to be after the last line of the row range
4575            if end_row <= buffer.max_point().row {
4576                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4577                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4578
4579                // Don't move lines across excerpt boundaries
4580                if buffer
4581                    .excerpt_boundaries_in_range((
4582                        Bound::Excluded(range_to_move.start),
4583                        Bound::Included(insertion_point),
4584                    ))
4585                    .next()
4586                    .is_none()
4587                {
4588                    let mut text = String::from("\n");
4589                    text.extend(buffer.text_for_range(range_to_move.clone()));
4590                    text.pop(); // Drop trailing newline
4591                    edits.push((
4592                        buffer.anchor_after(range_to_move.start)
4593                            ..buffer.anchor_before(range_to_move.end),
4594                        String::new(),
4595                    ));
4596                    let insertion_anchor = buffer.anchor_after(insertion_point);
4597                    edits.push((insertion_anchor..insertion_anchor, text));
4598
4599                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4600
4601                    // Move selections down
4602                    new_selections.extend(contiguous_row_selections.drain(..).map(
4603                        |mut selection| {
4604                            selection.start.row += row_delta;
4605                            selection.end.row += row_delta;
4606                            selection
4607                        },
4608                    ));
4609
4610                    // Move folds down
4611                    unfold_ranges.push(range_to_move.clone());
4612                    for fold in display_map.folds_in_range(
4613                        buffer.anchor_before(range_to_move.start)
4614                            ..buffer.anchor_after(range_to_move.end),
4615                    ) {
4616                        let mut start = fold.start.to_point(&buffer);
4617                        let mut end = fold.end.to_point(&buffer);
4618                        start.row += row_delta;
4619                        end.row += row_delta;
4620                        refold_ranges.push(start..end);
4621                    }
4622                }
4623            }
4624
4625            // If we didn't move line(s), preserve the existing selections
4626            new_selections.append(&mut contiguous_row_selections);
4627        }
4628
4629        self.transact(cx, |this, cx| {
4630            this.unfold_ranges(unfold_ranges, true, true, cx);
4631            this.buffer.update(cx, |buffer, cx| {
4632                for (range, text) in edits {
4633                    buffer.edit([(range, text)], None, cx);
4634                }
4635            });
4636            this.fold_ranges(refold_ranges, true, cx);
4637            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4638        });
4639    }
4640
4641    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4642        self.transact(cx, |this, cx| {
4643            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4644                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4645                let line_mode = s.line_mode;
4646                s.move_with(|display_map, selection| {
4647                    if !selection.is_empty() || line_mode {
4648                        return;
4649                    }
4650
4651                    let mut head = selection.head();
4652                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4653                    if head.column() == display_map.line_len(head.row()) {
4654                        transpose_offset = display_map
4655                            .buffer_snapshot
4656                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4657                    }
4658
4659                    if transpose_offset == 0 {
4660                        return;
4661                    }
4662
4663                    *head.column_mut() += 1;
4664                    head = display_map.clip_point(head, Bias::Right);
4665                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4666
4667                    let transpose_start = display_map
4668                        .buffer_snapshot
4669                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4670                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4671                        let transpose_end = display_map
4672                            .buffer_snapshot
4673                            .clip_offset(transpose_offset + 1, Bias::Right);
4674                        if let Some(ch) =
4675                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4676                        {
4677                            edits.push((transpose_start..transpose_offset, String::new()));
4678                            edits.push((transpose_end..transpose_end, ch.to_string()));
4679                        }
4680                    }
4681                });
4682                edits
4683            });
4684            this.buffer
4685                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4686            let selections = this.selections.all::<usize>(cx);
4687            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4688                s.select(selections);
4689            });
4690        });
4691    }
4692
4693    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4694        let mut text = String::new();
4695        let buffer = self.buffer.read(cx).snapshot(cx);
4696        let mut selections = self.selections.all::<Point>(cx);
4697        let mut clipboard_selections = Vec::with_capacity(selections.len());
4698        {
4699            let max_point = buffer.max_point();
4700            for selection in &mut selections {
4701                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4702                if is_entire_line {
4703                    selection.start = Point::new(selection.start.row, 0);
4704                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4705                    selection.goal = SelectionGoal::None;
4706                }
4707                let mut len = 0;
4708                for chunk in buffer.text_for_range(selection.start..selection.end) {
4709                    text.push_str(chunk);
4710                    len += chunk.len();
4711                }
4712                clipboard_selections.push(ClipboardSelection {
4713                    len,
4714                    is_entire_line,
4715                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4716                });
4717            }
4718        }
4719
4720        self.transact(cx, |this, cx| {
4721            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4722                s.select(selections);
4723            });
4724            this.insert("", cx);
4725            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4726        });
4727    }
4728
4729    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4730        let selections = self.selections.all::<Point>(cx);
4731        let buffer = self.buffer.read(cx).read(cx);
4732        let mut text = String::new();
4733
4734        let mut clipboard_selections = Vec::with_capacity(selections.len());
4735        {
4736            let max_point = buffer.max_point();
4737            for selection in selections.iter() {
4738                let mut start = selection.start;
4739                let mut end = selection.end;
4740                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4741                if is_entire_line {
4742                    start = Point::new(start.row, 0);
4743                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4744                }
4745                let mut len = 0;
4746                for chunk in buffer.text_for_range(start..end) {
4747                    text.push_str(chunk);
4748                    len += chunk.len();
4749                }
4750                clipboard_selections.push(ClipboardSelection {
4751                    len,
4752                    is_entire_line,
4753                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4754                });
4755            }
4756        }
4757
4758        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4759    }
4760
4761    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4762        self.transact(cx, |this, cx| {
4763            if let Some(item) = cx.read_from_clipboard() {
4764                let mut clipboard_text = Cow::Borrowed(item.text());
4765                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4766                    let old_selections = this.selections.all::<usize>(cx);
4767                    let all_selections_were_entire_line =
4768                        clipboard_selections.iter().all(|s| s.is_entire_line);
4769                    let first_selection_indent_column =
4770                        clipboard_selections.first().map(|s| s.first_line_indent);
4771                    if clipboard_selections.len() != old_selections.len() {
4772                        let mut newline_separated_text = String::new();
4773                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4774                        let mut ix = 0;
4775                        while let Some(clipboard_selection) = clipboard_selections.next() {
4776                            newline_separated_text
4777                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4778                            ix += clipboard_selection.len;
4779                            if clipboard_selections.peek().is_some() {
4780                                newline_separated_text.push('\n');
4781                            }
4782                        }
4783                        clipboard_text = Cow::Owned(newline_separated_text);
4784                    }
4785
4786                    this.buffer.update(cx, |buffer, cx| {
4787                        let snapshot = buffer.read(cx);
4788                        let mut start_offset = 0;
4789                        let mut edits = Vec::new();
4790                        let mut original_indent_columns = Vec::new();
4791                        let line_mode = this.selections.line_mode;
4792                        for (ix, selection) in old_selections.iter().enumerate() {
4793                            let to_insert;
4794                            let entire_line;
4795                            let original_indent_column;
4796                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4797                                let end_offset = start_offset + clipboard_selection.len;
4798                                to_insert = &clipboard_text[start_offset..end_offset];
4799                                entire_line = clipboard_selection.is_entire_line;
4800                                start_offset = end_offset;
4801                                original_indent_column =
4802                                    Some(clipboard_selection.first_line_indent);
4803                            } else {
4804                                to_insert = clipboard_text.as_str();
4805                                entire_line = all_selections_were_entire_line;
4806                                original_indent_column = first_selection_indent_column
4807                            }
4808
4809                            // If the corresponding selection was empty when this slice of the
4810                            // clipboard text was written, then the entire line containing the
4811                            // selection was copied. If this selection is also currently empty,
4812                            // then paste the line before the current line of the buffer.
4813                            let range = if selection.is_empty() && !line_mode && entire_line {
4814                                let column = selection.start.to_point(&snapshot).column as usize;
4815                                let line_start = selection.start - column;
4816                                line_start..line_start
4817                            } else {
4818                                selection.range()
4819                            };
4820
4821                            edits.push((range, to_insert));
4822                            original_indent_columns.extend(original_indent_column);
4823                        }
4824                        drop(snapshot);
4825
4826                        buffer.edit(
4827                            edits,
4828                            Some(AutoindentMode::Block {
4829                                original_indent_columns,
4830                            }),
4831                            cx,
4832                        );
4833                    });
4834
4835                    let selections = this.selections.all::<usize>(cx);
4836                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4837                } else {
4838                    this.insert(&clipboard_text, cx);
4839                }
4840            }
4841        });
4842    }
4843
4844    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4845        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4846            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4847                self.change_selections(None, cx, |s| {
4848                    s.select_anchors(selections.to_vec());
4849                });
4850            }
4851            self.request_autoscroll(Autoscroll::fit(), cx);
4852            self.unmark_text(cx);
4853            self.refresh_copilot_suggestions(true, cx);
4854            cx.emit(Event::Edited);
4855        }
4856    }
4857
4858    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4859        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4860            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4861            {
4862                self.change_selections(None, cx, |s| {
4863                    s.select_anchors(selections.to_vec());
4864                });
4865            }
4866            self.request_autoscroll(Autoscroll::fit(), cx);
4867            self.unmark_text(cx);
4868            self.refresh_copilot_suggestions(true, cx);
4869            cx.emit(Event::Edited);
4870        }
4871    }
4872
4873    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4874        self.buffer
4875            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4876    }
4877
4878    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4879        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4880            let line_mode = s.line_mode;
4881            s.move_with(|map, selection| {
4882                let cursor = if selection.is_empty() && !line_mode {
4883                    movement::left(map, selection.start)
4884                } else {
4885                    selection.start
4886                };
4887                selection.collapse_to(cursor, SelectionGoal::None);
4888            });
4889        })
4890    }
4891
4892    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4893        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4894            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4895        })
4896    }
4897
4898    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4899        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4900            let line_mode = s.line_mode;
4901            s.move_with(|map, selection| {
4902                let cursor = if selection.is_empty() && !line_mode {
4903                    movement::right(map, selection.end)
4904                } else {
4905                    selection.end
4906                };
4907                selection.collapse_to(cursor, SelectionGoal::None)
4908            });
4909        })
4910    }
4911
4912    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4913        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4914            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4915        })
4916    }
4917
4918    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4919        if self.take_rename(true, cx).is_some() {
4920            return;
4921        }
4922
4923        if let Some(context_menu) = self.context_menu.as_mut() {
4924            if context_menu.select_prev(cx) {
4925                return;
4926            }
4927        }
4928
4929        if matches!(self.mode, EditorMode::SingleLine) {
4930            cx.propagate_action();
4931            return;
4932        }
4933
4934        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4935            let line_mode = s.line_mode;
4936            s.move_with(|map, selection| {
4937                if !selection.is_empty() && !line_mode {
4938                    selection.goal = SelectionGoal::None;
4939                }
4940                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4941                selection.collapse_to(cursor, goal);
4942            });
4943        })
4944    }
4945
4946    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4947        if self.take_rename(true, cx).is_some() {
4948            return;
4949        }
4950
4951        if self
4952            .context_menu
4953            .as_mut()
4954            .map(|menu| menu.select_first(cx))
4955            .unwrap_or(false)
4956        {
4957            return;
4958        }
4959
4960        if matches!(self.mode, EditorMode::SingleLine) {
4961            cx.propagate_action();
4962            return;
4963        }
4964
4965        let row_count = if let Some(row_count) = self.visible_line_count() {
4966            row_count as u32 - 1
4967        } else {
4968            return;
4969        };
4970
4971        let autoscroll = if action.center_cursor {
4972            Autoscroll::center()
4973        } else {
4974            Autoscroll::fit()
4975        };
4976
4977        self.change_selections(Some(autoscroll), cx, |s| {
4978            let line_mode = s.line_mode;
4979            s.move_with(|map, selection| {
4980                if !selection.is_empty() && !line_mode {
4981                    selection.goal = SelectionGoal::None;
4982                }
4983                let (cursor, goal) =
4984                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4985                selection.collapse_to(cursor, goal);
4986            });
4987        });
4988    }
4989
4990    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4991        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4992            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4993        })
4994    }
4995
4996    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4997        self.take_rename(true, cx);
4998
4999        if let Some(context_menu) = self.context_menu.as_mut() {
5000            if context_menu.select_next(cx) {
5001                return;
5002            }
5003        }
5004
5005        if self.mode == EditorMode::SingleLine {
5006            cx.propagate_action();
5007            return;
5008        }
5009
5010        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5011            let line_mode = s.line_mode;
5012            s.move_with(|map, selection| {
5013                if !selection.is_empty() && !line_mode {
5014                    selection.goal = SelectionGoal::None;
5015                }
5016                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
5017                selection.collapse_to(cursor, goal);
5018            });
5019        });
5020    }
5021
5022    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5023        if self.take_rename(true, cx).is_some() {
5024            return;
5025        }
5026
5027        if self
5028            .context_menu
5029            .as_mut()
5030            .map(|menu| menu.select_last(cx))
5031            .unwrap_or(false)
5032        {
5033            return;
5034        }
5035
5036        if matches!(self.mode, EditorMode::SingleLine) {
5037            cx.propagate_action();
5038            return;
5039        }
5040
5041        let row_count = if let Some(row_count) = self.visible_line_count() {
5042            row_count as u32 - 1
5043        } else {
5044            return;
5045        };
5046
5047        let autoscroll = if action.center_cursor {
5048            Autoscroll::center()
5049        } else {
5050            Autoscroll::fit()
5051        };
5052
5053        self.change_selections(Some(autoscroll), cx, |s| {
5054            let line_mode = s.line_mode;
5055            s.move_with(|map, selection| {
5056                if !selection.is_empty() && !line_mode {
5057                    selection.goal = SelectionGoal::None;
5058                }
5059                let (cursor, goal) =
5060                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5061                selection.collapse_to(cursor, goal);
5062            });
5063        });
5064    }
5065
5066    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5067        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5068            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5069        });
5070    }
5071
5072    pub fn move_to_previous_word_start(
5073        &mut self,
5074        _: &MoveToPreviousWordStart,
5075        cx: &mut ViewContext<Self>,
5076    ) {
5077        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5078            s.move_cursors_with(|map, head, _| {
5079                (
5080                    movement::previous_word_start(map, head),
5081                    SelectionGoal::None,
5082                )
5083            });
5084        })
5085    }
5086
5087    pub fn move_to_previous_subword_start(
5088        &mut self,
5089        _: &MoveToPreviousSubwordStart,
5090        cx: &mut ViewContext<Self>,
5091    ) {
5092        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5093            s.move_cursors_with(|map, head, _| {
5094                (
5095                    movement::previous_subword_start(map, head),
5096                    SelectionGoal::None,
5097                )
5098            });
5099        })
5100    }
5101
5102    pub fn select_to_previous_word_start(
5103        &mut self,
5104        _: &SelectToPreviousWordStart,
5105        cx: &mut ViewContext<Self>,
5106    ) {
5107        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5108            s.move_heads_with(|map, head, _| {
5109                (
5110                    movement::previous_word_start(map, head),
5111                    SelectionGoal::None,
5112                )
5113            });
5114        })
5115    }
5116
5117    pub fn select_to_previous_subword_start(
5118        &mut self,
5119        _: &SelectToPreviousSubwordStart,
5120        cx: &mut ViewContext<Self>,
5121    ) {
5122        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5123            s.move_heads_with(|map, head, _| {
5124                (
5125                    movement::previous_subword_start(map, head),
5126                    SelectionGoal::None,
5127                )
5128            });
5129        })
5130    }
5131
5132    pub fn delete_to_previous_word_start(
5133        &mut self,
5134        _: &DeleteToPreviousWordStart,
5135        cx: &mut ViewContext<Self>,
5136    ) {
5137        self.transact(cx, |this, cx| {
5138            this.select_autoclose_pair(cx);
5139            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5140                let line_mode = s.line_mode;
5141                s.move_with(|map, selection| {
5142                    if selection.is_empty() && !line_mode {
5143                        let cursor = movement::previous_word_start(map, selection.head());
5144                        selection.set_head(cursor, SelectionGoal::None);
5145                    }
5146                });
5147            });
5148            this.insert("", cx);
5149        });
5150    }
5151
5152    pub fn delete_to_previous_subword_start(
5153        &mut self,
5154        _: &DeleteToPreviousSubwordStart,
5155        cx: &mut ViewContext<Self>,
5156    ) {
5157        self.transact(cx, |this, cx| {
5158            this.select_autoclose_pair(cx);
5159            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5160                let line_mode = s.line_mode;
5161                s.move_with(|map, selection| {
5162                    if selection.is_empty() && !line_mode {
5163                        let cursor = movement::previous_subword_start(map, selection.head());
5164                        selection.set_head(cursor, SelectionGoal::None);
5165                    }
5166                });
5167            });
5168            this.insert("", cx);
5169        });
5170    }
5171
5172    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5173        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5174            s.move_cursors_with(|map, head, _| {
5175                (movement::next_word_end(map, head), SelectionGoal::None)
5176            });
5177        })
5178    }
5179
5180    pub fn move_to_next_subword_end(
5181        &mut self,
5182        _: &MoveToNextSubwordEnd,
5183        cx: &mut ViewContext<Self>,
5184    ) {
5185        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5186            s.move_cursors_with(|map, head, _| {
5187                (movement::next_subword_end(map, head), SelectionGoal::None)
5188            });
5189        })
5190    }
5191
5192    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5193        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5194            s.move_heads_with(|map, head, _| {
5195                (movement::next_word_end(map, head), SelectionGoal::None)
5196            });
5197        })
5198    }
5199
5200    pub fn select_to_next_subword_end(
5201        &mut self,
5202        _: &SelectToNextSubwordEnd,
5203        cx: &mut ViewContext<Self>,
5204    ) {
5205        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5206            s.move_heads_with(|map, head, _| {
5207                (movement::next_subword_end(map, head), SelectionGoal::None)
5208            });
5209        })
5210    }
5211
5212    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5213        self.transact(cx, |this, cx| {
5214            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5215                let line_mode = s.line_mode;
5216                s.move_with(|map, selection| {
5217                    if selection.is_empty() && !line_mode {
5218                        let cursor = movement::next_word_end(map, selection.head());
5219                        selection.set_head(cursor, SelectionGoal::None);
5220                    }
5221                });
5222            });
5223            this.insert("", cx);
5224        });
5225    }
5226
5227    pub fn delete_to_next_subword_end(
5228        &mut self,
5229        _: &DeleteToNextSubwordEnd,
5230        cx: &mut ViewContext<Self>,
5231    ) {
5232        self.transact(cx, |this, cx| {
5233            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5234                s.move_with(|map, selection| {
5235                    if selection.is_empty() {
5236                        let cursor = movement::next_subword_end(map, selection.head());
5237                        selection.set_head(cursor, SelectionGoal::None);
5238                    }
5239                });
5240            });
5241            this.insert("", cx);
5242        });
5243    }
5244
5245    pub fn move_to_beginning_of_line(
5246        &mut self,
5247        _: &MoveToBeginningOfLine,
5248        cx: &mut ViewContext<Self>,
5249    ) {
5250        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5251            s.move_cursors_with(|map, head, _| {
5252                (
5253                    movement::indented_line_beginning(map, head, true),
5254                    SelectionGoal::None,
5255                )
5256            });
5257        })
5258    }
5259
5260    pub fn select_to_beginning_of_line(
5261        &mut self,
5262        action: &SelectToBeginningOfLine,
5263        cx: &mut ViewContext<Self>,
5264    ) {
5265        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5266            s.move_heads_with(|map, head, _| {
5267                (
5268                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5269                    SelectionGoal::None,
5270                )
5271            });
5272        });
5273    }
5274
5275    pub fn delete_to_beginning_of_line(
5276        &mut self,
5277        _: &DeleteToBeginningOfLine,
5278        cx: &mut ViewContext<Self>,
5279    ) {
5280        self.transact(cx, |this, cx| {
5281            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5282                s.move_with(|_, selection| {
5283                    selection.reversed = true;
5284                });
5285            });
5286
5287            this.select_to_beginning_of_line(
5288                &SelectToBeginningOfLine {
5289                    stop_at_soft_wraps: false,
5290                },
5291                cx,
5292            );
5293            this.backspace(&Backspace, cx);
5294        });
5295    }
5296
5297    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5298        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5299            s.move_cursors_with(|map, head, _| {
5300                (movement::line_end(map, head, true), SelectionGoal::None)
5301            });
5302        })
5303    }
5304
5305    pub fn select_to_end_of_line(
5306        &mut self,
5307        action: &SelectToEndOfLine,
5308        cx: &mut ViewContext<Self>,
5309    ) {
5310        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5311            s.move_heads_with(|map, head, _| {
5312                (
5313                    movement::line_end(map, head, action.stop_at_soft_wraps),
5314                    SelectionGoal::None,
5315                )
5316            });
5317        })
5318    }
5319
5320    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5321        self.transact(cx, |this, cx| {
5322            this.select_to_end_of_line(
5323                &SelectToEndOfLine {
5324                    stop_at_soft_wraps: false,
5325                },
5326                cx,
5327            );
5328            this.delete(&Delete, cx);
5329        });
5330    }
5331
5332    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5333        self.transact(cx, |this, cx| {
5334            this.select_to_end_of_line(
5335                &SelectToEndOfLine {
5336                    stop_at_soft_wraps: false,
5337                },
5338                cx,
5339            );
5340            this.cut(&Cut, cx);
5341        });
5342    }
5343
5344    pub fn move_to_start_of_paragraph(
5345        &mut self,
5346        _: &MoveToStartOfParagraph,
5347        cx: &mut ViewContext<Self>,
5348    ) {
5349        if matches!(self.mode, EditorMode::SingleLine) {
5350            cx.propagate_action();
5351            return;
5352        }
5353
5354        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5355            s.move_with(|map, selection| {
5356                selection.collapse_to(
5357                    movement::start_of_paragraph(map, selection.head(), 1),
5358                    SelectionGoal::None,
5359                )
5360            });
5361        })
5362    }
5363
5364    pub fn move_to_end_of_paragraph(
5365        &mut self,
5366        _: &MoveToEndOfParagraph,
5367        cx: &mut ViewContext<Self>,
5368    ) {
5369        if matches!(self.mode, EditorMode::SingleLine) {
5370            cx.propagate_action();
5371            return;
5372        }
5373
5374        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5375            s.move_with(|map, selection| {
5376                selection.collapse_to(
5377                    movement::end_of_paragraph(map, selection.head(), 1),
5378                    SelectionGoal::None,
5379                )
5380            });
5381        })
5382    }
5383
5384    pub fn select_to_start_of_paragraph(
5385        &mut self,
5386        _: &SelectToStartOfParagraph,
5387        cx: &mut ViewContext<Self>,
5388    ) {
5389        if matches!(self.mode, EditorMode::SingleLine) {
5390            cx.propagate_action();
5391            return;
5392        }
5393
5394        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5395            s.move_heads_with(|map, head, _| {
5396                (
5397                    movement::start_of_paragraph(map, head, 1),
5398                    SelectionGoal::None,
5399                )
5400            });
5401        })
5402    }
5403
5404    pub fn select_to_end_of_paragraph(
5405        &mut self,
5406        _: &SelectToEndOfParagraph,
5407        cx: &mut ViewContext<Self>,
5408    ) {
5409        if matches!(self.mode, EditorMode::SingleLine) {
5410            cx.propagate_action();
5411            return;
5412        }
5413
5414        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5415            s.move_heads_with(|map, head, _| {
5416                (
5417                    movement::end_of_paragraph(map, head, 1),
5418                    SelectionGoal::None,
5419                )
5420            });
5421        })
5422    }
5423
5424    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5425        if matches!(self.mode, EditorMode::SingleLine) {
5426            cx.propagate_action();
5427            return;
5428        }
5429
5430        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5431            s.select_ranges(vec![0..0]);
5432        });
5433    }
5434
5435    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5436        let mut selection = self.selections.last::<Point>(cx);
5437        selection.set_head(Point::zero(), SelectionGoal::None);
5438
5439        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5440            s.select(vec![selection]);
5441        });
5442    }
5443
5444    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5445        if matches!(self.mode, EditorMode::SingleLine) {
5446            cx.propagate_action();
5447            return;
5448        }
5449
5450        let cursor = self.buffer.read(cx).read(cx).len();
5451        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5452            s.select_ranges(vec![cursor..cursor])
5453        });
5454    }
5455
5456    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5457        self.nav_history = nav_history;
5458    }
5459
5460    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5461        self.nav_history.as_ref()
5462    }
5463
5464    fn push_to_nav_history(
5465        &mut self,
5466        cursor_anchor: Anchor,
5467        new_position: Option<Point>,
5468        cx: &mut ViewContext<Self>,
5469    ) {
5470        if let Some(nav_history) = self.nav_history.as_mut() {
5471            let buffer = self.buffer.read(cx).read(cx);
5472            let cursor_position = cursor_anchor.to_point(&buffer);
5473            let scroll_state = self.scroll_manager.anchor();
5474            let scroll_top_row = scroll_state.top_row(&buffer);
5475            drop(buffer);
5476
5477            if let Some(new_position) = new_position {
5478                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5479                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5480                    return;
5481                }
5482            }
5483
5484            nav_history.push(
5485                Some(NavigationData {
5486                    cursor_anchor,
5487                    cursor_position,
5488                    scroll_anchor: scroll_state,
5489                    scroll_top_row,
5490                }),
5491                cx,
5492            );
5493        }
5494    }
5495
5496    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5497        let buffer = self.buffer.read(cx).snapshot(cx);
5498        let mut selection = self.selections.first::<usize>(cx);
5499        selection.set_head(buffer.len(), SelectionGoal::None);
5500        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5501            s.select(vec![selection]);
5502        });
5503    }
5504
5505    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5506        let end = self.buffer.read(cx).read(cx).len();
5507        self.change_selections(None, cx, |s| {
5508            s.select_ranges(vec![0..end]);
5509        });
5510    }
5511
5512    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5513        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5514        let mut selections = self.selections.all::<Point>(cx);
5515        let max_point = display_map.buffer_snapshot.max_point();
5516        for selection in &mut selections {
5517            let rows = selection.spanned_rows(true, &display_map);
5518            selection.start = Point::new(rows.start, 0);
5519            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5520            selection.reversed = false;
5521        }
5522        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5523            s.select(selections);
5524        });
5525    }
5526
5527    pub fn split_selection_into_lines(
5528        &mut self,
5529        _: &SplitSelectionIntoLines,
5530        cx: &mut ViewContext<Self>,
5531    ) {
5532        let mut to_unfold = Vec::new();
5533        let mut new_selection_ranges = Vec::new();
5534        {
5535            let selections = self.selections.all::<Point>(cx);
5536            let buffer = self.buffer.read(cx).read(cx);
5537            for selection in selections {
5538                for row in selection.start.row..selection.end.row {
5539                    let cursor = Point::new(row, buffer.line_len(row));
5540                    new_selection_ranges.push(cursor..cursor);
5541                }
5542                new_selection_ranges.push(selection.end..selection.end);
5543                to_unfold.push(selection.start..selection.end);
5544            }
5545        }
5546        self.unfold_ranges(to_unfold, true, true, cx);
5547        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5548            s.select_ranges(new_selection_ranges);
5549        });
5550    }
5551
5552    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5553        self.add_selection(true, cx);
5554    }
5555
5556    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5557        self.add_selection(false, cx);
5558    }
5559
5560    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5561        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5562        let mut selections = self.selections.all::<Point>(cx);
5563        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5564            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5565            let range = oldest_selection.display_range(&display_map).sorted();
5566            let columns = cmp::min(range.start.column(), range.end.column())
5567                ..cmp::max(range.start.column(), range.end.column());
5568
5569            selections.clear();
5570            let mut stack = Vec::new();
5571            for row in range.start.row()..=range.end.row() {
5572                if let Some(selection) = self.selections.build_columnar_selection(
5573                    &display_map,
5574                    row,
5575                    &columns,
5576                    oldest_selection.reversed,
5577                ) {
5578                    stack.push(selection.id);
5579                    selections.push(selection);
5580                }
5581            }
5582
5583            if above {
5584                stack.reverse();
5585            }
5586
5587            AddSelectionsState { above, stack }
5588        });
5589
5590        let last_added_selection = *state.stack.last().unwrap();
5591        let mut new_selections = Vec::new();
5592        if above == state.above {
5593            let end_row = if above {
5594                0
5595            } else {
5596                display_map.max_point().row()
5597            };
5598
5599            'outer: for selection in selections {
5600                if selection.id == last_added_selection {
5601                    let range = selection.display_range(&display_map).sorted();
5602                    debug_assert_eq!(range.start.row(), range.end.row());
5603                    let mut row = range.start.row();
5604                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5605                    {
5606                        start..end
5607                    } else {
5608                        cmp::min(range.start.column(), range.end.column())
5609                            ..cmp::max(range.start.column(), range.end.column())
5610                    };
5611
5612                    while row != end_row {
5613                        if above {
5614                            row -= 1;
5615                        } else {
5616                            row += 1;
5617                        }
5618
5619                        if let Some(new_selection) = self.selections.build_columnar_selection(
5620                            &display_map,
5621                            row,
5622                            &columns,
5623                            selection.reversed,
5624                        ) {
5625                            state.stack.push(new_selection.id);
5626                            if above {
5627                                new_selections.push(new_selection);
5628                                new_selections.push(selection);
5629                            } else {
5630                                new_selections.push(selection);
5631                                new_selections.push(new_selection);
5632                            }
5633
5634                            continue 'outer;
5635                        }
5636                    }
5637                }
5638
5639                new_selections.push(selection);
5640            }
5641        } else {
5642            new_selections = selections;
5643            new_selections.retain(|s| s.id != last_added_selection);
5644            state.stack.pop();
5645        }
5646
5647        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5648            s.select(new_selections);
5649        });
5650        if state.stack.len() > 1 {
5651            self.add_selections_state = Some(state);
5652        }
5653    }
5654
5655    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5656        self.push_to_selection_history();
5657        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5658        let buffer = &display_map.buffer_snapshot;
5659        let mut selections = self.selections.all::<usize>(cx);
5660        if let Some(mut select_next_state) = self.select_next_state.take() {
5661            let query = &select_next_state.query;
5662            if !select_next_state.done {
5663                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5664                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5665                let mut next_selected_range = None;
5666
5667                let bytes_after_last_selection =
5668                    buffer.bytes_in_range(last_selection.end..buffer.len());
5669                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5670                let query_matches = query
5671                    .stream_find_iter(bytes_after_last_selection)
5672                    .map(|result| (last_selection.end, result))
5673                    .chain(
5674                        query
5675                            .stream_find_iter(bytes_before_first_selection)
5676                            .map(|result| (0, result)),
5677                    );
5678                for (start_offset, query_match) in query_matches {
5679                    let query_match = query_match.unwrap(); // can only fail due to I/O
5680                    let offset_range =
5681                        start_offset + query_match.start()..start_offset + query_match.end();
5682                    let display_range = offset_range.start.to_display_point(&display_map)
5683                        ..offset_range.end.to_display_point(&display_map);
5684
5685                    if !select_next_state.wordwise
5686                        || (!movement::is_inside_word(&display_map, display_range.start)
5687                            && !movement::is_inside_word(&display_map, display_range.end))
5688                    {
5689                        next_selected_range = Some(offset_range);
5690                        break;
5691                    }
5692                }
5693
5694                if let Some(next_selected_range) = next_selected_range {
5695                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5696                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5697                        if action.replace_newest {
5698                            s.delete(s.newest_anchor().id);
5699                        }
5700                        s.insert_range(next_selected_range);
5701                    });
5702                } else {
5703                    select_next_state.done = true;
5704                }
5705            }
5706
5707            self.select_next_state = Some(select_next_state);
5708        } else if selections.len() == 1 {
5709            let selection = selections.last_mut().unwrap();
5710            if selection.start == selection.end {
5711                let word_range = movement::surrounding_word(
5712                    &display_map,
5713                    selection.start.to_display_point(&display_map),
5714                );
5715                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5716                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5717                selection.goal = SelectionGoal::None;
5718                selection.reversed = false;
5719
5720                let query = buffer
5721                    .text_for_range(selection.start..selection.end)
5722                    .collect::<String>();
5723                let select_state = SelectNextState {
5724                    query: AhoCorasick::new_auto_configured(&[query]),
5725                    wordwise: true,
5726                    done: false,
5727                };
5728                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5729                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5730                    s.select(selections);
5731                });
5732                self.select_next_state = Some(select_state);
5733            } else {
5734                let query = buffer
5735                    .text_for_range(selection.start..selection.end)
5736                    .collect::<String>();
5737                self.select_next_state = Some(SelectNextState {
5738                    query: AhoCorasick::new_auto_configured(&[query]),
5739                    wordwise: false,
5740                    done: false,
5741                });
5742                self.select_next(action, cx);
5743            }
5744        }
5745    }
5746
5747    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5748        self.push_to_selection_history();
5749        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5750        let buffer = &display_map.buffer_snapshot;
5751        let mut selections = self.selections.all::<usize>(cx);
5752        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5753            let query = &select_prev_state.query;
5754            if !select_prev_state.done {
5755                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5756                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5757                let mut next_selected_range = None;
5758                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5759                let bytes_before_last_selection =
5760                    buffer.reversed_bytes_in_range(0..last_selection.start);
5761                let bytes_after_first_selection =
5762                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5763                let query_matches = query
5764                    .stream_find_iter(bytes_before_last_selection)
5765                    .map(|result| (last_selection.start, result))
5766                    .chain(
5767                        query
5768                            .stream_find_iter(bytes_after_first_selection)
5769                            .map(|result| (buffer.len(), result)),
5770                    );
5771                for (end_offset, query_match) in query_matches {
5772                    let query_match = query_match.unwrap(); // can only fail due to I/O
5773                    let offset_range =
5774                        end_offset - query_match.end()..end_offset - query_match.start();
5775                    let display_range = offset_range.start.to_display_point(&display_map)
5776                        ..offset_range.end.to_display_point(&display_map);
5777
5778                    if !select_prev_state.wordwise
5779                        || (!movement::is_inside_word(&display_map, display_range.start)
5780                            && !movement::is_inside_word(&display_map, display_range.end))
5781                    {
5782                        next_selected_range = Some(offset_range);
5783                        break;
5784                    }
5785                }
5786
5787                if let Some(next_selected_range) = next_selected_range {
5788                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5789                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5790                        if action.replace_newest {
5791                            s.delete(s.newest_anchor().id);
5792                        }
5793                        s.insert_range(next_selected_range);
5794                    });
5795                } else {
5796                    select_prev_state.done = true;
5797                }
5798            }
5799
5800            self.select_prev_state = Some(select_prev_state);
5801        } else if selections.len() == 1 {
5802            let selection = selections.last_mut().unwrap();
5803            if selection.start == selection.end {
5804                let word_range = movement::surrounding_word(
5805                    &display_map,
5806                    selection.start.to_display_point(&display_map),
5807                );
5808                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5809                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5810                selection.goal = SelectionGoal::None;
5811                selection.reversed = false;
5812
5813                let query = buffer
5814                    .text_for_range(selection.start..selection.end)
5815                    .collect::<String>();
5816                let query = query.chars().rev().collect::<String>();
5817                let select_state = SelectNextState {
5818                    query: AhoCorasick::new_auto_configured(&[query]),
5819                    wordwise: true,
5820                    done: false,
5821                };
5822                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5823                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5824                    s.select(selections);
5825                });
5826                self.select_prev_state = Some(select_state);
5827            } else {
5828                let query = buffer
5829                    .text_for_range(selection.start..selection.end)
5830                    .collect::<String>();
5831                let query = query.chars().rev().collect::<String>();
5832                self.select_prev_state = Some(SelectNextState {
5833                    query: AhoCorasick::new_auto_configured(&[query]),
5834                    wordwise: false,
5835                    done: false,
5836                });
5837                self.select_previous(action, cx);
5838            }
5839        }
5840    }
5841
5842    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5843        self.transact(cx, |this, cx| {
5844            let mut selections = this.selections.all::<Point>(cx);
5845            let mut edits = Vec::new();
5846            let mut selection_edit_ranges = Vec::new();
5847            let mut last_toggled_row = None;
5848            let snapshot = this.buffer.read(cx).read(cx);
5849            let empty_str: Arc<str> = "".into();
5850            let mut suffixes_inserted = Vec::new();
5851
5852            fn comment_prefix_range(
5853                snapshot: &MultiBufferSnapshot,
5854                row: u32,
5855                comment_prefix: &str,
5856                comment_prefix_whitespace: &str,
5857            ) -> Range<Point> {
5858                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5859
5860                let mut line_bytes = snapshot
5861                    .bytes_in_range(start..snapshot.max_point())
5862                    .flatten()
5863                    .copied();
5864
5865                // If this line currently begins with the line comment prefix, then record
5866                // the range containing the prefix.
5867                if line_bytes
5868                    .by_ref()
5869                    .take(comment_prefix.len())
5870                    .eq(comment_prefix.bytes())
5871                {
5872                    // Include any whitespace that matches the comment prefix.
5873                    let matching_whitespace_len = line_bytes
5874                        .zip(comment_prefix_whitespace.bytes())
5875                        .take_while(|(a, b)| a == b)
5876                        .count() as u32;
5877                    let end = Point::new(
5878                        start.row,
5879                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5880                    );
5881                    start..end
5882                } else {
5883                    start..start
5884                }
5885            }
5886
5887            fn comment_suffix_range(
5888                snapshot: &MultiBufferSnapshot,
5889                row: u32,
5890                comment_suffix: &str,
5891                comment_suffix_has_leading_space: bool,
5892            ) -> Range<Point> {
5893                let end = Point::new(row, snapshot.line_len(row));
5894                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5895
5896                let mut line_end_bytes = snapshot
5897                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5898                    .flatten()
5899                    .copied();
5900
5901                let leading_space_len = if suffix_start_column > 0
5902                    && line_end_bytes.next() == Some(b' ')
5903                    && comment_suffix_has_leading_space
5904                {
5905                    1
5906                } else {
5907                    0
5908                };
5909
5910                // If this line currently begins with the line comment prefix, then record
5911                // the range containing the prefix.
5912                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5913                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5914                    start..end
5915                } else {
5916                    end..end
5917                }
5918            }
5919
5920            // TODO: Handle selections that cross excerpts
5921            for selection in &mut selections {
5922                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5923                let language = if let Some(language) =
5924                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5925                {
5926                    language
5927                } else {
5928                    continue;
5929                };
5930
5931                selection_edit_ranges.clear();
5932
5933                // If multiple selections contain a given row, avoid processing that
5934                // row more than once.
5935                let mut start_row = selection.start.row;
5936                if last_toggled_row == Some(start_row) {
5937                    start_row += 1;
5938                }
5939                let end_row =
5940                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5941                        selection.end.row - 1
5942                    } else {
5943                        selection.end.row
5944                    };
5945                last_toggled_row = Some(end_row);
5946
5947                if start_row > end_row {
5948                    continue;
5949                }
5950
5951                // If the language has line comments, toggle those.
5952                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5953                    // Split the comment prefix's trailing whitespace into a separate string,
5954                    // as that portion won't be used for detecting if a line is a comment.
5955                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5956                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5957                    let mut all_selection_lines_are_comments = true;
5958
5959                    for row in start_row..=end_row {
5960                        if snapshot.is_line_blank(row) && start_row < end_row {
5961                            continue;
5962                        }
5963
5964                        let prefix_range = comment_prefix_range(
5965                            snapshot.deref(),
5966                            row,
5967                            comment_prefix,
5968                            comment_prefix_whitespace,
5969                        );
5970                        if prefix_range.is_empty() {
5971                            all_selection_lines_are_comments = false;
5972                        }
5973                        selection_edit_ranges.push(prefix_range);
5974                    }
5975
5976                    if all_selection_lines_are_comments {
5977                        edits.extend(
5978                            selection_edit_ranges
5979                                .iter()
5980                                .cloned()
5981                                .map(|range| (range, empty_str.clone())),
5982                        );
5983                    } else {
5984                        let min_column = selection_edit_ranges
5985                            .iter()
5986                            .map(|r| r.start.column)
5987                            .min()
5988                            .unwrap_or(0);
5989                        edits.extend(selection_edit_ranges.iter().map(|range| {
5990                            let position = Point::new(range.start.row, min_column);
5991                            (position..position, full_comment_prefix.clone())
5992                        }));
5993                    }
5994                } else if let Some((full_comment_prefix, comment_suffix)) =
5995                    language.block_comment_delimiters()
5996                {
5997                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5998                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5999                    let prefix_range = comment_prefix_range(
6000                        snapshot.deref(),
6001                        start_row,
6002                        comment_prefix,
6003                        comment_prefix_whitespace,
6004                    );
6005                    let suffix_range = comment_suffix_range(
6006                        snapshot.deref(),
6007                        end_row,
6008                        comment_suffix.trim_start_matches(' '),
6009                        comment_suffix.starts_with(' '),
6010                    );
6011
6012                    if prefix_range.is_empty() || suffix_range.is_empty() {
6013                        edits.push((
6014                            prefix_range.start..prefix_range.start,
6015                            full_comment_prefix.clone(),
6016                        ));
6017                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6018                        suffixes_inserted.push((end_row, comment_suffix.len()));
6019                    } else {
6020                        edits.push((prefix_range, empty_str.clone()));
6021                        edits.push((suffix_range, empty_str.clone()));
6022                    }
6023                } else {
6024                    continue;
6025                }
6026            }
6027
6028            drop(snapshot);
6029            this.buffer.update(cx, |buffer, cx| {
6030                buffer.edit(edits, None, cx);
6031            });
6032
6033            // Adjust selections so that they end before any comment suffixes that
6034            // were inserted.
6035            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6036            let mut selections = this.selections.all::<Point>(cx);
6037            let snapshot = this.buffer.read(cx).read(cx);
6038            for selection in &mut selections {
6039                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6040                    match row.cmp(&selection.end.row) {
6041                        Ordering::Less => {
6042                            suffixes_inserted.next();
6043                            continue;
6044                        }
6045                        Ordering::Greater => break,
6046                        Ordering::Equal => {
6047                            if selection.end.column == snapshot.line_len(row) {
6048                                if selection.is_empty() {
6049                                    selection.start.column -= suffix_len as u32;
6050                                }
6051                                selection.end.column -= suffix_len as u32;
6052                            }
6053                            break;
6054                        }
6055                    }
6056                }
6057            }
6058
6059            drop(snapshot);
6060            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6061
6062            let selections = this.selections.all::<Point>(cx);
6063            let selections_on_single_row = selections.windows(2).all(|selections| {
6064                selections[0].start.row == selections[1].start.row
6065                    && selections[0].end.row == selections[1].end.row
6066                    && selections[0].start.row == selections[0].end.row
6067            });
6068            let selections_selecting = selections
6069                .iter()
6070                .any(|selection| selection.start != selection.end);
6071            let advance_downwards = action.advance_downwards
6072                && selections_on_single_row
6073                && !selections_selecting
6074                && this.mode != EditorMode::SingleLine;
6075
6076            if advance_downwards {
6077                let snapshot = this.buffer.read(cx).snapshot(cx);
6078
6079                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6080                    s.move_cursors_with(|display_snapshot, display_point, _| {
6081                        let mut point = display_point.to_point(display_snapshot);
6082                        point.row += 1;
6083                        point = snapshot.clip_point(point, Bias::Left);
6084                        let display_point = point.to_display_point(display_snapshot);
6085                        (display_point, SelectionGoal::Column(display_point.column()))
6086                    })
6087                });
6088            }
6089        });
6090    }
6091
6092    pub fn select_larger_syntax_node(
6093        &mut self,
6094        _: &SelectLargerSyntaxNode,
6095        cx: &mut ViewContext<Self>,
6096    ) {
6097        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6098        let buffer = self.buffer.read(cx).snapshot(cx);
6099        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6100
6101        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6102        let mut selected_larger_node = false;
6103        let new_selections = old_selections
6104            .iter()
6105            .map(|selection| {
6106                let old_range = selection.start..selection.end;
6107                let mut new_range = old_range.clone();
6108                while let Some(containing_range) =
6109                    buffer.range_for_syntax_ancestor(new_range.clone())
6110                {
6111                    new_range = containing_range;
6112                    if !display_map.intersects_fold(new_range.start)
6113                        && !display_map.intersects_fold(new_range.end)
6114                    {
6115                        break;
6116                    }
6117                }
6118
6119                selected_larger_node |= new_range != old_range;
6120                Selection {
6121                    id: selection.id,
6122                    start: new_range.start,
6123                    end: new_range.end,
6124                    goal: SelectionGoal::None,
6125                    reversed: selection.reversed,
6126                }
6127            })
6128            .collect::<Vec<_>>();
6129
6130        if selected_larger_node {
6131            stack.push(old_selections);
6132            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6133                s.select(new_selections);
6134            });
6135        }
6136        self.select_larger_syntax_node_stack = stack;
6137    }
6138
6139    pub fn select_smaller_syntax_node(
6140        &mut self,
6141        _: &SelectSmallerSyntaxNode,
6142        cx: &mut ViewContext<Self>,
6143    ) {
6144        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6145        if let Some(selections) = stack.pop() {
6146            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6147                s.select(selections.to_vec());
6148            });
6149        }
6150        self.select_larger_syntax_node_stack = stack;
6151    }
6152
6153    pub fn move_to_enclosing_bracket(
6154        &mut self,
6155        _: &MoveToEnclosingBracket,
6156        cx: &mut ViewContext<Self>,
6157    ) {
6158        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6159            s.move_offsets_with(|snapshot, selection| {
6160                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
6161                    return;
6162                };
6163
6164                let mut best_length = usize::MAX;
6165                let mut best_inside = false;
6166                let mut best_in_bracket_range = false;
6167                let mut best_destination = None;
6168                for (open, close) in enclosing_bracket_ranges {
6169                    let close = close.to_inclusive();
6170                    let length = close.end() - open.start;
6171                    let inside = selection.start >= open.end && selection.end <= *close.start();
6172                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
6173
6174                    // If best is next to a bracket and current isn't, skip
6175                    if !in_bracket_range && best_in_bracket_range {
6176                        continue;
6177                    }
6178
6179                    // Prefer smaller lengths unless best is inside and current isn't
6180                    if length > best_length && (best_inside || !inside) {
6181                        continue;
6182                    }
6183
6184                    best_length = length;
6185                    best_inside = inside;
6186                    best_in_bracket_range = in_bracket_range;
6187                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
6188                        if inside {
6189                            open.end
6190                        } else {
6191                            open.start
6192                        }
6193                    } else {
6194                        if inside {
6195                            *close.start()
6196                        } else {
6197                            *close.end()
6198                        }
6199                    });
6200                }
6201
6202                if let Some(destination) = best_destination {
6203                    selection.collapse_to(destination, SelectionGoal::None);
6204                }
6205            })
6206        });
6207    }
6208
6209    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6210        self.end_selection(cx);
6211        self.selection_history.mode = SelectionHistoryMode::Undoing;
6212        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6213            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6214            self.select_next_state = entry.select_next_state;
6215            self.select_prev_state = entry.select_prev_state;
6216            self.add_selections_state = entry.add_selections_state;
6217            self.request_autoscroll(Autoscroll::newest(), cx);
6218        }
6219        self.selection_history.mode = SelectionHistoryMode::Normal;
6220    }
6221
6222    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6223        self.end_selection(cx);
6224        self.selection_history.mode = SelectionHistoryMode::Redoing;
6225        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6226            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6227            self.select_next_state = entry.select_next_state;
6228            self.select_prev_state = entry.select_prev_state;
6229            self.add_selections_state = entry.add_selections_state;
6230            self.request_autoscroll(Autoscroll::newest(), cx);
6231        }
6232        self.selection_history.mode = SelectionHistoryMode::Normal;
6233    }
6234
6235    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6236        self.go_to_diagnostic_impl(Direction::Next, cx)
6237    }
6238
6239    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6240        self.go_to_diagnostic_impl(Direction::Prev, cx)
6241    }
6242
6243    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6244        let buffer = self.buffer.read(cx).snapshot(cx);
6245        let selection = self.selections.newest::<usize>(cx);
6246
6247        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6248        if direction == Direction::Next {
6249            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6250                let (group_id, jump_to) = popover.activation_info();
6251                if self.activate_diagnostics(group_id, cx) {
6252                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6253                        let mut new_selection = s.newest_anchor().clone();
6254                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6255                        s.select_anchors(vec![new_selection.clone()]);
6256                    });
6257                }
6258                return;
6259            }
6260        }
6261
6262        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6263            active_diagnostics
6264                .primary_range
6265                .to_offset(&buffer)
6266                .to_inclusive()
6267        });
6268        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6269            if active_primary_range.contains(&selection.head()) {
6270                *active_primary_range.end()
6271            } else {
6272                selection.head()
6273            }
6274        } else {
6275            selection.head()
6276        };
6277
6278        loop {
6279            let mut diagnostics = if direction == Direction::Prev {
6280                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6281            } else {
6282                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6283            };
6284            let group = diagnostics.find_map(|entry| {
6285                if entry.diagnostic.is_primary
6286                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6287                    && !entry.range.is_empty()
6288                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6289                {
6290                    Some((entry.range, entry.diagnostic.group_id))
6291                } else {
6292                    None
6293                }
6294            });
6295
6296            if let Some((primary_range, group_id)) = group {
6297                if self.activate_diagnostics(group_id, cx) {
6298                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6299                        s.select(vec![Selection {
6300                            id: selection.id,
6301                            start: primary_range.start,
6302                            end: primary_range.start,
6303                            reversed: false,
6304                            goal: SelectionGoal::None,
6305                        }]);
6306                    });
6307                }
6308                break;
6309            } else {
6310                // Cycle around to the start of the buffer, potentially moving back to the start of
6311                // the currently active diagnostic.
6312                active_primary_range.take();
6313                if direction == Direction::Prev {
6314                    if search_start == buffer.len() {
6315                        break;
6316                    } else {
6317                        search_start = buffer.len();
6318                    }
6319                } else if search_start == 0 {
6320                    break;
6321                } else {
6322                    search_start = 0;
6323                }
6324            }
6325        }
6326    }
6327
6328    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6329        let snapshot = self
6330            .display_map
6331            .update(cx, |display_map, cx| display_map.snapshot(cx));
6332        let selection = self.selections.newest::<Point>(cx);
6333
6334        if !self.seek_in_direction(
6335            &snapshot,
6336            selection.head(),
6337            false,
6338            snapshot
6339                .buffer_snapshot
6340                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6341            cx,
6342        ) {
6343            let wrapped_point = Point::zero();
6344            self.seek_in_direction(
6345                &snapshot,
6346                wrapped_point,
6347                true,
6348                snapshot
6349                    .buffer_snapshot
6350                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6351                cx,
6352            );
6353        }
6354    }
6355
6356    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6357        let snapshot = self
6358            .display_map
6359            .update(cx, |display_map, cx| display_map.snapshot(cx));
6360        let selection = self.selections.newest::<Point>(cx);
6361
6362        if !self.seek_in_direction(
6363            &snapshot,
6364            selection.head(),
6365            false,
6366            snapshot
6367                .buffer_snapshot
6368                .git_diff_hunks_in_range_rev(0..selection.head().row),
6369            cx,
6370        ) {
6371            let wrapped_point = snapshot.buffer_snapshot.max_point();
6372            self.seek_in_direction(
6373                &snapshot,
6374                wrapped_point,
6375                true,
6376                snapshot
6377                    .buffer_snapshot
6378                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6379                cx,
6380            );
6381        }
6382    }
6383
6384    fn seek_in_direction(
6385        &mut self,
6386        snapshot: &DisplaySnapshot,
6387        initial_point: Point,
6388        is_wrapped: bool,
6389        hunks: impl Iterator<Item = DiffHunk<u32>>,
6390        cx: &mut ViewContext<Editor>,
6391    ) -> bool {
6392        let display_point = initial_point.to_display_point(snapshot);
6393        let mut hunks = hunks
6394            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6395            .skip_while(|hunk| {
6396                if is_wrapped {
6397                    false
6398                } else {
6399                    hunk.contains_display_row(display_point.row())
6400                }
6401            })
6402            .dedup();
6403
6404        if let Some(hunk) = hunks.next() {
6405            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6406                let row = hunk.start_display_row();
6407                let point = DisplayPoint::new(row, 0);
6408                s.select_display_ranges([point..point]);
6409            });
6410
6411            true
6412        } else {
6413            false
6414        }
6415    }
6416
6417    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6418        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6419    }
6420
6421    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6422        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6423    }
6424
6425    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6426        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6427    }
6428
6429    pub fn go_to_type_definition_split(
6430        &mut self,
6431        _: &GoToTypeDefinitionSplit,
6432        cx: &mut ViewContext<Self>,
6433    ) {
6434        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6435    }
6436
6437    fn go_to_definition_of_kind(
6438        &mut self,
6439        kind: GotoDefinitionKind,
6440        split: bool,
6441        cx: &mut ViewContext<Self>,
6442    ) {
6443        let Some(workspace) = self.workspace(cx) else { return };
6444        let buffer = self.buffer.read(cx);
6445        let head = self.selections.newest::<usize>(cx).head();
6446        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6447            text_anchor
6448        } else {
6449            return;
6450        };
6451
6452        let project = workspace.read(cx).project().clone();
6453        let definitions = project.update(cx, |project, cx| match kind {
6454            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6455            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6456        });
6457
6458        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6459            let definitions = definitions.await?;
6460            editor.update(&mut cx, |editor, cx| {
6461                editor.navigate_to_definitions(definitions, split, cx);
6462            })?;
6463            Ok::<(), anyhow::Error>(())
6464        })
6465        .detach_and_log_err(cx);
6466    }
6467
6468    pub fn navigate_to_definitions(
6469        &mut self,
6470        mut definitions: Vec<LocationLink>,
6471        split: bool,
6472        cx: &mut ViewContext<Editor>,
6473    ) {
6474        let Some(workspace) = self.workspace(cx) else { return };
6475        let pane = workspace.read(cx).active_pane().clone();
6476        // If there is one definition, just open it directly
6477        if definitions.len() == 1 {
6478            let definition = definitions.pop().unwrap();
6479            let range = definition
6480                .target
6481                .range
6482                .to_offset(definition.target.buffer.read(cx));
6483
6484            let range = self.range_for_match(&range);
6485            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6486                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6487                    s.select_ranges([range]);
6488                });
6489            } else {
6490                cx.window_context().defer(move |cx| {
6491                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6492                        if split {
6493                            workspace.split_project_item(definition.target.buffer.clone(), cx)
6494                        } else {
6495                            workspace.open_project_item(definition.target.buffer.clone(), cx)
6496                        }
6497                    });
6498                    target_editor.update(cx, |target_editor, cx| {
6499                        // When selecting a definition in a different buffer, disable the nav history
6500                        // to avoid creating a history entry at the previous cursor location.
6501                        pane.update(cx, |pane, _| pane.disable_history());
6502                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6503                            s.select_ranges([range]);
6504                        });
6505                        pane.update(cx, |pane, _| pane.enable_history());
6506                    });
6507                });
6508            }
6509        } else if !definitions.is_empty() {
6510            let replica_id = self.replica_id(cx);
6511            cx.window_context().defer(move |cx| {
6512                let title = definitions
6513                    .iter()
6514                    .find(|definition| definition.origin.is_some())
6515                    .and_then(|definition| {
6516                        definition.origin.as_ref().map(|origin| {
6517                            let buffer = origin.buffer.read(cx);
6518                            format!(
6519                                "Definitions for {}",
6520                                buffer
6521                                    .text_for_range(origin.range.clone())
6522                                    .collect::<String>()
6523                            )
6524                        })
6525                    })
6526                    .unwrap_or("Definitions".to_owned());
6527                let locations = definitions
6528                    .into_iter()
6529                    .map(|definition| definition.target)
6530                    .collect();
6531                workspace.update(cx, |workspace, cx| {
6532                    Self::open_locations_in_multibuffer(
6533                        workspace, locations, replica_id, title, split, cx,
6534                    )
6535                });
6536            });
6537        }
6538    }
6539
6540    pub fn find_all_references(
6541        workspace: &mut Workspace,
6542        _: &FindAllReferences,
6543        cx: &mut ViewContext<Workspace>,
6544    ) -> Option<Task<Result<()>>> {
6545        let active_item = workspace.active_item(cx)?;
6546        let editor_handle = active_item.act_as::<Self>(cx)?;
6547
6548        let editor = editor_handle.read(cx);
6549        let buffer = editor.buffer.read(cx);
6550        let head = editor.selections.newest::<usize>(cx).head();
6551        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6552        let replica_id = editor.replica_id(cx);
6553
6554        let project = workspace.project().clone();
6555        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6556        Some(cx.spawn_labeled(
6557            "Finding All References...",
6558            |workspace, mut cx| async move {
6559                let locations = references.await?;
6560                if locations.is_empty() {
6561                    return Ok(());
6562                }
6563
6564                workspace.update(&mut cx, |workspace, cx| {
6565                    let title = locations
6566                        .first()
6567                        .as_ref()
6568                        .map(|location| {
6569                            let buffer = location.buffer.read(cx);
6570                            format!(
6571                                "References to `{}`",
6572                                buffer
6573                                    .text_for_range(location.range.clone())
6574                                    .collect::<String>()
6575                            )
6576                        })
6577                        .unwrap();
6578                    Self::open_locations_in_multibuffer(
6579                        workspace, locations, replica_id, title, false, cx,
6580                    );
6581                })?;
6582
6583                Ok(())
6584            },
6585        ))
6586    }
6587
6588    /// Opens a multibuffer with the given project locations in it
6589    pub fn open_locations_in_multibuffer(
6590        workspace: &mut Workspace,
6591        mut locations: Vec<Location>,
6592        replica_id: ReplicaId,
6593        title: String,
6594        split: bool,
6595        cx: &mut ViewContext<Workspace>,
6596    ) {
6597        // If there are multiple definitions, open them in a multibuffer
6598        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6599        let mut locations = locations.into_iter().peekable();
6600        let mut ranges_to_highlight = Vec::new();
6601
6602        let excerpt_buffer = cx.add_model(|cx| {
6603            let mut multibuffer = MultiBuffer::new(replica_id);
6604            while let Some(location) = locations.next() {
6605                let buffer = location.buffer.read(cx);
6606                let mut ranges_for_buffer = Vec::new();
6607                let range = location.range.to_offset(buffer);
6608                ranges_for_buffer.push(range.clone());
6609
6610                while let Some(next_location) = locations.peek() {
6611                    if next_location.buffer == location.buffer {
6612                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6613                        locations.next();
6614                    } else {
6615                        break;
6616                    }
6617                }
6618
6619                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6620                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6621                    location.buffer.clone(),
6622                    ranges_for_buffer,
6623                    1,
6624                    cx,
6625                ))
6626            }
6627
6628            multibuffer.with_title(title)
6629        });
6630
6631        let editor = cx.add_view(|cx| {
6632            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6633        });
6634        editor.update(cx, |editor, cx| {
6635            editor.highlight_background::<Self>(
6636                ranges_to_highlight,
6637                |theme| theme.editor.highlighted_line_background,
6638                cx,
6639            );
6640        });
6641        if split {
6642            workspace.split_item(Box::new(editor), cx);
6643        } else {
6644            workspace.add_item(Box::new(editor), cx);
6645        }
6646    }
6647
6648    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6649        use language::ToOffset as _;
6650
6651        let project = self.project.clone()?;
6652        let selection = self.selections.newest_anchor().clone();
6653        let (cursor_buffer, cursor_buffer_position) = self
6654            .buffer
6655            .read(cx)
6656            .text_anchor_for_position(selection.head(), cx)?;
6657        let (tail_buffer, _) = self
6658            .buffer
6659            .read(cx)
6660            .text_anchor_for_position(selection.tail(), cx)?;
6661        if tail_buffer != cursor_buffer {
6662            return None;
6663        }
6664
6665        let snapshot = cursor_buffer.read(cx).snapshot();
6666        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6667        let prepare_rename = project.update(cx, |project, cx| {
6668            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6669        });
6670
6671        Some(cx.spawn(|this, mut cx| async move {
6672            let rename_range = if let Some(range) = prepare_rename.await? {
6673                Some(range)
6674            } else {
6675                this.read_with(&cx, |this, cx| {
6676                    let buffer = this.buffer.read(cx).snapshot(cx);
6677                    let mut buffer_highlights = this
6678                        .document_highlights_for_position(selection.head(), &buffer)
6679                        .filter(|highlight| {
6680                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6681                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6682                        });
6683                    buffer_highlights
6684                        .next()
6685                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6686                })?
6687            };
6688            if let Some(rename_range) = rename_range {
6689                let rename_buffer_range = rename_range.to_offset(&snapshot);
6690                let cursor_offset_in_rename_range =
6691                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6692
6693                this.update(&mut cx, |this, cx| {
6694                    this.take_rename(false, cx);
6695                    let style = this.style(cx);
6696                    let buffer = this.buffer.read(cx).read(cx);
6697                    let cursor_offset = selection.head().to_offset(&buffer);
6698                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6699                    let rename_end = rename_start + rename_buffer_range.len();
6700                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6701                    let mut old_highlight_id = None;
6702                    let old_name: Arc<str> = buffer
6703                        .chunks(rename_start..rename_end, true)
6704                        .map(|chunk| {
6705                            if old_highlight_id.is_none() {
6706                                old_highlight_id = chunk.syntax_highlight_id;
6707                            }
6708                            chunk.text
6709                        })
6710                        .collect::<String>()
6711                        .into();
6712
6713                    drop(buffer);
6714
6715                    // Position the selection in the rename editor so that it matches the current selection.
6716                    this.show_local_selections = false;
6717                    let rename_editor = cx.add_view(|cx| {
6718                        let mut editor = Editor::single_line(None, cx);
6719                        if let Some(old_highlight_id) = old_highlight_id {
6720                            editor.override_text_style =
6721                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6722                        }
6723                        editor.buffer.update(cx, |buffer, cx| {
6724                            buffer.edit([(0..0, old_name.clone())], None, cx)
6725                        });
6726                        editor.select_all(&SelectAll, cx);
6727                        editor
6728                    });
6729
6730                    let ranges = this
6731                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6732                        .into_iter()
6733                        .flat_map(|(_, ranges)| ranges)
6734                        .chain(
6735                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6736                                .into_iter()
6737                                .flat_map(|(_, ranges)| ranges),
6738                        )
6739                        .collect();
6740
6741                    this.highlight_text::<Rename>(
6742                        ranges,
6743                        HighlightStyle {
6744                            fade_out: Some(style.rename_fade),
6745                            ..Default::default()
6746                        },
6747                        cx,
6748                    );
6749                    cx.focus(&rename_editor);
6750                    let block_id = this.insert_blocks(
6751                        [BlockProperties {
6752                            style: BlockStyle::Flex,
6753                            position: range.start.clone(),
6754                            height: 1,
6755                            render: Arc::new({
6756                                let editor = rename_editor.clone();
6757                                move |cx: &mut BlockContext| {
6758                                    ChildView::new(&editor, cx)
6759                                        .contained()
6760                                        .with_padding_left(cx.anchor_x)
6761                                        .into_any()
6762                                }
6763                            }),
6764                            disposition: BlockDisposition::Below,
6765                        }],
6766                        Some(Autoscroll::fit()),
6767                        cx,
6768                    )[0];
6769                    this.pending_rename = Some(RenameState {
6770                        range,
6771                        old_name,
6772                        editor: rename_editor,
6773                        block_id,
6774                    });
6775                })?;
6776            }
6777
6778            Ok(())
6779        }))
6780    }
6781
6782    pub fn confirm_rename(
6783        workspace: &mut Workspace,
6784        _: &ConfirmRename,
6785        cx: &mut ViewContext<Workspace>,
6786    ) -> Option<Task<Result<()>>> {
6787        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6788
6789        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6790            let rename = editor.take_rename(false, cx)?;
6791            let buffer = editor.buffer.read(cx);
6792            let (start_buffer, start) =
6793                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6794            let (end_buffer, end) =
6795                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6796            if start_buffer == end_buffer {
6797                let new_name = rename.editor.read(cx).text(cx);
6798                Some((start_buffer, start..end, rename.old_name, new_name))
6799            } else {
6800                None
6801            }
6802        })?;
6803
6804        let rename = workspace.project().clone().update(cx, |project, cx| {
6805            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6806        });
6807
6808        let editor = editor.downgrade();
6809        Some(cx.spawn(|workspace, mut cx| async move {
6810            let project_transaction = rename.await?;
6811            Self::open_project_transaction(
6812                &editor,
6813                workspace,
6814                project_transaction,
6815                format!("Rename: {}{}", old_name, new_name),
6816                cx.clone(),
6817            )
6818            .await?;
6819
6820            editor.update(&mut cx, |editor, cx| {
6821                editor.refresh_document_highlights(cx);
6822            })?;
6823            Ok(())
6824        }))
6825    }
6826
6827    fn take_rename(
6828        &mut self,
6829        moving_cursor: bool,
6830        cx: &mut ViewContext<Self>,
6831    ) -> Option<RenameState> {
6832        let rename = self.pending_rename.take()?;
6833        self.remove_blocks(
6834            [rename.block_id].into_iter().collect(),
6835            Some(Autoscroll::fit()),
6836            cx,
6837        );
6838        self.clear_text_highlights::<Rename>(cx);
6839        self.show_local_selections = true;
6840
6841        if moving_cursor {
6842            let rename_editor = rename.editor.read(cx);
6843            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6844
6845            // Update the selection to match the position of the selection inside
6846            // the rename editor.
6847            let snapshot = self.buffer.read(cx).read(cx);
6848            let rename_range = rename.range.to_offset(&snapshot);
6849            let cursor_in_editor = snapshot
6850                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6851                .min(rename_range.end);
6852            drop(snapshot);
6853
6854            self.change_selections(None, cx, |s| {
6855                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6856            });
6857        } else {
6858            self.refresh_document_highlights(cx);
6859        }
6860
6861        Some(rename)
6862    }
6863
6864    #[cfg(any(test, feature = "test-support"))]
6865    pub fn pending_rename(&self) -> Option<&RenameState> {
6866        self.pending_rename.as_ref()
6867    }
6868
6869    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6870        let project = match &self.project {
6871            Some(project) => project.clone(),
6872            None => return None,
6873        };
6874
6875        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6876    }
6877
6878    fn perform_format(
6879        &mut self,
6880        project: ModelHandle<Project>,
6881        trigger: FormatTrigger,
6882        cx: &mut ViewContext<Self>,
6883    ) -> Task<Result<()>> {
6884        let buffer = self.buffer().clone();
6885        let buffers = buffer.read(cx).all_buffers();
6886
6887        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6888        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6889
6890        cx.spawn(|_, mut cx| async move {
6891            let transaction = futures::select_biased! {
6892                _ = timeout => {
6893                    log::warn!("timed out waiting for formatting");
6894                    None
6895                }
6896                transaction = format.log_err().fuse() => transaction,
6897            };
6898
6899            buffer.update(&mut cx, |buffer, cx| {
6900                if let Some(transaction) = transaction {
6901                    if !buffer.is_singleton() {
6902                        buffer.push_transaction(&transaction.0, cx);
6903                    }
6904                }
6905
6906                cx.notify();
6907            });
6908
6909            Ok(())
6910        })
6911    }
6912
6913    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6914        if let Some(project) = self.project.clone() {
6915            self.buffer.update(cx, |multi_buffer, cx| {
6916                project.update(cx, |project, cx| {
6917                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6918                });
6919            })
6920        }
6921    }
6922
6923    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6924        cx.show_character_palette();
6925    }
6926
6927    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6928        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6929            let buffer = self.buffer.read(cx).snapshot(cx);
6930            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6931            let is_valid = buffer
6932                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6933                .any(|entry| {
6934                    entry.diagnostic.is_primary
6935                        && !entry.range.is_empty()
6936                        && entry.range.start == primary_range_start
6937                        && entry.diagnostic.message == active_diagnostics.primary_message
6938                });
6939
6940            if is_valid != active_diagnostics.is_valid {
6941                active_diagnostics.is_valid = is_valid;
6942                let mut new_styles = HashMap::default();
6943                for (block_id, diagnostic) in &active_diagnostics.blocks {
6944                    new_styles.insert(
6945                        *block_id,
6946                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6947                    );
6948                }
6949                self.display_map
6950                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6951            }
6952        }
6953    }
6954
6955    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6956        self.dismiss_diagnostics(cx);
6957        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6958            let buffer = self.buffer.read(cx).snapshot(cx);
6959
6960            let mut primary_range = None;
6961            let mut primary_message = None;
6962            let mut group_end = Point::zero();
6963            let diagnostic_group = buffer
6964                .diagnostic_group::<Point>(group_id)
6965                .map(|entry| {
6966                    if entry.range.end > group_end {
6967                        group_end = entry.range.end;
6968                    }
6969                    if entry.diagnostic.is_primary {
6970                        primary_range = Some(entry.range.clone());
6971                        primary_message = Some(entry.diagnostic.message.clone());
6972                    }
6973                    entry
6974                })
6975                .collect::<Vec<_>>();
6976            let primary_range = primary_range?;
6977            let primary_message = primary_message?;
6978            let primary_range =
6979                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6980
6981            let blocks = display_map
6982                .insert_blocks(
6983                    diagnostic_group.iter().map(|entry| {
6984                        let diagnostic = entry.diagnostic.clone();
6985                        let message_height = diagnostic.message.lines().count() as u8;
6986                        BlockProperties {
6987                            style: BlockStyle::Fixed,
6988                            position: buffer.anchor_after(entry.range.start),
6989                            height: message_height,
6990                            render: diagnostic_block_renderer(diagnostic, true),
6991                            disposition: BlockDisposition::Below,
6992                        }
6993                    }),
6994                    cx,
6995                )
6996                .into_iter()
6997                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6998                .collect();
6999
7000            Some(ActiveDiagnosticGroup {
7001                primary_range,
7002                primary_message,
7003                blocks,
7004                is_valid: true,
7005            })
7006        });
7007        self.active_diagnostics.is_some()
7008    }
7009
7010    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7011        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7012            self.display_map.update(cx, |display_map, cx| {
7013                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7014            });
7015            cx.notify();
7016        }
7017    }
7018
7019    pub fn set_selections_from_remote(
7020        &mut self,
7021        selections: Vec<Selection<Anchor>>,
7022        pending_selection: Option<Selection<Anchor>>,
7023        cx: &mut ViewContext<Self>,
7024    ) {
7025        let old_cursor_position = self.selections.newest_anchor().head();
7026        self.selections.change_with(cx, |s| {
7027            s.select_anchors(selections);
7028            if let Some(pending_selection) = pending_selection {
7029                s.set_pending(pending_selection, SelectMode::Character);
7030            } else {
7031                s.clear_pending();
7032            }
7033        });
7034        self.selections_did_change(false, &old_cursor_position, cx);
7035    }
7036
7037    fn push_to_selection_history(&mut self) {
7038        self.selection_history.push(SelectionHistoryEntry {
7039            selections: self.selections.disjoint_anchors(),
7040            select_next_state: self.select_next_state.clone(),
7041            select_prev_state: self.select_prev_state.clone(),
7042            add_selections_state: self.add_selections_state.clone(),
7043        });
7044    }
7045
7046    pub fn transact(
7047        &mut self,
7048        cx: &mut ViewContext<Self>,
7049        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7050    ) -> Option<TransactionId> {
7051        self.start_transaction_at(Instant::now(), cx);
7052        update(self, cx);
7053        self.end_transaction_at(Instant::now(), cx)
7054    }
7055
7056    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7057        self.end_selection(cx);
7058        if let Some(tx_id) = self
7059            .buffer
7060            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7061        {
7062            self.selection_history
7063                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7064        }
7065    }
7066
7067    fn end_transaction_at(
7068        &mut self,
7069        now: Instant,
7070        cx: &mut ViewContext<Self>,
7071    ) -> Option<TransactionId> {
7072        if let Some(tx_id) = self
7073            .buffer
7074            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7075        {
7076            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7077                *end_selections = Some(self.selections.disjoint_anchors());
7078            } else {
7079                error!("unexpectedly ended a transaction that wasn't started by this editor");
7080            }
7081
7082            cx.emit(Event::Edited);
7083            Some(tx_id)
7084        } else {
7085            None
7086        }
7087    }
7088
7089    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7090        let mut fold_ranges = Vec::new();
7091
7092        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7093
7094        let selections = self.selections.all::<Point>(cx);
7095        for selection in selections {
7096            let range = selection.range().sorted();
7097            let buffer_start_row = range.start.row;
7098
7099            for row in (0..=range.end.row).rev() {
7100                let fold_range = display_map.foldable_range(row);
7101
7102                if let Some(fold_range) = fold_range {
7103                    if fold_range.end.row >= buffer_start_row {
7104                        fold_ranges.push(fold_range);
7105                        if row <= range.start.row {
7106                            break;
7107                        }
7108                    }
7109                }
7110            }
7111        }
7112
7113        self.fold_ranges(fold_ranges, true, cx);
7114    }
7115
7116    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7117        let buffer_row = fold_at.buffer_row;
7118        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7119
7120        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7121            let autoscroll = self
7122                .selections
7123                .all::<Point>(cx)
7124                .iter()
7125                .any(|selection| fold_range.overlaps(&selection.range()));
7126
7127            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7128        }
7129    }
7130
7131    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7132        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7133        let buffer = &display_map.buffer_snapshot;
7134        let selections = self.selections.all::<Point>(cx);
7135        let ranges = selections
7136            .iter()
7137            .map(|s| {
7138                let range = s.display_range(&display_map).sorted();
7139                let mut start = range.start.to_point(&display_map);
7140                let mut end = range.end.to_point(&display_map);
7141                start.column = 0;
7142                end.column = buffer.line_len(end.row);
7143                start..end
7144            })
7145            .collect::<Vec<_>>();
7146
7147        self.unfold_ranges(ranges, true, true, cx);
7148    }
7149
7150    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7151        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7152
7153        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7154            ..Point::new(
7155                unfold_at.buffer_row,
7156                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7157            );
7158
7159        let autoscroll = self
7160            .selections
7161            .all::<Point>(cx)
7162            .iter()
7163            .any(|selection| selection.range().overlaps(&intersection_range));
7164
7165        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7166    }
7167
7168    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7169        let selections = self.selections.all::<Point>(cx);
7170        let ranges = selections.into_iter().map(|s| s.start..s.end);
7171        self.fold_ranges(ranges, true, cx);
7172    }
7173
7174    pub fn fold_ranges<T: ToOffset + Clone>(
7175        &mut self,
7176        ranges: impl IntoIterator<Item = Range<T>>,
7177        auto_scroll: bool,
7178        cx: &mut ViewContext<Self>,
7179    ) {
7180        let mut ranges = ranges.into_iter().peekable();
7181        if ranges.peek().is_some() {
7182            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7183
7184            if auto_scroll {
7185                self.request_autoscroll(Autoscroll::fit(), cx);
7186            }
7187
7188            cx.notify();
7189        }
7190    }
7191
7192    pub fn unfold_ranges<T: ToOffset + Clone>(
7193        &mut self,
7194        ranges: impl IntoIterator<Item = Range<T>>,
7195        inclusive: bool,
7196        auto_scroll: bool,
7197        cx: &mut ViewContext<Self>,
7198    ) {
7199        let mut ranges = ranges.into_iter().peekable();
7200        if ranges.peek().is_some() {
7201            self.display_map
7202                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7203            if auto_scroll {
7204                self.request_autoscroll(Autoscroll::fit(), cx);
7205            }
7206
7207            cx.notify();
7208        }
7209    }
7210
7211    pub fn gutter_hover(
7212        &mut self,
7213        GutterHover { hovered }: &GutterHover,
7214        cx: &mut ViewContext<Self>,
7215    ) {
7216        self.gutter_hovered = *hovered;
7217        cx.notify();
7218    }
7219
7220    pub fn insert_blocks(
7221        &mut self,
7222        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7223        autoscroll: Option<Autoscroll>,
7224        cx: &mut ViewContext<Self>,
7225    ) -> Vec<BlockId> {
7226        let blocks = self
7227            .display_map
7228            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7229        if let Some(autoscroll) = autoscroll {
7230            self.request_autoscroll(autoscroll, cx);
7231        }
7232        blocks
7233    }
7234
7235    pub fn replace_blocks(
7236        &mut self,
7237        blocks: HashMap<BlockId, RenderBlock>,
7238        autoscroll: Option<Autoscroll>,
7239        cx: &mut ViewContext<Self>,
7240    ) {
7241        self.display_map
7242            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7243        if let Some(autoscroll) = autoscroll {
7244            self.request_autoscroll(autoscroll, cx);
7245        }
7246    }
7247
7248    pub fn remove_blocks(
7249        &mut self,
7250        block_ids: HashSet<BlockId>,
7251        autoscroll: Option<Autoscroll>,
7252        cx: &mut ViewContext<Self>,
7253    ) {
7254        self.display_map.update(cx, |display_map, cx| {
7255            display_map.remove_blocks(block_ids, cx)
7256        });
7257        if let Some(autoscroll) = autoscroll {
7258            self.request_autoscroll(autoscroll, cx);
7259        }
7260    }
7261
7262    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7263        self.display_map
7264            .update(cx, |map, cx| map.snapshot(cx))
7265            .longest_row()
7266    }
7267
7268    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7269        self.display_map
7270            .update(cx, |map, cx| map.snapshot(cx))
7271            .max_point()
7272    }
7273
7274    pub fn text(&self, cx: &AppContext) -> String {
7275        self.buffer.read(cx).read(cx).text()
7276    }
7277
7278    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7279        self.transact(cx, |this, cx| {
7280            this.buffer
7281                .read(cx)
7282                .as_singleton()
7283                .expect("you can only call set_text on editors for singleton buffers")
7284                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7285        });
7286    }
7287
7288    pub fn display_text(&self, cx: &mut AppContext) -> String {
7289        self.display_map
7290            .update(cx, |map, cx| map.snapshot(cx))
7291            .text()
7292    }
7293
7294    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7295        let mut wrap_guides = smallvec::smallvec![];
7296
7297        if self.show_wrap_guides == Some(false) {
7298            return wrap_guides;
7299        }
7300
7301        let settings = self.buffer.read(cx).settings_at(0, cx);
7302        if settings.show_wrap_guides {
7303            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7304                wrap_guides.push((soft_wrap as usize, true));
7305            }
7306            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7307        }
7308
7309        wrap_guides
7310    }
7311
7312    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7313        let settings = self.buffer.read(cx).settings_at(0, cx);
7314        let mode = self
7315            .soft_wrap_mode_override
7316            .unwrap_or_else(|| settings.soft_wrap);
7317        match mode {
7318            language_settings::SoftWrap::None => SoftWrap::None,
7319            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7320            language_settings::SoftWrap::PreferredLineLength => {
7321                SoftWrap::Column(settings.preferred_line_length)
7322            }
7323        }
7324    }
7325
7326    pub fn set_soft_wrap_mode(
7327        &mut self,
7328        mode: language_settings::SoftWrap,
7329        cx: &mut ViewContext<Self>,
7330    ) {
7331        self.soft_wrap_mode_override = Some(mode);
7332        cx.notify();
7333    }
7334
7335    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7336        self.display_map
7337            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7338    }
7339
7340    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7341        if self.soft_wrap_mode_override.is_some() {
7342            self.soft_wrap_mode_override.take();
7343        } else {
7344            let soft_wrap = match self.soft_wrap_mode(cx) {
7345                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7346                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7347            };
7348            self.soft_wrap_mode_override = Some(soft_wrap);
7349        }
7350        cx.notify();
7351    }
7352
7353    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7354        self.show_gutter = show_gutter;
7355        cx.notify();
7356    }
7357
7358    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7359        self.show_wrap_guides = Some(show_gutter);
7360        cx.notify();
7361    }
7362
7363    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7364        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7365            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7366                cx.reveal_path(&file.abs_path(cx));
7367            }
7368        }
7369    }
7370
7371    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7372        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7373            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7374                if let Some(path) = file.abs_path(cx).to_str() {
7375                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7376                }
7377            }
7378        }
7379    }
7380
7381    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7382        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7383            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7384                if let Some(path) = file.path().to_str() {
7385                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7386                }
7387            }
7388        }
7389    }
7390
7391    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7392        self.highlighted_rows = rows;
7393    }
7394
7395    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7396        self.highlighted_rows.clone()
7397    }
7398
7399    pub fn highlight_background<T: 'static>(
7400        &mut self,
7401        ranges: Vec<Range<Anchor>>,
7402        color_fetcher: fn(&Theme) -> Color,
7403        cx: &mut ViewContext<Self>,
7404    ) {
7405        self.background_highlights
7406            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7407        cx.notify();
7408    }
7409
7410    #[allow(clippy::type_complexity)]
7411    pub fn clear_background_highlights<T: 'static>(
7412        &mut self,
7413        cx: &mut ViewContext<Self>,
7414    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7415        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7416        if highlights.is_some() {
7417            cx.notify();
7418        }
7419        highlights
7420    }
7421
7422    #[cfg(feature = "test-support")]
7423    pub fn all_background_highlights(
7424        &mut self,
7425        cx: &mut ViewContext<Self>,
7426    ) -> Vec<(Range<DisplayPoint>, Color)> {
7427        let snapshot = self.snapshot(cx);
7428        let buffer = &snapshot.buffer_snapshot;
7429        let start = buffer.anchor_before(0);
7430        let end = buffer.anchor_after(buffer.len());
7431        let theme = theme::current(cx);
7432        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7433    }
7434
7435    fn document_highlights_for_position<'a>(
7436        &'a self,
7437        position: Anchor,
7438        buffer: &'a MultiBufferSnapshot,
7439    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7440        let read_highlights = self
7441            .background_highlights
7442            .get(&TypeId::of::<DocumentHighlightRead>())
7443            .map(|h| &h.1);
7444        let write_highlights = self
7445            .background_highlights
7446            .get(&TypeId::of::<DocumentHighlightWrite>())
7447            .map(|h| &h.1);
7448        let left_position = position.bias_left(buffer);
7449        let right_position = position.bias_right(buffer);
7450        read_highlights
7451            .into_iter()
7452            .chain(write_highlights)
7453            .flat_map(move |ranges| {
7454                let start_ix = match ranges.binary_search_by(|probe| {
7455                    let cmp = probe.end.cmp(&left_position, buffer);
7456                    if cmp.is_ge() {
7457                        Ordering::Greater
7458                    } else {
7459                        Ordering::Less
7460                    }
7461                }) {
7462                    Ok(i) | Err(i) => i,
7463                };
7464
7465                let right_position = right_position.clone();
7466                ranges[start_ix..]
7467                    .iter()
7468                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7469            })
7470    }
7471
7472    pub fn background_highlights_in_range(
7473        &self,
7474        search_range: Range<Anchor>,
7475        display_snapshot: &DisplaySnapshot,
7476        theme: &Theme,
7477    ) -> Vec<(Range<DisplayPoint>, Color)> {
7478        let mut results = Vec::new();
7479        let buffer = &display_snapshot.buffer_snapshot;
7480        for (color_fetcher, ranges) in self.background_highlights.values() {
7481            let color = color_fetcher(theme);
7482            let start_ix = match ranges.binary_search_by(|probe| {
7483                let cmp = probe.end.cmp(&search_range.start, buffer);
7484                if cmp.is_gt() {
7485                    Ordering::Greater
7486                } else {
7487                    Ordering::Less
7488                }
7489            }) {
7490                Ok(i) | Err(i) => i,
7491            };
7492            for range in &ranges[start_ix..] {
7493                if range.start.cmp(&search_range.end, buffer).is_ge() {
7494                    break;
7495                }
7496                let start = range
7497                    .start
7498                    .to_point(buffer)
7499                    .to_display_point(display_snapshot);
7500                let end = range
7501                    .end
7502                    .to_point(buffer)
7503                    .to_display_point(display_snapshot);
7504                results.push((start..end, color))
7505            }
7506        }
7507        results
7508    }
7509    pub fn background_highlights_in_range_for<T: 'static>(
7510        &self,
7511        search_range: Range<Anchor>,
7512        display_snapshot: &DisplaySnapshot,
7513        theme: &Theme,
7514    ) -> Vec<(Range<DisplayPoint>, Color)> {
7515        let mut results = Vec::new();
7516        let buffer = &display_snapshot.buffer_snapshot;
7517        let Some((color_fetcher, ranges)) = self.background_highlights
7518            .get(&TypeId::of::<T>()) else {
7519                return vec![];
7520            };
7521
7522        let color = color_fetcher(theme);
7523        let start_ix = match ranges.binary_search_by(|probe| {
7524            let cmp = probe.end.cmp(&search_range.start, buffer);
7525            if cmp.is_gt() {
7526                Ordering::Greater
7527            } else {
7528                Ordering::Less
7529            }
7530        }) {
7531            Ok(i) | Err(i) => i,
7532        };
7533        for range in &ranges[start_ix..] {
7534            if range.start.cmp(&search_range.end, buffer).is_ge() {
7535                break;
7536            }
7537            let start = range
7538                .start
7539                .to_point(buffer)
7540                .to_display_point(display_snapshot);
7541            let end = range
7542                .end
7543                .to_point(buffer)
7544                .to_display_point(display_snapshot);
7545            results.push((start..end, color))
7546        }
7547
7548        results
7549    }
7550
7551    pub fn background_highlight_row_ranges<T: 'static>(
7552        &self,
7553        search_range: Range<Anchor>,
7554        display_snapshot: &DisplaySnapshot,
7555        count: usize,
7556    ) -> Vec<RangeInclusive<DisplayPoint>> {
7557        let mut results = Vec::new();
7558        let buffer = &display_snapshot.buffer_snapshot;
7559        let Some((_, ranges)) = self.background_highlights
7560            .get(&TypeId::of::<T>()) else {
7561                return vec![];
7562            };
7563
7564        let start_ix = match ranges.binary_search_by(|probe| {
7565            let cmp = probe.end.cmp(&search_range.start, buffer);
7566            if cmp.is_gt() {
7567                Ordering::Greater
7568            } else {
7569                Ordering::Less
7570            }
7571        }) {
7572            Ok(i) | Err(i) => i,
7573        };
7574        let mut push_region = |start: Option<Point>, end: Option<Point>| {
7575            if let (Some(start_display), Some(end_display)) = (start, end) {
7576                results.push(
7577                    start_display.to_display_point(display_snapshot)
7578                        ..=end_display.to_display_point(display_snapshot),
7579                );
7580            }
7581        };
7582        let mut start_row: Option<Point> = None;
7583        let mut end_row: Option<Point> = None;
7584        if ranges.len() > count {
7585            return vec![];
7586        }
7587        for range in &ranges[start_ix..] {
7588            if range.start.cmp(&search_range.end, buffer).is_ge() {
7589                break;
7590            }
7591            let end = range.end.to_point(buffer);
7592            if let Some(current_row) = &end_row {
7593                if end.row == current_row.row {
7594                    continue;
7595                }
7596            }
7597            let start = range.start.to_point(buffer);
7598
7599            if start_row.is_none() {
7600                assert_eq!(end_row, None);
7601                start_row = Some(start);
7602                end_row = Some(end);
7603                continue;
7604            }
7605            if let Some(current_end) = end_row.as_mut() {
7606                if start.row > current_end.row + 1 {
7607                    push_region(start_row, end_row);
7608                    start_row = Some(start);
7609                    end_row = Some(end);
7610                } else {
7611                    // Merge two hunks.
7612                    *current_end = end;
7613                }
7614            } else {
7615                unreachable!();
7616            }
7617        }
7618        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
7619        push_region(start_row, end_row);
7620        results
7621    }
7622
7623    pub fn highlight_text<T: 'static>(
7624        &mut self,
7625        ranges: Vec<Range<Anchor>>,
7626        style: HighlightStyle,
7627        cx: &mut ViewContext<Self>,
7628    ) {
7629        self.display_map.update(cx, |map, _| {
7630            map.highlight_text(TypeId::of::<T>(), ranges, style)
7631        });
7632        cx.notify();
7633    }
7634
7635    pub fn text_highlights<'a, T: 'static>(
7636        &'a self,
7637        cx: &'a AppContext,
7638    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7639        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7640    }
7641
7642    pub fn clear_text_highlights<T: 'static>(
7643        &mut self,
7644        cx: &mut ViewContext<Self>,
7645    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7646        let highlights = self
7647            .display_map
7648            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7649        if highlights.is_some() {
7650            cx.notify();
7651        }
7652        highlights
7653    }
7654
7655    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7656        self.blink_manager.read(cx).visible() && self.focused
7657    }
7658
7659    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7660        cx.notify();
7661    }
7662
7663    fn on_buffer_event(
7664        &mut self,
7665        multibuffer: ModelHandle<MultiBuffer>,
7666        event: &multi_buffer::Event,
7667        cx: &mut ViewContext<Self>,
7668    ) {
7669        match event {
7670            multi_buffer::Event::Edited => {
7671                self.refresh_active_diagnostics(cx);
7672                self.refresh_code_actions(cx);
7673                if self.has_active_copilot_suggestion(cx) {
7674                    self.update_visible_copilot_suggestion(cx);
7675                }
7676                cx.emit(Event::BufferEdited);
7677
7678                if let Some(project) = &self.project {
7679                    let project = project.read(cx);
7680                    let languages_affected = multibuffer
7681                        .read(cx)
7682                        .all_buffers()
7683                        .into_iter()
7684                        .filter_map(|buffer| {
7685                            let buffer = buffer.read(cx);
7686                            let language = buffer.language()?;
7687                            if project.is_local()
7688                                && project.language_servers_for_buffer(buffer, cx).count() == 0
7689                            {
7690                                None
7691                            } else {
7692                                Some(language)
7693                            }
7694                        })
7695                        .cloned()
7696                        .collect::<HashSet<_>>();
7697                    if !languages_affected.is_empty() {
7698                        self.refresh_inlays(
7699                            InlayRefreshReason::BufferEdited(languages_affected),
7700                            cx,
7701                        );
7702                    }
7703                }
7704            }
7705            multi_buffer::Event::ExcerptsAdded {
7706                buffer,
7707                predecessor,
7708                excerpts,
7709            } => cx.emit(Event::ExcerptsAdded {
7710                buffer: buffer.clone(),
7711                predecessor: *predecessor,
7712                excerpts: excerpts.clone(),
7713            }),
7714            multi_buffer::Event::ExcerptsRemoved { ids } => {
7715                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7716            }
7717            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7718            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7719            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7720            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7721            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7722            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7723            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7724            multi_buffer::Event::DiagnosticsUpdated => {
7725                self.refresh_active_diagnostics(cx);
7726            }
7727            _ => {}
7728        };
7729    }
7730
7731    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7732        cx.notify();
7733    }
7734
7735    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7736        self.refresh_copilot_suggestions(true, cx);
7737        self.refresh_inlays(
7738            InlayRefreshReason::SettingsChange(inlay_hint_settings(
7739                self.selections.newest_anchor().head(),
7740                &self.buffer.read(cx).snapshot(cx),
7741                cx,
7742            )),
7743            cx,
7744        );
7745    }
7746
7747    pub fn set_searchable(&mut self, searchable: bool) {
7748        self.searchable = searchable;
7749    }
7750
7751    pub fn searchable(&self) -> bool {
7752        self.searchable
7753    }
7754
7755    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7756        let active_item = workspace.active_item(cx);
7757        let editor_handle = if let Some(editor) = active_item
7758            .as_ref()
7759            .and_then(|item| item.act_as::<Self>(cx))
7760        {
7761            editor
7762        } else {
7763            cx.propagate_action();
7764            return;
7765        };
7766
7767        let editor = editor_handle.read(cx);
7768        let buffer = editor.buffer.read(cx);
7769        if buffer.is_singleton() {
7770            cx.propagate_action();
7771            return;
7772        }
7773
7774        let mut new_selections_by_buffer = HashMap::default();
7775        for selection in editor.selections.all::<usize>(cx) {
7776            for (buffer, mut range, _) in
7777                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7778            {
7779                if selection.reversed {
7780                    mem::swap(&mut range.start, &mut range.end);
7781                }
7782                new_selections_by_buffer
7783                    .entry(buffer)
7784                    .or_insert(Vec::new())
7785                    .push(range)
7786            }
7787        }
7788
7789        editor_handle.update(cx, |editor, cx| {
7790            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7791        });
7792        let pane = workspace.active_pane().clone();
7793        pane.update(cx, |pane, _| pane.disable_history());
7794
7795        // We defer the pane interaction because we ourselves are a workspace item
7796        // and activating a new item causes the pane to call a method on us reentrantly,
7797        // which panics if we're on the stack.
7798        cx.defer(move |workspace, cx| {
7799            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7800                let editor = workspace.open_project_item::<Self>(buffer, cx);
7801                editor.update(cx, |editor, cx| {
7802                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7803                        s.select_ranges(ranges);
7804                    });
7805                });
7806            }
7807
7808            pane.update(cx, |pane, _| pane.enable_history());
7809        });
7810    }
7811
7812    fn jump(
7813        workspace: &mut Workspace,
7814        path: ProjectPath,
7815        position: Point,
7816        anchor: language::Anchor,
7817        cx: &mut ViewContext<Workspace>,
7818    ) {
7819        let editor = workspace.open_path(path, None, true, cx);
7820        cx.spawn(|_, mut cx| async move {
7821            let editor = editor
7822                .await?
7823                .downcast::<Editor>()
7824                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7825                .downgrade();
7826            editor.update(&mut cx, |editor, cx| {
7827                let buffer = editor
7828                    .buffer()
7829                    .read(cx)
7830                    .as_singleton()
7831                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7832                let buffer = buffer.read(cx);
7833                let cursor = if buffer.can_resolve(&anchor) {
7834                    language::ToPoint::to_point(&anchor, buffer)
7835                } else {
7836                    buffer.clip_point(position, Bias::Left)
7837                };
7838
7839                let nav_history = editor.nav_history.take();
7840                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7841                    s.select_ranges([cursor..cursor]);
7842                });
7843                editor.nav_history = nav_history;
7844
7845                anyhow::Ok(())
7846            })??;
7847
7848            anyhow::Ok(())
7849        })
7850        .detach_and_log_err(cx);
7851    }
7852
7853    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7854        let snapshot = self.buffer.read(cx).read(cx);
7855        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7856        Some(
7857            ranges
7858                .iter()
7859                .map(move |range| {
7860                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7861                })
7862                .collect(),
7863        )
7864    }
7865
7866    fn selection_replacement_ranges(
7867        &self,
7868        range: Range<OffsetUtf16>,
7869        cx: &AppContext,
7870    ) -> Vec<Range<OffsetUtf16>> {
7871        let selections = self.selections.all::<OffsetUtf16>(cx);
7872        let newest_selection = selections
7873            .iter()
7874            .max_by_key(|selection| selection.id)
7875            .unwrap();
7876        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7877        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7878        let snapshot = self.buffer.read(cx).read(cx);
7879        selections
7880            .into_iter()
7881            .map(|mut selection| {
7882                selection.start.0 =
7883                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7884                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7885                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7886                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7887            })
7888            .collect()
7889    }
7890
7891    fn report_copilot_event(
7892        &self,
7893        suggestion_id: Option<String>,
7894        suggestion_accepted: bool,
7895        cx: &AppContext,
7896    ) {
7897        let Some(project) = &self.project else {
7898            return
7899        };
7900
7901        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7902        let file_extension = self
7903            .buffer
7904            .read(cx)
7905            .as_singleton()
7906            .and_then(|b| b.read(cx).file())
7907            .and_then(|file| Path::new(file.file_name(cx)).extension())
7908            .and_then(|e| e.to_str())
7909            .map(|a| a.to_string());
7910
7911        let telemetry = project.read(cx).client().telemetry().clone();
7912        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7913
7914        let event = ClickhouseEvent::Copilot {
7915            suggestion_id,
7916            suggestion_accepted,
7917            file_extension,
7918        };
7919        telemetry.report_clickhouse_event(event, telemetry_settings);
7920    }
7921
7922    fn report_editor_event(
7923        &self,
7924        operation: &'static str,
7925        file_extension: Option<String>,
7926        cx: &AppContext,
7927    ) {
7928        let Some(project) = &self.project else {
7929            return
7930        };
7931
7932        // If None, we are in a file without an extension
7933        let file = self
7934            .buffer
7935            .read(cx)
7936            .as_singleton()
7937            .and_then(|b| b.read(cx).file());
7938        let file_extension = file_extension.or(file
7939            .as_ref()
7940            .and_then(|file| Path::new(file.file_name(cx)).extension())
7941            .and_then(|e| e.to_str())
7942            .map(|a| a.to_string()));
7943
7944        let vim_mode = cx
7945            .global::<SettingsStore>()
7946            .raw_user_settings()
7947            .get("vim_mode")
7948            == Some(&serde_json::Value::Bool(true));
7949        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7950        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
7951        let copilot_enabled_for_language = self
7952            .buffer
7953            .read(cx)
7954            .settings_at(0, cx)
7955            .show_copilot_suggestions;
7956
7957        let telemetry = project.read(cx).client().telemetry().clone();
7958        let event = ClickhouseEvent::Editor {
7959            file_extension,
7960            vim_mode,
7961            operation,
7962            copilot_enabled,
7963            copilot_enabled_for_language,
7964        };
7965        telemetry.report_clickhouse_event(event, telemetry_settings)
7966    }
7967
7968    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7969    /// with each line being an array of {text, highlight} objects.
7970    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7971        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7972            return;
7973        };
7974
7975        #[derive(Serialize)]
7976        struct Chunk<'a> {
7977            text: String,
7978            highlight: Option<&'a str>,
7979        }
7980
7981        let snapshot = buffer.read(cx).snapshot();
7982        let range = self
7983            .selected_text_range(cx)
7984            .and_then(|selected_range| {
7985                if selected_range.is_empty() {
7986                    None
7987                } else {
7988                    Some(selected_range)
7989                }
7990            })
7991            .unwrap_or_else(|| 0..snapshot.len());
7992
7993        let chunks = snapshot.chunks(range, true);
7994        let mut lines = Vec::new();
7995        let mut line: VecDeque<Chunk> = VecDeque::new();
7996
7997        let theme = &theme::current(cx).editor.syntax;
7998
7999        for chunk in chunks {
8000            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8001            let mut chunk_lines = chunk.text.split("\n").peekable();
8002            while let Some(text) = chunk_lines.next() {
8003                let mut merged_with_last_token = false;
8004                if let Some(last_token) = line.back_mut() {
8005                    if last_token.highlight == highlight {
8006                        last_token.text.push_str(text);
8007                        merged_with_last_token = true;
8008                    }
8009                }
8010
8011                if !merged_with_last_token {
8012                    line.push_back(Chunk {
8013                        text: text.into(),
8014                        highlight,
8015                    });
8016                }
8017
8018                if chunk_lines.peek().is_some() {
8019                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8020                        line.pop_front();
8021                    }
8022                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8023                        line.pop_back();
8024                    }
8025
8026                    lines.push(mem::take(&mut line));
8027                }
8028            }
8029        }
8030
8031        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
8032        cx.write_to_clipboard(ClipboardItem::new(lines));
8033    }
8034
8035    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8036        &self.inlay_hint_cache
8037    }
8038}
8039
8040fn inlay_hint_settings(
8041    location: Anchor,
8042    snapshot: &MultiBufferSnapshot,
8043    cx: &mut ViewContext<'_, '_, Editor>,
8044) -> InlayHintSettings {
8045    let file = snapshot.file_at(location);
8046    let language = snapshot.language_at(location);
8047    let settings = all_language_settings(file, cx);
8048    settings
8049        .language(language.map(|l| l.name()).as_deref())
8050        .inlay_hints
8051}
8052
8053fn consume_contiguous_rows(
8054    contiguous_row_selections: &mut Vec<Selection<Point>>,
8055    selection: &Selection<Point>,
8056    display_map: &DisplaySnapshot,
8057    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8058) -> (u32, u32) {
8059    contiguous_row_selections.push(selection.clone());
8060    let start_row = selection.start.row;
8061    let mut end_row = ending_row(selection, display_map);
8062
8063    while let Some(next_selection) = selections.peek() {
8064        if next_selection.start.row <= end_row {
8065            end_row = ending_row(next_selection, display_map);
8066            contiguous_row_selections.push(selections.next().unwrap().clone());
8067        } else {
8068            break;
8069        }
8070    }
8071    (start_row, end_row)
8072}
8073
8074fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8075    if next_selection.end.column > 0 || next_selection.is_empty() {
8076        display_map.next_line_boundary(next_selection.end).0.row + 1
8077    } else {
8078        next_selection.end.row
8079    }
8080}
8081
8082impl EditorSnapshot {
8083    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8084        self.display_snapshot.buffer_snapshot.language_at(position)
8085    }
8086
8087    pub fn is_focused(&self) -> bool {
8088        self.is_focused
8089    }
8090
8091    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8092        self.placeholder_text.as_ref()
8093    }
8094
8095    pub fn scroll_position(&self) -> Vector2F {
8096        self.scroll_anchor.scroll_position(&self.display_snapshot)
8097    }
8098}
8099
8100impl Deref for EditorSnapshot {
8101    type Target = DisplaySnapshot;
8102
8103    fn deref(&self) -> &Self::Target {
8104        &self.display_snapshot
8105    }
8106}
8107
8108#[derive(Clone, Debug, PartialEq, Eq)]
8109pub enum Event {
8110    InputIgnored {
8111        text: Arc<str>,
8112    },
8113    ExcerptsAdded {
8114        buffer: ModelHandle<Buffer>,
8115        predecessor: ExcerptId,
8116        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8117    },
8118    ExcerptsRemoved {
8119        ids: Vec<ExcerptId>,
8120    },
8121    BufferEdited,
8122    Edited,
8123    Reparsed,
8124    Focused,
8125    Blurred,
8126    DirtyChanged,
8127    Saved,
8128    TitleChanged,
8129    DiffBaseChanged,
8130    SelectionsChanged {
8131        local: bool,
8132    },
8133    ScrollPositionChanged {
8134        local: bool,
8135        autoscroll: bool,
8136    },
8137    Closed,
8138}
8139
8140pub struct EditorFocused(pub ViewHandle<Editor>);
8141pub struct EditorBlurred(pub ViewHandle<Editor>);
8142pub struct EditorReleased(pub WeakViewHandle<Editor>);
8143
8144impl Entity for Editor {
8145    type Event = Event;
8146
8147    fn release(&mut self, cx: &mut AppContext) {
8148        cx.emit_global(EditorReleased(self.handle.clone()));
8149    }
8150}
8151
8152impl View for Editor {
8153    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8154        let style = self.style(cx);
8155        let font_changed = self.display_map.update(cx, |map, cx| {
8156            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8157            map.set_font(style.text.font_id, style.text.font_size, cx)
8158        });
8159
8160        if font_changed {
8161            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8162                hide_hover(editor, cx);
8163                hide_link_definition(editor, cx);
8164            });
8165        }
8166
8167        Stack::new()
8168            .with_child(EditorElement::new(style.clone()))
8169            .with_child(ChildView::new(&self.mouse_context_menu, cx))
8170            .into_any()
8171    }
8172
8173    fn ui_name() -> &'static str {
8174        "Editor"
8175    }
8176
8177    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8178        if cx.is_self_focused() {
8179            let focused_event = EditorFocused(cx.handle());
8180            cx.emit(Event::Focused);
8181            cx.emit_global(focused_event);
8182        }
8183        if let Some(rename) = self.pending_rename.as_ref() {
8184            cx.focus(&rename.editor);
8185        } else {
8186            if !self.focused {
8187                self.blink_manager.update(cx, BlinkManager::enable);
8188            }
8189            self.focused = true;
8190            self.buffer.update(cx, |buffer, cx| {
8191                buffer.finalize_last_transaction(cx);
8192                if self.leader_replica_id.is_none() {
8193                    buffer.set_active_selections(
8194                        &self.selections.disjoint_anchors(),
8195                        self.selections.line_mode,
8196                        self.cursor_shape,
8197                        cx,
8198                    );
8199                }
8200            });
8201        }
8202    }
8203
8204    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8205        let blurred_event = EditorBlurred(cx.handle());
8206        cx.emit_global(blurred_event);
8207        self.focused = false;
8208        self.blink_manager.update(cx, BlinkManager::disable);
8209        self.buffer
8210            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8211        self.hide_context_menu(cx);
8212        hide_hover(self, cx);
8213        cx.emit(Event::Blurred);
8214        cx.notify();
8215    }
8216
8217    fn modifiers_changed(
8218        &mut self,
8219        event: &gpui::platform::ModifiersChangedEvent,
8220        cx: &mut ViewContext<Self>,
8221    ) -> bool {
8222        let pending_selection = self.has_pending_selection();
8223
8224        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
8225            if event.cmd && !pending_selection {
8226                let snapshot = self.snapshot(cx);
8227                let kind = if event.shift {
8228                    LinkDefinitionKind::Type
8229                } else {
8230                    LinkDefinitionKind::Symbol
8231                };
8232
8233                show_link_definition(kind, self, point, snapshot, cx);
8234                return false;
8235            }
8236        }
8237
8238        {
8239            if self.link_go_to_definition_state.symbol_range.is_some()
8240                || !self.link_go_to_definition_state.definitions.is_empty()
8241            {
8242                self.link_go_to_definition_state.symbol_range.take();
8243                self.link_go_to_definition_state.definitions.clear();
8244                cx.notify();
8245            }
8246
8247            self.link_go_to_definition_state.task = None;
8248
8249            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8250        }
8251
8252        false
8253    }
8254
8255    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8256        Self::reset_to_default_keymap_context(keymap);
8257        let mode = match self.mode {
8258            EditorMode::SingleLine => "single_line",
8259            EditorMode::AutoHeight { .. } => "auto_height",
8260            EditorMode::Full => "full",
8261        };
8262        keymap.add_key("mode", mode);
8263        if self.pending_rename.is_some() {
8264            keymap.add_identifier("renaming");
8265        }
8266        match self.context_menu.as_ref() {
8267            Some(ContextMenu::Completions(_)) => {
8268                keymap.add_identifier("menu");
8269                keymap.add_identifier("showing_completions")
8270            }
8271            Some(ContextMenu::CodeActions(_)) => {
8272                keymap.add_identifier("menu");
8273                keymap.add_identifier("showing_code_actions")
8274            }
8275            None => {}
8276        }
8277        for layer in self.keymap_context_layers.values() {
8278            keymap.extend(layer);
8279        }
8280
8281        if let Some(extension) = self
8282            .buffer
8283            .read(cx)
8284            .as_singleton()
8285            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8286        {
8287            keymap.add_key("extension", extension.to_string());
8288        }
8289    }
8290
8291    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8292        Some(
8293            self.buffer
8294                .read(cx)
8295                .read(cx)
8296                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8297                .collect(),
8298        )
8299    }
8300
8301    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8302        // Prevent the IME menu from appearing when holding down an alphabetic key
8303        // while input is disabled.
8304        if !self.input_enabled {
8305            return None;
8306        }
8307
8308        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8309        Some(range.start.0..range.end.0)
8310    }
8311
8312    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8313        let snapshot = self.buffer.read(cx).read(cx);
8314        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8315        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8316    }
8317
8318    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8319        self.clear_text_highlights::<InputComposition>(cx);
8320        self.ime_transaction.take();
8321    }
8322
8323    fn replace_text_in_range(
8324        &mut self,
8325        range_utf16: Option<Range<usize>>,
8326        text: &str,
8327        cx: &mut ViewContext<Self>,
8328    ) {
8329        self.transact(cx, |this, cx| {
8330            if this.input_enabled {
8331                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8332                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8333                    Some(this.selection_replacement_ranges(range_utf16, cx))
8334                } else {
8335                    this.marked_text_ranges(cx)
8336                };
8337
8338                if let Some(new_selected_ranges) = new_selected_ranges {
8339                    this.change_selections(None, cx, |selections| {
8340                        selections.select_ranges(new_selected_ranges)
8341                    });
8342                }
8343            }
8344
8345            this.handle_input(text, cx);
8346        });
8347
8348        if !self.input_enabled {
8349            return;
8350        }
8351
8352        if let Some(transaction) = self.ime_transaction {
8353            self.buffer.update(cx, |buffer, cx| {
8354                buffer.group_until_transaction(transaction, cx);
8355            });
8356        }
8357
8358        self.unmark_text(cx);
8359    }
8360
8361    fn replace_and_mark_text_in_range(
8362        &mut self,
8363        range_utf16: Option<Range<usize>>,
8364        text: &str,
8365        new_selected_range_utf16: Option<Range<usize>>,
8366        cx: &mut ViewContext<Self>,
8367    ) {
8368        if !self.input_enabled {
8369            return;
8370        }
8371
8372        let transaction = self.transact(cx, |this, cx| {
8373            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8374                let snapshot = this.buffer.read(cx).read(cx);
8375                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8376                    for marked_range in &mut marked_ranges {
8377                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8378                        marked_range.start.0 += relative_range_utf16.start;
8379                        marked_range.start =
8380                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8381                        marked_range.end =
8382                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8383                    }
8384                }
8385                Some(marked_ranges)
8386            } else if let Some(range_utf16) = range_utf16 {
8387                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8388                Some(this.selection_replacement_ranges(range_utf16, cx))
8389            } else {
8390                None
8391            };
8392
8393            if let Some(ranges) = ranges_to_replace {
8394                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8395            }
8396
8397            let marked_ranges = {
8398                let snapshot = this.buffer.read(cx).read(cx);
8399                this.selections
8400                    .disjoint_anchors()
8401                    .iter()
8402                    .map(|selection| {
8403                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8404                    })
8405                    .collect::<Vec<_>>()
8406            };
8407
8408            if text.is_empty() {
8409                this.unmark_text(cx);
8410            } else {
8411                this.highlight_text::<InputComposition>(
8412                    marked_ranges.clone(),
8413                    this.style(cx).composition_mark,
8414                    cx,
8415                );
8416            }
8417
8418            this.handle_input(text, cx);
8419
8420            if let Some(new_selected_range) = new_selected_range_utf16 {
8421                let snapshot = this.buffer.read(cx).read(cx);
8422                let new_selected_ranges = marked_ranges
8423                    .into_iter()
8424                    .map(|marked_range| {
8425                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8426                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8427                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8428                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8429                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8430                    })
8431                    .collect::<Vec<_>>();
8432
8433                drop(snapshot);
8434                this.change_selections(None, cx, |selections| {
8435                    selections.select_ranges(new_selected_ranges)
8436                });
8437            }
8438        });
8439
8440        self.ime_transaction = self.ime_transaction.or(transaction);
8441        if let Some(transaction) = self.ime_transaction {
8442            self.buffer.update(cx, |buffer, cx| {
8443                buffer.group_until_transaction(transaction, cx);
8444            });
8445        }
8446
8447        if self.text_highlights::<InputComposition>(cx).is_none() {
8448            self.ime_transaction.take();
8449        }
8450    }
8451}
8452
8453fn build_style(
8454    settings: &ThemeSettings,
8455    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8456    override_text_style: Option<&OverrideTextStyle>,
8457    cx: &AppContext,
8458) -> EditorStyle {
8459    let font_cache = cx.font_cache();
8460    let line_height_scalar = settings.line_height();
8461    let theme_id = settings.theme.meta.id;
8462    let mut theme = settings.theme.editor.clone();
8463    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8464        let field_editor_theme = get_field_editor_theme(&settings.theme);
8465        theme.text_color = field_editor_theme.text.color;
8466        theme.selection = field_editor_theme.selection;
8467        theme.background = field_editor_theme
8468            .container
8469            .background_color
8470            .unwrap_or_default();
8471        EditorStyle {
8472            text: field_editor_theme.text,
8473            placeholder_text: field_editor_theme.placeholder_text,
8474            line_height_scalar,
8475            theme,
8476            theme_id,
8477        }
8478    } else {
8479        let font_family_id = settings.buffer_font_family;
8480        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8481        let font_properties = Default::default();
8482        let font_id = font_cache
8483            .select_font(font_family_id, &font_properties)
8484            .unwrap();
8485        let font_size = settings.buffer_font_size(cx);
8486        EditorStyle {
8487            text: TextStyle {
8488                color: settings.theme.editor.text_color,
8489                font_family_name,
8490                font_family_id,
8491                font_id,
8492                font_size,
8493                font_properties,
8494                underline: Default::default(),
8495            },
8496            placeholder_text: None,
8497            line_height_scalar,
8498            theme,
8499            theme_id,
8500        }
8501    };
8502
8503    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8504        if let Some(highlighted) = style
8505            .text
8506            .clone()
8507            .highlight(highlight_style, font_cache)
8508            .log_err()
8509        {
8510            style.text = highlighted;
8511        }
8512    }
8513
8514    style
8515}
8516
8517trait SelectionExt {
8518    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8519    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8520    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8521    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8522        -> Range<u32>;
8523}
8524
8525impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8526    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8527        let start = self.start.to_point(buffer);
8528        let end = self.end.to_point(buffer);
8529        if self.reversed {
8530            end..start
8531        } else {
8532            start..end
8533        }
8534    }
8535
8536    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8537        let start = self.start.to_offset(buffer);
8538        let end = self.end.to_offset(buffer);
8539        if self.reversed {
8540            end..start
8541        } else {
8542            start..end
8543        }
8544    }
8545
8546    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8547        let start = self
8548            .start
8549            .to_point(&map.buffer_snapshot)
8550            .to_display_point(map);
8551        let end = self
8552            .end
8553            .to_point(&map.buffer_snapshot)
8554            .to_display_point(map);
8555        if self.reversed {
8556            end..start
8557        } else {
8558            start..end
8559        }
8560    }
8561
8562    fn spanned_rows(
8563        &self,
8564        include_end_if_at_line_start: bool,
8565        map: &DisplaySnapshot,
8566    ) -> Range<u32> {
8567        let start = self.start.to_point(&map.buffer_snapshot);
8568        let mut end = self.end.to_point(&map.buffer_snapshot);
8569        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8570            end.row -= 1;
8571        }
8572
8573        let buffer_start = map.prev_line_boundary(start).0;
8574        let buffer_end = map.next_line_boundary(end).0;
8575        buffer_start.row..buffer_end.row + 1
8576    }
8577}
8578
8579impl<T: InvalidationRegion> InvalidationStack<T> {
8580    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8581    where
8582        S: Clone + ToOffset,
8583    {
8584        while let Some(region) = self.last() {
8585            let all_selections_inside_invalidation_ranges =
8586                if selections.len() == region.ranges().len() {
8587                    selections
8588                        .iter()
8589                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8590                        .all(|(selection, invalidation_range)| {
8591                            let head = selection.head().to_offset(buffer);
8592                            invalidation_range.start <= head && invalidation_range.end >= head
8593                        })
8594                } else {
8595                    false
8596                };
8597
8598            if all_selections_inside_invalidation_ranges {
8599                break;
8600            } else {
8601                self.pop();
8602            }
8603        }
8604    }
8605}
8606
8607impl<T> Default for InvalidationStack<T> {
8608    fn default() -> Self {
8609        Self(Default::default())
8610    }
8611}
8612
8613impl<T> Deref for InvalidationStack<T> {
8614    type Target = Vec<T>;
8615
8616    fn deref(&self) -> &Self::Target {
8617        &self.0
8618    }
8619}
8620
8621impl<T> DerefMut for InvalidationStack<T> {
8622    fn deref_mut(&mut self) -> &mut Self::Target {
8623        &mut self.0
8624    }
8625}
8626
8627impl InvalidationRegion for SnippetState {
8628    fn ranges(&self) -> &[Range<Anchor>] {
8629        &self.ranges[self.active_index]
8630    }
8631}
8632
8633impl Deref for EditorStyle {
8634    type Target = theme::Editor;
8635
8636    fn deref(&self) -> &Self::Target {
8637        &self.theme
8638    }
8639}
8640
8641pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8642    let mut highlighted_lines = Vec::new();
8643
8644    for (index, line) in diagnostic.message.lines().enumerate() {
8645        let line = match &diagnostic.source {
8646            Some(source) if index == 0 => {
8647                let source_highlight = Vec::from_iter(0..source.len());
8648                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8649            }
8650
8651            _ => highlight_diagnostic_message(Vec::new(), line),
8652        };
8653        highlighted_lines.push(line);
8654    }
8655    let message = diagnostic.message;
8656    Arc::new(move |cx: &mut BlockContext| {
8657        let message = message.clone();
8658        let settings = settings::get::<ThemeSettings>(cx);
8659        let tooltip_style = settings.theme.tooltip.clone();
8660        let theme = &settings.theme.editor;
8661        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8662        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8663        let anchor_x = cx.anchor_x;
8664        enum BlockContextToolip {}
8665        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
8666            Flex::column()
8667                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8668                    Label::new(
8669                        line.clone(),
8670                        style.message.clone().with_font_size(font_size),
8671                    )
8672                    .with_highlights(highlights.clone())
8673                    .contained()
8674                    .with_margin_left(anchor_x)
8675                }))
8676                .aligned()
8677                .left()
8678                .into_any()
8679        })
8680        .with_cursor_style(CursorStyle::PointingHand)
8681        .on_click(MouseButton::Left, move |_, _, cx| {
8682            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8683        })
8684        // We really need to rethink this ID system...
8685        .with_tooltip::<BlockContextToolip>(
8686            cx.block_id,
8687            "Copy diagnostic message",
8688            None,
8689            tooltip_style,
8690            cx,
8691        )
8692        .into_any()
8693    })
8694}
8695
8696pub fn highlight_diagnostic_message(
8697    initial_highlights: Vec<usize>,
8698    message: &str,
8699) -> (String, Vec<usize>) {
8700    let mut message_without_backticks = String::new();
8701    let mut prev_offset = 0;
8702    let mut inside_block = false;
8703    let mut highlights = initial_highlights;
8704    for (match_ix, (offset, _)) in message
8705        .match_indices('`')
8706        .chain([(message.len(), "")])
8707        .enumerate()
8708    {
8709        message_without_backticks.push_str(&message[prev_offset..offset]);
8710        if inside_block {
8711            highlights.extend(prev_offset - match_ix..offset - match_ix);
8712        }
8713
8714        inside_block = !inside_block;
8715        prev_offset = offset + 1;
8716    }
8717
8718    (message_without_backticks, highlights)
8719}
8720
8721pub fn diagnostic_style(
8722    severity: DiagnosticSeverity,
8723    valid: bool,
8724    theme: &theme::Editor,
8725) -> DiagnosticStyle {
8726    match (severity, valid) {
8727        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8728        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8729        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8730        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8731        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8732        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8733        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8734        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8735        _ => theme.invalid_hint_diagnostic.clone(),
8736    }
8737}
8738
8739pub fn combine_syntax_and_fuzzy_match_highlights(
8740    text: &str,
8741    default_style: HighlightStyle,
8742    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8743    match_indices: &[usize],
8744) -> Vec<(Range<usize>, HighlightStyle)> {
8745    let mut result = Vec::new();
8746    let mut match_indices = match_indices.iter().copied().peekable();
8747
8748    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8749    {
8750        syntax_highlight.weight = None;
8751
8752        // Add highlights for any fuzzy match characters before the next
8753        // syntax highlight range.
8754        while let Some(&match_index) = match_indices.peek() {
8755            if match_index >= range.start {
8756                break;
8757            }
8758            match_indices.next();
8759            let end_index = char_ix_after(match_index, text);
8760            let mut match_style = default_style;
8761            match_style.weight = Some(fonts::Weight::BOLD);
8762            result.push((match_index..end_index, match_style));
8763        }
8764
8765        if range.start == usize::MAX {
8766            break;
8767        }
8768
8769        // Add highlights for any fuzzy match characters within the
8770        // syntax highlight range.
8771        let mut offset = range.start;
8772        while let Some(&match_index) = match_indices.peek() {
8773            if match_index >= range.end {
8774                break;
8775            }
8776
8777            match_indices.next();
8778            if match_index > offset {
8779                result.push((offset..match_index, syntax_highlight));
8780            }
8781
8782            let mut end_index = char_ix_after(match_index, text);
8783            while let Some(&next_match_index) = match_indices.peek() {
8784                if next_match_index == end_index && next_match_index < range.end {
8785                    end_index = char_ix_after(next_match_index, text);
8786                    match_indices.next();
8787                } else {
8788                    break;
8789                }
8790            }
8791
8792            let mut match_style = syntax_highlight;
8793            match_style.weight = Some(fonts::Weight::BOLD);
8794            result.push((match_index..end_index, match_style));
8795            offset = end_index;
8796        }
8797
8798        if offset < range.end {
8799            result.push((offset..range.end, syntax_highlight));
8800        }
8801    }
8802
8803    fn char_ix_after(ix: usize, text: &str) -> usize {
8804        ix + text[ix..].chars().next().unwrap().len_utf8()
8805    }
8806
8807    result
8808}
8809
8810pub fn styled_runs_for_code_label<'a>(
8811    label: &'a CodeLabel,
8812    syntax_theme: &'a theme::SyntaxTheme,
8813) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8814    let fade_out = HighlightStyle {
8815        fade_out: Some(0.35),
8816        ..Default::default()
8817    };
8818
8819    let mut prev_end = label.filter_range.end;
8820    label
8821        .runs
8822        .iter()
8823        .enumerate()
8824        .flat_map(move |(ix, (range, highlight_id))| {
8825            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8826                style
8827            } else {
8828                return Default::default();
8829            };
8830            let mut muted_style = style;
8831            muted_style.highlight(fade_out);
8832
8833            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8834            if range.start >= label.filter_range.end {
8835                if range.start > prev_end {
8836                    runs.push((prev_end..range.start, fade_out));
8837                }
8838                runs.push((range.clone(), muted_style));
8839            } else if range.end <= label.filter_range.end {
8840                runs.push((range.clone(), style));
8841            } else {
8842                runs.push((range.start..label.filter_range.end, style));
8843                runs.push((label.filter_range.end..range.end, muted_style));
8844            }
8845            prev_end = cmp::max(prev_end, range.end);
8846
8847            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8848                runs.push((prev_end..label.text.len(), fade_out));
8849            }
8850
8851            runs
8852        })
8853}
8854
8855pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8856    let mut index = 0;
8857    let mut codepoints = text.char_indices().peekable();
8858
8859    std::iter::from_fn(move || {
8860        let start_index = index;
8861        while let Some((new_index, codepoint)) = codepoints.next() {
8862            index = new_index + codepoint.len_utf8();
8863            let current_upper = codepoint.is_uppercase();
8864            let next_upper = codepoints
8865                .peek()
8866                .map(|(_, c)| c.is_uppercase())
8867                .unwrap_or(false);
8868
8869            if !current_upper && next_upper {
8870                return Some(&text[start_index..index]);
8871            }
8872        }
8873
8874        index = text.len();
8875        if start_index < text.len() {
8876            return Some(&text[start_index..]);
8877        }
8878        None
8879    })
8880    .flat_map(|word| word.split_inclusive('_'))
8881}
8882
8883trait RangeToAnchorExt {
8884    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8885}
8886
8887impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8888    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8889        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8890    }
8891}