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