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::{hide_link_definition, show_link_definition, LinkGoToDefinitionState};
  68use log::error;
  69use multi_buffer::ToOffsetUtf16;
  70pub use multi_buffer::{
  71    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  72    ToPoint,
  73};
  74use ordered_float::OrderedFloat;
  75use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  76use rand::{seq::SliceRandom, thread_rng};
  77use scroll::{
  78    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  79};
  80use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  81use serde::{Deserialize, Serialize};
  82use settings::SettingsStore;
  83use smallvec::SmallVec;
  84use snippet::Snippet;
  85use std::{
  86    any::TypeId,
  87    borrow::Cow,
  88    cmp::{self, Ordering, Reverse},
  89    mem,
  90    num::NonZeroU32,
  91    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
  92    path::Path,
  93    sync::Arc,
  94    time::{Duration, Instant},
  95};
  96pub use sum_tree::Bias;
  97use text::Rope;
  98use theme::{DiagnosticStyle, Theme, ThemeSettings};
  99use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
 100use workspace::{ItemNavHistory, ViewId, Workspace};
 101
 102use crate::git::diff_hunk_to_display;
 103
 104const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 105const MAX_LINE_LEN: usize = 1024;
 106const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 107const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 108const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 109
 110pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 111
 112#[derive(Clone, Deserialize, PartialEq, Default)]
 113pub struct SelectNext {
 114    #[serde(default)]
 115    pub replace_newest: bool,
 116}
 117
 118#[derive(Clone, Deserialize, PartialEq, Default)]
 119pub struct SelectPrevious {
 120    #[serde(default)]
 121    pub replace_newest: bool,
 122}
 123
 124#[derive(Clone, Deserialize, PartialEq)]
 125pub struct SelectToBeginningOfLine {
 126    #[serde(default)]
 127    stop_at_soft_wraps: bool,
 128}
 129
 130#[derive(Clone, Default, Deserialize, PartialEq)]
 131pub struct MovePageUp {
 132    #[serde(default)]
 133    center_cursor: bool,
 134}
 135
 136#[derive(Clone, Default, Deserialize, PartialEq)]
 137pub struct MovePageDown {
 138    #[serde(default)]
 139    center_cursor: bool,
 140}
 141
 142#[derive(Clone, Deserialize, PartialEq)]
 143pub struct SelectToEndOfLine {
 144    #[serde(default)]
 145    stop_at_soft_wraps: bool,
 146}
 147
 148#[derive(Clone, Deserialize, PartialEq)]
 149pub struct ToggleCodeActions {
 150    #[serde(default)]
 151    pub deployed_from_indicator: bool,
 152}
 153
 154#[derive(Clone, Default, Deserialize, PartialEq)]
 155pub struct ConfirmCompletion {
 156    #[serde(default)]
 157    pub item_ix: Option<usize>,
 158}
 159
 160#[derive(Clone, Default, Deserialize, PartialEq)]
 161pub struct ConfirmCodeAction {
 162    #[serde(default)]
 163    pub item_ix: Option<usize>,
 164}
 165
 166#[derive(Clone, Default, Deserialize, PartialEq)]
 167pub struct ToggleComments {
 168    #[serde(default)]
 169    pub advance_downwards: bool,
 170}
 171
 172#[derive(Clone, Default, Deserialize, PartialEq)]
 173pub struct FoldAt {
 174    pub buffer_row: u32,
 175}
 176
 177#[derive(Clone, Default, Deserialize, PartialEq)]
 178pub struct UnfoldAt {
 179    pub buffer_row: u32,
 180}
 181
 182#[derive(Clone, Default, Deserialize, PartialEq)]
 183pub struct GutterHover {
 184    pub hovered: bool,
 185}
 186
 187#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 188pub enum InlayId {
 189    Suggestion(usize),
 190    Hint(usize),
 191}
 192
 193impl InlayId {
 194    fn id(&self) -> usize {
 195        match self {
 196            Self::Suggestion(id) => *id,
 197            Self::Hint(id) => *id,
 198        }
 199    }
 200}
 201
 202actions!(
 203    editor,
 204    [
 205        Cancel,
 206        Backspace,
 207        Delete,
 208        Newline,
 209        NewlineAbove,
 210        NewlineBelow,
 211        GoToDiagnostic,
 212        GoToPrevDiagnostic,
 213        GoToHunk,
 214        GoToPrevHunk,
 215        Indent,
 216        Outdent,
 217        DeleteLine,
 218        DeleteToPreviousWordStart,
 219        DeleteToPreviousSubwordStart,
 220        DeleteToNextWordEnd,
 221        DeleteToNextSubwordEnd,
 222        DeleteToBeginningOfLine,
 223        DeleteToEndOfLine,
 224        CutToEndOfLine,
 225        DuplicateLine,
 226        MoveLineUp,
 227        MoveLineDown,
 228        JoinLines,
 229        SortLinesCaseSensitive,
 230        SortLinesCaseInsensitive,
 231        ReverseLines,
 232        ShuffleLines,
 233        ConvertToUpperCase,
 234        ConvertToLowerCase,
 235        ConvertToTitleCase,
 236        ConvertToSnakeCase,
 237        ConvertToKebabCase,
 238        ConvertToUpperCamelCase,
 239        ConvertToLowerCamelCase,
 240        Transpose,
 241        Cut,
 242        Copy,
 243        Paste,
 244        Undo,
 245        Redo,
 246        MoveUp,
 247        PageUp,
 248        MoveDown,
 249        PageDown,
 250        MoveLeft,
 251        MoveRight,
 252        MoveToPreviousWordStart,
 253        MoveToPreviousSubwordStart,
 254        MoveToNextWordEnd,
 255        MoveToNextSubwordEnd,
 256        MoveToBeginningOfLine,
 257        MoveToEndOfLine,
 258        MoveToStartOfParagraph,
 259        MoveToEndOfParagraph,
 260        MoveToBeginning,
 261        MoveToEnd,
 262        SelectUp,
 263        SelectDown,
 264        SelectLeft,
 265        SelectRight,
 266        SelectToPreviousWordStart,
 267        SelectToPreviousSubwordStart,
 268        SelectToNextWordEnd,
 269        SelectToNextSubwordEnd,
 270        SelectToStartOfParagraph,
 271        SelectToEndOfParagraph,
 272        SelectToBeginning,
 273        SelectToEnd,
 274        SelectAll,
 275        SelectLine,
 276        SplitSelectionIntoLines,
 277        AddSelectionAbove,
 278        AddSelectionBelow,
 279        Tab,
 280        TabPrev,
 281        ShowCharacterPalette,
 282        SelectLargerSyntaxNode,
 283        SelectSmallerSyntaxNode,
 284        GoToDefinition,
 285        GoToDefinitionSplit,
 286        GoToTypeDefinition,
 287        GoToTypeDefinitionSplit,
 288        MoveToEnclosingBracket,
 289        UndoSelection,
 290        RedoSelection,
 291        FindAllReferences,
 292        Rename,
 293        ConfirmRename,
 294        Fold,
 295        UnfoldLines,
 296        FoldSelectedRanges,
 297        ShowCompletions,
 298        OpenExcerpts,
 299        RestartLanguageServer,
 300        Hover,
 301        Format,
 302        ToggleSoftWrap,
 303        ToggleInlayHints,
 304        RevealInFinder,
 305        CopyPath,
 306        CopyRelativePath,
 307        CopyHighlightJson,
 308    ]
 309);
 310
 311impl_actions!(
 312    editor,
 313    [
 314        SelectNext,
 315        SelectPrevious,
 316        SelectToBeginningOfLine,
 317        SelectToEndOfLine,
 318        ToggleCodeActions,
 319        MovePageUp,
 320        MovePageDown,
 321        ConfirmCompletion,
 322        ConfirmCodeAction,
 323        ToggleComments,
 324        FoldAt,
 325        UnfoldAt,
 326        GutterHover
 327    ]
 328);
 329
 330enum DocumentHighlightRead {}
 331enum DocumentHighlightWrite {}
 332enum InputComposition {}
 333
 334#[derive(Copy, Clone, PartialEq, Eq)]
 335pub enum Direction {
 336    Prev,
 337    Next,
 338}
 339
 340pub fn init_settings(cx: &mut AppContext) {
 341    settings::register::<EditorSettings>(cx);
 342}
 343
 344pub fn init(cx: &mut AppContext) {
 345    init_settings(cx);
 346    cx.add_action(Editor::new_file);
 347    cx.add_action(Editor::cancel);
 348    cx.add_action(Editor::newline);
 349    cx.add_action(Editor::newline_above);
 350    cx.add_action(Editor::newline_below);
 351    cx.add_action(Editor::backspace);
 352    cx.add_action(Editor::delete);
 353    cx.add_action(Editor::tab);
 354    cx.add_action(Editor::tab_prev);
 355    cx.add_action(Editor::indent);
 356    cx.add_action(Editor::outdent);
 357    cx.add_action(Editor::delete_line);
 358    cx.add_action(Editor::join_lines);
 359    cx.add_action(Editor::sort_lines_case_sensitive);
 360    cx.add_action(Editor::sort_lines_case_insensitive);
 361    cx.add_action(Editor::reverse_lines);
 362    cx.add_action(Editor::shuffle_lines);
 363    cx.add_action(Editor::convert_to_upper_case);
 364    cx.add_action(Editor::convert_to_lower_case);
 365    cx.add_action(Editor::convert_to_title_case);
 366    cx.add_action(Editor::convert_to_snake_case);
 367    cx.add_action(Editor::convert_to_kebab_case);
 368    cx.add_action(Editor::convert_to_upper_camel_case);
 369    cx.add_action(Editor::convert_to_lower_camel_case);
 370    cx.add_action(Editor::delete_to_previous_word_start);
 371    cx.add_action(Editor::delete_to_previous_subword_start);
 372    cx.add_action(Editor::delete_to_next_word_end);
 373    cx.add_action(Editor::delete_to_next_subword_end);
 374    cx.add_action(Editor::delete_to_beginning_of_line);
 375    cx.add_action(Editor::delete_to_end_of_line);
 376    cx.add_action(Editor::cut_to_end_of_line);
 377    cx.add_action(Editor::duplicate_line);
 378    cx.add_action(Editor::move_line_up);
 379    cx.add_action(Editor::move_line_down);
 380    cx.add_action(Editor::transpose);
 381    cx.add_action(Editor::cut);
 382    cx.add_action(Editor::copy);
 383    cx.add_action(Editor::paste);
 384    cx.add_action(Editor::undo);
 385    cx.add_action(Editor::redo);
 386    cx.add_action(Editor::move_up);
 387    cx.add_action(Editor::move_page_up);
 388    cx.add_action(Editor::move_down);
 389    cx.add_action(Editor::move_page_down);
 390    cx.add_action(Editor::next_screen);
 391    cx.add_action(Editor::move_left);
 392    cx.add_action(Editor::move_right);
 393    cx.add_action(Editor::move_to_previous_word_start);
 394    cx.add_action(Editor::move_to_previous_subword_start);
 395    cx.add_action(Editor::move_to_next_word_end);
 396    cx.add_action(Editor::move_to_next_subword_end);
 397    cx.add_action(Editor::move_to_beginning_of_line);
 398    cx.add_action(Editor::move_to_end_of_line);
 399    cx.add_action(Editor::move_to_start_of_paragraph);
 400    cx.add_action(Editor::move_to_end_of_paragraph);
 401    cx.add_action(Editor::move_to_beginning);
 402    cx.add_action(Editor::move_to_end);
 403    cx.add_action(Editor::select_up);
 404    cx.add_action(Editor::select_down);
 405    cx.add_action(Editor::select_left);
 406    cx.add_action(Editor::select_right);
 407    cx.add_action(Editor::select_to_previous_word_start);
 408    cx.add_action(Editor::select_to_previous_subword_start);
 409    cx.add_action(Editor::select_to_next_word_end);
 410    cx.add_action(Editor::select_to_next_subword_end);
 411    cx.add_action(Editor::select_to_beginning_of_line);
 412    cx.add_action(Editor::select_to_end_of_line);
 413    cx.add_action(Editor::select_to_start_of_paragraph);
 414    cx.add_action(Editor::select_to_end_of_paragraph);
 415    cx.add_action(Editor::select_to_beginning);
 416    cx.add_action(Editor::select_to_end);
 417    cx.add_action(Editor::select_all);
 418    cx.add_action(Editor::select_line);
 419    cx.add_action(Editor::split_selection_into_lines);
 420    cx.add_action(Editor::add_selection_above);
 421    cx.add_action(Editor::add_selection_below);
 422    cx.add_action(Editor::select_next);
 423    cx.add_action(Editor::select_previous);
 424    cx.add_action(Editor::toggle_comments);
 425    cx.add_action(Editor::select_larger_syntax_node);
 426    cx.add_action(Editor::select_smaller_syntax_node);
 427    cx.add_action(Editor::move_to_enclosing_bracket);
 428    cx.add_action(Editor::undo_selection);
 429    cx.add_action(Editor::redo_selection);
 430    cx.add_action(Editor::go_to_diagnostic);
 431    cx.add_action(Editor::go_to_prev_diagnostic);
 432    cx.add_action(Editor::go_to_hunk);
 433    cx.add_action(Editor::go_to_prev_hunk);
 434    cx.add_action(Editor::go_to_definition);
 435    cx.add_action(Editor::go_to_definition_split);
 436    cx.add_action(Editor::go_to_type_definition);
 437    cx.add_action(Editor::go_to_type_definition_split);
 438    cx.add_action(Editor::fold);
 439    cx.add_action(Editor::fold_at);
 440    cx.add_action(Editor::unfold_lines);
 441    cx.add_action(Editor::unfold_at);
 442    cx.add_action(Editor::gutter_hover);
 443    cx.add_action(Editor::fold_selected_ranges);
 444    cx.add_action(Editor::show_completions);
 445    cx.add_action(Editor::toggle_code_actions);
 446    cx.add_action(Editor::open_excerpts);
 447    cx.add_action(Editor::toggle_soft_wrap);
 448    cx.add_action(Editor::toggle_inlay_hints);
 449    cx.add_action(Editor::reveal_in_finder);
 450    cx.add_action(Editor::copy_path);
 451    cx.add_action(Editor::copy_relative_path);
 452    cx.add_action(Editor::copy_highlight_json);
 453    cx.add_async_action(Editor::format);
 454    cx.add_action(Editor::restart_language_server);
 455    cx.add_action(Editor::show_character_palette);
 456    cx.add_async_action(Editor::confirm_completion);
 457    cx.add_async_action(Editor::confirm_code_action);
 458    cx.add_async_action(Editor::rename);
 459    cx.add_async_action(Editor::confirm_rename);
 460    cx.add_async_action(Editor::find_all_references);
 461    cx.add_action(Editor::next_copilot_suggestion);
 462    cx.add_action(Editor::previous_copilot_suggestion);
 463    cx.add_action(Editor::copilot_suggest);
 464
 465    hover_popover::init(cx);
 466    scroll::actions::init(cx);
 467
 468    workspace::register_project_item::<Editor>(cx);
 469    workspace::register_followable_item::<Editor>(cx);
 470    workspace::register_deserializable_item::<Editor>(cx);
 471}
 472
 473trait InvalidationRegion {
 474    fn ranges(&self) -> &[Range<Anchor>];
 475}
 476
 477#[derive(Clone, Debug, PartialEq)]
 478pub enum SelectPhase {
 479    Begin {
 480        position: DisplayPoint,
 481        add: bool,
 482        click_count: usize,
 483    },
 484    BeginColumnar {
 485        position: DisplayPoint,
 486        goal_column: u32,
 487    },
 488    Extend {
 489        position: DisplayPoint,
 490        click_count: usize,
 491    },
 492    Update {
 493        position: DisplayPoint,
 494        goal_column: u32,
 495        scroll_position: Vector2F,
 496    },
 497    End,
 498}
 499
 500#[derive(Clone, Debug)]
 501pub enum SelectMode {
 502    Character,
 503    Word(Range<Anchor>),
 504    Line(Range<Anchor>),
 505    All,
 506}
 507
 508#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 509pub enum EditorMode {
 510    SingleLine,
 511    AutoHeight { max_lines: usize },
 512    Full,
 513}
 514
 515#[derive(Clone, Debug)]
 516pub enum SoftWrap {
 517    None,
 518    EditorWidth,
 519    Column(u32),
 520}
 521
 522#[derive(Clone)]
 523pub struct EditorStyle {
 524    pub text: TextStyle,
 525    pub line_height_scalar: f32,
 526    pub placeholder_text: Option<TextStyle>,
 527    pub theme: theme::Editor,
 528    pub theme_id: usize,
 529}
 530
 531type CompletionId = usize;
 532
 533type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 534type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 535
 536pub struct Editor {
 537    handle: WeakViewHandle<Self>,
 538    buffer: ModelHandle<MultiBuffer>,
 539    display_map: ModelHandle<DisplayMap>,
 540    pub selections: SelectionsCollection,
 541    pub scroll_manager: ScrollManager,
 542    columnar_selection_tail: Option<Anchor>,
 543    add_selections_state: Option<AddSelectionsState>,
 544    select_next_state: Option<SelectNextState>,
 545    select_prev_state: Option<SelectNextState>,
 546    selection_history: SelectionHistory,
 547    autoclose_regions: Vec<AutocloseRegion>,
 548    snippet_stack: InvalidationStack<SnippetState>,
 549    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 550    ime_transaction: Option<TransactionId>,
 551    active_diagnostics: Option<ActiveDiagnosticGroup>,
 552    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 553    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 554    override_text_style: Option<Box<OverrideTextStyle>>,
 555    project: Option<ModelHandle<Project>>,
 556    focused: bool,
 557    blink_manager: ModelHandle<BlinkManager>,
 558    show_local_selections: bool,
 559    mode: EditorMode,
 560    replica_id_mapping: Option<HashMap<ReplicaId, ReplicaId>>,
 561    show_gutter: bool,
 562    show_wrap_guides: Option<bool>,
 563    placeholder_text: Option<Arc<str>>,
 564    highlighted_rows: Option<Range<u32>>,
 565    #[allow(clippy::type_complexity)]
 566    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 567    nav_history: Option<ItemNavHistory>,
 568    context_menu: Option<ContextMenu>,
 569    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 570    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 571    next_completion_id: CompletionId,
 572    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 573    code_actions_task: Option<Task<()>>,
 574    document_highlights_task: Option<Task<()>>,
 575    pending_rename: Option<RenameState>,
 576    searchable: bool,
 577    cursor_shape: CursorShape,
 578    collapse_matches: bool,
 579    autoindent_mode: Option<AutoindentMode>,
 580    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 581    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 582    input_enabled: bool,
 583    read_only: bool,
 584    leader_replica_id: Option<u16>,
 585    remote_id: Option<ViewId>,
 586    hover_state: HoverState,
 587    gutter_hovered: bool,
 588    link_go_to_definition_state: LinkGoToDefinitionState,
 589    copilot_state: CopilotState,
 590    inlay_hint_cache: InlayHintCache,
 591    next_inlay_id: usize,
 592    _subscriptions: Vec<Subscription>,
 593    pixel_position_of_newest_cursor: Option<Vector2F>,
 594}
 595
 596pub struct EditorSnapshot {
 597    pub mode: EditorMode,
 598    pub show_gutter: bool,
 599    pub display_snapshot: DisplaySnapshot,
 600    pub placeholder_text: Option<Arc<str>>,
 601    is_focused: bool,
 602    scroll_anchor: ScrollAnchor,
 603    ongoing_scroll: OngoingScroll,
 604}
 605
 606#[derive(Clone, Debug)]
 607struct SelectionHistoryEntry {
 608    selections: Arc<[Selection<Anchor>]>,
 609    select_next_state: Option<SelectNextState>,
 610    select_prev_state: Option<SelectNextState>,
 611    add_selections_state: Option<AddSelectionsState>,
 612}
 613
 614enum SelectionHistoryMode {
 615    Normal,
 616    Undoing,
 617    Redoing,
 618}
 619
 620impl Default for SelectionHistoryMode {
 621    fn default() -> Self {
 622        Self::Normal
 623    }
 624}
 625
 626#[derive(Default)]
 627struct SelectionHistory {
 628    #[allow(clippy::type_complexity)]
 629    selections_by_transaction:
 630        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 631    mode: SelectionHistoryMode,
 632    undo_stack: VecDeque<SelectionHistoryEntry>,
 633    redo_stack: VecDeque<SelectionHistoryEntry>,
 634}
 635
 636impl SelectionHistory {
 637    fn insert_transaction(
 638        &mut self,
 639        transaction_id: TransactionId,
 640        selections: Arc<[Selection<Anchor>]>,
 641    ) {
 642        self.selections_by_transaction
 643            .insert(transaction_id, (selections, None));
 644    }
 645
 646    #[allow(clippy::type_complexity)]
 647    fn transaction(
 648        &self,
 649        transaction_id: TransactionId,
 650    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 651        self.selections_by_transaction.get(&transaction_id)
 652    }
 653
 654    #[allow(clippy::type_complexity)]
 655    fn transaction_mut(
 656        &mut self,
 657        transaction_id: TransactionId,
 658    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 659        self.selections_by_transaction.get_mut(&transaction_id)
 660    }
 661
 662    fn push(&mut self, entry: SelectionHistoryEntry) {
 663        if !entry.selections.is_empty() {
 664            match self.mode {
 665                SelectionHistoryMode::Normal => {
 666                    self.push_undo(entry);
 667                    self.redo_stack.clear();
 668                }
 669                SelectionHistoryMode::Undoing => self.push_redo(entry),
 670                SelectionHistoryMode::Redoing => self.push_undo(entry),
 671            }
 672        }
 673    }
 674
 675    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 676        if self
 677            .undo_stack
 678            .back()
 679            .map_or(true, |e| e.selections != entry.selections)
 680        {
 681            self.undo_stack.push_back(entry);
 682            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 683                self.undo_stack.pop_front();
 684            }
 685        }
 686    }
 687
 688    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 689        if self
 690            .redo_stack
 691            .back()
 692            .map_or(true, |e| e.selections != entry.selections)
 693        {
 694            self.redo_stack.push_back(entry);
 695            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 696                self.redo_stack.pop_front();
 697            }
 698        }
 699    }
 700}
 701
 702#[derive(Clone, Debug)]
 703struct AddSelectionsState {
 704    above: bool,
 705    stack: Vec<usize>,
 706}
 707
 708#[derive(Clone, Debug)]
 709struct SelectNextState {
 710    query: AhoCorasick,
 711    wordwise: bool,
 712    done: bool,
 713}
 714
 715#[derive(Debug)]
 716struct AutocloseRegion {
 717    selection_id: usize,
 718    range: Range<Anchor>,
 719    pair: BracketPair,
 720}
 721
 722#[derive(Debug)]
 723struct SnippetState {
 724    ranges: Vec<Vec<Range<Anchor>>>,
 725    active_index: usize,
 726}
 727
 728pub struct RenameState {
 729    pub range: Range<Anchor>,
 730    pub old_name: Arc<str>,
 731    pub editor: ViewHandle<Editor>,
 732    block_id: BlockId,
 733}
 734
 735struct InvalidationStack<T>(Vec<T>);
 736
 737enum ContextMenu {
 738    Completions(CompletionsMenu),
 739    CodeActions(CodeActionsMenu),
 740}
 741
 742impl ContextMenu {
 743    fn select_first(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 744        if self.visible() {
 745            match self {
 746                ContextMenu::Completions(menu) => menu.select_first(cx),
 747                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 748            }
 749            true
 750        } else {
 751            false
 752        }
 753    }
 754
 755    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 756        if self.visible() {
 757            match self {
 758                ContextMenu::Completions(menu) => menu.select_prev(cx),
 759                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 760            }
 761            true
 762        } else {
 763            false
 764        }
 765    }
 766
 767    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 768        if self.visible() {
 769            match self {
 770                ContextMenu::Completions(menu) => menu.select_next(cx),
 771                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 772            }
 773            true
 774        } else {
 775            false
 776        }
 777    }
 778
 779    fn select_last(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 780        if self.visible() {
 781            match self {
 782                ContextMenu::Completions(menu) => menu.select_last(cx),
 783                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 784            }
 785            true
 786        } else {
 787            false
 788        }
 789    }
 790
 791    fn visible(&self) -> bool {
 792        match self {
 793            ContextMenu::Completions(menu) => menu.visible(),
 794            ContextMenu::CodeActions(menu) => menu.visible(),
 795        }
 796    }
 797
 798    fn render(
 799        &self,
 800        cursor_position: DisplayPoint,
 801        style: EditorStyle,
 802        cx: &mut ViewContext<Editor>,
 803    ) -> (DisplayPoint, AnyElement<Editor>) {
 804        match self {
 805            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 806            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 807        }
 808    }
 809}
 810
 811struct CompletionsMenu {
 812    id: CompletionId,
 813    initial_position: Anchor,
 814    buffer: ModelHandle<Buffer>,
 815    completions: Arc<[Completion]>,
 816    match_candidates: Vec<StringMatchCandidate>,
 817    matches: Arc<[StringMatch]>,
 818    selected_item: usize,
 819    list: UniformListState,
 820}
 821
 822impl CompletionsMenu {
 823    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 824        self.selected_item = 0;
 825        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 826        cx.notify();
 827    }
 828
 829    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 830        if self.selected_item > 0 {
 831            self.selected_item -= 1;
 832            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 833        }
 834        cx.notify();
 835    }
 836
 837    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 838        if self.selected_item + 1 < self.matches.len() {
 839            self.selected_item += 1;
 840            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 841        }
 842        cx.notify();
 843    }
 844
 845    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 846        self.selected_item = self.matches.len() - 1;
 847        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 848        cx.notify();
 849    }
 850
 851    fn visible(&self) -> bool {
 852        !self.matches.is_empty()
 853    }
 854
 855    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
 856        enum CompletionTag {}
 857
 858        let completions = self.completions.clone();
 859        let matches = self.matches.clone();
 860        let selected_item = self.selected_item;
 861        let container_style = style.autocomplete.container;
 862        UniformList::new(
 863            self.list.clone(),
 864            matches.len(),
 865            cx,
 866            move |_, range, items, cx| {
 867                let start_ix = range.start;
 868                for (ix, mat) in matches[range].iter().enumerate() {
 869                    let completion = &completions[mat.candidate_id];
 870                    let item_ix = start_ix + ix;
 871                    items.push(
 872                        MouseEventHandler::new::<CompletionTag, _>(
 873                            mat.candidate_id,
 874                            cx,
 875                            |state, _| {
 876                                let item_style = if item_ix == selected_item {
 877                                    style.autocomplete.selected_item
 878                                } else if state.hovered() {
 879                                    style.autocomplete.hovered_item
 880                                } else {
 881                                    style.autocomplete.item
 882                                };
 883
 884                                Text::new(completion.label.text.clone(), style.text.clone())
 885                                    .with_soft_wrap(false)
 886                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 887                                        &completion.label.text,
 888                                        style.text.color.into(),
 889                                        styled_runs_for_code_label(
 890                                            &completion.label,
 891                                            &style.syntax,
 892                                        ),
 893                                        &mat.positions,
 894                                    ))
 895                                    .contained()
 896                                    .with_style(item_style)
 897                            },
 898                        )
 899                        .with_cursor_style(CursorStyle::PointingHand)
 900                        .on_down(MouseButton::Left, move |_, this, cx| {
 901                            this.confirm_completion(
 902                                &ConfirmCompletion {
 903                                    item_ix: Some(item_ix),
 904                                },
 905                                cx,
 906                            );
 907                        })
 908                        .into_any(),
 909                    );
 910                }
 911            },
 912        )
 913        .with_width_from_item(
 914            self.matches
 915                .iter()
 916                .enumerate()
 917                .max_by_key(|(_, mat)| {
 918                    self.completions[mat.candidate_id]
 919                        .label
 920                        .text
 921                        .chars()
 922                        .count()
 923                })
 924                .map(|(ix, _)| ix),
 925        )
 926        .contained()
 927        .with_style(container_style)
 928        .into_any()
 929    }
 930
 931    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 932        let mut matches = if let Some(query) = query {
 933            fuzzy::match_strings(
 934                &self.match_candidates,
 935                query,
 936                query.chars().any(|c| c.is_uppercase()),
 937                100,
 938                &Default::default(),
 939                executor,
 940            )
 941            .await
 942        } else {
 943            self.match_candidates
 944                .iter()
 945                .enumerate()
 946                .map(|(candidate_id, candidate)| StringMatch {
 947                    candidate_id,
 948                    score: Default::default(),
 949                    positions: Default::default(),
 950                    string: candidate.string.clone(),
 951                })
 952                .collect()
 953        };
 954
 955        //Remove all candidates where the query's start does not match the start of any word in the candidate
 956        if let Some(query) = query {
 957            if let Some(query_start) = query.chars().next() {
 958                matches.retain(|string_match| {
 959                    split_words(&string_match.string).any(|word| {
 960                        //Check that the first codepoint of the word as lowercase matches the first
 961                        //codepoint of the query as lowercase
 962                        word.chars()
 963                            .flat_map(|codepoint| codepoint.to_lowercase())
 964                            .zip(query_start.to_lowercase())
 965                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 966                    })
 967                });
 968            }
 969        }
 970
 971        matches.sort_unstable_by_key(|mat| {
 972            let completion = &self.completions[mat.candidate_id];
 973            (
 974                completion.lsp_completion.sort_text.as_ref(),
 975                Reverse(OrderedFloat(mat.score)),
 976                completion.sort_key(),
 977            )
 978        });
 979
 980        for mat in &mut matches {
 981            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 982            for position in &mut mat.positions {
 983                *position += filter_start;
 984            }
 985        }
 986
 987        self.matches = matches.into();
 988    }
 989}
 990
 991#[derive(Clone)]
 992struct CodeActionsMenu {
 993    actions: Arc<[CodeAction]>,
 994    buffer: ModelHandle<Buffer>,
 995    selected_item: usize,
 996    list: UniformListState,
 997    deployed_from_indicator: bool,
 998}
 999
1000impl CodeActionsMenu {
1001    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
1002        self.selected_item = 0;
1003        cx.notify()
1004    }
1005
1006    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
1007        if self.selected_item > 0 {
1008            self.selected_item -= 1;
1009            cx.notify()
1010        }
1011    }
1012
1013    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
1014        if self.selected_item + 1 < self.actions.len() {
1015            self.selected_item += 1;
1016            cx.notify()
1017        }
1018    }
1019
1020    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
1021        self.selected_item = self.actions.len() - 1;
1022        cx.notify()
1023    }
1024
1025    fn visible(&self) -> bool {
1026        !self.actions.is_empty()
1027    }
1028
1029    fn render(
1030        &self,
1031        mut cursor_position: DisplayPoint,
1032        style: EditorStyle,
1033        cx: &mut ViewContext<Editor>,
1034    ) -> (DisplayPoint, AnyElement<Editor>) {
1035        enum ActionTag {}
1036
1037        let container_style = style.autocomplete.container;
1038        let actions = self.actions.clone();
1039        let selected_item = self.selected_item;
1040        let element = UniformList::new(
1041            self.list.clone(),
1042            actions.len(),
1043            cx,
1044            move |_, range, items, cx| {
1045                let start_ix = range.start;
1046                for (ix, action) in actions[range].iter().enumerate() {
1047                    let item_ix = start_ix + ix;
1048                    items.push(
1049                        MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
1050                            let item_style = if item_ix == selected_item {
1051                                style.autocomplete.selected_item
1052                            } else if state.hovered() {
1053                                style.autocomplete.hovered_item
1054                            } else {
1055                                style.autocomplete.item
1056                            };
1057
1058                            Text::new(action.lsp_action.title.clone(), style.text.clone())
1059                                .with_soft_wrap(false)
1060                                .contained()
1061                                .with_style(item_style)
1062                        })
1063                        .with_cursor_style(CursorStyle::PointingHand)
1064                        .on_down(MouseButton::Left, move |_, this, cx| {
1065                            let workspace = this
1066                                .workspace
1067                                .as_ref()
1068                                .and_then(|(workspace, _)| workspace.upgrade(cx));
1069                            cx.window_context().defer(move |cx| {
1070                                if let Some(workspace) = workspace {
1071                                    workspace.update(cx, |workspace, cx| {
1072                                        if let Some(task) = Editor::confirm_code_action(
1073                                            workspace,
1074                                            &Default::default(),
1075                                            cx,
1076                                        ) {
1077                                            task.detach_and_log_err(cx);
1078                                        }
1079                                    });
1080                                }
1081                            });
1082                        })
1083                        .into_any(),
1084                    );
1085                }
1086            },
1087        )
1088        .with_width_from_item(
1089            self.actions
1090                .iter()
1091                .enumerate()
1092                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1093                .map(|(ix, _)| ix),
1094        )
1095        .contained()
1096        .with_style(container_style)
1097        .into_any();
1098
1099        if self.deployed_from_indicator {
1100            *cursor_position.column_mut() = 0;
1101        }
1102
1103        (cursor_position, element)
1104    }
1105}
1106
1107pub struct CopilotState {
1108    excerpt_id: Option<ExcerptId>,
1109    pending_refresh: Task<Option<()>>,
1110    pending_cycling_refresh: Task<Option<()>>,
1111    cycled: bool,
1112    completions: Vec<copilot::Completion>,
1113    active_completion_index: usize,
1114    suggestion: Option<Inlay>,
1115}
1116
1117impl Default for CopilotState {
1118    fn default() -> Self {
1119        Self {
1120            excerpt_id: None,
1121            pending_cycling_refresh: Task::ready(Some(())),
1122            pending_refresh: Task::ready(Some(())),
1123            completions: Default::default(),
1124            active_completion_index: 0,
1125            cycled: false,
1126            suggestion: None,
1127        }
1128    }
1129}
1130
1131impl CopilotState {
1132    fn active_completion(&self) -> Option<&copilot::Completion> {
1133        self.completions.get(self.active_completion_index)
1134    }
1135
1136    fn text_for_active_completion(
1137        &self,
1138        cursor: Anchor,
1139        buffer: &MultiBufferSnapshot,
1140    ) -> Option<&str> {
1141        use language::ToOffset as _;
1142
1143        let completion = self.active_completion()?;
1144        let excerpt_id = self.excerpt_id?;
1145        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1146        if excerpt_id != cursor.excerpt_id
1147            || !completion.range.start.is_valid(completion_buffer)
1148            || !completion.range.end.is_valid(completion_buffer)
1149        {
1150            return None;
1151        }
1152
1153        let mut completion_range = completion.range.to_offset(&completion_buffer);
1154        let prefix_len = Self::common_prefix(
1155            completion_buffer.chars_for_range(completion_range.clone()),
1156            completion.text.chars(),
1157        );
1158        completion_range.start += prefix_len;
1159        let suffix_len = Self::common_prefix(
1160            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1161            completion.text[prefix_len..].chars().rev(),
1162        );
1163        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1164
1165        if completion_range.is_empty()
1166            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1167        {
1168            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1169        } else {
1170            None
1171        }
1172    }
1173
1174    fn cycle_completions(&mut self, direction: Direction) {
1175        match direction {
1176            Direction::Prev => {
1177                self.active_completion_index = if self.active_completion_index == 0 {
1178                    self.completions.len().saturating_sub(1)
1179                } else {
1180                    self.active_completion_index - 1
1181                };
1182            }
1183            Direction::Next => {
1184                if self.completions.len() == 0 {
1185                    self.active_completion_index = 0
1186                } else {
1187                    self.active_completion_index =
1188                        (self.active_completion_index + 1) % self.completions.len();
1189                }
1190            }
1191        }
1192    }
1193
1194    fn push_completion(&mut self, new_completion: copilot::Completion) {
1195        for completion in &self.completions {
1196            if completion.text == new_completion.text && completion.range == new_completion.range {
1197                return;
1198            }
1199        }
1200        self.completions.push(new_completion);
1201    }
1202
1203    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1204        a.zip(b)
1205            .take_while(|(a, b)| a == b)
1206            .map(|(a, _)| a.len_utf8())
1207            .sum()
1208    }
1209}
1210
1211#[derive(Debug)]
1212struct ActiveDiagnosticGroup {
1213    primary_range: Range<Anchor>,
1214    primary_message: String,
1215    blocks: HashMap<BlockId, Diagnostic>,
1216    is_valid: bool,
1217}
1218
1219#[derive(Serialize, Deserialize)]
1220pub struct ClipboardSelection {
1221    pub len: usize,
1222    pub is_entire_line: bool,
1223    pub first_line_indent: u32,
1224}
1225
1226#[derive(Debug)]
1227pub struct NavigationData {
1228    cursor_anchor: Anchor,
1229    cursor_position: Point,
1230    scroll_anchor: ScrollAnchor,
1231    scroll_top_row: u32,
1232}
1233
1234pub struct EditorCreated(pub ViewHandle<Editor>);
1235
1236enum GotoDefinitionKind {
1237    Symbol,
1238    Type,
1239}
1240
1241#[derive(Debug, Clone)]
1242enum InlayHintRefreshReason {
1243    Toggle(bool),
1244    SettingsChange(InlayHintSettings),
1245    NewLinesShown,
1246    BufferEdited(HashSet<Arc<Language>>),
1247    RefreshRequested,
1248}
1249
1250impl Editor {
1251    pub fn single_line(
1252        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1253        cx: &mut ViewContext<Self>,
1254    ) -> Self {
1255        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1256        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1257        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1258    }
1259
1260    pub fn multi_line(
1261        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1262        cx: &mut ViewContext<Self>,
1263    ) -> Self {
1264        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1265        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1266        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1267    }
1268
1269    pub fn auto_height(
1270        max_lines: usize,
1271        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1272        cx: &mut ViewContext<Self>,
1273    ) -> Self {
1274        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1275        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1276        Self::new(
1277            EditorMode::AutoHeight { max_lines },
1278            buffer,
1279            None,
1280            field_editor_style,
1281            cx,
1282        )
1283    }
1284
1285    pub fn for_buffer(
1286        buffer: ModelHandle<Buffer>,
1287        project: Option<ModelHandle<Project>>,
1288        cx: &mut ViewContext<Self>,
1289    ) -> Self {
1290        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1291        Self::new(EditorMode::Full, buffer, project, None, cx)
1292    }
1293
1294    pub fn for_multibuffer(
1295        buffer: ModelHandle<MultiBuffer>,
1296        project: Option<ModelHandle<Project>>,
1297        cx: &mut ViewContext<Self>,
1298    ) -> Self {
1299        Self::new(EditorMode::Full, buffer, project, None, cx)
1300    }
1301
1302    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1303        let mut clone = Self::new(
1304            self.mode,
1305            self.buffer.clone(),
1306            self.project.clone(),
1307            self.get_field_editor_theme.clone(),
1308            cx,
1309        );
1310        self.display_map.update(cx, |display_map, cx| {
1311            let snapshot = display_map.snapshot(cx);
1312            clone.display_map.update(cx, |display_map, cx| {
1313                display_map.set_state(&snapshot, cx);
1314            });
1315        });
1316        clone.selections.clone_state(&self.selections);
1317        clone.scroll_manager.clone_state(&self.scroll_manager);
1318        clone.searchable = self.searchable;
1319        clone
1320    }
1321
1322    fn new(
1323        mode: EditorMode,
1324        buffer: ModelHandle<MultiBuffer>,
1325        project: Option<ModelHandle<Project>>,
1326        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1327        cx: &mut ViewContext<Self>,
1328    ) -> Self {
1329        let editor_view_id = cx.view_id();
1330        let display_map = cx.add_model(|cx| {
1331            let settings = settings::get::<ThemeSettings>(cx);
1332            let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
1333            DisplayMap::new(
1334                buffer.clone(),
1335                style.text.font_id,
1336                style.text.font_size,
1337                None,
1338                2,
1339                1,
1340                cx,
1341            )
1342        });
1343
1344        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1345
1346        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1347
1348        let soft_wrap_mode_override =
1349            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1350
1351        let mut project_subscriptions = Vec::new();
1352        if mode == EditorMode::Full {
1353            if let Some(project) = project.as_ref() {
1354                if buffer.read(cx).is_singleton() {
1355                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
1356                        cx.emit(Event::TitleChanged);
1357                    }));
1358                }
1359                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
1360                    if let project::Event::RefreshInlayHints = event {
1361                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
1362                    };
1363                }));
1364            }
1365        }
1366
1367        let inlay_hint_settings = inlay_hint_settings(
1368            selections.newest_anchor().head(),
1369            &buffer.read(cx).snapshot(cx),
1370            cx,
1371        );
1372
1373        let mut this = Self {
1374            handle: cx.weak_handle(),
1375            buffer: buffer.clone(),
1376            display_map: display_map.clone(),
1377            selections,
1378            scroll_manager: ScrollManager::new(),
1379            columnar_selection_tail: None,
1380            add_selections_state: None,
1381            select_next_state: None,
1382            select_prev_state: None,
1383            selection_history: Default::default(),
1384            autoclose_regions: Default::default(),
1385            snippet_stack: Default::default(),
1386            select_larger_syntax_node_stack: Vec::new(),
1387            ime_transaction: Default::default(),
1388            active_diagnostics: None,
1389            soft_wrap_mode_override,
1390            get_field_editor_theme,
1391            project,
1392            focused: false,
1393            blink_manager: blink_manager.clone(),
1394            show_local_selections: true,
1395            mode,
1396            replica_id_mapping: None,
1397            show_gutter: mode == EditorMode::Full,
1398            show_wrap_guides: None,
1399            placeholder_text: None,
1400            highlighted_rows: None,
1401            background_highlights: Default::default(),
1402            nav_history: None,
1403            context_menu: None,
1404            mouse_context_menu: cx
1405                .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
1406            completion_tasks: Default::default(),
1407            next_completion_id: 0,
1408            next_inlay_id: 0,
1409            available_code_actions: Default::default(),
1410            code_actions_task: Default::default(),
1411            document_highlights_task: Default::default(),
1412            pending_rename: Default::default(),
1413            searchable: true,
1414            override_text_style: None,
1415            cursor_shape: Default::default(),
1416            autoindent_mode: Some(AutoindentMode::EachLine),
1417            collapse_matches: false,
1418            workspace: None,
1419            keymap_context_layers: Default::default(),
1420            input_enabled: true,
1421            read_only: false,
1422            leader_replica_id: None,
1423            remote_id: None,
1424            hover_state: Default::default(),
1425            link_go_to_definition_state: Default::default(),
1426            copilot_state: Default::default(),
1427            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
1428            gutter_hovered: false,
1429            pixel_position_of_newest_cursor: None,
1430            _subscriptions: vec![
1431                cx.observe(&buffer, Self::on_buffer_changed),
1432                cx.subscribe(&buffer, Self::on_buffer_event),
1433                cx.observe(&display_map, Self::on_display_map_changed),
1434                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1435                cx.observe_global::<SettingsStore, _>(Self::settings_changed),
1436            ],
1437        };
1438
1439        this._subscriptions.extend(project_subscriptions);
1440
1441        this.end_selection(cx);
1442        this.scroll_manager.show_scrollbar(cx);
1443
1444        let editor_created_event = EditorCreated(cx.handle());
1445        cx.emit_global(editor_created_event);
1446
1447        if mode == EditorMode::Full {
1448            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1449            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1450        }
1451
1452        this.report_editor_event("open", None, cx);
1453        this
1454    }
1455
1456    pub fn new_file(
1457        workspace: &mut Workspace,
1458        _: &workspace::NewFile,
1459        cx: &mut ViewContext<Workspace>,
1460    ) {
1461        let project = workspace.project().clone();
1462        if project.read(cx).is_remote() {
1463            cx.propagate_action();
1464        } else if let Some(buffer) = project
1465            .update(cx, |project, cx| project.create_buffer("", None, cx))
1466            .log_err()
1467        {
1468            workspace.add_item(
1469                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1470                cx,
1471            );
1472        }
1473    }
1474
1475    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1476        self.buffer.read(cx).replica_id()
1477    }
1478
1479    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1480        self.leader_replica_id
1481    }
1482
1483    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1484        &self.buffer
1485    }
1486
1487    fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
1488        self.workspace.as_ref()?.0.upgrade(cx)
1489    }
1490
1491    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1492        self.buffer().read(cx).title(cx)
1493    }
1494
1495    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1496        EditorSnapshot {
1497            mode: self.mode,
1498            show_gutter: self.show_gutter,
1499            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1500            scroll_anchor: self.scroll_manager.anchor(),
1501            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1502            placeholder_text: self.placeholder_text.clone(),
1503            is_focused: self
1504                .handle
1505                .upgrade(cx)
1506                .map_or(false, |handle| handle.is_focused(cx)),
1507        }
1508    }
1509
1510    pub fn language_at<'a, T: ToOffset>(
1511        &self,
1512        point: T,
1513        cx: &'a AppContext,
1514    ) -> Option<Arc<Language>> {
1515        self.buffer.read(cx).language_at(point, cx)
1516    }
1517
1518    pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
1519        self.buffer.read(cx).read(cx).file_at(point).cloned()
1520    }
1521
1522    pub fn active_excerpt(
1523        &self,
1524        cx: &AppContext,
1525    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1526        self.buffer
1527            .read(cx)
1528            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1529    }
1530
1531    fn style(&self, cx: &AppContext) -> EditorStyle {
1532        build_style(
1533            settings::get::<ThemeSettings>(cx),
1534            self.get_field_editor_theme.as_deref(),
1535            self.override_text_style.as_deref(),
1536            cx,
1537        )
1538    }
1539
1540    pub fn mode(&self) -> EditorMode {
1541        self.mode
1542    }
1543
1544    pub fn set_placeholder_text(
1545        &mut self,
1546        placeholder_text: impl Into<Arc<str>>,
1547        cx: &mut ViewContext<Self>,
1548    ) {
1549        self.placeholder_text = Some(placeholder_text.into());
1550        cx.notify();
1551    }
1552
1553    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1554        self.cursor_shape = cursor_shape;
1555        cx.notify();
1556    }
1557
1558    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
1559        self.collapse_matches = collapse_matches;
1560    }
1561
1562    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
1563        if self.collapse_matches {
1564            return range.start..range.start;
1565        }
1566        range.clone()
1567    }
1568
1569    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1570        if self.display_map.read(cx).clip_at_line_ends != clip {
1571            self.display_map
1572                .update(cx, |map, _| map.clip_at_line_ends = clip);
1573        }
1574    }
1575
1576    pub fn set_keymap_context_layer<Tag: 'static>(
1577        &mut self,
1578        context: KeymapContext,
1579        cx: &mut ViewContext<Self>,
1580    ) {
1581        self.keymap_context_layers
1582            .insert(TypeId::of::<Tag>(), context);
1583        cx.notify();
1584    }
1585
1586    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1587        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1588        cx.notify();
1589    }
1590
1591    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1592        self.input_enabled = input_enabled;
1593    }
1594
1595    pub fn set_autoindent(&mut self, autoindent: bool) {
1596        if autoindent {
1597            self.autoindent_mode = Some(AutoindentMode::EachLine);
1598        } else {
1599            self.autoindent_mode = None;
1600        }
1601    }
1602
1603    pub fn set_read_only(&mut self, read_only: bool) {
1604        self.read_only = read_only;
1605    }
1606
1607    pub fn replica_id_map(&self) -> Option<&HashMap<ReplicaId, ReplicaId>> {
1608        self.replica_id_mapping.as_ref()
1609    }
1610
1611    pub fn set_replica_id_map(
1612        &mut self,
1613        mapping: Option<HashMap<ReplicaId, ReplicaId>>,
1614        cx: &mut ViewContext<Self>,
1615    ) {
1616        self.replica_id_mapping = mapping;
1617        cx.notify();
1618    }
1619
1620    fn selections_did_change(
1621        &mut self,
1622        local: bool,
1623        old_cursor_position: &Anchor,
1624        cx: &mut ViewContext<Self>,
1625    ) {
1626        if self.focused && self.leader_replica_id.is_none() {
1627            self.buffer.update(cx, |buffer, cx| {
1628                buffer.set_active_selections(
1629                    &self.selections.disjoint_anchors(),
1630                    self.selections.line_mode,
1631                    self.cursor_shape,
1632                    cx,
1633                )
1634            });
1635        }
1636
1637        let display_map = self
1638            .display_map
1639            .update(cx, |display_map, cx| display_map.snapshot(cx));
1640        let buffer = &display_map.buffer_snapshot;
1641        self.add_selections_state = None;
1642        self.select_next_state = None;
1643        self.select_prev_state = None;
1644        self.select_larger_syntax_node_stack.clear();
1645        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1646        self.snippet_stack
1647            .invalidate(&self.selections.disjoint_anchors(), buffer);
1648        self.take_rename(false, cx);
1649
1650        let new_cursor_position = self.selections.newest_anchor().head();
1651
1652        self.push_to_nav_history(
1653            old_cursor_position.clone(),
1654            Some(new_cursor_position.to_point(buffer)),
1655            cx,
1656        );
1657
1658        if local {
1659            let new_cursor_position = self.selections.newest_anchor().head();
1660            let completion_menu = match self.context_menu.as_mut() {
1661                Some(ContextMenu::Completions(menu)) => Some(menu),
1662                _ => {
1663                    self.context_menu.take();
1664                    None
1665                }
1666            };
1667
1668            if let Some(completion_menu) = completion_menu {
1669                let cursor_position = new_cursor_position.to_offset(buffer);
1670                let (word_range, kind) =
1671                    buffer.surrounding_word(completion_menu.initial_position.clone());
1672                if kind == Some(CharKind::Word)
1673                    && word_range.to_inclusive().contains(&cursor_position)
1674                {
1675                    let query = Self::completion_query(buffer, cursor_position);
1676                    cx.background()
1677                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1678                    self.show_completions(&ShowCompletions, cx);
1679                } else {
1680                    self.hide_context_menu(cx);
1681                }
1682            }
1683
1684            hide_hover(self, cx);
1685
1686            if old_cursor_position.to_display_point(&display_map).row()
1687                != new_cursor_position.to_display_point(&display_map).row()
1688            {
1689                self.available_code_actions.take();
1690            }
1691            self.refresh_code_actions(cx);
1692            self.refresh_document_highlights(cx);
1693            refresh_matching_bracket_highlights(self, cx);
1694            self.discard_copilot_suggestion(cx);
1695        }
1696
1697        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1698        cx.emit(Event::SelectionsChanged { local });
1699        cx.notify();
1700    }
1701
1702    pub fn change_selections<R>(
1703        &mut self,
1704        autoscroll: Option<Autoscroll>,
1705        cx: &mut ViewContext<Self>,
1706        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1707    ) -> R {
1708        let old_cursor_position = self.selections.newest_anchor().head();
1709        self.push_to_selection_history();
1710
1711        let (changed, result) = self.selections.change_with(cx, change);
1712
1713        if changed {
1714            if let Some(autoscroll) = autoscroll {
1715                self.request_autoscroll(autoscroll, cx);
1716            }
1717            self.selections_did_change(true, &old_cursor_position, cx);
1718        }
1719
1720        result
1721    }
1722
1723    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1724    where
1725        I: IntoIterator<Item = (Range<S>, T)>,
1726        S: ToOffset,
1727        T: Into<Arc<str>>,
1728    {
1729        if self.read_only {
1730            return;
1731        }
1732
1733        self.buffer
1734            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1735    }
1736
1737    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1738    where
1739        I: IntoIterator<Item = (Range<S>, T)>,
1740        S: ToOffset,
1741        T: Into<Arc<str>>,
1742    {
1743        if self.read_only {
1744            return;
1745        }
1746
1747        self.buffer.update(cx, |buffer, cx| {
1748            buffer.edit(edits, self.autoindent_mode.clone(), cx)
1749        });
1750    }
1751
1752    pub fn edit_with_block_indent<I, S, T>(
1753        &mut self,
1754        edits: I,
1755        original_indent_columns: Vec<u32>,
1756        cx: &mut ViewContext<Self>,
1757    ) where
1758        I: IntoIterator<Item = (Range<S>, T)>,
1759        S: ToOffset,
1760        T: Into<Arc<str>>,
1761    {
1762        if self.read_only {
1763            return;
1764        }
1765
1766        self.buffer.update(cx, |buffer, cx| {
1767            buffer.edit(
1768                edits,
1769                Some(AutoindentMode::Block {
1770                    original_indent_columns,
1771                }),
1772                cx,
1773            )
1774        });
1775    }
1776
1777    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
1778        self.hide_context_menu(cx);
1779
1780        match phase {
1781            SelectPhase::Begin {
1782                position,
1783                add,
1784                click_count,
1785            } => self.begin_selection(position, add, click_count, cx),
1786            SelectPhase::BeginColumnar {
1787                position,
1788                goal_column,
1789            } => self.begin_columnar_selection(position, goal_column, cx),
1790            SelectPhase::Extend {
1791                position,
1792                click_count,
1793            } => self.extend_selection(position, click_count, cx),
1794            SelectPhase::Update {
1795                position,
1796                goal_column,
1797                scroll_position,
1798            } => self.update_selection(position, goal_column, scroll_position, cx),
1799            SelectPhase::End => self.end_selection(cx),
1800        }
1801    }
1802
1803    fn extend_selection(
1804        &mut self,
1805        position: DisplayPoint,
1806        click_count: usize,
1807        cx: &mut ViewContext<Self>,
1808    ) {
1809        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1810        let tail = self.selections.newest::<usize>(cx).tail();
1811        self.begin_selection(position, false, click_count, cx);
1812
1813        let position = position.to_offset(&display_map, Bias::Left);
1814        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1815
1816        let mut pending_selection = self
1817            .selections
1818            .pending_anchor()
1819            .expect("extend_selection not called with pending selection");
1820        if position >= tail {
1821            pending_selection.start = tail_anchor;
1822        } else {
1823            pending_selection.end = tail_anchor;
1824            pending_selection.reversed = true;
1825        }
1826
1827        let mut pending_mode = self.selections.pending_mode().unwrap();
1828        match &mut pending_mode {
1829            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1830            _ => {}
1831        }
1832
1833        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1834            s.set_pending(pending_selection, pending_mode)
1835        });
1836    }
1837
1838    fn begin_selection(
1839        &mut self,
1840        position: DisplayPoint,
1841        add: bool,
1842        click_count: usize,
1843        cx: &mut ViewContext<Self>,
1844    ) {
1845        if !self.focused {
1846            cx.focus_self();
1847        }
1848
1849        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1850        let buffer = &display_map.buffer_snapshot;
1851        let newest_selection = self.selections.newest_anchor().clone();
1852        let position = display_map.clip_point(position, Bias::Left);
1853
1854        let start;
1855        let end;
1856        let mode;
1857        let auto_scroll;
1858        match click_count {
1859            1 => {
1860                start = buffer.anchor_before(position.to_point(&display_map));
1861                end = start.clone();
1862                mode = SelectMode::Character;
1863                auto_scroll = true;
1864            }
1865            2 => {
1866                let range = movement::surrounding_word(&display_map, position);
1867                start = buffer.anchor_before(range.start.to_point(&display_map));
1868                end = buffer.anchor_before(range.end.to_point(&display_map));
1869                mode = SelectMode::Word(start.clone()..end.clone());
1870                auto_scroll = true;
1871            }
1872            3 => {
1873                let position = display_map
1874                    .clip_point(position, Bias::Left)
1875                    .to_point(&display_map);
1876                let line_start = display_map.prev_line_boundary(position).0;
1877                let next_line_start = buffer.clip_point(
1878                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1879                    Bias::Left,
1880                );
1881                start = buffer.anchor_before(line_start);
1882                end = buffer.anchor_before(next_line_start);
1883                mode = SelectMode::Line(start.clone()..end.clone());
1884                auto_scroll = true;
1885            }
1886            _ => {
1887                start = buffer.anchor_before(0);
1888                end = buffer.anchor_before(buffer.len());
1889                mode = SelectMode::All;
1890                auto_scroll = false;
1891            }
1892        }
1893
1894        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
1895            if !add {
1896                s.clear_disjoint();
1897            } else if click_count > 1 {
1898                s.delete(newest_selection.id)
1899            }
1900
1901            s.set_pending_anchor_range(start..end, mode);
1902        });
1903    }
1904
1905    fn begin_columnar_selection(
1906        &mut self,
1907        position: DisplayPoint,
1908        goal_column: u32,
1909        cx: &mut ViewContext<Self>,
1910    ) {
1911        if !self.focused {
1912            cx.focus_self();
1913        }
1914
1915        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1916        let tail = self.selections.newest::<Point>(cx).tail();
1917        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1918
1919        self.select_columns(
1920            tail.to_display_point(&display_map),
1921            position,
1922            goal_column,
1923            &display_map,
1924            cx,
1925        );
1926    }
1927
1928    fn update_selection(
1929        &mut self,
1930        position: DisplayPoint,
1931        goal_column: u32,
1932        scroll_position: Vector2F,
1933        cx: &mut ViewContext<Self>,
1934    ) {
1935        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1936
1937        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1938            let tail = tail.to_display_point(&display_map);
1939            self.select_columns(tail, position, goal_column, &display_map, cx);
1940        } else if let Some(mut pending) = self.selections.pending_anchor() {
1941            let buffer = self.buffer.read(cx).snapshot(cx);
1942            let head;
1943            let tail;
1944            let mode = self.selections.pending_mode().unwrap();
1945            match &mode {
1946                SelectMode::Character => {
1947                    head = position.to_point(&display_map);
1948                    tail = pending.tail().to_point(&buffer);
1949                }
1950                SelectMode::Word(original_range) => {
1951                    let original_display_range = original_range.start.to_display_point(&display_map)
1952                        ..original_range.end.to_display_point(&display_map);
1953                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1954                        ..original_display_range.end.to_point(&display_map);
1955                    if movement::is_inside_word(&display_map, position)
1956                        || original_display_range.contains(&position)
1957                    {
1958                        let word_range = movement::surrounding_word(&display_map, position);
1959                        if word_range.start < original_display_range.start {
1960                            head = word_range.start.to_point(&display_map);
1961                        } else {
1962                            head = word_range.end.to_point(&display_map);
1963                        }
1964                    } else {
1965                        head = position.to_point(&display_map);
1966                    }
1967
1968                    if head <= original_buffer_range.start {
1969                        tail = original_buffer_range.end;
1970                    } else {
1971                        tail = original_buffer_range.start;
1972                    }
1973                }
1974                SelectMode::Line(original_range) => {
1975                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1976
1977                    let position = display_map
1978                        .clip_point(position, Bias::Left)
1979                        .to_point(&display_map);
1980                    let line_start = display_map.prev_line_boundary(position).0;
1981                    let next_line_start = buffer.clip_point(
1982                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1983                        Bias::Left,
1984                    );
1985
1986                    if line_start < original_range.start {
1987                        head = line_start
1988                    } else {
1989                        head = next_line_start
1990                    }
1991
1992                    if head <= original_range.start {
1993                        tail = original_range.end;
1994                    } else {
1995                        tail = original_range.start;
1996                    }
1997                }
1998                SelectMode::All => {
1999                    return;
2000                }
2001            };
2002
2003            if head < tail {
2004                pending.start = buffer.anchor_before(head);
2005                pending.end = buffer.anchor_before(tail);
2006                pending.reversed = true;
2007            } else {
2008                pending.start = buffer.anchor_before(tail);
2009                pending.end = buffer.anchor_before(head);
2010                pending.reversed = false;
2011            }
2012
2013            self.change_selections(None, cx, |s| {
2014                s.set_pending(pending, mode);
2015            });
2016        } else {
2017            error!("update_selection dispatched with no pending selection");
2018            return;
2019        }
2020
2021        self.set_scroll_position(scroll_position, cx);
2022        cx.notify();
2023    }
2024
2025    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
2026        self.columnar_selection_tail.take();
2027        if self.selections.pending_anchor().is_some() {
2028            let selections = self.selections.all::<usize>(cx);
2029            self.change_selections(None, cx, |s| {
2030                s.select(selections);
2031                s.clear_pending();
2032            });
2033        }
2034    }
2035
2036    fn select_columns(
2037        &mut self,
2038        tail: DisplayPoint,
2039        head: DisplayPoint,
2040        goal_column: u32,
2041        display_map: &DisplaySnapshot,
2042        cx: &mut ViewContext<Self>,
2043    ) {
2044        let start_row = cmp::min(tail.row(), head.row());
2045        let end_row = cmp::max(tail.row(), head.row());
2046        let start_column = cmp::min(tail.column(), goal_column);
2047        let end_column = cmp::max(tail.column(), goal_column);
2048        let reversed = start_column < tail.column();
2049
2050        let selection_ranges = (start_row..=end_row)
2051            .filter_map(|row| {
2052                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
2053                    let start = display_map
2054                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
2055                        .to_point(display_map);
2056                    let end = display_map
2057                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
2058                        .to_point(display_map);
2059                    if reversed {
2060                        Some(end..start)
2061                    } else {
2062                        Some(start..end)
2063                    }
2064                } else {
2065                    None
2066                }
2067            })
2068            .collect::<Vec<_>>();
2069
2070        self.change_selections(None, cx, |s| {
2071            s.select_ranges(selection_ranges);
2072        });
2073        cx.notify();
2074    }
2075
2076    pub fn has_pending_nonempty_selection(&self) -> bool {
2077        let pending_nonempty_selection = match self.selections.pending_anchor() {
2078            Some(Selection { start, end, .. }) => start != end,
2079            None => false,
2080        };
2081        pending_nonempty_selection || self.columnar_selection_tail.is_some()
2082    }
2083
2084    pub fn has_pending_selection(&self) -> bool {
2085        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
2086    }
2087
2088    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
2089        if self.take_rename(false, cx).is_some() {
2090            return;
2091        }
2092
2093        if hide_hover(self, cx) {
2094            return;
2095        }
2096
2097        if self.hide_context_menu(cx).is_some() {
2098            return;
2099        }
2100
2101        if self.discard_copilot_suggestion(cx) {
2102            return;
2103        }
2104
2105        if self.snippet_stack.pop().is_some() {
2106            return;
2107        }
2108
2109        if self.mode == EditorMode::Full {
2110            if self.active_diagnostics.is_some() {
2111                self.dismiss_diagnostics(cx);
2112                return;
2113            }
2114
2115            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
2116                return;
2117            }
2118        }
2119
2120        cx.propagate_action();
2121    }
2122
2123    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2124        let text: Arc<str> = text.into();
2125
2126        if self.read_only {
2127            return;
2128        }
2129        if !self.input_enabled {
2130            cx.emit(Event::InputIgnored { text });
2131            return;
2132        }
2133
2134        let selections = self.selections.all_adjusted(cx);
2135        let mut brace_inserted = false;
2136        let mut edits = Vec::new();
2137        let mut new_selections = Vec::with_capacity(selections.len());
2138        let mut new_autoclose_regions = Vec::new();
2139        let snapshot = self.buffer.read(cx).read(cx);
2140
2141        for (selection, autoclose_region) in
2142            self.selections_with_autoclose_regions(selections, &snapshot)
2143        {
2144            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
2145                // Determine if the inserted text matches the opening or closing
2146                // bracket of any of this language's bracket pairs.
2147                let mut bracket_pair = None;
2148                let mut is_bracket_pair_start = false;
2149                for (pair, enabled) in scope.brackets() {
2150                    if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
2151                        bracket_pair = Some(pair.clone());
2152                        is_bracket_pair_start = true;
2153                        break;
2154                    } else if pair.end.as_str() == text.as_ref() {
2155                        bracket_pair = Some(pair.clone());
2156                        break;
2157                    }
2158                }
2159
2160                if let Some(bracket_pair) = bracket_pair {
2161                    if selection.is_empty() {
2162                        if is_bracket_pair_start {
2163                            let prefix_len = bracket_pair.start.len() - text.len();
2164
2165                            // If the inserted text is a suffix of an opening bracket and the
2166                            // selection is preceded by the rest of the opening bracket, then
2167                            // insert the closing bracket.
2168                            let following_text_allows_autoclose = snapshot
2169                                .chars_at(selection.start)
2170                                .next()
2171                                .map_or(true, |c| scope.should_autoclose_before(c));
2172                            let preceding_text_matches_prefix = prefix_len == 0
2173                                || (selection.start.column >= (prefix_len as u32)
2174                                    && snapshot.contains_str_at(
2175                                        Point::new(
2176                                            selection.start.row,
2177                                            selection.start.column - (prefix_len as u32),
2178                                        ),
2179                                        &bracket_pair.start[..prefix_len],
2180                                    ));
2181                            if following_text_allows_autoclose && preceding_text_matches_prefix {
2182                                let anchor = snapshot.anchor_before(selection.end);
2183                                new_selections.push((selection.map(|_| anchor), text.len()));
2184                                new_autoclose_regions.push((
2185                                    anchor,
2186                                    text.len(),
2187                                    selection.id,
2188                                    bracket_pair.clone(),
2189                                ));
2190                                edits.push((
2191                                    selection.range(),
2192                                    format!("{}{}", text, bracket_pair.end).into(),
2193                                ));
2194                                brace_inserted = true;
2195                                continue;
2196                            }
2197                        }
2198
2199                        if let Some(region) = autoclose_region {
2200                            // If the selection is followed by an auto-inserted closing bracket,
2201                            // then don't insert that closing bracket again; just move the selection
2202                            // past the closing bracket.
2203                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2204                                && text.as_ref() == region.pair.end.as_str();
2205                            if should_skip {
2206                                let anchor = snapshot.anchor_after(selection.end);
2207                                new_selections
2208                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2209                                continue;
2210                            }
2211                        }
2212                    }
2213                    // If an opening bracket is 1 character long and is typed while
2214                    // text is selected, then surround that text with the bracket pair.
2215                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2216                        edits.push((selection.start..selection.start, text.clone()));
2217                        edits.push((
2218                            selection.end..selection.end,
2219                            bracket_pair.end.as_str().into(),
2220                        ));
2221                        brace_inserted = true;
2222                        new_selections.push((
2223                            Selection {
2224                                id: selection.id,
2225                                start: snapshot.anchor_after(selection.start),
2226                                end: snapshot.anchor_before(selection.end),
2227                                reversed: selection.reversed,
2228                                goal: selection.goal,
2229                            },
2230                            0,
2231                        ));
2232                        continue;
2233                    }
2234                }
2235            }
2236
2237            // If not handling any auto-close operation, then just replace the selected
2238            // text with the given input and move the selection to the end of the
2239            // newly inserted text.
2240            let anchor = snapshot.anchor_after(selection.end);
2241            new_selections.push((selection.map(|_| anchor), 0));
2242            edits.push((selection.start..selection.end, text.clone()));
2243        }
2244
2245        drop(snapshot);
2246        self.transact(cx, |this, cx| {
2247            this.buffer.update(cx, |buffer, cx| {
2248                buffer.edit(edits, this.autoindent_mode.clone(), cx);
2249            });
2250
2251            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2252            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2253            let snapshot = this.buffer.read(cx).read(cx);
2254            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2255                .zip(new_selection_deltas)
2256                .map(|(selection, delta)| selection.map(|e| e + delta))
2257                .collect::<Vec<_>>();
2258
2259            let mut i = 0;
2260            for (position, delta, selection_id, pair) in new_autoclose_regions {
2261                let position = position.to_offset(&snapshot) + delta;
2262                let start = snapshot.anchor_before(position);
2263                let end = snapshot.anchor_after(position);
2264                while let Some(existing_state) = this.autoclose_regions.get(i) {
2265                    match existing_state.range.start.cmp(&start, &snapshot) {
2266                        Ordering::Less => i += 1,
2267                        Ordering::Greater => break,
2268                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2269                            Ordering::Less => i += 1,
2270                            Ordering::Equal => break,
2271                            Ordering::Greater => break,
2272                        },
2273                    }
2274                }
2275                this.autoclose_regions.insert(
2276                    i,
2277                    AutocloseRegion {
2278                        selection_id,
2279                        range: start..end,
2280                        pair,
2281                    },
2282                );
2283            }
2284
2285            drop(snapshot);
2286            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2287            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2288
2289            if !brace_inserted && settings::get::<EditorSettings>(cx).use_on_type_format {
2290                if let Some(on_type_format_task) =
2291                    this.trigger_on_type_formatting(text.to_string(), cx)
2292                {
2293                    on_type_format_task.detach_and_log_err(cx);
2294                }
2295            }
2296
2297            if had_active_copilot_suggestion {
2298                this.refresh_copilot_suggestions(true, cx);
2299                if !this.has_active_copilot_suggestion(cx) {
2300                    this.trigger_completion_on_input(&text, cx);
2301                }
2302            } else {
2303                this.trigger_completion_on_input(&text, cx);
2304                this.refresh_copilot_suggestions(true, cx);
2305            }
2306        });
2307    }
2308
2309    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2310        self.transact(cx, |this, cx| {
2311            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2312                let selections = this.selections.all::<usize>(cx);
2313                let multi_buffer = this.buffer.read(cx);
2314                let buffer = multi_buffer.snapshot(cx);
2315                selections
2316                    .iter()
2317                    .map(|selection| {
2318                        let start_point = selection.start.to_point(&buffer);
2319                        let mut indent = buffer.indent_size_for_line(start_point.row);
2320                        indent.len = cmp::min(indent.len, start_point.column);
2321                        let start = selection.start;
2322                        let end = selection.end;
2323                        let is_cursor = start == end;
2324                        let language_scope = buffer.language_scope_at(start);
2325                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
2326                            &language_scope
2327                        {
2328                            let leading_whitespace_len = buffer
2329                                .reversed_chars_at(start)
2330                                .take_while(|c| c.is_whitespace() && *c != '\n')
2331                                .map(|c| c.len_utf8())
2332                                .sum::<usize>();
2333
2334                            let trailing_whitespace_len = buffer
2335                                .chars_at(end)
2336                                .take_while(|c| c.is_whitespace() && *c != '\n')
2337                                .map(|c| c.len_utf8())
2338                                .sum::<usize>();
2339
2340                            let insert_extra_newline =
2341                                language.brackets().any(|(pair, enabled)| {
2342                                    let pair_start = pair.start.trim_end();
2343                                    let pair_end = pair.end.trim_start();
2344
2345                                    enabled
2346                                        && pair.newline
2347                                        && buffer.contains_str_at(
2348                                            end + trailing_whitespace_len,
2349                                            pair_end,
2350                                        )
2351                                        && buffer.contains_str_at(
2352                                            (start - leading_whitespace_len)
2353                                                .saturating_sub(pair_start.len()),
2354                                            pair_start,
2355                                        )
2356                                });
2357                            // Comment extension on newline is allowed only for cursor selections
2358                            let comment_delimiter = language.line_comment_prefix().filter(|_| {
2359                                let is_comment_extension_enabled =
2360                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
2361                                is_cursor && is_comment_extension_enabled
2362                            });
2363                            let comment_delimiter = if let Some(delimiter) = comment_delimiter {
2364                                buffer
2365                                    .buffer_line_for_row(start_point.row)
2366                                    .is_some_and(|(snapshot, range)| {
2367                                        let mut index_of_first_non_whitespace = 0;
2368                                        let line_starts_with_comment = snapshot
2369                                            .chars_for_range(range)
2370                                            .skip_while(|c| {
2371                                                let should_skip = c.is_whitespace();
2372                                                if should_skip {
2373                                                    index_of_first_non_whitespace += 1;
2374                                                }
2375                                                should_skip
2376                                            })
2377                                            .take(delimiter.len())
2378                                            .eq(delimiter.chars());
2379                                        let cursor_is_placed_after_comment_marker =
2380                                            index_of_first_non_whitespace + delimiter.len()
2381                                                <= start_point.column as usize;
2382                                        line_starts_with_comment
2383                                            && cursor_is_placed_after_comment_marker
2384                                    })
2385                                    .then(|| delimiter.clone())
2386                            } else {
2387                                None
2388                            };
2389                            (comment_delimiter, insert_extra_newline)
2390                        } else {
2391                            (None, false)
2392                        };
2393
2394                        let capacity_for_delimiter = comment_delimiter
2395                            .as_deref()
2396                            .map(str::len)
2397                            .unwrap_or_default();
2398                        let mut new_text =
2399                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
2400                        new_text.push_str("\n");
2401                        new_text.extend(indent.chars());
2402                        if let Some(delimiter) = &comment_delimiter {
2403                            new_text.push_str(&delimiter);
2404                        }
2405                        if insert_extra_newline {
2406                            new_text = new_text.repeat(2);
2407                        }
2408
2409                        let anchor = buffer.anchor_after(end);
2410                        let new_selection = selection.map(|_| anchor);
2411                        (
2412                            (start..end, new_text),
2413                            (insert_extra_newline, new_selection),
2414                        )
2415                    })
2416                    .unzip()
2417            };
2418
2419            this.edit_with_autoindent(edits, cx);
2420            let buffer = this.buffer.read(cx).snapshot(cx);
2421            let new_selections = selection_fixup_info
2422                .into_iter()
2423                .map(|(extra_newline_inserted, new_selection)| {
2424                    let mut cursor = new_selection.end.to_point(&buffer);
2425                    if extra_newline_inserted {
2426                        cursor.row -= 1;
2427                        cursor.column = buffer.line_len(cursor.row);
2428                    }
2429                    new_selection.map(|_| cursor)
2430                })
2431                .collect();
2432
2433            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2434            this.refresh_copilot_suggestions(true, cx);
2435        });
2436    }
2437
2438    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2439        let buffer = self.buffer.read(cx);
2440        let snapshot = buffer.snapshot(cx);
2441
2442        let mut edits = Vec::new();
2443        let mut rows = Vec::new();
2444        let mut rows_inserted = 0;
2445
2446        for selection in self.selections.all_adjusted(cx) {
2447            let cursor = selection.head();
2448            let row = cursor.row;
2449
2450            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2451
2452            let newline = "\n".to_string();
2453            edits.push((start_of_line..start_of_line, newline));
2454
2455            rows.push(row + rows_inserted);
2456            rows_inserted += 1;
2457        }
2458
2459        self.transact(cx, |editor, cx| {
2460            editor.edit(edits, cx);
2461
2462            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2463                let mut index = 0;
2464                s.move_cursors_with(|map, _, _| {
2465                    let row = rows[index];
2466                    index += 1;
2467
2468                    let point = Point::new(row, 0);
2469                    let boundary = map.next_line_boundary(point).1;
2470                    let clipped = map.clip_point(boundary, Bias::Left);
2471
2472                    (clipped, SelectionGoal::None)
2473                });
2474            });
2475
2476            let mut indent_edits = Vec::new();
2477            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2478            for row in rows {
2479                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2480                for (row, indent) in indents {
2481                    if indent.len == 0 {
2482                        continue;
2483                    }
2484
2485                    let text = match indent.kind {
2486                        IndentKind::Space => " ".repeat(indent.len as usize),
2487                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2488                    };
2489                    let point = Point::new(row, 0);
2490                    indent_edits.push((point..point, text));
2491                }
2492            }
2493            editor.edit(indent_edits, cx);
2494        });
2495    }
2496
2497    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2498        let buffer = self.buffer.read(cx);
2499        let snapshot = buffer.snapshot(cx);
2500
2501        let mut edits = Vec::new();
2502        let mut rows = Vec::new();
2503        let mut rows_inserted = 0;
2504
2505        for selection in self.selections.all_adjusted(cx) {
2506            let cursor = selection.head();
2507            let row = cursor.row;
2508
2509            let point = Point::new(row + 1, 0);
2510            let start_of_line = snapshot.clip_point(point, Bias::Left);
2511
2512            let newline = "\n".to_string();
2513            edits.push((start_of_line..start_of_line, newline));
2514
2515            rows_inserted += 1;
2516            rows.push(row + rows_inserted);
2517        }
2518
2519        self.transact(cx, |editor, cx| {
2520            editor.edit(edits, cx);
2521
2522            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2523                let mut index = 0;
2524                s.move_cursors_with(|map, _, _| {
2525                    let row = rows[index];
2526                    index += 1;
2527
2528                    let point = Point::new(row, 0);
2529                    let boundary = map.next_line_boundary(point).1;
2530                    let clipped = map.clip_point(boundary, Bias::Left);
2531
2532                    (clipped, SelectionGoal::None)
2533                });
2534            });
2535
2536            let mut indent_edits = Vec::new();
2537            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2538            for row in rows {
2539                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2540                for (row, indent) in indents {
2541                    if indent.len == 0 {
2542                        continue;
2543                    }
2544
2545                    let text = match indent.kind {
2546                        IndentKind::Space => " ".repeat(indent.len as usize),
2547                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2548                    };
2549                    let point = Point::new(row, 0);
2550                    indent_edits.push((point..point, text));
2551                }
2552            }
2553            editor.edit(indent_edits, cx);
2554        });
2555    }
2556
2557    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2558        self.insert_with_autoindent_mode(
2559            text,
2560            Some(AutoindentMode::Block {
2561                original_indent_columns: Vec::new(),
2562            }),
2563            cx,
2564        );
2565    }
2566
2567    fn insert_with_autoindent_mode(
2568        &mut self,
2569        text: &str,
2570        autoindent_mode: Option<AutoindentMode>,
2571        cx: &mut ViewContext<Self>,
2572    ) {
2573        if self.read_only {
2574            return;
2575        }
2576
2577        let text: Arc<str> = text.into();
2578        self.transact(cx, |this, cx| {
2579            let old_selections = this.selections.all_adjusted(cx);
2580            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2581                let anchors = {
2582                    let snapshot = buffer.read(cx);
2583                    old_selections
2584                        .iter()
2585                        .map(|s| {
2586                            let anchor = snapshot.anchor_after(s.head());
2587                            s.map(|_| anchor)
2588                        })
2589                        .collect::<Vec<_>>()
2590                };
2591                buffer.edit(
2592                    old_selections
2593                        .iter()
2594                        .map(|s| (s.start..s.end, text.clone())),
2595                    autoindent_mode,
2596                    cx,
2597                );
2598                anchors
2599            });
2600
2601            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2602                s.select_anchors(selection_anchors);
2603            })
2604        });
2605    }
2606
2607    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2608        if !settings::get::<EditorSettings>(cx).show_completions_on_input {
2609            return;
2610        }
2611
2612        let selection = self.selections.newest_anchor();
2613        if self
2614            .buffer
2615            .read(cx)
2616            .is_completion_trigger(selection.head(), text, cx)
2617        {
2618            self.show_completions(&ShowCompletions, cx);
2619        } else {
2620            self.hide_context_menu(cx);
2621        }
2622    }
2623
2624    /// If any empty selections is touching the start of its innermost containing autoclose
2625    /// region, expand it to select the brackets.
2626    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2627        let selections = self.selections.all::<usize>(cx);
2628        let buffer = self.buffer.read(cx).read(cx);
2629        let mut new_selections = Vec::new();
2630        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2631            if let (Some(region), true) = (region, selection.is_empty()) {
2632                let mut range = region.range.to_offset(&buffer);
2633                if selection.start == range.start {
2634                    if range.start >= region.pair.start.len() {
2635                        range.start -= region.pair.start.len();
2636                        if buffer.contains_str_at(range.start, &region.pair.start) {
2637                            if buffer.contains_str_at(range.end, &region.pair.end) {
2638                                range.end += region.pair.end.len();
2639                                selection.start = range.start;
2640                                selection.end = range.end;
2641                            }
2642                        }
2643                    }
2644                }
2645            }
2646            new_selections.push(selection);
2647        }
2648
2649        drop(buffer);
2650        self.change_selections(None, cx, |selections| selections.select(new_selections));
2651    }
2652
2653    /// Iterate the given selections, and for each one, find the smallest surrounding
2654    /// autoclose region. This uses the ordering of the selections and the autoclose
2655    /// regions to avoid repeated comparisons.
2656    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2657        &'a self,
2658        selections: impl IntoIterator<Item = Selection<D>>,
2659        buffer: &'a MultiBufferSnapshot,
2660    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2661        let mut i = 0;
2662        let mut regions = self.autoclose_regions.as_slice();
2663        selections.into_iter().map(move |selection| {
2664            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2665
2666            let mut enclosing = None;
2667            while let Some(pair_state) = regions.get(i) {
2668                if pair_state.range.end.to_offset(buffer) < range.start {
2669                    regions = &regions[i + 1..];
2670                    i = 0;
2671                } else if pair_state.range.start.to_offset(buffer) > range.end {
2672                    break;
2673                } else if pair_state.selection_id == selection.id {
2674                    enclosing = Some(pair_state);
2675                    i += 1;
2676                }
2677            }
2678
2679            (selection.clone(), enclosing)
2680        })
2681    }
2682
2683    /// Remove any autoclose regions that no longer contain their selection.
2684    fn invalidate_autoclose_regions(
2685        &mut self,
2686        mut selections: &[Selection<Anchor>],
2687        buffer: &MultiBufferSnapshot,
2688    ) {
2689        self.autoclose_regions.retain(|state| {
2690            let mut i = 0;
2691            while let Some(selection) = selections.get(i) {
2692                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2693                    selections = &selections[1..];
2694                    continue;
2695                }
2696                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2697                    break;
2698                }
2699                if selection.id == state.selection_id {
2700                    return true;
2701                } else {
2702                    i += 1;
2703                }
2704            }
2705            false
2706        });
2707    }
2708    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2709        let offset = position.to_offset(buffer);
2710        let (word_range, kind) = buffer.surrounding_word(offset);
2711        if offset > word_range.start && kind == Some(CharKind::Word) {
2712            Some(
2713                buffer
2714                    .text_for_range(word_range.start..offset)
2715                    .collect::<String>(),
2716            )
2717        } else {
2718            None
2719        }
2720    }
2721
2722    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
2723        self.refresh_inlay_hints(
2724            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
2725            cx,
2726        );
2727    }
2728
2729    pub fn inlay_hints_enabled(&self) -> bool {
2730        self.inlay_hint_cache.enabled
2731    }
2732
2733    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
2734        if self.project.is_none() || self.mode != EditorMode::Full {
2735            return;
2736        }
2737
2738        let (invalidate_cache, required_languages) = match reason {
2739            InlayHintRefreshReason::Toggle(enabled) => {
2740                self.inlay_hint_cache.enabled = enabled;
2741                if enabled {
2742                    (InvalidationStrategy::RefreshRequested, None)
2743                } else {
2744                    self.inlay_hint_cache.clear();
2745                    self.splice_inlay_hints(
2746                        self.visible_inlay_hints(cx)
2747                            .iter()
2748                            .map(|inlay| inlay.id)
2749                            .collect(),
2750                        Vec::new(),
2751                        cx,
2752                    );
2753                    return;
2754                }
2755            }
2756            InlayHintRefreshReason::SettingsChange(new_settings) => {
2757                match self.inlay_hint_cache.update_settings(
2758                    &self.buffer,
2759                    new_settings,
2760                    self.visible_inlay_hints(cx),
2761                    cx,
2762                ) {
2763                    ControlFlow::Break(Some(InlaySplice {
2764                        to_remove,
2765                        to_insert,
2766                    })) => {
2767                        self.splice_inlay_hints(to_remove, to_insert, cx);
2768                        return;
2769                    }
2770                    ControlFlow::Break(None) => return,
2771                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
2772                }
2773            }
2774            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
2775            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
2776                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
2777            }
2778            InlayHintRefreshReason::RefreshRequested => {
2779                (InvalidationStrategy::RefreshRequested, None)
2780            }
2781        };
2782
2783        if let Some(InlaySplice {
2784            to_remove,
2785            to_insert,
2786        }) = self.inlay_hint_cache.spawn_hint_refresh(
2787            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
2788            invalidate_cache,
2789            cx,
2790        ) {
2791            self.splice_inlay_hints(to_remove, to_insert, cx);
2792        }
2793    }
2794
2795    fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> {
2796        self.display_map
2797            .read(cx)
2798            .current_inlays()
2799            .filter(move |inlay| {
2800                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
2801            })
2802            .cloned()
2803            .collect()
2804    }
2805
2806    pub fn excerpt_visible_offsets(
2807        &self,
2808        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
2809        cx: &mut ViewContext<'_, '_, Editor>,
2810    ) -> HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)> {
2811        let multi_buffer = self.buffer().read(cx);
2812        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
2813        let multi_buffer_visible_start = self
2814            .scroll_manager
2815            .anchor()
2816            .anchor
2817            .to_point(&multi_buffer_snapshot);
2818        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
2819            multi_buffer_visible_start
2820                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
2821            Bias::Left,
2822        );
2823        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
2824        multi_buffer
2825            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
2826            .into_iter()
2827            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
2828            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
2829                let buffer = buffer_handle.read(cx);
2830                let language = buffer.language()?;
2831                if let Some(restrict_to_languages) = restrict_to_languages {
2832                    if !restrict_to_languages.contains(language) {
2833                        return None;
2834                    }
2835                }
2836                Some((
2837                    excerpt_id,
2838                    (
2839                        buffer_handle,
2840                        buffer.version().clone(),
2841                        excerpt_visible_range,
2842                    ),
2843                ))
2844            })
2845            .collect()
2846    }
2847
2848    fn splice_inlay_hints(
2849        &self,
2850        to_remove: Vec<InlayId>,
2851        to_insert: Vec<Inlay>,
2852        cx: &mut ViewContext<Self>,
2853    ) {
2854        self.display_map.update(cx, |display_map, cx| {
2855            display_map.splice_inlays(to_remove, to_insert, cx);
2856        });
2857        cx.notify();
2858    }
2859
2860    fn trigger_on_type_formatting(
2861        &self,
2862        input: String,
2863        cx: &mut ViewContext<Self>,
2864    ) -> Option<Task<Result<()>>> {
2865        if input.len() != 1 {
2866            return None;
2867        }
2868
2869        let project = self.project.as_ref()?;
2870        let position = self.selections.newest_anchor().head();
2871        let (buffer, buffer_position) = self
2872            .buffer
2873            .read(cx)
2874            .text_anchor_for_position(position.clone(), cx)?;
2875
2876        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
2877        // hence we do LSP request & edit on host side only — add formats to host's history.
2878        let push_to_lsp_host_history = true;
2879        // If this is not the host, append its history with new edits.
2880        let push_to_client_history = project.read(cx).is_remote();
2881
2882        let on_type_formatting = project.update(cx, |project, cx| {
2883            project.on_type_format(
2884                buffer.clone(),
2885                buffer_position,
2886                input,
2887                push_to_lsp_host_history,
2888                cx,
2889            )
2890        });
2891        Some(cx.spawn(|editor, mut cx| async move {
2892            if let Some(transaction) = on_type_formatting.await? {
2893                if push_to_client_history {
2894                    buffer.update(&mut cx, |buffer, _| {
2895                        buffer.push_transaction(transaction, Instant::now());
2896                    });
2897                }
2898                editor.update(&mut cx, |editor, cx| {
2899                    editor.refresh_document_highlights(cx);
2900                })?;
2901            }
2902            Ok(())
2903        }))
2904    }
2905
2906    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2907        if self.pending_rename.is_some() {
2908            return;
2909        }
2910
2911        let project = if let Some(project) = self.project.clone() {
2912            project
2913        } else {
2914            return;
2915        };
2916
2917        let position = self.selections.newest_anchor().head();
2918        let (buffer, buffer_position) = if let Some(output) = self
2919            .buffer
2920            .read(cx)
2921            .text_anchor_for_position(position.clone(), cx)
2922        {
2923            output
2924        } else {
2925            return;
2926        };
2927
2928        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2929        let completions = project.update(cx, |project, cx| {
2930            project.completions(&buffer, buffer_position, cx)
2931        });
2932
2933        let id = post_inc(&mut self.next_completion_id);
2934        let task = cx.spawn(|this, mut cx| {
2935            async move {
2936                let menu = if let Some(completions) = completions.await.log_err() {
2937                    let mut menu = CompletionsMenu {
2938                        id,
2939                        initial_position: position,
2940                        match_candidates: completions
2941                            .iter()
2942                            .enumerate()
2943                            .map(|(id, completion)| {
2944                                StringMatchCandidate::new(
2945                                    id,
2946                                    completion.label.text[completion.label.filter_range.clone()]
2947                                        .into(),
2948                                )
2949                            })
2950                            .collect(),
2951                        buffer,
2952                        completions: completions.into(),
2953                        matches: Vec::new().into(),
2954                        selected_item: 0,
2955                        list: Default::default(),
2956                    };
2957                    menu.filter(query.as_deref(), cx.background()).await;
2958                    if menu.matches.is_empty() {
2959                        None
2960                    } else {
2961                        Some(menu)
2962                    }
2963                } else {
2964                    None
2965                };
2966
2967                this.update(&mut cx, |this, cx| {
2968                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2969
2970                    match this.context_menu.as_ref() {
2971                        None => {}
2972                        Some(ContextMenu::Completions(prev_menu)) => {
2973                            if prev_menu.id > id {
2974                                return;
2975                            }
2976                        }
2977                        _ => return,
2978                    }
2979
2980                    if this.focused && menu.is_some() {
2981                        let menu = menu.unwrap();
2982                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2983                    } else if this.completion_tasks.is_empty() {
2984                        // If there are no more completion tasks and the last menu was
2985                        // empty, we should hide it. If it was already hidden, we should
2986                        // also show the copilot suggestion when available.
2987                        if this.hide_context_menu(cx).is_none() {
2988                            this.update_visible_copilot_suggestion(cx);
2989                        }
2990                    }
2991                })?;
2992
2993                Ok::<_, anyhow::Error>(())
2994            }
2995            .log_err()
2996        });
2997        self.completion_tasks.push((id, task));
2998    }
2999
3000    pub fn confirm_completion(
3001        &mut self,
3002        action: &ConfirmCompletion,
3003        cx: &mut ViewContext<Self>,
3004    ) -> Option<Task<Result<()>>> {
3005        use language::ToOffset as _;
3006
3007        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
3008            menu
3009        } else {
3010            return None;
3011        };
3012
3013        let mat = completions_menu
3014            .matches
3015            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
3016        let buffer_handle = completions_menu.buffer;
3017        let completion = completions_menu.completions.get(mat.candidate_id)?;
3018
3019        let snippet;
3020        let text;
3021        if completion.is_snippet() {
3022            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
3023            text = snippet.as_ref().unwrap().text.clone();
3024        } else {
3025            snippet = None;
3026            text = completion.new_text.clone();
3027        };
3028        let selections = self.selections.all::<usize>(cx);
3029        let buffer = buffer_handle.read(cx);
3030        let old_range = completion.old_range.to_offset(buffer);
3031        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
3032
3033        let newest_selection = self.selections.newest_anchor();
3034        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
3035            return None;
3036        }
3037
3038        let lookbehind = newest_selection
3039            .start
3040            .text_anchor
3041            .to_offset(buffer)
3042            .saturating_sub(old_range.start);
3043        let lookahead = old_range
3044            .end
3045            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
3046        let mut common_prefix_len = old_text
3047            .bytes()
3048            .zip(text.bytes())
3049            .take_while(|(a, b)| a == b)
3050            .count();
3051
3052        let snapshot = self.buffer.read(cx).snapshot(cx);
3053        let mut ranges = Vec::new();
3054        for selection in &selections {
3055            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
3056                let start = selection.start.saturating_sub(lookbehind);
3057                let end = selection.end + lookahead;
3058                ranges.push(start + common_prefix_len..end);
3059            } else {
3060                common_prefix_len = 0;
3061                ranges.clear();
3062                ranges.extend(selections.iter().map(|s| {
3063                    if s.id == newest_selection.id {
3064                        old_range.clone()
3065                    } else {
3066                        s.start..s.end
3067                    }
3068                }));
3069                break;
3070            }
3071        }
3072        let text = &text[common_prefix_len..];
3073
3074        self.transact(cx, |this, cx| {
3075            if let Some(mut snippet) = snippet {
3076                snippet.text = text.to_string();
3077                for tabstop in snippet.tabstops.iter_mut().flatten() {
3078                    tabstop.start -= common_prefix_len as isize;
3079                    tabstop.end -= common_prefix_len as isize;
3080                }
3081
3082                this.insert_snippet(&ranges, snippet, cx).log_err();
3083            } else {
3084                this.buffer.update(cx, |buffer, cx| {
3085                    buffer.edit(
3086                        ranges.iter().map(|range| (range.clone(), text)),
3087                        this.autoindent_mode.clone(),
3088                        cx,
3089                    );
3090                });
3091            }
3092
3093            this.refresh_copilot_suggestions(true, cx);
3094        });
3095
3096        let project = self.project.clone()?;
3097        let apply_edits = project.update(cx, |project, cx| {
3098            project.apply_additional_edits_for_completion(
3099                buffer_handle,
3100                completion.clone(),
3101                true,
3102                cx,
3103            )
3104        });
3105        Some(cx.foreground().spawn(async move {
3106            apply_edits.await?;
3107            Ok(())
3108        }))
3109    }
3110
3111    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3112        if matches!(
3113            self.context_menu.as_ref(),
3114            Some(ContextMenu::CodeActions(_))
3115        ) {
3116            self.context_menu.take();
3117            cx.notify();
3118            return;
3119        }
3120
3121        let deployed_from_indicator = action.deployed_from_indicator;
3122        let mut task = self.code_actions_task.take();
3123        cx.spawn(|this, mut cx| async move {
3124            while let Some(prev_task) = task {
3125                prev_task.await;
3126                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3127            }
3128
3129            this.update(&mut cx, |this, cx| {
3130                if this.focused {
3131                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3132                        this.show_context_menu(
3133                            ContextMenu::CodeActions(CodeActionsMenu {
3134                                buffer,
3135                                actions,
3136                                selected_item: Default::default(),
3137                                list: Default::default(),
3138                                deployed_from_indicator,
3139                            }),
3140                            cx,
3141                        );
3142                    }
3143                }
3144            })?;
3145
3146            Ok::<_, anyhow::Error>(())
3147        })
3148        .detach_and_log_err(cx);
3149    }
3150
3151    pub fn confirm_code_action(
3152        workspace: &mut Workspace,
3153        action: &ConfirmCodeAction,
3154        cx: &mut ViewContext<Workspace>,
3155    ) -> Option<Task<Result<()>>> {
3156        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3157        let actions_menu = if let ContextMenu::CodeActions(menu) =
3158            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3159        {
3160            menu
3161        } else {
3162            return None;
3163        };
3164        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3165        let action = actions_menu.actions.get(action_ix)?.clone();
3166        let title = action.lsp_action.title.clone();
3167        let buffer = actions_menu.buffer;
3168
3169        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3170            project.apply_code_action(buffer, action, true, cx)
3171        });
3172        let editor = editor.downgrade();
3173        Some(cx.spawn(|workspace, cx| async move {
3174            let project_transaction = apply_code_actions.await?;
3175            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3176        }))
3177    }
3178
3179    async fn open_project_transaction(
3180        this: &WeakViewHandle<Editor>,
3181        workspace: WeakViewHandle<Workspace>,
3182        transaction: ProjectTransaction,
3183        title: String,
3184        mut cx: AsyncAppContext,
3185    ) -> Result<()> {
3186        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3187
3188        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3189        entries.sort_unstable_by_key(|(buffer, _)| {
3190            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3191        });
3192
3193        // If the project transaction's edits are all contained within this editor, then
3194        // avoid opening a new editor to display them.
3195
3196        if let Some((buffer, transaction)) = entries.first() {
3197            if entries.len() == 1 {
3198                let excerpt = this.read_with(&cx, |editor, cx| {
3199                    editor
3200                        .buffer()
3201                        .read(cx)
3202                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3203                })?;
3204                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3205                    if excerpted_buffer == *buffer {
3206                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3207                            let excerpt_range = excerpt_range.to_offset(buffer);
3208                            buffer
3209                                .edited_ranges_for_transaction::<usize>(transaction)
3210                                .all(|range| {
3211                                    excerpt_range.start <= range.start
3212                                        && excerpt_range.end >= range.end
3213                                })
3214                        });
3215
3216                        if all_edits_within_excerpt {
3217                            return Ok(());
3218                        }
3219                    }
3220                }
3221            }
3222        } else {
3223            return Ok(());
3224        }
3225
3226        let mut ranges_to_highlight = Vec::new();
3227        let excerpt_buffer = cx.add_model(|cx| {
3228            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3229            for (buffer_handle, transaction) in &entries {
3230                let buffer = buffer_handle.read(cx);
3231                ranges_to_highlight.extend(
3232                    multibuffer.push_excerpts_with_context_lines(
3233                        buffer_handle.clone(),
3234                        buffer
3235                            .edited_ranges_for_transaction::<usize>(transaction)
3236                            .collect(),
3237                        1,
3238                        cx,
3239                    ),
3240                );
3241            }
3242            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3243            multibuffer
3244        });
3245
3246        workspace.update(&mut cx, |workspace, cx| {
3247            let project = workspace.project().clone();
3248            let editor =
3249                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3250            workspace.add_item(Box::new(editor.clone()), cx);
3251            editor.update(cx, |editor, cx| {
3252                editor.highlight_background::<Self>(
3253                    ranges_to_highlight,
3254                    |theme| theme.editor.highlighted_line_background,
3255                    cx,
3256                );
3257            });
3258        })?;
3259
3260        Ok(())
3261    }
3262
3263    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3264        let project = self.project.as_ref()?;
3265        let buffer = self.buffer.read(cx);
3266        let newest_selection = self.selections.newest_anchor().clone();
3267        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3268        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3269        if start_buffer != end_buffer {
3270            return None;
3271        }
3272
3273        let actions = project.update(cx, |project, cx| {
3274            project.code_actions(&start_buffer, start..end, cx)
3275        });
3276        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3277            let actions = actions.await;
3278            this.update(&mut cx, |this, cx| {
3279                this.available_code_actions = actions.log_err().and_then(|actions| {
3280                    if actions.is_empty() {
3281                        None
3282                    } else {
3283                        Some((start_buffer, actions.into()))
3284                    }
3285                });
3286                cx.notify();
3287            })
3288            .log_err();
3289        }));
3290        None
3291    }
3292
3293    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3294        if self.pending_rename.is_some() {
3295            return None;
3296        }
3297
3298        let project = self.project.as_ref()?;
3299        let buffer = self.buffer.read(cx);
3300        let newest_selection = self.selections.newest_anchor().clone();
3301        let cursor_position = newest_selection.head();
3302        let (cursor_buffer, cursor_buffer_position) =
3303            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3304        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3305        if cursor_buffer != tail_buffer {
3306            return None;
3307        }
3308
3309        let highlights = project.update(cx, |project, cx| {
3310            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3311        });
3312
3313        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3314            if let Some(highlights) = highlights.await.log_err() {
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_trigger_point {
8309            if event.cmd && !pending_selection {
8310                let point = point.clone();
8311                let snapshot = self.snapshot(cx);
8312                let kind = point.definition_kind(event.shift);
8313
8314                show_link_definition(kind, self, point, snapshot, cx);
8315                return false;
8316            }
8317        }
8318
8319        {
8320            if self.link_go_to_definition_state.symbol_range.is_some()
8321                || !self.link_go_to_definition_state.definitions.is_empty()
8322            {
8323                self.link_go_to_definition_state.symbol_range.take();
8324                self.link_go_to_definition_state.definitions.clear();
8325                cx.notify();
8326            }
8327
8328            self.link_go_to_definition_state.task = None;
8329
8330            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8331        }
8332
8333        false
8334    }
8335
8336    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8337        Self::reset_to_default_keymap_context(keymap);
8338        let mode = match self.mode {
8339            EditorMode::SingleLine => "single_line",
8340            EditorMode::AutoHeight { .. } => "auto_height",
8341            EditorMode::Full => "full",
8342        };
8343        keymap.add_key("mode", mode);
8344        if self.pending_rename.is_some() {
8345            keymap.add_identifier("renaming");
8346        }
8347        match self.context_menu.as_ref() {
8348            Some(ContextMenu::Completions(_)) => {
8349                keymap.add_identifier("menu");
8350                keymap.add_identifier("showing_completions")
8351            }
8352            Some(ContextMenu::CodeActions(_)) => {
8353                keymap.add_identifier("menu");
8354                keymap.add_identifier("showing_code_actions")
8355            }
8356            None => {}
8357        }
8358        for layer in self.keymap_context_layers.values() {
8359            keymap.extend(layer);
8360        }
8361
8362        if let Some(extension) = self
8363            .buffer
8364            .read(cx)
8365            .as_singleton()
8366            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8367        {
8368            keymap.add_key("extension", extension.to_string());
8369        }
8370    }
8371
8372    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8373        Some(
8374            self.buffer
8375                .read(cx)
8376                .read(cx)
8377                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8378                .collect(),
8379        )
8380    }
8381
8382    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8383        // Prevent the IME menu from appearing when holding down an alphabetic key
8384        // while input is disabled.
8385        if !self.input_enabled {
8386            return None;
8387        }
8388
8389        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8390        Some(range.start.0..range.end.0)
8391    }
8392
8393    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8394        let snapshot = self.buffer.read(cx).read(cx);
8395        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8396        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8397    }
8398
8399    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8400        self.clear_text_highlights::<InputComposition>(cx);
8401        self.ime_transaction.take();
8402    }
8403
8404    fn replace_text_in_range(
8405        &mut self,
8406        range_utf16: Option<Range<usize>>,
8407        text: &str,
8408        cx: &mut ViewContext<Self>,
8409    ) {
8410        self.transact(cx, |this, cx| {
8411            if this.input_enabled {
8412                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8413                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8414                    Some(this.selection_replacement_ranges(range_utf16, cx))
8415                } else {
8416                    this.marked_text_ranges(cx)
8417                };
8418
8419                if let Some(new_selected_ranges) = new_selected_ranges {
8420                    this.change_selections(None, cx, |selections| {
8421                        selections.select_ranges(new_selected_ranges)
8422                    });
8423                }
8424            }
8425
8426            this.handle_input(text, cx);
8427        });
8428
8429        if !self.input_enabled {
8430            return;
8431        }
8432
8433        if let Some(transaction) = self.ime_transaction {
8434            self.buffer.update(cx, |buffer, cx| {
8435                buffer.group_until_transaction(transaction, cx);
8436            });
8437        }
8438
8439        self.unmark_text(cx);
8440    }
8441
8442    fn replace_and_mark_text_in_range(
8443        &mut self,
8444        range_utf16: Option<Range<usize>>,
8445        text: &str,
8446        new_selected_range_utf16: Option<Range<usize>>,
8447        cx: &mut ViewContext<Self>,
8448    ) {
8449        if !self.input_enabled {
8450            return;
8451        }
8452
8453        let transaction = self.transact(cx, |this, cx| {
8454            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8455                let snapshot = this.buffer.read(cx).read(cx);
8456                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8457                    for marked_range in &mut marked_ranges {
8458                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8459                        marked_range.start.0 += relative_range_utf16.start;
8460                        marked_range.start =
8461                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8462                        marked_range.end =
8463                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8464                    }
8465                }
8466                Some(marked_ranges)
8467            } else if let Some(range_utf16) = range_utf16 {
8468                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8469                Some(this.selection_replacement_ranges(range_utf16, cx))
8470            } else {
8471                None
8472            };
8473
8474            if let Some(ranges) = ranges_to_replace {
8475                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8476            }
8477
8478            let marked_ranges = {
8479                let snapshot = this.buffer.read(cx).read(cx);
8480                this.selections
8481                    .disjoint_anchors()
8482                    .iter()
8483                    .map(|selection| {
8484                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8485                    })
8486                    .collect::<Vec<_>>()
8487            };
8488
8489            if text.is_empty() {
8490                this.unmark_text(cx);
8491            } else {
8492                this.highlight_text::<InputComposition>(
8493                    marked_ranges.clone(),
8494                    this.style(cx).composition_mark,
8495                    cx,
8496                );
8497            }
8498
8499            this.handle_input(text, cx);
8500
8501            if let Some(new_selected_range) = new_selected_range_utf16 {
8502                let snapshot = this.buffer.read(cx).read(cx);
8503                let new_selected_ranges = marked_ranges
8504                    .into_iter()
8505                    .map(|marked_range| {
8506                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8507                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8508                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8509                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8510                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8511                    })
8512                    .collect::<Vec<_>>();
8513
8514                drop(snapshot);
8515                this.change_selections(None, cx, |selections| {
8516                    selections.select_ranges(new_selected_ranges)
8517                });
8518            }
8519        });
8520
8521        self.ime_transaction = self.ime_transaction.or(transaction);
8522        if let Some(transaction) = self.ime_transaction {
8523            self.buffer.update(cx, |buffer, cx| {
8524                buffer.group_until_transaction(transaction, cx);
8525            });
8526        }
8527
8528        if self.text_highlights::<InputComposition>(cx).is_none() {
8529            self.ime_transaction.take();
8530        }
8531    }
8532}
8533
8534fn build_style(
8535    settings: &ThemeSettings,
8536    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8537    override_text_style: Option<&OverrideTextStyle>,
8538    cx: &AppContext,
8539) -> EditorStyle {
8540    let font_cache = cx.font_cache();
8541    let line_height_scalar = settings.line_height();
8542    let theme_id = settings.theme.meta.id;
8543    let mut theme = settings.theme.editor.clone();
8544    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8545        let field_editor_theme = get_field_editor_theme(&settings.theme);
8546        theme.text_color = field_editor_theme.text.color;
8547        theme.selection = field_editor_theme.selection;
8548        theme.background = field_editor_theme
8549            .container
8550            .background_color
8551            .unwrap_or_default();
8552        EditorStyle {
8553            text: field_editor_theme.text,
8554            placeholder_text: field_editor_theme.placeholder_text,
8555            line_height_scalar,
8556            theme,
8557            theme_id,
8558        }
8559    } else {
8560        let font_family_id = settings.buffer_font_family;
8561        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8562        let font_properties = Default::default();
8563        let font_id = font_cache
8564            .select_font(font_family_id, &font_properties)
8565            .unwrap();
8566        let font_size = settings.buffer_font_size(cx);
8567        EditorStyle {
8568            text: TextStyle {
8569                color: settings.theme.editor.text_color,
8570                font_family_name,
8571                font_family_id,
8572                font_id,
8573                font_size,
8574                font_properties,
8575                underline: Default::default(),
8576                soft_wrap: false,
8577            },
8578            placeholder_text: None,
8579            line_height_scalar,
8580            theme,
8581            theme_id,
8582        }
8583    };
8584
8585    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8586        if let Some(highlighted) = style
8587            .text
8588            .clone()
8589            .highlight(highlight_style, font_cache)
8590            .log_err()
8591        {
8592            style.text = highlighted;
8593        }
8594    }
8595
8596    style
8597}
8598
8599trait SelectionExt {
8600    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8601    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8602    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8603    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8604        -> Range<u32>;
8605}
8606
8607impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8608    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8609        let start = self.start.to_point(buffer);
8610        let end = self.end.to_point(buffer);
8611        if self.reversed {
8612            end..start
8613        } else {
8614            start..end
8615        }
8616    }
8617
8618    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8619        let start = self.start.to_offset(buffer);
8620        let end = self.end.to_offset(buffer);
8621        if self.reversed {
8622            end..start
8623        } else {
8624            start..end
8625        }
8626    }
8627
8628    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8629        let start = self
8630            .start
8631            .to_point(&map.buffer_snapshot)
8632            .to_display_point(map);
8633        let end = self
8634            .end
8635            .to_point(&map.buffer_snapshot)
8636            .to_display_point(map);
8637        if self.reversed {
8638            end..start
8639        } else {
8640            start..end
8641        }
8642    }
8643
8644    fn spanned_rows(
8645        &self,
8646        include_end_if_at_line_start: bool,
8647        map: &DisplaySnapshot,
8648    ) -> Range<u32> {
8649        let start = self.start.to_point(&map.buffer_snapshot);
8650        let mut end = self.end.to_point(&map.buffer_snapshot);
8651        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8652            end.row -= 1;
8653        }
8654
8655        let buffer_start = map.prev_line_boundary(start).0;
8656        let buffer_end = map.next_line_boundary(end).0;
8657        buffer_start.row..buffer_end.row + 1
8658    }
8659}
8660
8661impl<T: InvalidationRegion> InvalidationStack<T> {
8662    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8663    where
8664        S: Clone + ToOffset,
8665    {
8666        while let Some(region) = self.last() {
8667            let all_selections_inside_invalidation_ranges =
8668                if selections.len() == region.ranges().len() {
8669                    selections
8670                        .iter()
8671                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8672                        .all(|(selection, invalidation_range)| {
8673                            let head = selection.head().to_offset(buffer);
8674                            invalidation_range.start <= head && invalidation_range.end >= head
8675                        })
8676                } else {
8677                    false
8678                };
8679
8680            if all_selections_inside_invalidation_ranges {
8681                break;
8682            } else {
8683                self.pop();
8684            }
8685        }
8686    }
8687}
8688
8689impl<T> Default for InvalidationStack<T> {
8690    fn default() -> Self {
8691        Self(Default::default())
8692    }
8693}
8694
8695impl<T> Deref for InvalidationStack<T> {
8696    type Target = Vec<T>;
8697
8698    fn deref(&self) -> &Self::Target {
8699        &self.0
8700    }
8701}
8702
8703impl<T> DerefMut for InvalidationStack<T> {
8704    fn deref_mut(&mut self) -> &mut Self::Target {
8705        &mut self.0
8706    }
8707}
8708
8709impl InvalidationRegion for SnippetState {
8710    fn ranges(&self) -> &[Range<Anchor>] {
8711        &self.ranges[self.active_index]
8712    }
8713}
8714
8715impl Deref for EditorStyle {
8716    type Target = theme::Editor;
8717
8718    fn deref(&self) -> &Self::Target {
8719        &self.theme
8720    }
8721}
8722
8723pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8724    let mut highlighted_lines = Vec::new();
8725
8726    for (index, line) in diagnostic.message.lines().enumerate() {
8727        let line = match &diagnostic.source {
8728            Some(source) if index == 0 => {
8729                let source_highlight = Vec::from_iter(0..source.len());
8730                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8731            }
8732
8733            _ => highlight_diagnostic_message(Vec::new(), line),
8734        };
8735        highlighted_lines.push(line);
8736    }
8737    let message = diagnostic.message;
8738    Arc::new(move |cx: &mut BlockContext| {
8739        let message = message.clone();
8740        let settings = settings::get::<ThemeSettings>(cx);
8741        let tooltip_style = settings.theme.tooltip.clone();
8742        let theme = &settings.theme.editor;
8743        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8744        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8745        let anchor_x = cx.anchor_x;
8746        enum BlockContextToolip {}
8747        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
8748            Flex::column()
8749                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8750                    Label::new(
8751                        line.clone(),
8752                        style.message.clone().with_font_size(font_size),
8753                    )
8754                    .with_highlights(highlights.clone())
8755                    .contained()
8756                    .with_margin_left(anchor_x)
8757                }))
8758                .aligned()
8759                .left()
8760                .into_any()
8761        })
8762        .with_cursor_style(CursorStyle::PointingHand)
8763        .on_click(MouseButton::Left, move |_, _, cx| {
8764            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8765        })
8766        // We really need to rethink this ID system...
8767        .with_tooltip::<BlockContextToolip>(
8768            cx.block_id,
8769            "Copy diagnostic message",
8770            None,
8771            tooltip_style,
8772            cx,
8773        )
8774        .into_any()
8775    })
8776}
8777
8778pub fn highlight_diagnostic_message(
8779    initial_highlights: Vec<usize>,
8780    message: &str,
8781) -> (String, Vec<usize>) {
8782    let mut message_without_backticks = String::new();
8783    let mut prev_offset = 0;
8784    let mut inside_block = false;
8785    let mut highlights = initial_highlights;
8786    for (match_ix, (offset, _)) in message
8787        .match_indices('`')
8788        .chain([(message.len(), "")])
8789        .enumerate()
8790    {
8791        message_without_backticks.push_str(&message[prev_offset..offset]);
8792        if inside_block {
8793            highlights.extend(prev_offset - match_ix..offset - match_ix);
8794        }
8795
8796        inside_block = !inside_block;
8797        prev_offset = offset + 1;
8798    }
8799
8800    (message_without_backticks, highlights)
8801}
8802
8803pub fn diagnostic_style(
8804    severity: DiagnosticSeverity,
8805    valid: bool,
8806    theme: &theme::Editor,
8807) -> DiagnosticStyle {
8808    match (severity, valid) {
8809        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8810        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8811        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8812        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8813        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8814        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8815        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8816        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8817        _ => theme.invalid_hint_diagnostic.clone(),
8818    }
8819}
8820
8821pub fn combine_syntax_and_fuzzy_match_highlights(
8822    text: &str,
8823    default_style: HighlightStyle,
8824    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
8825    match_indices: &[usize],
8826) -> Vec<(Range<usize>, HighlightStyle)> {
8827    let mut result = Vec::new();
8828    let mut match_indices = match_indices.iter().copied().peekable();
8829
8830    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
8831    {
8832        syntax_highlight.weight = None;
8833
8834        // Add highlights for any fuzzy match characters before the next
8835        // syntax highlight range.
8836        while let Some(&match_index) = match_indices.peek() {
8837            if match_index >= range.start {
8838                break;
8839            }
8840            match_indices.next();
8841            let end_index = char_ix_after(match_index, text);
8842            let mut match_style = default_style;
8843            match_style.weight = Some(fonts::Weight::BOLD);
8844            result.push((match_index..end_index, match_style));
8845        }
8846
8847        if range.start == usize::MAX {
8848            break;
8849        }
8850
8851        // Add highlights for any fuzzy match characters within the
8852        // syntax highlight range.
8853        let mut offset = range.start;
8854        while let Some(&match_index) = match_indices.peek() {
8855            if match_index >= range.end {
8856                break;
8857            }
8858
8859            match_indices.next();
8860            if match_index > offset {
8861                result.push((offset..match_index, syntax_highlight));
8862            }
8863
8864            let mut end_index = char_ix_after(match_index, text);
8865            while let Some(&next_match_index) = match_indices.peek() {
8866                if next_match_index == end_index && next_match_index < range.end {
8867                    end_index = char_ix_after(next_match_index, text);
8868                    match_indices.next();
8869                } else {
8870                    break;
8871                }
8872            }
8873
8874            let mut match_style = syntax_highlight;
8875            match_style.weight = Some(fonts::Weight::BOLD);
8876            result.push((match_index..end_index, match_style));
8877            offset = end_index;
8878        }
8879
8880        if offset < range.end {
8881            result.push((offset..range.end, syntax_highlight));
8882        }
8883    }
8884
8885    fn char_ix_after(ix: usize, text: &str) -> usize {
8886        ix + text[ix..].chars().next().unwrap().len_utf8()
8887    }
8888
8889    result
8890}
8891
8892pub fn styled_runs_for_code_label<'a>(
8893    label: &'a CodeLabel,
8894    syntax_theme: &'a theme::SyntaxTheme,
8895) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
8896    let fade_out = HighlightStyle {
8897        fade_out: Some(0.35),
8898        ..Default::default()
8899    };
8900
8901    let mut prev_end = label.filter_range.end;
8902    label
8903        .runs
8904        .iter()
8905        .enumerate()
8906        .flat_map(move |(ix, (range, highlight_id))| {
8907            let style = if let Some(style) = highlight_id.style(syntax_theme) {
8908                style
8909            } else {
8910                return Default::default();
8911            };
8912            let mut muted_style = style;
8913            muted_style.highlight(fade_out);
8914
8915            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
8916            if range.start >= label.filter_range.end {
8917                if range.start > prev_end {
8918                    runs.push((prev_end..range.start, fade_out));
8919                }
8920                runs.push((range.clone(), muted_style));
8921            } else if range.end <= label.filter_range.end {
8922                runs.push((range.clone(), style));
8923            } else {
8924                runs.push((range.start..label.filter_range.end, style));
8925                runs.push((label.filter_range.end..range.end, muted_style));
8926            }
8927            prev_end = cmp::max(prev_end, range.end);
8928
8929            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
8930                runs.push((prev_end..label.text.len(), fade_out));
8931            }
8932
8933            runs
8934        })
8935}
8936
8937pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
8938    let mut index = 0;
8939    let mut codepoints = text.char_indices().peekable();
8940
8941    std::iter::from_fn(move || {
8942        let start_index = index;
8943        while let Some((new_index, codepoint)) = codepoints.next() {
8944            index = new_index + codepoint.len_utf8();
8945            let current_upper = codepoint.is_uppercase();
8946            let next_upper = codepoints
8947                .peek()
8948                .map(|(_, c)| c.is_uppercase())
8949                .unwrap_or(false);
8950
8951            if !current_upper && next_upper {
8952                return Some(&text[start_index..index]);
8953            }
8954        }
8955
8956        index = text.len();
8957        if start_index < text.len() {
8958            return Some(&text[start_index..]);
8959        }
8960        None
8961    })
8962    .flat_map(|word| word.split_inclusive('_'))
8963}
8964
8965trait RangeToAnchorExt {
8966    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
8967}
8968
8969impl<T: ToOffset> RangeToAnchorExt for Range<T> {
8970    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
8971        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
8972    }
8973}