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