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