editor.rs

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