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