editor.rs

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