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