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