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