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