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