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