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