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