editor.rs

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