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                                dbg!(start_offset, end_offset, &clipboard_text, &to_insert);
4870                                entire_line = clipboard_selection.is_entire_line;
4871                                start_offset = end_offset + 1;
4872                                original_indent_column =
4873                                    Some(clipboard_selection.first_line_indent);
4874                            } else {
4875                                to_insert = clipboard_text.as_str();
4876                                entire_line = all_selections_were_entire_line;
4877                                original_indent_column = first_selection_indent_column
4878                            }
4879
4880                            // If the corresponding selection was empty when this slice of the
4881                            // clipboard text was written, then the entire line containing the
4882                            // selection was copied. If this selection is also currently empty,
4883                            // then paste the line before the current line of the buffer.
4884                            let range = if selection.is_empty() && !line_mode && entire_line {
4885                                let column = selection.start.to_point(&snapshot).column as usize;
4886                                let line_start = selection.start - column;
4887                                line_start..line_start
4888                            } else {
4889                                selection.range()
4890                            };
4891
4892                            edits.push((range, to_insert));
4893                            original_indent_columns.extend(original_indent_column);
4894                        }
4895                        drop(snapshot);
4896
4897                        buffer.edit(
4898                            edits,
4899                            Some(AutoindentMode::Block {
4900                                original_indent_columns,
4901                            }),
4902                            cx,
4903                        );
4904                    });
4905
4906                    let selections = this.selections.all::<usize>(cx);
4907                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4908                } else {
4909                    this.insert(&clipboard_text, cx);
4910                }
4911            }
4912        });
4913    }
4914
4915    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4916        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4917            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4918                self.change_selections(None, cx, |s| {
4919                    s.select_anchors(selections.to_vec());
4920                });
4921            }
4922            self.request_autoscroll(Autoscroll::fit(), cx);
4923            self.unmark_text(cx);
4924            self.refresh_copilot_suggestions(true, cx);
4925            cx.emit(Event::Edited);
4926        }
4927    }
4928
4929    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4930        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4931            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4932            {
4933                self.change_selections(None, cx, |s| {
4934                    s.select_anchors(selections.to_vec());
4935                });
4936            }
4937            self.request_autoscroll(Autoscroll::fit(), cx);
4938            self.unmark_text(cx);
4939            self.refresh_copilot_suggestions(true, cx);
4940            cx.emit(Event::Edited);
4941        }
4942    }
4943
4944    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4945        self.buffer
4946            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4947    }
4948
4949    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4950        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4951            let line_mode = s.line_mode;
4952            s.move_with(|map, selection| {
4953                let cursor = if selection.is_empty() && !line_mode {
4954                    movement::left(map, selection.start)
4955                } else {
4956                    selection.start
4957                };
4958                selection.collapse_to(cursor, SelectionGoal::None);
4959            });
4960        })
4961    }
4962
4963    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4964        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4965            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4966        })
4967    }
4968
4969    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4970        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4971            let line_mode = s.line_mode;
4972            s.move_with(|map, selection| {
4973                let cursor = if selection.is_empty() && !line_mode {
4974                    movement::right(map, selection.end)
4975                } else {
4976                    selection.end
4977                };
4978                selection.collapse_to(cursor, SelectionGoal::None)
4979            });
4980        })
4981    }
4982
4983    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4984        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4985            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4986        })
4987    }
4988
4989    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4990        if self.take_rename(true, cx).is_some() {
4991            return;
4992        }
4993
4994        if let Some(context_menu) = self.context_menu.as_mut() {
4995            if context_menu.select_prev(cx) {
4996                return;
4997            }
4998        }
4999
5000        if matches!(self.mode, EditorMode::SingleLine) {
5001            cx.propagate_action();
5002            return;
5003        }
5004
5005        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5006            let line_mode = s.line_mode;
5007            s.move_with(|map, selection| {
5008                if !selection.is_empty() && !line_mode {
5009                    selection.goal = SelectionGoal::None;
5010                }
5011                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
5012                selection.collapse_to(cursor, goal);
5013            });
5014        })
5015    }
5016
5017    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5018        if self.take_rename(true, cx).is_some() {
5019            return;
5020        }
5021
5022        if self
5023            .context_menu
5024            .as_mut()
5025            .map(|menu| menu.select_first(cx))
5026            .unwrap_or(false)
5027        {
5028            return;
5029        }
5030
5031        if matches!(self.mode, EditorMode::SingleLine) {
5032            cx.propagate_action();
5033            return;
5034        }
5035
5036        let row_count = if let Some(row_count) = self.visible_line_count() {
5037            row_count as u32 - 1
5038        } else {
5039            return;
5040        };
5041
5042        let autoscroll = if action.center_cursor {
5043            Autoscroll::center()
5044        } else {
5045            Autoscroll::fit()
5046        };
5047
5048        self.change_selections(Some(autoscroll), cx, |s| {
5049            let line_mode = s.line_mode;
5050            s.move_with(|map, selection| {
5051                if !selection.is_empty() && !line_mode {
5052                    selection.goal = SelectionGoal::None;
5053                }
5054                let (cursor, goal) =
5055                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
5056                selection.collapse_to(cursor, goal);
5057            });
5058        });
5059    }
5060
5061    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5062        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5063            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
5064        })
5065    }
5066
5067    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5068        self.take_rename(true, cx);
5069
5070        if let Some(context_menu) = self.context_menu.as_mut() {
5071            if context_menu.select_next(cx) {
5072                return;
5073            }
5074        }
5075
5076        if self.mode == EditorMode::SingleLine {
5077            cx.propagate_action();
5078            return;
5079        }
5080
5081        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5082            let line_mode = s.line_mode;
5083            s.move_with(|map, selection| {
5084                if !selection.is_empty() && !line_mode {
5085                    selection.goal = SelectionGoal::None;
5086                }
5087                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
5088                selection.collapse_to(cursor, goal);
5089            });
5090        });
5091    }
5092
5093    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5094        if self.take_rename(true, cx).is_some() {
5095            return;
5096        }
5097
5098        if self
5099            .context_menu
5100            .as_mut()
5101            .map(|menu| menu.select_last(cx))
5102            .unwrap_or(false)
5103        {
5104            return;
5105        }
5106
5107        if matches!(self.mode, EditorMode::SingleLine) {
5108            cx.propagate_action();
5109            return;
5110        }
5111
5112        let row_count = if let Some(row_count) = self.visible_line_count() {
5113            row_count as u32 - 1
5114        } else {
5115            return;
5116        };
5117
5118        let autoscroll = if action.center_cursor {
5119            Autoscroll::center()
5120        } else {
5121            Autoscroll::fit()
5122        };
5123
5124        self.change_selections(Some(autoscroll), cx, |s| {
5125            let line_mode = s.line_mode;
5126            s.move_with(|map, selection| {
5127                if !selection.is_empty() && !line_mode {
5128                    selection.goal = SelectionGoal::None;
5129                }
5130                let (cursor, goal) =
5131                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5132                selection.collapse_to(cursor, goal);
5133            });
5134        });
5135    }
5136
5137    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5138        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5139            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5140        });
5141    }
5142
5143    pub fn move_to_previous_word_start(
5144        &mut self,
5145        _: &MoveToPreviousWordStart,
5146        cx: &mut ViewContext<Self>,
5147    ) {
5148        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5149            s.move_cursors_with(|map, head, _| {
5150                (
5151                    movement::previous_word_start(map, head),
5152                    SelectionGoal::None,
5153                )
5154            });
5155        })
5156    }
5157
5158    pub fn move_to_previous_subword_start(
5159        &mut self,
5160        _: &MoveToPreviousSubwordStart,
5161        cx: &mut ViewContext<Self>,
5162    ) {
5163        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5164            s.move_cursors_with(|map, head, _| {
5165                (
5166                    movement::previous_subword_start(map, head),
5167                    SelectionGoal::None,
5168                )
5169            });
5170        })
5171    }
5172
5173    pub fn select_to_previous_word_start(
5174        &mut self,
5175        _: &SelectToPreviousWordStart,
5176        cx: &mut ViewContext<Self>,
5177    ) {
5178        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5179            s.move_heads_with(|map, head, _| {
5180                (
5181                    movement::previous_word_start(map, head),
5182                    SelectionGoal::None,
5183                )
5184            });
5185        })
5186    }
5187
5188    pub fn select_to_previous_subword_start(
5189        &mut self,
5190        _: &SelectToPreviousSubwordStart,
5191        cx: &mut ViewContext<Self>,
5192    ) {
5193        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5194            s.move_heads_with(|map, head, _| {
5195                (
5196                    movement::previous_subword_start(map, head),
5197                    SelectionGoal::None,
5198                )
5199            });
5200        })
5201    }
5202
5203    pub fn delete_to_previous_word_start(
5204        &mut self,
5205        _: &DeleteToPreviousWordStart,
5206        cx: &mut ViewContext<Self>,
5207    ) {
5208        self.transact(cx, |this, cx| {
5209            this.select_autoclose_pair(cx);
5210            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5211                let line_mode = s.line_mode;
5212                s.move_with(|map, selection| {
5213                    if selection.is_empty() && !line_mode {
5214                        let cursor = movement::previous_word_start(map, selection.head());
5215                        selection.set_head(cursor, SelectionGoal::None);
5216                    }
5217                });
5218            });
5219            this.insert("", cx);
5220        });
5221    }
5222
5223    pub fn delete_to_previous_subword_start(
5224        &mut self,
5225        _: &DeleteToPreviousSubwordStart,
5226        cx: &mut ViewContext<Self>,
5227    ) {
5228        self.transact(cx, |this, cx| {
5229            this.select_autoclose_pair(cx);
5230            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5231                let line_mode = s.line_mode;
5232                s.move_with(|map, selection| {
5233                    if selection.is_empty() && !line_mode {
5234                        let cursor = movement::previous_subword_start(map, selection.head());
5235                        selection.set_head(cursor, SelectionGoal::None);
5236                    }
5237                });
5238            });
5239            this.insert("", cx);
5240        });
5241    }
5242
5243    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5244        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5245            s.move_cursors_with(|map, head, _| {
5246                (movement::next_word_end(map, head), SelectionGoal::None)
5247            });
5248        })
5249    }
5250
5251    pub fn move_to_next_subword_end(
5252        &mut self,
5253        _: &MoveToNextSubwordEnd,
5254        cx: &mut ViewContext<Self>,
5255    ) {
5256        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5257            s.move_cursors_with(|map, head, _| {
5258                (movement::next_subword_end(map, head), SelectionGoal::None)
5259            });
5260        })
5261    }
5262
5263    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5264        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5265            s.move_heads_with(|map, head, _| {
5266                (movement::next_word_end(map, head), SelectionGoal::None)
5267            });
5268        })
5269    }
5270
5271    pub fn select_to_next_subword_end(
5272        &mut self,
5273        _: &SelectToNextSubwordEnd,
5274        cx: &mut ViewContext<Self>,
5275    ) {
5276        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5277            s.move_heads_with(|map, head, _| {
5278                (movement::next_subword_end(map, head), SelectionGoal::None)
5279            });
5280        })
5281    }
5282
5283    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5284        self.transact(cx, |this, cx| {
5285            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5286                let line_mode = s.line_mode;
5287                s.move_with(|map, selection| {
5288                    if selection.is_empty() && !line_mode {
5289                        let cursor = movement::next_word_end(map, selection.head());
5290                        selection.set_head(cursor, SelectionGoal::None);
5291                    }
5292                });
5293            });
5294            this.insert("", cx);
5295        });
5296    }
5297
5298    pub fn delete_to_next_subword_end(
5299        &mut self,
5300        _: &DeleteToNextSubwordEnd,
5301        cx: &mut ViewContext<Self>,
5302    ) {
5303        self.transact(cx, |this, cx| {
5304            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5305                s.move_with(|map, selection| {
5306                    if selection.is_empty() {
5307                        let cursor = movement::next_subword_end(map, selection.head());
5308                        selection.set_head(cursor, SelectionGoal::None);
5309                    }
5310                });
5311            });
5312            this.insert("", cx);
5313        });
5314    }
5315
5316    pub fn move_to_beginning_of_line(
5317        &mut self,
5318        _: &MoveToBeginningOfLine,
5319        cx: &mut ViewContext<Self>,
5320    ) {
5321        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5322            s.move_cursors_with(|map, head, _| {
5323                (
5324                    movement::indented_line_beginning(map, head, true),
5325                    SelectionGoal::None,
5326                )
5327            });
5328        })
5329    }
5330
5331    pub fn select_to_beginning_of_line(
5332        &mut self,
5333        action: &SelectToBeginningOfLine,
5334        cx: &mut ViewContext<Self>,
5335    ) {
5336        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5337            s.move_heads_with(|map, head, _| {
5338                (
5339                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5340                    SelectionGoal::None,
5341                )
5342            });
5343        });
5344    }
5345
5346    pub fn delete_to_beginning_of_line(
5347        &mut self,
5348        _: &DeleteToBeginningOfLine,
5349        cx: &mut ViewContext<Self>,
5350    ) {
5351        self.transact(cx, |this, cx| {
5352            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5353                s.move_with(|_, selection| {
5354                    selection.reversed = true;
5355                });
5356            });
5357
5358            this.select_to_beginning_of_line(
5359                &SelectToBeginningOfLine {
5360                    stop_at_soft_wraps: false,
5361                },
5362                cx,
5363            );
5364            this.backspace(&Backspace, cx);
5365        });
5366    }
5367
5368    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5369        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5370            s.move_cursors_with(|map, head, _| {
5371                (movement::line_end(map, head, true), SelectionGoal::None)
5372            });
5373        })
5374    }
5375
5376    pub fn select_to_end_of_line(
5377        &mut self,
5378        action: &SelectToEndOfLine,
5379        cx: &mut ViewContext<Self>,
5380    ) {
5381        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5382            s.move_heads_with(|map, head, _| {
5383                (
5384                    movement::line_end(map, head, action.stop_at_soft_wraps),
5385                    SelectionGoal::None,
5386                )
5387            });
5388        })
5389    }
5390
5391    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5392        self.transact(cx, |this, cx| {
5393            this.select_to_end_of_line(
5394                &SelectToEndOfLine {
5395                    stop_at_soft_wraps: false,
5396                },
5397                cx,
5398            );
5399            this.delete(&Delete, cx);
5400        });
5401    }
5402
5403    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5404        self.transact(cx, |this, cx| {
5405            this.select_to_end_of_line(
5406                &SelectToEndOfLine {
5407                    stop_at_soft_wraps: false,
5408                },
5409                cx,
5410            );
5411            this.cut(&Cut, cx);
5412        });
5413    }
5414
5415    pub fn move_to_start_of_paragraph(
5416        &mut self,
5417        _: &MoveToStartOfParagraph,
5418        cx: &mut ViewContext<Self>,
5419    ) {
5420        if matches!(self.mode, EditorMode::SingleLine) {
5421            cx.propagate_action();
5422            return;
5423        }
5424
5425        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5426            s.move_with(|map, selection| {
5427                selection.collapse_to(
5428                    movement::start_of_paragraph(map, selection.head(), 1),
5429                    SelectionGoal::None,
5430                )
5431            });
5432        })
5433    }
5434
5435    pub fn move_to_end_of_paragraph(
5436        &mut self,
5437        _: &MoveToEndOfParagraph,
5438        cx: &mut ViewContext<Self>,
5439    ) {
5440        if matches!(self.mode, EditorMode::SingleLine) {
5441            cx.propagate_action();
5442            return;
5443        }
5444
5445        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5446            s.move_with(|map, selection| {
5447                selection.collapse_to(
5448                    movement::end_of_paragraph(map, selection.head(), 1),
5449                    SelectionGoal::None,
5450                )
5451            });
5452        })
5453    }
5454
5455    pub fn select_to_start_of_paragraph(
5456        &mut self,
5457        _: &SelectToStartOfParagraph,
5458        cx: &mut ViewContext<Self>,
5459    ) {
5460        if matches!(self.mode, EditorMode::SingleLine) {
5461            cx.propagate_action();
5462            return;
5463        }
5464
5465        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5466            s.move_heads_with(|map, head, _| {
5467                (
5468                    movement::start_of_paragraph(map, head, 1),
5469                    SelectionGoal::None,
5470                )
5471            });
5472        })
5473    }
5474
5475    pub fn select_to_end_of_paragraph(
5476        &mut self,
5477        _: &SelectToEndOfParagraph,
5478        cx: &mut ViewContext<Self>,
5479    ) {
5480        if matches!(self.mode, EditorMode::SingleLine) {
5481            cx.propagate_action();
5482            return;
5483        }
5484
5485        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5486            s.move_heads_with(|map, head, _| {
5487                (
5488                    movement::end_of_paragraph(map, head, 1),
5489                    SelectionGoal::None,
5490                )
5491            });
5492        })
5493    }
5494
5495    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5496        if matches!(self.mode, EditorMode::SingleLine) {
5497            cx.propagate_action();
5498            return;
5499        }
5500
5501        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5502            s.select_ranges(vec![0..0]);
5503        });
5504    }
5505
5506    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5507        let mut selection = self.selections.last::<Point>(cx);
5508        selection.set_head(Point::zero(), SelectionGoal::None);
5509
5510        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5511            s.select(vec![selection]);
5512        });
5513    }
5514
5515    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5516        if matches!(self.mode, EditorMode::SingleLine) {
5517            cx.propagate_action();
5518            return;
5519        }
5520
5521        let cursor = self.buffer.read(cx).read(cx).len();
5522        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5523            s.select_ranges(vec![cursor..cursor])
5524        });
5525    }
5526
5527    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5528        self.nav_history = nav_history;
5529    }
5530
5531    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5532        self.nav_history.as_ref()
5533    }
5534
5535    fn push_to_nav_history(
5536        &mut self,
5537        cursor_anchor: Anchor,
5538        new_position: Option<Point>,
5539        cx: &mut ViewContext<Self>,
5540    ) {
5541        if let Some(nav_history) = self.nav_history.as_mut() {
5542            let buffer = self.buffer.read(cx).read(cx);
5543            let cursor_position = cursor_anchor.to_point(&buffer);
5544            let scroll_state = self.scroll_manager.anchor();
5545            let scroll_top_row = scroll_state.top_row(&buffer);
5546            drop(buffer);
5547
5548            if let Some(new_position) = new_position {
5549                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5550                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5551                    return;
5552                }
5553            }
5554
5555            nav_history.push(
5556                Some(NavigationData {
5557                    cursor_anchor,
5558                    cursor_position,
5559                    scroll_anchor: scroll_state,
5560                    scroll_top_row,
5561                }),
5562                cx,
5563            );
5564        }
5565    }
5566
5567    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5568        let buffer = self.buffer.read(cx).snapshot(cx);
5569        let mut selection = self.selections.first::<usize>(cx);
5570        selection.set_head(buffer.len(), SelectionGoal::None);
5571        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5572            s.select(vec![selection]);
5573        });
5574    }
5575
5576    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5577        let end = self.buffer.read(cx).read(cx).len();
5578        self.change_selections(None, cx, |s| {
5579            s.select_ranges(vec![0..end]);
5580        });
5581    }
5582
5583    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5584        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5585        let mut selections = self.selections.all::<Point>(cx);
5586        let max_point = display_map.buffer_snapshot.max_point();
5587        for selection in &mut selections {
5588            let rows = selection.spanned_rows(true, &display_map);
5589            selection.start = Point::new(rows.start, 0);
5590            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5591            selection.reversed = false;
5592        }
5593        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5594            s.select(selections);
5595        });
5596    }
5597
5598    pub fn split_selection_into_lines(
5599        &mut self,
5600        _: &SplitSelectionIntoLines,
5601        cx: &mut ViewContext<Self>,
5602    ) {
5603        let mut to_unfold = Vec::new();
5604        let mut new_selection_ranges = Vec::new();
5605        {
5606            let selections = self.selections.all::<Point>(cx);
5607            let buffer = self.buffer.read(cx).read(cx);
5608            for selection in selections {
5609                for row in selection.start.row..selection.end.row {
5610                    let cursor = Point::new(row, buffer.line_len(row));
5611                    new_selection_ranges.push(cursor..cursor);
5612                }
5613                new_selection_ranges.push(selection.end..selection.end);
5614                to_unfold.push(selection.start..selection.end);
5615            }
5616        }
5617        self.unfold_ranges(to_unfold, true, true, cx);
5618        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5619            s.select_ranges(new_selection_ranges);
5620        });
5621    }
5622
5623    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5624        self.add_selection(true, cx);
5625    }
5626
5627    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5628        self.add_selection(false, cx);
5629    }
5630
5631    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5632        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5633        let mut selections = self.selections.all::<Point>(cx);
5634        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5635            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5636            let range = oldest_selection.display_range(&display_map).sorted();
5637            let columns = cmp::min(range.start.column(), range.end.column())
5638                ..cmp::max(range.start.column(), range.end.column());
5639
5640            selections.clear();
5641            let mut stack = Vec::new();
5642            for row in range.start.row()..=range.end.row() {
5643                if let Some(selection) = self.selections.build_columnar_selection(
5644                    &display_map,
5645                    row,
5646                    &columns,
5647                    oldest_selection.reversed,
5648                ) {
5649                    stack.push(selection.id);
5650                    selections.push(selection);
5651                }
5652            }
5653
5654            if above {
5655                stack.reverse();
5656            }
5657
5658            AddSelectionsState { above, stack }
5659        });
5660
5661        let last_added_selection = *state.stack.last().unwrap();
5662        let mut new_selections = Vec::new();
5663        if above == state.above {
5664            let end_row = if above {
5665                0
5666            } else {
5667                display_map.max_point().row()
5668            };
5669
5670            'outer: for selection in selections {
5671                if selection.id == last_added_selection {
5672                    let range = selection.display_range(&display_map).sorted();
5673                    debug_assert_eq!(range.start.row(), range.end.row());
5674                    let mut row = range.start.row();
5675                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5676                    {
5677                        start..end
5678                    } else {
5679                        cmp::min(range.start.column(), range.end.column())
5680                            ..cmp::max(range.start.column(), range.end.column())
5681                    };
5682
5683                    while row != end_row {
5684                        if above {
5685                            row -= 1;
5686                        } else {
5687                            row += 1;
5688                        }
5689
5690                        if let Some(new_selection) = self.selections.build_columnar_selection(
5691                            &display_map,
5692                            row,
5693                            &columns,
5694                            selection.reversed,
5695                        ) {
5696                            state.stack.push(new_selection.id);
5697                            if above {
5698                                new_selections.push(new_selection);
5699                                new_selections.push(selection);
5700                            } else {
5701                                new_selections.push(selection);
5702                                new_selections.push(new_selection);
5703                            }
5704
5705                            continue 'outer;
5706                        }
5707                    }
5708                }
5709
5710                new_selections.push(selection);
5711            }
5712        } else {
5713            new_selections = selections;
5714            new_selections.retain(|s| s.id != last_added_selection);
5715            state.stack.pop();
5716        }
5717
5718        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5719            s.select(new_selections);
5720        });
5721        if state.stack.len() > 1 {
5722            self.add_selections_state = Some(state);
5723        }
5724    }
5725
5726    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5727        self.push_to_selection_history();
5728        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5729        let buffer = &display_map.buffer_snapshot;
5730        let mut selections = self.selections.all::<usize>(cx);
5731        if let Some(mut select_next_state) = self.select_next_state.take() {
5732            let query = &select_next_state.query;
5733            if !select_next_state.done {
5734                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5735                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5736                let mut next_selected_range = None;
5737
5738                let bytes_after_last_selection =
5739                    buffer.bytes_in_range(last_selection.end..buffer.len());
5740                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5741                let query_matches = query
5742                    .stream_find_iter(bytes_after_last_selection)
5743                    .map(|result| (last_selection.end, result))
5744                    .chain(
5745                        query
5746                            .stream_find_iter(bytes_before_first_selection)
5747                            .map(|result| (0, result)),
5748                    );
5749                for (start_offset, query_match) in query_matches {
5750                    let query_match = query_match.unwrap(); // can only fail due to I/O
5751                    let offset_range =
5752                        start_offset + query_match.start()..start_offset + query_match.end();
5753                    let display_range = offset_range.start.to_display_point(&display_map)
5754                        ..offset_range.end.to_display_point(&display_map);
5755
5756                    if !select_next_state.wordwise
5757                        || (!movement::is_inside_word(&display_map, display_range.start)
5758                            && !movement::is_inside_word(&display_map, display_range.end))
5759                    {
5760                        next_selected_range = Some(offset_range);
5761                        break;
5762                    }
5763                }
5764
5765                if let Some(next_selected_range) = next_selected_range {
5766                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5767                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5768                        if action.replace_newest {
5769                            s.delete(s.newest_anchor().id);
5770                        }
5771                        s.insert_range(next_selected_range);
5772                    });
5773                } else {
5774                    select_next_state.done = true;
5775                }
5776            }
5777
5778            self.select_next_state = Some(select_next_state);
5779        } else if selections.len() == 1 {
5780            let selection = selections.last_mut().unwrap();
5781            if selection.start == selection.end {
5782                let word_range = movement::surrounding_word(
5783                    &display_map,
5784                    selection.start.to_display_point(&display_map),
5785                );
5786                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5787                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5788                selection.goal = SelectionGoal::None;
5789                selection.reversed = false;
5790
5791                let query = buffer
5792                    .text_for_range(selection.start..selection.end)
5793                    .collect::<String>();
5794                let select_state = SelectNextState {
5795                    query: AhoCorasick::new_auto_configured(&[query]),
5796                    wordwise: true,
5797                    done: false,
5798                };
5799                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5800                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5801                    s.select(selections);
5802                });
5803                self.select_next_state = Some(select_state);
5804            } else {
5805                let query = buffer
5806                    .text_for_range(selection.start..selection.end)
5807                    .collect::<String>();
5808                self.select_next_state = Some(SelectNextState {
5809                    query: AhoCorasick::new_auto_configured(&[query]),
5810                    wordwise: false,
5811                    done: false,
5812                });
5813                self.select_next(action, cx);
5814            }
5815        }
5816    }
5817
5818    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5819        self.push_to_selection_history();
5820        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5821        let buffer = &display_map.buffer_snapshot;
5822        let mut selections = self.selections.all::<usize>(cx);
5823        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5824            let query = &select_prev_state.query;
5825            if !select_prev_state.done {
5826                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5827                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5828                let mut next_selected_range = None;
5829                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5830                let bytes_before_last_selection =
5831                    buffer.reversed_bytes_in_range(0..last_selection.start);
5832                let bytes_after_first_selection =
5833                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5834                let query_matches = query
5835                    .stream_find_iter(bytes_before_last_selection)
5836                    .map(|result| (last_selection.start, result))
5837                    .chain(
5838                        query
5839                            .stream_find_iter(bytes_after_first_selection)
5840                            .map(|result| (buffer.len(), result)),
5841                    );
5842                for (end_offset, query_match) in query_matches {
5843                    let query_match = query_match.unwrap(); // can only fail due to I/O
5844                    let offset_range =
5845                        end_offset - query_match.end()..end_offset - query_match.start();
5846                    let display_range = offset_range.start.to_display_point(&display_map)
5847                        ..offset_range.end.to_display_point(&display_map);
5848
5849                    if !select_prev_state.wordwise
5850                        || (!movement::is_inside_word(&display_map, display_range.start)
5851                            && !movement::is_inside_word(&display_map, display_range.end))
5852                    {
5853                        next_selected_range = Some(offset_range);
5854                        break;
5855                    }
5856                }
5857
5858                if let Some(next_selected_range) = next_selected_range {
5859                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5860                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5861                        if action.replace_newest {
5862                            s.delete(s.newest_anchor().id);
5863                        }
5864                        s.insert_range(next_selected_range);
5865                    });
5866                } else {
5867                    select_prev_state.done = true;
5868                }
5869            }
5870
5871            self.select_prev_state = Some(select_prev_state);
5872        } else if selections.len() == 1 {
5873            let selection = selections.last_mut().unwrap();
5874            if selection.start == selection.end {
5875                let word_range = movement::surrounding_word(
5876                    &display_map,
5877                    selection.start.to_display_point(&display_map),
5878                );
5879                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5880                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5881                selection.goal = SelectionGoal::None;
5882                selection.reversed = false;
5883
5884                let query = buffer
5885                    .text_for_range(selection.start..selection.end)
5886                    .collect::<String>();
5887                let query = query.chars().rev().collect::<String>();
5888                let select_state = SelectNextState {
5889                    query: AhoCorasick::new_auto_configured(&[query]),
5890                    wordwise: true,
5891                    done: false,
5892                };
5893                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5894                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5895                    s.select(selections);
5896                });
5897                self.select_prev_state = Some(select_state);
5898            } else {
5899                let query = buffer
5900                    .text_for_range(selection.start..selection.end)
5901                    .collect::<String>();
5902                let query = query.chars().rev().collect::<String>();
5903                self.select_prev_state = Some(SelectNextState {
5904                    query: AhoCorasick::new_auto_configured(&[query]),
5905                    wordwise: false,
5906                    done: false,
5907                });
5908                self.select_previous(action, cx);
5909            }
5910        }
5911    }
5912
5913    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5914        self.transact(cx, |this, cx| {
5915            let mut selections = this.selections.all::<Point>(cx);
5916            let mut edits = Vec::new();
5917            let mut selection_edit_ranges = Vec::new();
5918            let mut last_toggled_row = None;
5919            let snapshot = this.buffer.read(cx).read(cx);
5920            let empty_str: Arc<str> = "".into();
5921            let mut suffixes_inserted = Vec::new();
5922
5923            fn comment_prefix_range(
5924                snapshot: &MultiBufferSnapshot,
5925                row: u32,
5926                comment_prefix: &str,
5927                comment_prefix_whitespace: &str,
5928            ) -> Range<Point> {
5929                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5930
5931                let mut line_bytes = snapshot
5932                    .bytes_in_range(start..snapshot.max_point())
5933                    .flatten()
5934                    .copied();
5935
5936                // If this line currently begins with the line comment prefix, then record
5937                // the range containing the prefix.
5938                if line_bytes
5939                    .by_ref()
5940                    .take(comment_prefix.len())
5941                    .eq(comment_prefix.bytes())
5942                {
5943                    // Include any whitespace that matches the comment prefix.
5944                    let matching_whitespace_len = line_bytes
5945                        .zip(comment_prefix_whitespace.bytes())
5946                        .take_while(|(a, b)| a == b)
5947                        .count() as u32;
5948                    let end = Point::new(
5949                        start.row,
5950                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5951                    );
5952                    start..end
5953                } else {
5954                    start..start
5955                }
5956            }
5957
5958            fn comment_suffix_range(
5959                snapshot: &MultiBufferSnapshot,
5960                row: u32,
5961                comment_suffix: &str,
5962                comment_suffix_has_leading_space: bool,
5963            ) -> Range<Point> {
5964                let end = Point::new(row, snapshot.line_len(row));
5965                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5966
5967                let mut line_end_bytes = snapshot
5968                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5969                    .flatten()
5970                    .copied();
5971
5972                let leading_space_len = if suffix_start_column > 0
5973                    && line_end_bytes.next() == Some(b' ')
5974                    && comment_suffix_has_leading_space
5975                {
5976                    1
5977                } else {
5978                    0
5979                };
5980
5981                // If this line currently begins with the line comment prefix, then record
5982                // the range containing the prefix.
5983                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5984                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5985                    start..end
5986                } else {
5987                    end..end
5988                }
5989            }
5990
5991            // TODO: Handle selections that cross excerpts
5992            for selection in &mut selections {
5993                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5994                let language = if let Some(language) =
5995                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5996                {
5997                    language
5998                } else {
5999                    continue;
6000                };
6001
6002                selection_edit_ranges.clear();
6003
6004                // If multiple selections contain a given row, avoid processing that
6005                // row more than once.
6006                let mut start_row = selection.start.row;
6007                if last_toggled_row == Some(start_row) {
6008                    start_row += 1;
6009                }
6010                let end_row =
6011                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6012                        selection.end.row - 1
6013                    } else {
6014                        selection.end.row
6015                    };
6016                last_toggled_row = Some(end_row);
6017
6018                if start_row > end_row {
6019                    continue;
6020                }
6021
6022                // If the language has line comments, toggle those.
6023                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6024                    // Split the comment prefix's trailing whitespace into a separate string,
6025                    // as that portion won't be used for detecting if a line is a comment.
6026                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6027                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6028                    let mut all_selection_lines_are_comments = true;
6029
6030                    for row in start_row..=end_row {
6031                        if snapshot.is_line_blank(row) && start_row < end_row {
6032                            continue;
6033                        }
6034
6035                        let prefix_range = comment_prefix_range(
6036                            snapshot.deref(),
6037                            row,
6038                            comment_prefix,
6039                            comment_prefix_whitespace,
6040                        );
6041                        if prefix_range.is_empty() {
6042                            all_selection_lines_are_comments = false;
6043                        }
6044                        selection_edit_ranges.push(prefix_range);
6045                    }
6046
6047                    if all_selection_lines_are_comments {
6048                        edits.extend(
6049                            selection_edit_ranges
6050                                .iter()
6051                                .cloned()
6052                                .map(|range| (range, empty_str.clone())),
6053                        );
6054                    } else {
6055                        let min_column = selection_edit_ranges
6056                            .iter()
6057                            .map(|r| r.start.column)
6058                            .min()
6059                            .unwrap_or(0);
6060                        edits.extend(selection_edit_ranges.iter().map(|range| {
6061                            let position = Point::new(range.start.row, min_column);
6062                            (position..position, full_comment_prefix.clone())
6063                        }));
6064                    }
6065                } else if let Some((full_comment_prefix, comment_suffix)) =
6066                    language.block_comment_delimiters()
6067                {
6068                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6069                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6070                    let prefix_range = comment_prefix_range(
6071                        snapshot.deref(),
6072                        start_row,
6073                        comment_prefix,
6074                        comment_prefix_whitespace,
6075                    );
6076                    let suffix_range = comment_suffix_range(
6077                        snapshot.deref(),
6078                        end_row,
6079                        comment_suffix.trim_start_matches(' '),
6080                        comment_suffix.starts_with(' '),
6081                    );
6082
6083                    if prefix_range.is_empty() || suffix_range.is_empty() {
6084                        edits.push((
6085                            prefix_range.start..prefix_range.start,
6086                            full_comment_prefix.clone(),
6087                        ));
6088                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6089                        suffixes_inserted.push((end_row, comment_suffix.len()));
6090                    } else {
6091                        edits.push((prefix_range, empty_str.clone()));
6092                        edits.push((suffix_range, empty_str.clone()));
6093                    }
6094                } else {
6095                    continue;
6096                }
6097            }
6098
6099            drop(snapshot);
6100            this.buffer.update(cx, |buffer, cx| {
6101                buffer.edit(edits, None, cx);
6102            });
6103
6104            // Adjust selections so that they end before any comment suffixes that
6105            // were inserted.
6106            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6107            let mut selections = this.selections.all::<Point>(cx);
6108            let snapshot = this.buffer.read(cx).read(cx);
6109            for selection in &mut selections {
6110                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6111                    match row.cmp(&selection.end.row) {
6112                        Ordering::Less => {
6113                            suffixes_inserted.next();
6114                            continue;
6115                        }
6116                        Ordering::Greater => break,
6117                        Ordering::Equal => {
6118                            if selection.end.column == snapshot.line_len(row) {
6119                                if selection.is_empty() {
6120                                    selection.start.column -= suffix_len as u32;
6121                                }
6122                                selection.end.column -= suffix_len as u32;
6123                            }
6124                            break;
6125                        }
6126                    }
6127                }
6128            }
6129
6130            drop(snapshot);
6131            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6132
6133            let selections = this.selections.all::<Point>(cx);
6134            let selections_on_single_row = selections.windows(2).all(|selections| {
6135                selections[0].start.row == selections[1].start.row
6136                    && selections[0].end.row == selections[1].end.row
6137                    && selections[0].start.row == selections[0].end.row
6138            });
6139            let selections_selecting = selections
6140                .iter()
6141                .any(|selection| selection.start != selection.end);
6142            let advance_downwards = action.advance_downwards
6143                && selections_on_single_row
6144                && !selections_selecting
6145                && this.mode != EditorMode::SingleLine;
6146
6147            if advance_downwards {
6148                let snapshot = this.buffer.read(cx).snapshot(cx);
6149
6150                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6151                    s.move_cursors_with(|display_snapshot, display_point, _| {
6152                        let mut point = display_point.to_point(display_snapshot);
6153                        point.row += 1;
6154                        point = snapshot.clip_point(point, Bias::Left);
6155                        let display_point = point.to_display_point(display_snapshot);
6156                        (display_point, SelectionGoal::Column(display_point.column()))
6157                    })
6158                });
6159            }
6160        });
6161    }
6162
6163    pub fn select_larger_syntax_node(
6164        &mut self,
6165        _: &SelectLargerSyntaxNode,
6166        cx: &mut ViewContext<Self>,
6167    ) {
6168        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6169        let buffer = self.buffer.read(cx).snapshot(cx);
6170        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6171
6172        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6173        let mut selected_larger_node = false;
6174        let new_selections = old_selections
6175            .iter()
6176            .map(|selection| {
6177                let old_range = selection.start..selection.end;
6178                let mut new_range = old_range.clone();
6179                while let Some(containing_range) =
6180                    buffer.range_for_syntax_ancestor(new_range.clone())
6181                {
6182                    new_range = containing_range;
6183                    if !display_map.intersects_fold(new_range.start)
6184                        && !display_map.intersects_fold(new_range.end)
6185                    {
6186                        break;
6187                    }
6188                }
6189
6190                selected_larger_node |= new_range != old_range;
6191                Selection {
6192                    id: selection.id,
6193                    start: new_range.start,
6194                    end: new_range.end,
6195                    goal: SelectionGoal::None,
6196                    reversed: selection.reversed,
6197                }
6198            })
6199            .collect::<Vec<_>>();
6200
6201        if selected_larger_node {
6202            stack.push(old_selections);
6203            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6204                s.select(new_selections);
6205            });
6206        }
6207        self.select_larger_syntax_node_stack = stack;
6208    }
6209
6210    pub fn select_smaller_syntax_node(
6211        &mut self,
6212        _: &SelectSmallerSyntaxNode,
6213        cx: &mut ViewContext<Self>,
6214    ) {
6215        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6216        if let Some(selections) = stack.pop() {
6217            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6218                s.select(selections.to_vec());
6219            });
6220        }
6221        self.select_larger_syntax_node_stack = stack;
6222    }
6223
6224    pub fn move_to_enclosing_bracket(
6225        &mut self,
6226        _: &MoveToEnclosingBracket,
6227        cx: &mut ViewContext<Self>,
6228    ) {
6229        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6230            s.move_offsets_with(|snapshot, selection| {
6231                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
6232                    return;
6233                };
6234
6235                let mut best_length = usize::MAX;
6236                let mut best_inside = false;
6237                let mut best_in_bracket_range = false;
6238                let mut best_destination = None;
6239                for (open, close) in enclosing_bracket_ranges {
6240                    let close = close.to_inclusive();
6241                    let length = close.end() - open.start;
6242                    let inside = selection.start >= open.end && selection.end <= *close.start();
6243                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
6244
6245                    // If best is next to a bracket and current isn't, skip
6246                    if !in_bracket_range && best_in_bracket_range {
6247                        continue;
6248                    }
6249
6250                    // Prefer smaller lengths unless best is inside and current isn't
6251                    if length > best_length && (best_inside || !inside) {
6252                        continue;
6253                    }
6254
6255                    best_length = length;
6256                    best_inside = inside;
6257                    best_in_bracket_range = in_bracket_range;
6258                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
6259                        if inside {
6260                            open.end
6261                        } else {
6262                            open.start
6263                        }
6264                    } else {
6265                        if inside {
6266                            *close.start()
6267                        } else {
6268                            *close.end()
6269                        }
6270                    });
6271                }
6272
6273                if let Some(destination) = best_destination {
6274                    selection.collapse_to(destination, SelectionGoal::None);
6275                }
6276            })
6277        });
6278    }
6279
6280    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6281        self.end_selection(cx);
6282        self.selection_history.mode = SelectionHistoryMode::Undoing;
6283        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6284            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6285            self.select_next_state = entry.select_next_state;
6286            self.select_prev_state = entry.select_prev_state;
6287            self.add_selections_state = entry.add_selections_state;
6288            self.request_autoscroll(Autoscroll::newest(), cx);
6289        }
6290        self.selection_history.mode = SelectionHistoryMode::Normal;
6291    }
6292
6293    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6294        self.end_selection(cx);
6295        self.selection_history.mode = SelectionHistoryMode::Redoing;
6296        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6297            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6298            self.select_next_state = entry.select_next_state;
6299            self.select_prev_state = entry.select_prev_state;
6300            self.add_selections_state = entry.add_selections_state;
6301            self.request_autoscroll(Autoscroll::newest(), cx);
6302        }
6303        self.selection_history.mode = SelectionHistoryMode::Normal;
6304    }
6305
6306    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6307        self.go_to_diagnostic_impl(Direction::Next, cx)
6308    }
6309
6310    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6311        self.go_to_diagnostic_impl(Direction::Prev, cx)
6312    }
6313
6314    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6315        let buffer = self.buffer.read(cx).snapshot(cx);
6316        let selection = self.selections.newest::<usize>(cx);
6317
6318        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6319        if direction == Direction::Next {
6320            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6321                let (group_id, jump_to) = popover.activation_info();
6322                if self.activate_diagnostics(group_id, cx) {
6323                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6324                        let mut new_selection = s.newest_anchor().clone();
6325                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6326                        s.select_anchors(vec![new_selection.clone()]);
6327                    });
6328                }
6329                return;
6330            }
6331        }
6332
6333        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6334            active_diagnostics
6335                .primary_range
6336                .to_offset(&buffer)
6337                .to_inclusive()
6338        });
6339        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6340            if active_primary_range.contains(&selection.head()) {
6341                *active_primary_range.end()
6342            } else {
6343                selection.head()
6344            }
6345        } else {
6346            selection.head()
6347        };
6348
6349        loop {
6350            let mut diagnostics = if direction == Direction::Prev {
6351                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6352            } else {
6353                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6354            };
6355            let group = diagnostics.find_map(|entry| {
6356                if entry.diagnostic.is_primary
6357                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6358                    && !entry.range.is_empty()
6359                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6360                {
6361                    Some((entry.range, entry.diagnostic.group_id))
6362                } else {
6363                    None
6364                }
6365            });
6366
6367            if let Some((primary_range, group_id)) = group {
6368                if self.activate_diagnostics(group_id, cx) {
6369                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6370                        s.select(vec![Selection {
6371                            id: selection.id,
6372                            start: primary_range.start,
6373                            end: primary_range.start,
6374                            reversed: false,
6375                            goal: SelectionGoal::None,
6376                        }]);
6377                    });
6378                }
6379                break;
6380            } else {
6381                // Cycle around to the start of the buffer, potentially moving back to the start of
6382                // the currently active diagnostic.
6383                active_primary_range.take();
6384                if direction == Direction::Prev {
6385                    if search_start == buffer.len() {
6386                        break;
6387                    } else {
6388                        search_start = buffer.len();
6389                    }
6390                } else if search_start == 0 {
6391                    break;
6392                } else {
6393                    search_start = 0;
6394                }
6395            }
6396        }
6397    }
6398
6399    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6400        let snapshot = self
6401            .display_map
6402            .update(cx, |display_map, cx| display_map.snapshot(cx));
6403        let selection = self.selections.newest::<Point>(cx);
6404
6405        if !self.seek_in_direction(
6406            &snapshot,
6407            selection.head(),
6408            false,
6409            snapshot
6410                .buffer_snapshot
6411                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6412            cx,
6413        ) {
6414            let wrapped_point = Point::zero();
6415            self.seek_in_direction(
6416                &snapshot,
6417                wrapped_point,
6418                true,
6419                snapshot
6420                    .buffer_snapshot
6421                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6422                cx,
6423            );
6424        }
6425    }
6426
6427    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6428        let snapshot = self
6429            .display_map
6430            .update(cx, |display_map, cx| display_map.snapshot(cx));
6431        let selection = self.selections.newest::<Point>(cx);
6432
6433        if !self.seek_in_direction(
6434            &snapshot,
6435            selection.head(),
6436            false,
6437            snapshot
6438                .buffer_snapshot
6439                .git_diff_hunks_in_range_rev(0..selection.head().row),
6440            cx,
6441        ) {
6442            let wrapped_point = snapshot.buffer_snapshot.max_point();
6443            self.seek_in_direction(
6444                &snapshot,
6445                wrapped_point,
6446                true,
6447                snapshot
6448                    .buffer_snapshot
6449                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6450                cx,
6451            );
6452        }
6453    }
6454
6455    fn seek_in_direction(
6456        &mut self,
6457        snapshot: &DisplaySnapshot,
6458        initial_point: Point,
6459        is_wrapped: bool,
6460        hunks: impl Iterator<Item = DiffHunk<u32>>,
6461        cx: &mut ViewContext<Editor>,
6462    ) -> bool {
6463        let display_point = initial_point.to_display_point(snapshot);
6464        let mut hunks = hunks
6465            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6466            .skip_while(|hunk| {
6467                if is_wrapped {
6468                    false
6469                } else {
6470                    hunk.contains_display_row(display_point.row())
6471                }
6472            })
6473            .dedup();
6474
6475        if let Some(hunk) = hunks.next() {
6476            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6477                let row = hunk.start_display_row();
6478                let point = DisplayPoint::new(row, 0);
6479                s.select_display_ranges([point..point]);
6480            });
6481
6482            true
6483        } else {
6484            false
6485        }
6486    }
6487
6488    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6489        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6490    }
6491
6492    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6493        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6494    }
6495
6496    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6497        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6498    }
6499
6500    pub fn go_to_type_definition_split(
6501        &mut self,
6502        _: &GoToTypeDefinitionSplit,
6503        cx: &mut ViewContext<Self>,
6504    ) {
6505        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6506    }
6507
6508    fn go_to_definition_of_kind(
6509        &mut self,
6510        kind: GotoDefinitionKind,
6511        split: bool,
6512        cx: &mut ViewContext<Self>,
6513    ) {
6514        let Some(workspace) = self.workspace(cx) else { return };
6515        let buffer = self.buffer.read(cx);
6516        let head = self.selections.newest::<usize>(cx).head();
6517        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6518            text_anchor
6519        } else {
6520            return;
6521        };
6522
6523        let project = workspace.read(cx).project().clone();
6524        let definitions = project.update(cx, |project, cx| match kind {
6525            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6526            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6527        });
6528
6529        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6530            let definitions = definitions.await?;
6531            editor.update(&mut cx, |editor, cx| {
6532                editor.navigate_to_definitions(definitions, split, cx);
6533            })?;
6534            Ok::<(), anyhow::Error>(())
6535        })
6536        .detach_and_log_err(cx);
6537    }
6538
6539    pub fn navigate_to_definitions(
6540        &mut self,
6541        mut definitions: Vec<LocationLink>,
6542        split: bool,
6543        cx: &mut ViewContext<Editor>,
6544    ) {
6545        let Some(workspace) = self.workspace(cx) else { return };
6546        let pane = workspace.read(cx).active_pane().clone();
6547        // If there is one definition, just open it directly
6548        if definitions.len() == 1 {
6549            let definition = definitions.pop().unwrap();
6550            let range = definition
6551                .target
6552                .range
6553                .to_offset(definition.target.buffer.read(cx));
6554
6555            let range = self.range_for_match(&range);
6556            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
6557                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6558                    s.select_ranges([range]);
6559                });
6560            } else {
6561                cx.window_context().defer(move |cx| {
6562                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
6563                        if split {
6564                            workspace.split_project_item(definition.target.buffer.clone(), cx)
6565                        } else {
6566                            workspace.open_project_item(definition.target.buffer.clone(), cx)
6567                        }
6568                    });
6569                    target_editor.update(cx, |target_editor, cx| {
6570                        // When selecting a definition in a different buffer, disable the nav history
6571                        // to avoid creating a history entry at the previous cursor location.
6572                        pane.update(cx, |pane, _| pane.disable_history());
6573                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6574                            s.select_ranges([range]);
6575                        });
6576                        pane.update(cx, |pane, _| pane.enable_history());
6577                    });
6578                });
6579            }
6580        } else if !definitions.is_empty() {
6581            let replica_id = self.replica_id(cx);
6582            cx.window_context().defer(move |cx| {
6583                let title = definitions
6584                    .iter()
6585                    .find(|definition| definition.origin.is_some())
6586                    .and_then(|definition| {
6587                        definition.origin.as_ref().map(|origin| {
6588                            let buffer = origin.buffer.read(cx);
6589                            format!(
6590                                "Definitions for {}",
6591                                buffer
6592                                    .text_for_range(origin.range.clone())
6593                                    .collect::<String>()
6594                            )
6595                        })
6596                    })
6597                    .unwrap_or("Definitions".to_owned());
6598                let locations = definitions
6599                    .into_iter()
6600                    .map(|definition| definition.target)
6601                    .collect();
6602                workspace.update(cx, |workspace, cx| {
6603                    Self::open_locations_in_multibuffer(
6604                        workspace, locations, replica_id, title, split, cx,
6605                    )
6606                });
6607            });
6608        }
6609    }
6610
6611    pub fn find_all_references(
6612        workspace: &mut Workspace,
6613        _: &FindAllReferences,
6614        cx: &mut ViewContext<Workspace>,
6615    ) -> Option<Task<Result<()>>> {
6616        let active_item = workspace.active_item(cx)?;
6617        let editor_handle = active_item.act_as::<Self>(cx)?;
6618
6619        let editor = editor_handle.read(cx);
6620        let buffer = editor.buffer.read(cx);
6621        let head = editor.selections.newest::<usize>(cx).head();
6622        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6623        let replica_id = editor.replica_id(cx);
6624
6625        let project = workspace.project().clone();
6626        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6627        Some(cx.spawn_labeled(
6628            "Finding All References...",
6629            |workspace, mut cx| async move {
6630                let locations = references.await?;
6631                if locations.is_empty() {
6632                    return Ok(());
6633                }
6634
6635                workspace.update(&mut cx, |workspace, cx| {
6636                    let title = locations
6637                        .first()
6638                        .as_ref()
6639                        .map(|location| {
6640                            let buffer = location.buffer.read(cx);
6641                            format!(
6642                                "References to `{}`",
6643                                buffer
6644                                    .text_for_range(location.range.clone())
6645                                    .collect::<String>()
6646                            )
6647                        })
6648                        .unwrap();
6649                    Self::open_locations_in_multibuffer(
6650                        workspace, locations, replica_id, title, false, cx,
6651                    );
6652                })?;
6653
6654                Ok(())
6655            },
6656        ))
6657    }
6658
6659    /// Opens a multibuffer with the given project locations in it
6660    pub fn open_locations_in_multibuffer(
6661        workspace: &mut Workspace,
6662        mut locations: Vec<Location>,
6663        replica_id: ReplicaId,
6664        title: String,
6665        split: bool,
6666        cx: &mut ViewContext<Workspace>,
6667    ) {
6668        // If there are multiple definitions, open them in a multibuffer
6669        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6670        let mut locations = locations.into_iter().peekable();
6671        let mut ranges_to_highlight = Vec::new();
6672
6673        let excerpt_buffer = cx.add_model(|cx| {
6674            let mut multibuffer = MultiBuffer::new(replica_id);
6675            while let Some(location) = locations.next() {
6676                let buffer = location.buffer.read(cx);
6677                let mut ranges_for_buffer = Vec::new();
6678                let range = location.range.to_offset(buffer);
6679                ranges_for_buffer.push(range.clone());
6680
6681                while let Some(next_location) = locations.peek() {
6682                    if next_location.buffer == location.buffer {
6683                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6684                        locations.next();
6685                    } else {
6686                        break;
6687                    }
6688                }
6689
6690                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6691                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6692                    location.buffer.clone(),
6693                    ranges_for_buffer,
6694                    1,
6695                    cx,
6696                ))
6697            }
6698
6699            multibuffer.with_title(title)
6700        });
6701
6702        let editor = cx.add_view(|cx| {
6703            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6704        });
6705        editor.update(cx, |editor, cx| {
6706            editor.highlight_background::<Self>(
6707                ranges_to_highlight,
6708                |theme| theme.editor.highlighted_line_background,
6709                cx,
6710            );
6711        });
6712        if split {
6713            workspace.split_item(Box::new(editor), cx);
6714        } else {
6715            workspace.add_item(Box::new(editor), cx);
6716        }
6717    }
6718
6719    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6720        use language::ToOffset as _;
6721
6722        let project = self.project.clone()?;
6723        let selection = self.selections.newest_anchor().clone();
6724        let (cursor_buffer, cursor_buffer_position) = self
6725            .buffer
6726            .read(cx)
6727            .text_anchor_for_position(selection.head(), cx)?;
6728        let (tail_buffer, _) = self
6729            .buffer
6730            .read(cx)
6731            .text_anchor_for_position(selection.tail(), cx)?;
6732        if tail_buffer != cursor_buffer {
6733            return None;
6734        }
6735
6736        let snapshot = cursor_buffer.read(cx).snapshot();
6737        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6738        let prepare_rename = project.update(cx, |project, cx| {
6739            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6740        });
6741
6742        Some(cx.spawn(|this, mut cx| async move {
6743            let rename_range = if let Some(range) = prepare_rename.await? {
6744                Some(range)
6745            } else {
6746                this.read_with(&cx, |this, cx| {
6747                    let buffer = this.buffer.read(cx).snapshot(cx);
6748                    let mut buffer_highlights = this
6749                        .document_highlights_for_position(selection.head(), &buffer)
6750                        .filter(|highlight| {
6751                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6752                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6753                        });
6754                    buffer_highlights
6755                        .next()
6756                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6757                })?
6758            };
6759            if let Some(rename_range) = rename_range {
6760                let rename_buffer_range = rename_range.to_offset(&snapshot);
6761                let cursor_offset_in_rename_range =
6762                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6763
6764                this.update(&mut cx, |this, cx| {
6765                    this.take_rename(false, cx);
6766                    let style = this.style(cx);
6767                    let buffer = this.buffer.read(cx).read(cx);
6768                    let cursor_offset = selection.head().to_offset(&buffer);
6769                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6770                    let rename_end = rename_start + rename_buffer_range.len();
6771                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6772                    let mut old_highlight_id = None;
6773                    let old_name: Arc<str> = buffer
6774                        .chunks(rename_start..rename_end, true)
6775                        .map(|chunk| {
6776                            if old_highlight_id.is_none() {
6777                                old_highlight_id = chunk.syntax_highlight_id;
6778                            }
6779                            chunk.text
6780                        })
6781                        .collect::<String>()
6782                        .into();
6783
6784                    drop(buffer);
6785
6786                    // Position the selection in the rename editor so that it matches the current selection.
6787                    this.show_local_selections = false;
6788                    let rename_editor = cx.add_view(|cx| {
6789                        let mut editor = Editor::single_line(None, cx);
6790                        if let Some(old_highlight_id) = old_highlight_id {
6791                            editor.override_text_style =
6792                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6793                        }
6794                        editor.buffer.update(cx, |buffer, cx| {
6795                            buffer.edit([(0..0, old_name.clone())], None, cx)
6796                        });
6797                        editor.select_all(&SelectAll, cx);
6798                        editor
6799                    });
6800
6801                    let ranges = this
6802                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6803                        .into_iter()
6804                        .flat_map(|(_, ranges)| ranges)
6805                        .chain(
6806                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6807                                .into_iter()
6808                                .flat_map(|(_, ranges)| ranges),
6809                        )
6810                        .collect();
6811
6812                    this.highlight_text::<Rename>(
6813                        ranges,
6814                        HighlightStyle {
6815                            fade_out: Some(style.rename_fade),
6816                            ..Default::default()
6817                        },
6818                        cx,
6819                    );
6820                    cx.focus(&rename_editor);
6821                    let block_id = this.insert_blocks(
6822                        [BlockProperties {
6823                            style: BlockStyle::Flex,
6824                            position: range.start.clone(),
6825                            height: 1,
6826                            render: Arc::new({
6827                                let editor = rename_editor.clone();
6828                                move |cx: &mut BlockContext| {
6829                                    ChildView::new(&editor, cx)
6830                                        .contained()
6831                                        .with_padding_left(cx.anchor_x)
6832                                        .into_any()
6833                                }
6834                            }),
6835                            disposition: BlockDisposition::Below,
6836                        }],
6837                        Some(Autoscroll::fit()),
6838                        cx,
6839                    )[0];
6840                    this.pending_rename = Some(RenameState {
6841                        range,
6842                        old_name,
6843                        editor: rename_editor,
6844                        block_id,
6845                    });
6846                })?;
6847            }
6848
6849            Ok(())
6850        }))
6851    }
6852
6853    pub fn confirm_rename(
6854        workspace: &mut Workspace,
6855        _: &ConfirmRename,
6856        cx: &mut ViewContext<Workspace>,
6857    ) -> Option<Task<Result<()>>> {
6858        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6859
6860        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6861            let rename = editor.take_rename(false, cx)?;
6862            let buffer = editor.buffer.read(cx);
6863            let (start_buffer, start) =
6864                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6865            let (end_buffer, end) =
6866                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6867            if start_buffer == end_buffer {
6868                let new_name = rename.editor.read(cx).text(cx);
6869                Some((start_buffer, start..end, rename.old_name, new_name))
6870            } else {
6871                None
6872            }
6873        })?;
6874
6875        let rename = workspace.project().clone().update(cx, |project, cx| {
6876            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6877        });
6878
6879        let editor = editor.downgrade();
6880        Some(cx.spawn(|workspace, mut cx| async move {
6881            let project_transaction = rename.await?;
6882            Self::open_project_transaction(
6883                &editor,
6884                workspace,
6885                project_transaction,
6886                format!("Rename: {}{}", old_name, new_name),
6887                cx.clone(),
6888            )
6889            .await?;
6890
6891            editor.update(&mut cx, |editor, cx| {
6892                editor.refresh_document_highlights(cx);
6893            })?;
6894            Ok(())
6895        }))
6896    }
6897
6898    fn take_rename(
6899        &mut self,
6900        moving_cursor: bool,
6901        cx: &mut ViewContext<Self>,
6902    ) -> Option<RenameState> {
6903        let rename = self.pending_rename.take()?;
6904        self.remove_blocks(
6905            [rename.block_id].into_iter().collect(),
6906            Some(Autoscroll::fit()),
6907            cx,
6908        );
6909        self.clear_text_highlights::<Rename>(cx);
6910        self.show_local_selections = true;
6911
6912        if moving_cursor {
6913            let rename_editor = rename.editor.read(cx);
6914            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6915
6916            // Update the selection to match the position of the selection inside
6917            // the rename editor.
6918            let snapshot = self.buffer.read(cx).read(cx);
6919            let rename_range = rename.range.to_offset(&snapshot);
6920            let cursor_in_editor = snapshot
6921                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6922                .min(rename_range.end);
6923            drop(snapshot);
6924
6925            self.change_selections(None, cx, |s| {
6926                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6927            });
6928        } else {
6929            self.refresh_document_highlights(cx);
6930        }
6931
6932        Some(rename)
6933    }
6934
6935    #[cfg(any(test, feature = "test-support"))]
6936    pub fn pending_rename(&self) -> Option<&RenameState> {
6937        self.pending_rename.as_ref()
6938    }
6939
6940    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6941        let project = match &self.project {
6942            Some(project) => project.clone(),
6943            None => return None,
6944        };
6945
6946        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6947    }
6948
6949    fn perform_format(
6950        &mut self,
6951        project: ModelHandle<Project>,
6952        trigger: FormatTrigger,
6953        cx: &mut ViewContext<Self>,
6954    ) -> Task<Result<()>> {
6955        let buffer = self.buffer().clone();
6956        let buffers = buffer.read(cx).all_buffers();
6957
6958        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6959        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6960
6961        cx.spawn(|_, mut cx| async move {
6962            let transaction = futures::select_biased! {
6963                _ = timeout => {
6964                    log::warn!("timed out waiting for formatting");
6965                    None
6966                }
6967                transaction = format.log_err().fuse() => transaction,
6968            };
6969
6970            buffer.update(&mut cx, |buffer, cx| {
6971                if let Some(transaction) = transaction {
6972                    if !buffer.is_singleton() {
6973                        buffer.push_transaction(&transaction.0, cx);
6974                    }
6975                }
6976
6977                cx.notify();
6978            });
6979
6980            Ok(())
6981        })
6982    }
6983
6984    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6985        if let Some(project) = self.project.clone() {
6986            self.buffer.update(cx, |multi_buffer, cx| {
6987                project.update(cx, |project, cx| {
6988                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6989                });
6990            })
6991        }
6992    }
6993
6994    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6995        cx.show_character_palette();
6996    }
6997
6998    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6999        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7000            let buffer = self.buffer.read(cx).snapshot(cx);
7001            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7002            let is_valid = buffer
7003                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7004                .any(|entry| {
7005                    entry.diagnostic.is_primary
7006                        && !entry.range.is_empty()
7007                        && entry.range.start == primary_range_start
7008                        && entry.diagnostic.message == active_diagnostics.primary_message
7009                });
7010
7011            if is_valid != active_diagnostics.is_valid {
7012                active_diagnostics.is_valid = is_valid;
7013                let mut new_styles = HashMap::default();
7014                for (block_id, diagnostic) in &active_diagnostics.blocks {
7015                    new_styles.insert(
7016                        *block_id,
7017                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7018                    );
7019                }
7020                self.display_map
7021                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7022            }
7023        }
7024    }
7025
7026    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7027        self.dismiss_diagnostics(cx);
7028        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7029            let buffer = self.buffer.read(cx).snapshot(cx);
7030
7031            let mut primary_range = None;
7032            let mut primary_message = None;
7033            let mut group_end = Point::zero();
7034            let diagnostic_group = buffer
7035                .diagnostic_group::<Point>(group_id)
7036                .map(|entry| {
7037                    if entry.range.end > group_end {
7038                        group_end = entry.range.end;
7039                    }
7040                    if entry.diagnostic.is_primary {
7041                        primary_range = Some(entry.range.clone());
7042                        primary_message = Some(entry.diagnostic.message.clone());
7043                    }
7044                    entry
7045                })
7046                .collect::<Vec<_>>();
7047            let primary_range = primary_range?;
7048            let primary_message = primary_message?;
7049            let primary_range =
7050                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7051
7052            let blocks = display_map
7053                .insert_blocks(
7054                    diagnostic_group.iter().map(|entry| {
7055                        let diagnostic = entry.diagnostic.clone();
7056                        let message_height = diagnostic.message.lines().count() as u8;
7057                        BlockProperties {
7058                            style: BlockStyle::Fixed,
7059                            position: buffer.anchor_after(entry.range.start),
7060                            height: message_height,
7061                            render: diagnostic_block_renderer(diagnostic, true),
7062                            disposition: BlockDisposition::Below,
7063                        }
7064                    }),
7065                    cx,
7066                )
7067                .into_iter()
7068                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7069                .collect();
7070
7071            Some(ActiveDiagnosticGroup {
7072                primary_range,
7073                primary_message,
7074                blocks,
7075                is_valid: true,
7076            })
7077        });
7078        self.active_diagnostics.is_some()
7079    }
7080
7081    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7082        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7083            self.display_map.update(cx, |display_map, cx| {
7084                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7085            });
7086            cx.notify();
7087        }
7088    }
7089
7090    pub fn set_selections_from_remote(
7091        &mut self,
7092        selections: Vec<Selection<Anchor>>,
7093        pending_selection: Option<Selection<Anchor>>,
7094        cx: &mut ViewContext<Self>,
7095    ) {
7096        let old_cursor_position = self.selections.newest_anchor().head();
7097        self.selections.change_with(cx, |s| {
7098            s.select_anchors(selections);
7099            if let Some(pending_selection) = pending_selection {
7100                s.set_pending(pending_selection, SelectMode::Character);
7101            } else {
7102                s.clear_pending();
7103            }
7104        });
7105        self.selections_did_change(false, &old_cursor_position, cx);
7106    }
7107
7108    fn push_to_selection_history(&mut self) {
7109        self.selection_history.push(SelectionHistoryEntry {
7110            selections: self.selections.disjoint_anchors(),
7111            select_next_state: self.select_next_state.clone(),
7112            select_prev_state: self.select_prev_state.clone(),
7113            add_selections_state: self.add_selections_state.clone(),
7114        });
7115    }
7116
7117    pub fn transact(
7118        &mut self,
7119        cx: &mut ViewContext<Self>,
7120        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7121    ) -> Option<TransactionId> {
7122        self.start_transaction_at(Instant::now(), cx);
7123        update(self, cx);
7124        self.end_transaction_at(Instant::now(), cx)
7125    }
7126
7127    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7128        self.end_selection(cx);
7129        if let Some(tx_id) = self
7130            .buffer
7131            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7132        {
7133            self.selection_history
7134                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7135        }
7136    }
7137
7138    fn end_transaction_at(
7139        &mut self,
7140        now: Instant,
7141        cx: &mut ViewContext<Self>,
7142    ) -> Option<TransactionId> {
7143        if let Some(tx_id) = self
7144            .buffer
7145            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7146        {
7147            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7148                *end_selections = Some(self.selections.disjoint_anchors());
7149            } else {
7150                error!("unexpectedly ended a transaction that wasn't started by this editor");
7151            }
7152
7153            cx.emit(Event::Edited);
7154            Some(tx_id)
7155        } else {
7156            None
7157        }
7158    }
7159
7160    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7161        let mut fold_ranges = Vec::new();
7162
7163        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7164
7165        let selections = self.selections.all::<Point>(cx);
7166        for selection in selections {
7167            let range = selection.range().sorted();
7168            let buffer_start_row = range.start.row;
7169
7170            for row in (0..=range.end.row).rev() {
7171                let fold_range = display_map.foldable_range(row);
7172
7173                if let Some(fold_range) = fold_range {
7174                    if fold_range.end.row >= buffer_start_row {
7175                        fold_ranges.push(fold_range);
7176                        if row <= range.start.row {
7177                            break;
7178                        }
7179                    }
7180                }
7181            }
7182        }
7183
7184        self.fold_ranges(fold_ranges, true, cx);
7185    }
7186
7187    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7188        let buffer_row = fold_at.buffer_row;
7189        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7190
7191        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7192            let autoscroll = self
7193                .selections
7194                .all::<Point>(cx)
7195                .iter()
7196                .any(|selection| fold_range.overlaps(&selection.range()));
7197
7198            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7199        }
7200    }
7201
7202    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7203        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7204        let buffer = &display_map.buffer_snapshot;
7205        let selections = self.selections.all::<Point>(cx);
7206        let ranges = selections
7207            .iter()
7208            .map(|s| {
7209                let range = s.display_range(&display_map).sorted();
7210                let mut start = range.start.to_point(&display_map);
7211                let mut end = range.end.to_point(&display_map);
7212                start.column = 0;
7213                end.column = buffer.line_len(end.row);
7214                start..end
7215            })
7216            .collect::<Vec<_>>();
7217
7218        self.unfold_ranges(ranges, true, true, cx);
7219    }
7220
7221    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7222        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7223
7224        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7225            ..Point::new(
7226                unfold_at.buffer_row,
7227                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7228            );
7229
7230        let autoscroll = self
7231            .selections
7232            .all::<Point>(cx)
7233            .iter()
7234            .any(|selection| selection.range().overlaps(&intersection_range));
7235
7236        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7237    }
7238
7239    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7240        let selections = self.selections.all::<Point>(cx);
7241        let ranges = selections.into_iter().map(|s| s.start..s.end);
7242        self.fold_ranges(ranges, true, cx);
7243    }
7244
7245    pub fn fold_ranges<T: ToOffset + Clone>(
7246        &mut self,
7247        ranges: impl IntoIterator<Item = Range<T>>,
7248        auto_scroll: bool,
7249        cx: &mut ViewContext<Self>,
7250    ) {
7251        let mut ranges = ranges.into_iter().peekable();
7252        if ranges.peek().is_some() {
7253            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7254
7255            if auto_scroll {
7256                self.request_autoscroll(Autoscroll::fit(), cx);
7257            }
7258
7259            cx.notify();
7260        }
7261    }
7262
7263    pub fn unfold_ranges<T: ToOffset + Clone>(
7264        &mut self,
7265        ranges: impl IntoIterator<Item = Range<T>>,
7266        inclusive: bool,
7267        auto_scroll: bool,
7268        cx: &mut ViewContext<Self>,
7269    ) {
7270        let mut ranges = ranges.into_iter().peekable();
7271        if ranges.peek().is_some() {
7272            self.display_map
7273                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7274            if auto_scroll {
7275                self.request_autoscroll(Autoscroll::fit(), cx);
7276            }
7277
7278            cx.notify();
7279        }
7280    }
7281
7282    pub fn gutter_hover(
7283        &mut self,
7284        GutterHover { hovered }: &GutterHover,
7285        cx: &mut ViewContext<Self>,
7286    ) {
7287        self.gutter_hovered = *hovered;
7288        cx.notify();
7289    }
7290
7291    pub fn insert_blocks(
7292        &mut self,
7293        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7294        autoscroll: Option<Autoscroll>,
7295        cx: &mut ViewContext<Self>,
7296    ) -> Vec<BlockId> {
7297        let blocks = self
7298            .display_map
7299            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7300        if let Some(autoscroll) = autoscroll {
7301            self.request_autoscroll(autoscroll, cx);
7302        }
7303        blocks
7304    }
7305
7306    pub fn replace_blocks(
7307        &mut self,
7308        blocks: HashMap<BlockId, RenderBlock>,
7309        autoscroll: Option<Autoscroll>,
7310        cx: &mut ViewContext<Self>,
7311    ) {
7312        self.display_map
7313            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7314        if let Some(autoscroll) = autoscroll {
7315            self.request_autoscroll(autoscroll, cx);
7316        }
7317    }
7318
7319    pub fn remove_blocks(
7320        &mut self,
7321        block_ids: HashSet<BlockId>,
7322        autoscroll: Option<Autoscroll>,
7323        cx: &mut ViewContext<Self>,
7324    ) {
7325        self.display_map.update(cx, |display_map, cx| {
7326            display_map.remove_blocks(block_ids, cx)
7327        });
7328        if let Some(autoscroll) = autoscroll {
7329            self.request_autoscroll(autoscroll, cx);
7330        }
7331    }
7332
7333    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7334        self.display_map
7335            .update(cx, |map, cx| map.snapshot(cx))
7336            .longest_row()
7337    }
7338
7339    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7340        self.display_map
7341            .update(cx, |map, cx| map.snapshot(cx))
7342            .max_point()
7343    }
7344
7345    pub fn text(&self, cx: &AppContext) -> String {
7346        self.buffer.read(cx).read(cx).text()
7347    }
7348
7349    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7350        self.transact(cx, |this, cx| {
7351            this.buffer
7352                .read(cx)
7353                .as_singleton()
7354                .expect("you can only call set_text on editors for singleton buffers")
7355                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7356        });
7357    }
7358
7359    pub fn display_text(&self, cx: &mut AppContext) -> String {
7360        self.display_map
7361            .update(cx, |map, cx| map.snapshot(cx))
7362            .text()
7363    }
7364
7365    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7366        let mut wrap_guides = smallvec::smallvec![];
7367
7368        if self.show_wrap_guides == Some(false) {
7369            return wrap_guides;
7370        }
7371
7372        let settings = self.buffer.read(cx).settings_at(0, cx);
7373        if settings.show_wrap_guides {
7374            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7375                wrap_guides.push((soft_wrap as usize, true));
7376            }
7377            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7378        }
7379
7380        wrap_guides
7381    }
7382
7383    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7384        let settings = self.buffer.read(cx).settings_at(0, cx);
7385        let mode = self
7386            .soft_wrap_mode_override
7387            .unwrap_or_else(|| settings.soft_wrap);
7388        match mode {
7389            language_settings::SoftWrap::None => SoftWrap::None,
7390            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7391            language_settings::SoftWrap::PreferredLineLength => {
7392                SoftWrap::Column(settings.preferred_line_length)
7393            }
7394        }
7395    }
7396
7397    pub fn set_soft_wrap_mode(
7398        &mut self,
7399        mode: language_settings::SoftWrap,
7400        cx: &mut ViewContext<Self>,
7401    ) {
7402        self.soft_wrap_mode_override = Some(mode);
7403        cx.notify();
7404    }
7405
7406    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7407        self.display_map
7408            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7409    }
7410
7411    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7412        if self.soft_wrap_mode_override.is_some() {
7413            self.soft_wrap_mode_override.take();
7414        } else {
7415            let soft_wrap = match self.soft_wrap_mode(cx) {
7416                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7417                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7418            };
7419            self.soft_wrap_mode_override = Some(soft_wrap);
7420        }
7421        cx.notify();
7422    }
7423
7424    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7425        self.show_gutter = show_gutter;
7426        cx.notify();
7427    }
7428
7429    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7430        self.show_wrap_guides = Some(show_gutter);
7431        cx.notify();
7432    }
7433
7434    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7435        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7436            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7437                cx.reveal_path(&file.abs_path(cx));
7438            }
7439        }
7440    }
7441
7442    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7443        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7444            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7445                if let Some(path) = file.abs_path(cx).to_str() {
7446                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7447                }
7448            }
7449        }
7450    }
7451
7452    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7453        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7454            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7455                if let Some(path) = file.path().to_str() {
7456                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7457                }
7458            }
7459        }
7460    }
7461
7462    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7463        self.highlighted_rows = rows;
7464    }
7465
7466    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7467        self.highlighted_rows.clone()
7468    }
7469
7470    pub fn highlight_background<T: 'static>(
7471        &mut self,
7472        ranges: Vec<Range<Anchor>>,
7473        color_fetcher: fn(&Theme) -> Color,
7474        cx: &mut ViewContext<Self>,
7475    ) {
7476        self.background_highlights
7477            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
7478        cx.notify();
7479    }
7480
7481    #[allow(clippy::type_complexity)]
7482    pub fn clear_background_highlights<T: 'static>(
7483        &mut self,
7484        cx: &mut ViewContext<Self>,
7485    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
7486        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7487        if highlights.is_some() {
7488            cx.notify();
7489        }
7490        highlights
7491    }
7492
7493    #[cfg(feature = "test-support")]
7494    pub fn all_background_highlights(
7495        &mut self,
7496        cx: &mut ViewContext<Self>,
7497    ) -> Vec<(Range<DisplayPoint>, Color)> {
7498        let snapshot = self.snapshot(cx);
7499        let buffer = &snapshot.buffer_snapshot;
7500        let start = buffer.anchor_before(0);
7501        let end = buffer.anchor_after(buffer.len());
7502        let theme = theme::current(cx);
7503        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7504    }
7505
7506    fn document_highlights_for_position<'a>(
7507        &'a self,
7508        position: Anchor,
7509        buffer: &'a MultiBufferSnapshot,
7510    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
7511        let read_highlights = self
7512            .background_highlights
7513            .get(&TypeId::of::<DocumentHighlightRead>())
7514            .map(|h| &h.1);
7515        let write_highlights = self
7516            .background_highlights
7517            .get(&TypeId::of::<DocumentHighlightWrite>())
7518            .map(|h| &h.1);
7519        let left_position = position.bias_left(buffer);
7520        let right_position = position.bias_right(buffer);
7521        read_highlights
7522            .into_iter()
7523            .chain(write_highlights)
7524            .flat_map(move |ranges| {
7525                let start_ix = match ranges.binary_search_by(|probe| {
7526                    let cmp = probe.end.cmp(&left_position, buffer);
7527                    if cmp.is_ge() {
7528                        Ordering::Greater
7529                    } else {
7530                        Ordering::Less
7531                    }
7532                }) {
7533                    Ok(i) | Err(i) => i,
7534                };
7535
7536                let right_position = right_position.clone();
7537                ranges[start_ix..]
7538                    .iter()
7539                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
7540            })
7541    }
7542
7543    pub fn background_highlights_in_range(
7544        &self,
7545        search_range: Range<Anchor>,
7546        display_snapshot: &DisplaySnapshot,
7547        theme: &Theme,
7548    ) -> Vec<(Range<DisplayPoint>, Color)> {
7549        let mut results = Vec::new();
7550        let buffer = &display_snapshot.buffer_snapshot;
7551        for (color_fetcher, ranges) in self.background_highlights.values() {
7552            let color = color_fetcher(theme);
7553            let start_ix = match ranges.binary_search_by(|probe| {
7554                let cmp = probe.end.cmp(&search_range.start, buffer);
7555                if cmp.is_gt() {
7556                    Ordering::Greater
7557                } else {
7558                    Ordering::Less
7559                }
7560            }) {
7561                Ok(i) | Err(i) => i,
7562            };
7563            for range in &ranges[start_ix..] {
7564                if range.start.cmp(&search_range.end, buffer).is_ge() {
7565                    break;
7566                }
7567                let start = range
7568                    .start
7569                    .to_point(buffer)
7570                    .to_display_point(display_snapshot);
7571                let end = range
7572                    .end
7573                    .to_point(buffer)
7574                    .to_display_point(display_snapshot);
7575                results.push((start..end, color))
7576            }
7577        }
7578        results
7579    }
7580    pub fn background_highlights_in_range_for<T: 'static>(
7581        &self,
7582        search_range: Range<Anchor>,
7583        display_snapshot: &DisplaySnapshot,
7584        theme: &Theme,
7585    ) -> Vec<(Range<DisplayPoint>, Color)> {
7586        let mut results = Vec::new();
7587        let buffer = &display_snapshot.buffer_snapshot;
7588        let Some((color_fetcher, ranges)) = self.background_highlights
7589            .get(&TypeId::of::<T>()) else {
7590                return vec![];
7591            };
7592
7593        let color = color_fetcher(theme);
7594        let start_ix = match ranges.binary_search_by(|probe| {
7595            let cmp = probe.end.cmp(&search_range.start, buffer);
7596            if cmp.is_gt() {
7597                Ordering::Greater
7598            } else {
7599                Ordering::Less
7600            }
7601        }) {
7602            Ok(i) | Err(i) => i,
7603        };
7604        for range in &ranges[start_ix..] {
7605            if range.start.cmp(&search_range.end, buffer).is_ge() {
7606                break;
7607            }
7608            let start = range
7609                .start
7610                .to_point(buffer)
7611                .to_display_point(display_snapshot);
7612            let end = range
7613                .end
7614                .to_point(buffer)
7615                .to_display_point(display_snapshot);
7616            results.push((start..end, color))
7617        }
7618
7619        results
7620    }
7621
7622    pub fn background_highlight_row_ranges<T: 'static>(
7623        &self,
7624        search_range: Range<Anchor>,
7625        display_snapshot: &DisplaySnapshot,
7626        count: usize,
7627    ) -> Vec<RangeInclusive<DisplayPoint>> {
7628        let mut results = Vec::new();
7629        let buffer = &display_snapshot.buffer_snapshot;
7630        let Some((_, ranges)) = self.background_highlights
7631            .get(&TypeId::of::<T>()) else {
7632                return vec![];
7633            };
7634
7635        let start_ix = match ranges.binary_search_by(|probe| {
7636            let cmp = probe.end.cmp(&search_range.start, buffer);
7637            if cmp.is_gt() {
7638                Ordering::Greater
7639            } else {
7640                Ordering::Less
7641            }
7642        }) {
7643            Ok(i) | Err(i) => i,
7644        };
7645        let mut push_region = |start: Option<Point>, end: Option<Point>| {
7646            if let (Some(start_display), Some(end_display)) = (start, end) {
7647                results.push(
7648                    start_display.to_display_point(display_snapshot)
7649                        ..=end_display.to_display_point(display_snapshot),
7650                );
7651            }
7652        };
7653        let mut start_row: Option<Point> = None;
7654        let mut end_row: Option<Point> = None;
7655        if ranges.len() > count {
7656            return vec![];
7657        }
7658        for range in &ranges[start_ix..] {
7659            if range.start.cmp(&search_range.end, buffer).is_ge() {
7660                break;
7661            }
7662            let end = range.end.to_point(buffer);
7663            if let Some(current_row) = &end_row {
7664                if end.row == current_row.row {
7665                    continue;
7666                }
7667            }
7668            let start = range.start.to_point(buffer);
7669
7670            if start_row.is_none() {
7671                assert_eq!(end_row, None);
7672                start_row = Some(start);
7673                end_row = Some(end);
7674                continue;
7675            }
7676            if let Some(current_end) = end_row.as_mut() {
7677                if start.row > current_end.row + 1 {
7678                    push_region(start_row, end_row);
7679                    start_row = Some(start);
7680                    end_row = Some(end);
7681                } else {
7682                    // Merge two hunks.
7683                    *current_end = end;
7684                }
7685            } else {
7686                unreachable!();
7687            }
7688        }
7689        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
7690        push_region(start_row, end_row);
7691        results
7692    }
7693
7694    pub fn highlight_text<T: 'static>(
7695        &mut self,
7696        ranges: Vec<Range<Anchor>>,
7697        style: HighlightStyle,
7698        cx: &mut ViewContext<Self>,
7699    ) {
7700        self.display_map.update(cx, |map, _| {
7701            map.highlight_text(TypeId::of::<T>(), ranges, style)
7702        });
7703        cx.notify();
7704    }
7705
7706    pub fn text_highlights<'a, T: 'static>(
7707        &'a self,
7708        cx: &'a AppContext,
7709    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
7710        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7711    }
7712
7713    pub fn clear_text_highlights<T: 'static>(
7714        &mut self,
7715        cx: &mut ViewContext<Self>,
7716    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
7717        let highlights = self
7718            .display_map
7719            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7720        if highlights.is_some() {
7721            cx.notify();
7722        }
7723        highlights
7724    }
7725
7726    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7727        self.blink_manager.read(cx).visible() && self.focused
7728    }
7729
7730    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7731        cx.notify();
7732    }
7733
7734    fn on_buffer_event(
7735        &mut self,
7736        multibuffer: ModelHandle<MultiBuffer>,
7737        event: &multi_buffer::Event,
7738        cx: &mut ViewContext<Self>,
7739    ) {
7740        match event {
7741            multi_buffer::Event::Edited => {
7742                self.refresh_active_diagnostics(cx);
7743                self.refresh_code_actions(cx);
7744                if self.has_active_copilot_suggestion(cx) {
7745                    self.update_visible_copilot_suggestion(cx);
7746                }
7747                cx.emit(Event::BufferEdited);
7748
7749                if let Some(project) = &self.project {
7750                    let project = project.read(cx);
7751                    let languages_affected = multibuffer
7752                        .read(cx)
7753                        .all_buffers()
7754                        .into_iter()
7755                        .filter_map(|buffer| {
7756                            let buffer = buffer.read(cx);
7757                            let language = buffer.language()?;
7758                            if project.is_local()
7759                                && project.language_servers_for_buffer(buffer, cx).count() == 0
7760                            {
7761                                None
7762                            } else {
7763                                Some(language)
7764                            }
7765                        })
7766                        .cloned()
7767                        .collect::<HashSet<_>>();
7768                    if !languages_affected.is_empty() {
7769                        self.refresh_inlay_hints(
7770                            InlayHintRefreshReason::BufferEdited(languages_affected),
7771                            cx,
7772                        );
7773                    }
7774                }
7775            }
7776            multi_buffer::Event::ExcerptsAdded {
7777                buffer,
7778                predecessor,
7779                excerpts,
7780            } => cx.emit(Event::ExcerptsAdded {
7781                buffer: buffer.clone(),
7782                predecessor: *predecessor,
7783                excerpts: excerpts.clone(),
7784            }),
7785            multi_buffer::Event::ExcerptsRemoved { ids } => {
7786                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7787            }
7788            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7789            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7790            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7791            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7792            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7793            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7794            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7795            multi_buffer::Event::DiagnosticsUpdated => {
7796                self.refresh_active_diagnostics(cx);
7797            }
7798            _ => {}
7799        };
7800    }
7801
7802    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7803        cx.notify();
7804    }
7805
7806    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7807        self.refresh_copilot_suggestions(true, cx);
7808        self.refresh_inlay_hints(
7809            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
7810                self.selections.newest_anchor().head(),
7811                &self.buffer.read(cx).snapshot(cx),
7812                cx,
7813            )),
7814            cx,
7815        );
7816    }
7817
7818    pub fn set_searchable(&mut self, searchable: bool) {
7819        self.searchable = searchable;
7820    }
7821
7822    pub fn searchable(&self) -> bool {
7823        self.searchable
7824    }
7825
7826    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
7827        let active_item = workspace.active_item(cx);
7828        let editor_handle = if let Some(editor) = active_item
7829            .as_ref()
7830            .and_then(|item| item.act_as::<Self>(cx))
7831        {
7832            editor
7833        } else {
7834            cx.propagate_action();
7835            return;
7836        };
7837
7838        let editor = editor_handle.read(cx);
7839        let buffer = editor.buffer.read(cx);
7840        if buffer.is_singleton() {
7841            cx.propagate_action();
7842            return;
7843        }
7844
7845        let mut new_selections_by_buffer = HashMap::default();
7846        for selection in editor.selections.all::<usize>(cx) {
7847            for (buffer, mut range, _) in
7848                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
7849            {
7850                if selection.reversed {
7851                    mem::swap(&mut range.start, &mut range.end);
7852                }
7853                new_selections_by_buffer
7854                    .entry(buffer)
7855                    .or_insert(Vec::new())
7856                    .push(range)
7857            }
7858        }
7859
7860        editor_handle.update(cx, |editor, cx| {
7861            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
7862        });
7863        let pane = workspace.active_pane().clone();
7864        pane.update(cx, |pane, _| pane.disable_history());
7865
7866        // We defer the pane interaction because we ourselves are a workspace item
7867        // and activating a new item causes the pane to call a method on us reentrantly,
7868        // which panics if we're on the stack.
7869        cx.defer(move |workspace, cx| {
7870            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
7871                let editor = workspace.open_project_item::<Self>(buffer, cx);
7872                editor.update(cx, |editor, cx| {
7873                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7874                        s.select_ranges(ranges);
7875                    });
7876                });
7877            }
7878
7879            pane.update(cx, |pane, _| pane.enable_history());
7880        });
7881    }
7882
7883    fn jump(
7884        workspace: &mut Workspace,
7885        path: ProjectPath,
7886        position: Point,
7887        anchor: language::Anchor,
7888        cx: &mut ViewContext<Workspace>,
7889    ) {
7890        let editor = workspace.open_path(path, None, true, cx);
7891        cx.spawn(|_, mut cx| async move {
7892            let editor = editor
7893                .await?
7894                .downcast::<Editor>()
7895                .ok_or_else(|| anyhow!("opened item was not an editor"))?
7896                .downgrade();
7897            editor.update(&mut cx, |editor, cx| {
7898                let buffer = editor
7899                    .buffer()
7900                    .read(cx)
7901                    .as_singleton()
7902                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
7903                let buffer = buffer.read(cx);
7904                let cursor = if buffer.can_resolve(&anchor) {
7905                    language::ToPoint::to_point(&anchor, buffer)
7906                } else {
7907                    buffer.clip_point(position, Bias::Left)
7908                };
7909
7910                let nav_history = editor.nav_history.take();
7911                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
7912                    s.select_ranges([cursor..cursor]);
7913                });
7914                editor.nav_history = nav_history;
7915
7916                anyhow::Ok(())
7917            })??;
7918
7919            anyhow::Ok(())
7920        })
7921        .detach_and_log_err(cx);
7922    }
7923
7924    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
7925        let snapshot = self.buffer.read(cx).read(cx);
7926        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
7927        Some(
7928            ranges
7929                .iter()
7930                .map(move |range| {
7931                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
7932                })
7933                .collect(),
7934        )
7935    }
7936
7937    fn selection_replacement_ranges(
7938        &self,
7939        range: Range<OffsetUtf16>,
7940        cx: &AppContext,
7941    ) -> Vec<Range<OffsetUtf16>> {
7942        let selections = self.selections.all::<OffsetUtf16>(cx);
7943        let newest_selection = selections
7944            .iter()
7945            .max_by_key(|selection| selection.id)
7946            .unwrap();
7947        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
7948        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
7949        let snapshot = self.buffer.read(cx).read(cx);
7950        selections
7951            .into_iter()
7952            .map(|mut selection| {
7953                selection.start.0 =
7954                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
7955                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
7956                snapshot.clip_offset_utf16(selection.start, Bias::Left)
7957                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
7958            })
7959            .collect()
7960    }
7961
7962    fn report_copilot_event(
7963        &self,
7964        suggestion_id: Option<String>,
7965        suggestion_accepted: bool,
7966        cx: &AppContext,
7967    ) {
7968        let Some(project) = &self.project else {
7969            return
7970        };
7971
7972        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7973        let file_extension = self
7974            .buffer
7975            .read(cx)
7976            .as_singleton()
7977            .and_then(|b| b.read(cx).file())
7978            .and_then(|file| Path::new(file.file_name(cx)).extension())
7979            .and_then(|e| e.to_str())
7980            .map(|a| a.to_string());
7981
7982        let telemetry = project.read(cx).client().telemetry().clone();
7983        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7984
7985        let event = ClickhouseEvent::Copilot {
7986            suggestion_id,
7987            suggestion_accepted,
7988            file_extension,
7989        };
7990        telemetry.report_clickhouse_event(event, telemetry_settings);
7991    }
7992
7993    fn report_editor_event(
7994        &self,
7995        operation: &'static str,
7996        file_extension: Option<String>,
7997        cx: &AppContext,
7998    ) {
7999        let Some(project) = &self.project else {
8000            return
8001        };
8002
8003        // If None, we are in a file without an extension
8004        let file = self
8005            .buffer
8006            .read(cx)
8007            .as_singleton()
8008            .and_then(|b| b.read(cx).file());
8009        let file_extension = file_extension.or(file
8010            .as_ref()
8011            .and_then(|file| Path::new(file.file_name(cx)).extension())
8012            .and_then(|e| e.to_str())
8013            .map(|a| a.to_string()));
8014
8015        let vim_mode = cx
8016            .global::<SettingsStore>()
8017            .raw_user_settings()
8018            .get("vim_mode")
8019            == Some(&serde_json::Value::Bool(true));
8020        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8021        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8022        let copilot_enabled_for_language = self
8023            .buffer
8024            .read(cx)
8025            .settings_at(0, cx)
8026            .show_copilot_suggestions;
8027
8028        let telemetry = project.read(cx).client().telemetry().clone();
8029        let event = ClickhouseEvent::Editor {
8030            file_extension,
8031            vim_mode,
8032            operation,
8033            copilot_enabled,
8034            copilot_enabled_for_language,
8035        };
8036        telemetry.report_clickhouse_event(event, telemetry_settings)
8037    }
8038
8039    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8040    /// with each line being an array of {text, highlight} objects.
8041    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8042        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8043            return;
8044        };
8045
8046        #[derive(Serialize)]
8047        struct Chunk<'a> {
8048            text: String,
8049            highlight: Option<&'a str>,
8050        }
8051
8052        let snapshot = buffer.read(cx).snapshot();
8053        let range = self
8054            .selected_text_range(cx)
8055            .and_then(|selected_range| {
8056                if selected_range.is_empty() {
8057                    None
8058                } else {
8059                    Some(selected_range)
8060                }
8061            })
8062            .unwrap_or_else(|| 0..snapshot.len());
8063
8064        let chunks = snapshot.chunks(range, true);
8065        let mut lines = Vec::new();
8066        let mut line: VecDeque<Chunk> = VecDeque::new();
8067
8068        let theme = &theme::current(cx).editor.syntax;
8069
8070        for chunk in chunks {
8071            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8072            let mut chunk_lines = chunk.text.split("\n").peekable();
8073            while let Some(text) = chunk_lines.next() {
8074                let mut merged_with_last_token = false;
8075                if let Some(last_token) = line.back_mut() {
8076                    if last_token.highlight == highlight {
8077                        last_token.text.push_str(text);
8078                        merged_with_last_token = true;
8079                    }
8080                }
8081
8082                if !merged_with_last_token {
8083                    line.push_back(Chunk {
8084                        text: text.into(),
8085                        highlight,
8086                    });
8087                }
8088
8089                if chunk_lines.peek().is_some() {
8090                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8091                        line.pop_front();
8092                    }
8093                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8094                        line.pop_back();
8095                    }
8096
8097                    lines.push(mem::take(&mut line));
8098                }
8099            }
8100        }
8101
8102        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
8103        cx.write_to_clipboard(ClipboardItem::new(lines));
8104    }
8105
8106    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8107        &self.inlay_hint_cache
8108    }
8109}
8110
8111fn inlay_hint_settings(
8112    location: Anchor,
8113    snapshot: &MultiBufferSnapshot,
8114    cx: &mut ViewContext<'_, '_, Editor>,
8115) -> InlayHintSettings {
8116    let file = snapshot.file_at(location);
8117    let language = snapshot.language_at(location);
8118    let settings = all_language_settings(file, cx);
8119    settings
8120        .language(language.map(|l| l.name()).as_deref())
8121        .inlay_hints
8122}
8123
8124fn consume_contiguous_rows(
8125    contiguous_row_selections: &mut Vec<Selection<Point>>,
8126    selection: &Selection<Point>,
8127    display_map: &DisplaySnapshot,
8128    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8129) -> (u32, u32) {
8130    contiguous_row_selections.push(selection.clone());
8131    let start_row = selection.start.row;
8132    let mut end_row = ending_row(selection, display_map);
8133
8134    while let Some(next_selection) = selections.peek() {
8135        if next_selection.start.row <= end_row {
8136            end_row = ending_row(next_selection, display_map);
8137            contiguous_row_selections.push(selections.next().unwrap().clone());
8138        } else {
8139            break;
8140        }
8141    }
8142    (start_row, end_row)
8143}
8144
8145fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8146    if next_selection.end.column > 0 || next_selection.is_empty() {
8147        display_map.next_line_boundary(next_selection.end).0.row + 1
8148    } else {
8149        next_selection.end.row
8150    }
8151}
8152
8153impl EditorSnapshot {
8154    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8155        self.display_snapshot.buffer_snapshot.language_at(position)
8156    }
8157
8158    pub fn is_focused(&self) -> bool {
8159        self.is_focused
8160    }
8161
8162    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8163        self.placeholder_text.as_ref()
8164    }
8165
8166    pub fn scroll_position(&self) -> Vector2F {
8167        self.scroll_anchor.scroll_position(&self.display_snapshot)
8168    }
8169}
8170
8171impl Deref for EditorSnapshot {
8172    type Target = DisplaySnapshot;
8173
8174    fn deref(&self) -> &Self::Target {
8175        &self.display_snapshot
8176    }
8177}
8178
8179#[derive(Clone, Debug, PartialEq, Eq)]
8180pub enum Event {
8181    InputIgnored {
8182        text: Arc<str>,
8183    },
8184    ExcerptsAdded {
8185        buffer: ModelHandle<Buffer>,
8186        predecessor: ExcerptId,
8187        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8188    },
8189    ExcerptsRemoved {
8190        ids: Vec<ExcerptId>,
8191    },
8192    BufferEdited,
8193    Edited,
8194    Reparsed,
8195    Focused,
8196    Blurred,
8197    DirtyChanged,
8198    Saved,
8199    TitleChanged,
8200    DiffBaseChanged,
8201    SelectionsChanged {
8202        local: bool,
8203    },
8204    ScrollPositionChanged {
8205        local: bool,
8206        autoscroll: bool,
8207    },
8208    Closed,
8209}
8210
8211pub struct EditorFocused(pub ViewHandle<Editor>);
8212pub struct EditorBlurred(pub ViewHandle<Editor>);
8213pub struct EditorReleased(pub WeakViewHandle<Editor>);
8214
8215impl Entity for Editor {
8216    type Event = Event;
8217
8218    fn release(&mut self, cx: &mut AppContext) {
8219        cx.emit_global(EditorReleased(self.handle.clone()));
8220    }
8221}
8222
8223impl View for Editor {
8224    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8225        let style = self.style(cx);
8226        let font_changed = self.display_map.update(cx, |map, cx| {
8227            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8228            map.set_font(style.text.font_id, style.text.font_size, cx)
8229        });
8230
8231        if font_changed {
8232            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8233                hide_hover(editor, cx);
8234                hide_link_definition(editor, cx);
8235            });
8236        }
8237
8238        Stack::new()
8239            .with_child(EditorElement::new(style.clone()))
8240            .with_child(ChildView::new(&self.mouse_context_menu, cx))
8241            .into_any()
8242    }
8243
8244    fn ui_name() -> &'static str {
8245        "Editor"
8246    }
8247
8248    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8249        if cx.is_self_focused() {
8250            let focused_event = EditorFocused(cx.handle());
8251            cx.emit(Event::Focused);
8252            cx.emit_global(focused_event);
8253        }
8254        if let Some(rename) = self.pending_rename.as_ref() {
8255            cx.focus(&rename.editor);
8256        } else {
8257            if !self.focused {
8258                self.blink_manager.update(cx, BlinkManager::enable);
8259            }
8260            self.focused = true;
8261            self.buffer.update(cx, |buffer, cx| {
8262                buffer.finalize_last_transaction(cx);
8263                if self.leader_replica_id.is_none() {
8264                    buffer.set_active_selections(
8265                        &self.selections.disjoint_anchors(),
8266                        self.selections.line_mode,
8267                        self.cursor_shape,
8268                        cx,
8269                    );
8270                }
8271            });
8272        }
8273    }
8274
8275    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8276        let blurred_event = EditorBlurred(cx.handle());
8277        cx.emit_global(blurred_event);
8278        self.focused = false;
8279        self.blink_manager.update(cx, BlinkManager::disable);
8280        self.buffer
8281            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8282        self.hide_context_menu(cx);
8283        hide_hover(self, cx);
8284        cx.emit(Event::Blurred);
8285        cx.notify();
8286    }
8287
8288    fn modifiers_changed(
8289        &mut self,
8290        event: &gpui::platform::ModifiersChangedEvent,
8291        cx: &mut ViewContext<Self>,
8292    ) -> bool {
8293        let pending_selection = self.has_pending_selection();
8294
8295        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
8296            if event.cmd && !pending_selection {
8297                let snapshot = self.snapshot(cx);
8298                let kind = if event.shift {
8299                    LinkDefinitionKind::Type
8300                } else {
8301                    LinkDefinitionKind::Symbol
8302                };
8303
8304                show_link_definition(kind, self, point, snapshot, cx);
8305                return false;
8306            }
8307        }
8308
8309        {
8310            if self.link_go_to_definition_state.symbol_range.is_some()
8311                || !self.link_go_to_definition_state.definitions.is_empty()
8312            {
8313                self.link_go_to_definition_state.symbol_range.take();
8314                self.link_go_to_definition_state.definitions.clear();
8315                cx.notify();
8316            }
8317
8318            self.link_go_to_definition_state.task = None;
8319
8320            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8321        }
8322
8323        false
8324    }
8325
8326    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8327        Self::reset_to_default_keymap_context(keymap);
8328        let mode = match self.mode {
8329            EditorMode::SingleLine => "single_line",
8330            EditorMode::AutoHeight { .. } => "auto_height",
8331            EditorMode::Full => "full",
8332        };
8333        keymap.add_key("mode", mode);
8334        if self.pending_rename.is_some() {
8335            keymap.add_identifier("renaming");
8336        }
8337        match self.context_menu.as_ref() {
8338            Some(ContextMenu::Completions(_)) => {
8339                keymap.add_identifier("menu");
8340                keymap.add_identifier("showing_completions")
8341            }
8342            Some(ContextMenu::CodeActions(_)) => {
8343                keymap.add_identifier("menu");
8344                keymap.add_identifier("showing_code_actions")
8345            }
8346            None => {}
8347        }
8348        for layer in self.keymap_context_layers.values() {
8349            keymap.extend(layer);
8350        }
8351
8352        if let Some(extension) = self
8353            .buffer
8354            .read(cx)
8355            .as_singleton()
8356            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8357        {
8358            keymap.add_key("extension", extension.to_string());
8359        }
8360    }
8361
8362    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8363        Some(
8364            self.buffer
8365                .read(cx)
8366                .read(cx)
8367                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8368                .collect(),
8369        )
8370    }
8371
8372    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8373        // Prevent the IME menu from appearing when holding down an alphabetic key
8374        // while input is disabled.
8375        if !self.input_enabled {
8376            return None;
8377        }
8378
8379        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8380        Some(range.start.0..range.end.0)
8381    }
8382
8383    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8384        let snapshot = self.buffer.read(cx).read(cx);
8385        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8386        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8387    }
8388
8389    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8390        self.clear_text_highlights::<InputComposition>(cx);
8391        self.ime_transaction.take();
8392    }
8393
8394    fn replace_text_in_range(
8395        &mut self,
8396        range_utf16: Option<Range<usize>>,
8397        text: &str,
8398        cx: &mut ViewContext<Self>,
8399    ) {
8400        self.transact(cx, |this, cx| {
8401            if this.input_enabled {
8402                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8403                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8404                    Some(this.selection_replacement_ranges(range_utf16, cx))
8405                } else {
8406                    this.marked_text_ranges(cx)
8407                };
8408
8409                if let Some(new_selected_ranges) = new_selected_ranges {
8410                    this.change_selections(None, cx, |selections| {
8411                        selections.select_ranges(new_selected_ranges)
8412                    });
8413                }
8414            }
8415
8416            this.handle_input(text, cx);
8417        });
8418
8419        if !self.input_enabled {
8420            return;
8421        }
8422
8423        if let Some(transaction) = self.ime_transaction {
8424            self.buffer.update(cx, |buffer, cx| {
8425                buffer.group_until_transaction(transaction, cx);
8426            });
8427        }
8428
8429        self.unmark_text(cx);
8430    }
8431
8432    fn replace_and_mark_text_in_range(
8433        &mut self,
8434        range_utf16: Option<Range<usize>>,
8435        text: &str,
8436        new_selected_range_utf16: Option<Range<usize>>,
8437        cx: &mut ViewContext<Self>,
8438    ) {
8439        if !self.input_enabled {
8440            return;
8441        }
8442
8443        let transaction = self.transact(cx, |this, cx| {
8444            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8445                let snapshot = this.buffer.read(cx).read(cx);
8446                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8447                    for marked_range in &mut marked_ranges {
8448                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8449                        marked_range.start.0 += relative_range_utf16.start;
8450                        marked_range.start =
8451                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8452                        marked_range.end =
8453                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8454                    }
8455                }
8456                Some(marked_ranges)
8457            } else if let Some(range_utf16) = range_utf16 {
8458                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8459                Some(this.selection_replacement_ranges(range_utf16, cx))
8460            } else {
8461                None
8462            };
8463
8464            if let Some(ranges) = ranges_to_replace {
8465                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8466            }
8467
8468            let marked_ranges = {
8469                let snapshot = this.buffer.read(cx).read(cx);
8470                this.selections
8471                    .disjoint_anchors()
8472                    .iter()
8473                    .map(|selection| {
8474                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8475                    })
8476                    .collect::<Vec<_>>()
8477            };
8478
8479            if text.is_empty() {
8480                this.unmark_text(cx);
8481            } else {
8482                this.highlight_text::<InputComposition>(
8483                    marked_ranges.clone(),
8484                    this.style(cx).composition_mark,
8485                    cx,
8486                );
8487            }
8488
8489            this.handle_input(text, cx);
8490
8491            if let Some(new_selected_range) = new_selected_range_utf16 {
8492                let snapshot = this.buffer.read(cx).read(cx);
8493                let new_selected_ranges = marked_ranges
8494                    .into_iter()
8495                    .map(|marked_range| {
8496                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8497                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8498                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8499                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8500                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8501                    })
8502                    .collect::<Vec<_>>();
8503
8504                drop(snapshot);
8505                this.change_selections(None, cx, |selections| {
8506                    selections.select_ranges(new_selected_ranges)
8507                });
8508            }
8509        });
8510
8511        self.ime_transaction = self.ime_transaction.or(transaction);
8512        if let Some(transaction) = self.ime_transaction {
8513            self.buffer.update(cx, |buffer, cx| {
8514                buffer.group_until_transaction(transaction, cx);
8515            });
8516        }
8517
8518        if self.text_highlights::<InputComposition>(cx).is_none() {
8519            self.ime_transaction.take();
8520        }
8521    }
8522}
8523
8524fn build_style(
8525    settings: &ThemeSettings,
8526    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8527    override_text_style: Option<&OverrideTextStyle>,
8528    cx: &AppContext,
8529) -> EditorStyle {
8530    let font_cache = cx.font_cache();
8531    let line_height_scalar = settings.line_height();
8532    let theme_id = settings.theme.meta.id;
8533    let mut theme = settings.theme.editor.clone();
8534    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8535        let field_editor_theme = get_field_editor_theme(&settings.theme);
8536        theme.text_color = field_editor_theme.text.color;
8537        theme.selection = field_editor_theme.selection;
8538        theme.background = field_editor_theme
8539            .container
8540            .background_color
8541            .unwrap_or_default();
8542        EditorStyle {
8543            text: field_editor_theme.text,
8544            placeholder_text: field_editor_theme.placeholder_text,
8545            line_height_scalar,
8546            theme,
8547            theme_id,
8548        }
8549    } else {
8550        let font_family_id = settings.buffer_font_family;
8551        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8552        let font_properties = Default::default();
8553        let font_id = font_cache
8554            .select_font(font_family_id, &font_properties)
8555            .unwrap();
8556        let font_size = settings.buffer_font_size(cx);
8557        EditorStyle {
8558            text: TextStyle {
8559                color: settings.theme.editor.text_color,
8560                font_family_name,
8561                font_family_id,
8562                font_id,
8563                font_size,
8564                font_properties,
8565                underline: Default::default(),
8566                soft_wrap: false,
8567            },
8568            placeholder_text: None,
8569            line_height_scalar,
8570            theme,
8571            theme_id,
8572        }
8573    };
8574
8575    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8576        if let Some(highlighted) = style
8577            .text
8578            .clone()
8579            .highlight(highlight_style, font_cache)
8580            .log_err()
8581        {
8582            style.text = highlighted;
8583        }
8584    }
8585
8586    style
8587}
8588
8589trait SelectionExt {
8590    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8591    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8592    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8593    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8594        -> Range<u32>;
8595}
8596
8597impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8598    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8599        let start = self.start.to_point(buffer);
8600        let end = self.end.to_point(buffer);
8601        if self.reversed {
8602            end..start
8603        } else {
8604            start..end
8605        }
8606    }
8607
8608    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8609        let start = self.start.to_offset(buffer);
8610        let end = self.end.to_offset(buffer);
8611        if self.reversed {
8612            end..start
8613        } else {
8614            start..end
8615        }
8616    }
8617
8618    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8619        let start = self
8620            .start
8621            .to_point(&map.buffer_snapshot)
8622            .to_display_point(map);
8623        let end = self
8624            .end
8625            .to_point(&map.buffer_snapshot)
8626            .to_display_point(map);
8627        if self.reversed {
8628            end..start
8629        } else {
8630            start..end
8631        }
8632    }
8633
8634    fn spanned_rows(
8635        &self,
8636        include_end_if_at_line_start: bool,
8637        map: &DisplaySnapshot,
8638    ) -> Range<u32> {
8639        let start = self.start.to_point(&map.buffer_snapshot);
8640        let mut end = self.end.to_point(&map.buffer_snapshot);
8641        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8642            end.row -= 1;
8643        }
8644
8645        let buffer_start = map.prev_line_boundary(start).0;
8646        let buffer_end = map.next_line_boundary(end).0;
8647        buffer_start.row..buffer_end.row + 1
8648    }
8649}
8650
8651impl<T: InvalidationRegion> InvalidationStack<T> {
8652    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8653    where
8654        S: Clone + ToOffset,
8655    {
8656        while let Some(region) = self.last() {
8657            let all_selections_inside_invalidation_ranges =
8658                if selections.len() == region.ranges().len() {
8659                    selections
8660                        .iter()
8661                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8662                        .all(|(selection, invalidation_range)| {
8663                            let head = selection.head().to_offset(buffer);
8664                            invalidation_range.start <= head && invalidation_range.end >= head
8665                        })
8666                } else {
8667                    false
8668                };
8669
8670            if all_selections_inside_invalidation_ranges {
8671                break;
8672            } else {
8673                self.pop();
8674            }
8675        }
8676    }
8677}
8678
8679impl<T> Default for InvalidationStack<T> {
8680    fn default() -> Self {
8681        Self(Default::default())
8682    }
8683}
8684
8685impl<T> Deref for InvalidationStack<T> {
8686    type Target = Vec<T>;
8687
8688    fn deref(&self) -> &Self::Target {
8689        &self.0
8690    }
8691}
8692
8693impl<T> DerefMut for InvalidationStack<T> {
8694    fn deref_mut(&mut self) -> &mut Self::Target {
8695        &mut self.0
8696    }
8697}
8698
8699impl InvalidationRegion for SnippetState {
8700    fn ranges(&self) -> &[Range<Anchor>] {
8701        &self.ranges[self.active_index]
8702    }
8703}
8704
8705impl Deref for EditorStyle {
8706    type Target = theme::Editor;
8707
8708    fn deref(&self) -> &Self::Target {
8709        &self.theme
8710    }
8711}
8712
8713pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8714    let mut highlighted_lines = Vec::new();
8715
8716    for (index, line) in diagnostic.message.lines().enumerate() {
8717        let line = match &diagnostic.source {
8718            Some(source) if index == 0 => {
8719                let source_highlight = Vec::from_iter(0..source.len());
8720                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8721            }
8722
8723            _ => highlight_diagnostic_message(Vec::new(), line),
8724        };
8725        highlighted_lines.push(line);
8726    }
8727    let message = diagnostic.message;
8728    Arc::new(move |cx: &mut BlockContext| {
8729        let message = message.clone();
8730        let settings = settings::get::<ThemeSettings>(cx);
8731        let tooltip_style = settings.theme.tooltip.clone();
8732        let theme = &settings.theme.editor;
8733        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8734        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8735        let anchor_x = cx.anchor_x;
8736        enum BlockContextToolip {}
8737        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
8738            Flex::column()
8739                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8740                    Label::new(
8741                        line.clone(),
8742                        style.message.clone().with_font_size(font_size),
8743                    )
8744                    .with_highlights(highlights.clone())
8745                    .contained()
8746                    .with_margin_left(anchor_x)
8747                }))
8748                .aligned()
8749                .left()
8750                .into_any()
8751        })
8752        .with_cursor_style(CursorStyle::PointingHand)
8753        .on_click(MouseButton::Left, move |_, _, cx| {
8754            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8755        })
8756        // We really need to rethink this ID system...
8757        .with_tooltip::<BlockContextToolip>(
8758            cx.block_id,
8759            "Copy diagnostic message",
8760            None,
8761            tooltip_style,
8762            cx,
8763        )
8764        .into_any()
8765    })
8766}
8767
8768pub fn highlight_diagnostic_message(
8769    initial_highlights: Vec<usize>,
8770    message: &str,
8771) -> (String, Vec<usize>) {
8772    let mut message_without_backticks = String::new();
8773    let mut prev_offset = 0;
8774    let mut inside_block = false;
8775    let mut highlights = initial_highlights;
8776    for (match_ix, (offset, _)) in message
8777        .match_indices('`')
8778        .chain([(message.len(), "")])
8779        .enumerate()
8780    {
8781        message_without_backticks.push_str(&message[prev_offset..offset]);
8782        if inside_block {
8783            highlights.extend(prev_offset - match_ix..offset - match_ix);
8784        }
8785
8786        inside_block = !inside_block;
8787        prev_offset = offset + 1;
8788    }
8789
8790    (message_without_backticks, highlights)
8791}
8792
8793pub fn diagnostic_style(
8794    severity: DiagnosticSeverity,
8795    valid: bool,
8796    theme: &theme::Editor,
8797) -> DiagnosticStyle {
8798    match (severity, valid) {
8799        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8800        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8801        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8802        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8803        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8804        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8805        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8806        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8807        _ => theme.invalid_hint_diagnostic.clone(),
8808    }
8809}
8810
8811pub fn combine_syntax_and_fuzzy_match_highlights(
8812    text: &str,
8813    default_style: HighlightStyle,
8814    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8815    match_indices: &[usize],
8816) -> Vec<(Range<usize>, HighlightStyle)> {
8817    let mut result = Vec::new();
8818    let mut match_indices = match_indices.iter().copied().peekable();
8819
8820    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8821    {
8822        syntax_highlight.weight = None;
8823
8824        // Add highlights for any fuzzy match characters before the next
8825        // syntax highlight range.
8826        while let Some(&match_index) = match_indices.peek() {
8827            if match_index >= range.start {
8828                break;
8829            }
8830            match_indices.next();
8831            let end_index = char_ix_after(match_index, text);
8832            let mut match_style = default_style;
8833            match_style.weight = Some(fonts::Weight::BOLD);
8834            result.push((match_index..end_index, match_style));
8835        }
8836
8837        if range.start == usize::MAX {
8838            break;
8839        }
8840
8841        // Add highlights for any fuzzy match characters within the
8842        // syntax highlight range.
8843        let mut offset = range.start;
8844        while let Some(&match_index) = match_indices.peek() {
8845            if match_index >= range.end {
8846                break;
8847            }
8848
8849            match_indices.next();
8850            if match_index > offset {
8851                result.push((offset..match_index, syntax_highlight));
8852            }
8853
8854            let mut end_index = char_ix_after(match_index, text);
8855            while let Some(&next_match_index) = match_indices.peek() {
8856                if next_match_index == end_index && next_match_index < range.end {
8857                    end_index = char_ix_after(next_match_index, text);
8858                    match_indices.next();
8859                } else {
8860                    break;
8861                }
8862            }
8863
8864            let mut match_style = syntax_highlight;
8865            match_style.weight = Some(fonts::Weight::BOLD);
8866            result.push((match_index..end_index, match_style));
8867            offset = end_index;
8868        }
8869
8870        if offset < range.end {
8871            result.push((offset..range.end, syntax_highlight));
8872        }
8873    }
8874
8875    fn char_ix_after(ix: usize, text: &str) -> usize {
8876        ix + text[ix..].chars().next().unwrap().len_utf8()
8877    }
8878
8879    result
8880}
8881
8882pub fn styled_runs_for_code_label<'a>(
8883    label: &'a CodeLabel,
8884    syntax_theme: &'a theme::SyntaxTheme,
8885) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8886    let fade_out = HighlightStyle {
8887        fade_out: Some(0.35),
8888        ..Default::default()
8889    };
8890
8891    let mut prev_end = label.filter_range.end;
8892    label
8893        .runs
8894        .iter()
8895        .enumerate()
8896        .flat_map(move |(ix, (range, highlight_id))| {
8897            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8898                style
8899            } else {
8900                return Default::default();
8901            };
8902            let mut muted_style = style;
8903            muted_style.highlight(fade_out);
8904
8905            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8906            if range.start >= label.filter_range.end {
8907                if range.start > prev_end {
8908                    runs.push((prev_end..range.start, fade_out));
8909                }
8910                runs.push((range.clone(), muted_style));
8911            } else if range.end <= label.filter_range.end {
8912                runs.push((range.clone(), style));
8913            } else {
8914                runs.push((range.start..label.filter_range.end, style));
8915                runs.push((label.filter_range.end..range.end, muted_style));
8916            }
8917            prev_end = cmp::max(prev_end, range.end);
8918
8919            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8920                runs.push((prev_end..label.text.len(), fade_out));
8921            }
8922
8923            runs
8924        })
8925}
8926
8927pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8928    let mut index = 0;
8929    let mut codepoints = text.char_indices().peekable();
8930
8931    std::iter::from_fn(move || {
8932        let start_index = index;
8933        while let Some((new_index, codepoint)) = codepoints.next() {
8934            index = new_index + codepoint.len_utf8();
8935            let current_upper = codepoint.is_uppercase();
8936            let next_upper = codepoints
8937                .peek()
8938                .map(|(_, c)| c.is_uppercase())
8939                .unwrap_or(false);
8940
8941            if !current_upper && next_upper {
8942                return Some(&text[start_index..index]);
8943            }
8944        }
8945
8946        index = text.len();
8947        if start_index < text.len() {
8948            return Some(&text[start_index..]);
8949        }
8950        None
8951    })
8952    .flat_map(|word| word.split_inclusive('_'))
8953}
8954
8955trait RangeToAnchorExt {
8956    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8957}
8958
8959impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8960    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8961        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8962    }
8963}