editor.rs

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