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