editor.rs

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