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