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