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