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