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