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