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