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