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                let InlaySplice {
2796                    to_remove,
2797                    to_insert,
2798                } = self.inlay_hint_cache.remove_excerpts(excerpts_removed);
2799                self.splice_inlay_hints(to_remove, to_insert, cx);
2800                return;
2801            }
2802            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
2803            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
2804                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
2805            }
2806            InlayHintRefreshReason::RefreshRequested => {
2807                (InvalidationStrategy::RefreshRequested, None)
2808            }
2809        };
2810
2811        if let Some(InlaySplice {
2812            to_remove,
2813            to_insert,
2814        }) = self.inlay_hint_cache.spawn_hint_refresh(
2815            reason_description,
2816            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
2817            invalidate_cache,
2818            cx,
2819        ) {
2820            self.splice_inlay_hints(to_remove, to_insert, cx);
2821        }
2822    }
2823
2824    fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> {
2825        self.display_map
2826            .read(cx)
2827            .current_inlays()
2828            .filter(move |inlay| {
2829                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
2830            })
2831            .cloned()
2832            .collect()
2833    }
2834
2835    pub fn excerpt_visible_offsets(
2836        &self,
2837        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
2838        cx: &mut ViewContext<'_, '_, Editor>,
2839    ) -> HashMap<ExcerptId, (ModelHandle<Buffer>, Global, Range<usize>)> {
2840        let multi_buffer = self.buffer().read(cx);
2841        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
2842        let multi_buffer_visible_start = self
2843            .scroll_manager
2844            .anchor()
2845            .anchor
2846            .to_point(&multi_buffer_snapshot);
2847        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
2848            multi_buffer_visible_start
2849                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
2850            Bias::Left,
2851        );
2852        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
2853        multi_buffer
2854            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
2855            .into_iter()
2856            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
2857            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
2858                let buffer = buffer_handle.read(cx);
2859                let language = buffer.language()?;
2860                if let Some(restrict_to_languages) = restrict_to_languages {
2861                    if !restrict_to_languages.contains(language) {
2862                        return None;
2863                    }
2864                }
2865                Some((
2866                    excerpt_id,
2867                    (
2868                        buffer_handle,
2869                        buffer.version().clone(),
2870                        excerpt_visible_range,
2871                    ),
2872                ))
2873            })
2874            .collect()
2875    }
2876
2877    fn splice_inlay_hints(
2878        &self,
2879        to_remove: Vec<InlayId>,
2880        to_insert: Vec<Inlay>,
2881        cx: &mut ViewContext<Self>,
2882    ) {
2883        self.display_map.update(cx, |display_map, cx| {
2884            display_map.splice_inlays(to_remove, to_insert, cx);
2885        });
2886        cx.notify();
2887    }
2888
2889    fn trigger_on_type_formatting(
2890        &self,
2891        input: String,
2892        cx: &mut ViewContext<Self>,
2893    ) -> Option<Task<Result<()>>> {
2894        if input.len() != 1 {
2895            return None;
2896        }
2897
2898        let project = self.project.as_ref()?;
2899        let position = self.selections.newest_anchor().head();
2900        let (buffer, buffer_position) = self
2901            .buffer
2902            .read(cx)
2903            .text_anchor_for_position(position.clone(), cx)?;
2904
2905        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
2906        // hence we do LSP request & edit on host side only — add formats to host's history.
2907        let push_to_lsp_host_history = true;
2908        // If this is not the host, append its history with new edits.
2909        let push_to_client_history = project.read(cx).is_remote();
2910
2911        let on_type_formatting = project.update(cx, |project, cx| {
2912            project.on_type_format(
2913                buffer.clone(),
2914                buffer_position,
2915                input,
2916                push_to_lsp_host_history,
2917                cx,
2918            )
2919        });
2920        Some(cx.spawn(|editor, mut cx| async move {
2921            if let Some(transaction) = on_type_formatting.await? {
2922                if push_to_client_history {
2923                    buffer.update(&mut cx, |buffer, _| {
2924                        buffer.push_transaction(transaction, Instant::now());
2925                    });
2926                }
2927                editor.update(&mut cx, |editor, cx| {
2928                    editor.refresh_document_highlights(cx);
2929                })?;
2930            }
2931            Ok(())
2932        }))
2933    }
2934
2935    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2936        if self.pending_rename.is_some() {
2937            return;
2938        }
2939
2940        let project = if let Some(project) = self.project.clone() {
2941            project
2942        } else {
2943            return;
2944        };
2945
2946        let position = self.selections.newest_anchor().head();
2947        let (buffer, buffer_position) = if let Some(output) = self
2948            .buffer
2949            .read(cx)
2950            .text_anchor_for_position(position.clone(), cx)
2951        {
2952            output
2953        } else {
2954            return;
2955        };
2956
2957        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2958        let completions = project.update(cx, |project, cx| {
2959            project.completions(&buffer, buffer_position, cx)
2960        });
2961
2962        let id = post_inc(&mut self.next_completion_id);
2963        let task = cx.spawn(|this, mut cx| {
2964            async move {
2965                let menu = if let Some(completions) = completions.await.log_err() {
2966                    let mut menu = CompletionsMenu {
2967                        id,
2968                        initial_position: position,
2969                        match_candidates: completions
2970                            .iter()
2971                            .enumerate()
2972                            .map(|(id, completion)| {
2973                                StringMatchCandidate::new(
2974                                    id,
2975                                    completion.label.text[completion.label.filter_range.clone()]
2976                                        .into(),
2977                                )
2978                            })
2979                            .collect(),
2980                        buffer,
2981                        completions: completions.into(),
2982                        matches: Vec::new().into(),
2983                        selected_item: 0,
2984                        list: Default::default(),
2985                    };
2986                    menu.filter(query.as_deref(), cx.background()).await;
2987                    if menu.matches.is_empty() {
2988                        None
2989                    } else {
2990                        Some(menu)
2991                    }
2992                } else {
2993                    None
2994                };
2995
2996                this.update(&mut cx, |this, cx| {
2997                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2998
2999                    match this.context_menu.as_ref() {
3000                        None => {}
3001                        Some(ContextMenu::Completions(prev_menu)) => {
3002                            if prev_menu.id > id {
3003                                return;
3004                            }
3005                        }
3006                        _ => return,
3007                    }
3008
3009                    if this.focused && menu.is_some() {
3010                        let menu = menu.unwrap();
3011                        this.show_context_menu(ContextMenu::Completions(menu), cx);
3012                    } else if this.completion_tasks.is_empty() {
3013                        // If there are no more completion tasks and the last menu was
3014                        // empty, we should hide it. If it was already hidden, we should
3015                        // also show the copilot suggestion when available.
3016                        if this.hide_context_menu(cx).is_none() {
3017                            this.update_visible_copilot_suggestion(cx);
3018                        }
3019                    }
3020                })?;
3021
3022                Ok::<_, anyhow::Error>(())
3023            }
3024            .log_err()
3025        });
3026        self.completion_tasks.push((id, task));
3027    }
3028
3029    pub fn confirm_completion(
3030        &mut self,
3031        action: &ConfirmCompletion,
3032        cx: &mut ViewContext<Self>,
3033    ) -> Option<Task<Result<()>>> {
3034        use language::ToOffset as _;
3035
3036        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
3037            menu
3038        } else {
3039            return None;
3040        };
3041
3042        let mat = completions_menu
3043            .matches
3044            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
3045        let buffer_handle = completions_menu.buffer;
3046        let completion = completions_menu.completions.get(mat.candidate_id)?;
3047
3048        let snippet;
3049        let text;
3050        if completion.is_snippet() {
3051            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
3052            text = snippet.as_ref().unwrap().text.clone();
3053        } else {
3054            snippet = None;
3055            text = completion.new_text.clone();
3056        };
3057        let selections = self.selections.all::<usize>(cx);
3058        let buffer = buffer_handle.read(cx);
3059        let old_range = completion.old_range.to_offset(buffer);
3060        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
3061
3062        let newest_selection = self.selections.newest_anchor();
3063        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
3064            return None;
3065        }
3066
3067        let lookbehind = newest_selection
3068            .start
3069            .text_anchor
3070            .to_offset(buffer)
3071            .saturating_sub(old_range.start);
3072        let lookahead = old_range
3073            .end
3074            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
3075        let mut common_prefix_len = old_text
3076            .bytes()
3077            .zip(text.bytes())
3078            .take_while(|(a, b)| a == b)
3079            .count();
3080
3081        let snapshot = self.buffer.read(cx).snapshot(cx);
3082        let mut ranges = Vec::new();
3083        for selection in &selections {
3084            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
3085                let start = selection.start.saturating_sub(lookbehind);
3086                let end = selection.end + lookahead;
3087                ranges.push(start + common_prefix_len..end);
3088            } else {
3089                common_prefix_len = 0;
3090                ranges.clear();
3091                ranges.extend(selections.iter().map(|s| {
3092                    if s.id == newest_selection.id {
3093                        old_range.clone()
3094                    } else {
3095                        s.start..s.end
3096                    }
3097                }));
3098                break;
3099            }
3100        }
3101        let text = &text[common_prefix_len..];
3102
3103        self.transact(cx, |this, cx| {
3104            if let Some(mut snippet) = snippet {
3105                snippet.text = text.to_string();
3106                for tabstop in snippet.tabstops.iter_mut().flatten() {
3107                    tabstop.start -= common_prefix_len as isize;
3108                    tabstop.end -= common_prefix_len as isize;
3109                }
3110
3111                this.insert_snippet(&ranges, snippet, cx).log_err();
3112            } else {
3113                this.buffer.update(cx, |buffer, cx| {
3114                    buffer.edit(
3115                        ranges.iter().map(|range| (range.clone(), text)),
3116                        this.autoindent_mode.clone(),
3117                        cx,
3118                    );
3119                });
3120            }
3121
3122            this.refresh_copilot_suggestions(true, cx);
3123        });
3124
3125        let project = self.project.clone()?;
3126        let apply_edits = project.update(cx, |project, cx| {
3127            project.apply_additional_edits_for_completion(
3128                buffer_handle,
3129                completion.clone(),
3130                true,
3131                cx,
3132            )
3133        });
3134        Some(cx.foreground().spawn(async move {
3135            apply_edits.await?;
3136            Ok(())
3137        }))
3138    }
3139
3140    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3141        if matches!(
3142            self.context_menu.as_ref(),
3143            Some(ContextMenu::CodeActions(_))
3144        ) {
3145            self.context_menu.take();
3146            cx.notify();
3147            return;
3148        }
3149
3150        let deployed_from_indicator = action.deployed_from_indicator;
3151        let mut task = self.code_actions_task.take();
3152        cx.spawn(|this, mut cx| async move {
3153            while let Some(prev_task) = task {
3154                prev_task.await;
3155                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3156            }
3157
3158            this.update(&mut cx, |this, cx| {
3159                if this.focused {
3160                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3161                        this.show_context_menu(
3162                            ContextMenu::CodeActions(CodeActionsMenu {
3163                                buffer,
3164                                actions,
3165                                selected_item: Default::default(),
3166                                list: Default::default(),
3167                                deployed_from_indicator,
3168                            }),
3169                            cx,
3170                        );
3171                    }
3172                }
3173            })?;
3174
3175            Ok::<_, anyhow::Error>(())
3176        })
3177        .detach_and_log_err(cx);
3178    }
3179
3180    pub fn confirm_code_action(
3181        workspace: &mut Workspace,
3182        action: &ConfirmCodeAction,
3183        cx: &mut ViewContext<Workspace>,
3184    ) -> Option<Task<Result<()>>> {
3185        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
3186        let actions_menu = if let ContextMenu::CodeActions(menu) =
3187            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
3188        {
3189            menu
3190        } else {
3191            return None;
3192        };
3193        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3194        let action = actions_menu.actions.get(action_ix)?.clone();
3195        let title = action.lsp_action.title.clone();
3196        let buffer = actions_menu.buffer;
3197
3198        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
3199            project.apply_code_action(buffer, action, true, cx)
3200        });
3201        let editor = editor.downgrade();
3202        Some(cx.spawn(|workspace, cx| async move {
3203            let project_transaction = apply_code_actions.await?;
3204            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3205        }))
3206    }
3207
3208    async fn open_project_transaction(
3209        this: &WeakViewHandle<Editor>,
3210        workspace: WeakViewHandle<Workspace>,
3211        transaction: ProjectTransaction,
3212        title: String,
3213        mut cx: AsyncAppContext,
3214    ) -> Result<()> {
3215        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
3216
3217        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3218        entries.sort_unstable_by_key(|(buffer, _)| {
3219            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
3220        });
3221
3222        // If the project transaction's edits are all contained within this editor, then
3223        // avoid opening a new editor to display them.
3224
3225        if let Some((buffer, transaction)) = entries.first() {
3226            if entries.len() == 1 {
3227                let excerpt = this.read_with(&cx, |editor, cx| {
3228                    editor
3229                        .buffer()
3230                        .read(cx)
3231                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3232                })?;
3233                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3234                    if excerpted_buffer == *buffer {
3235                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3236                            let excerpt_range = excerpt_range.to_offset(buffer);
3237                            buffer
3238                                .edited_ranges_for_transaction::<usize>(transaction)
3239                                .all(|range| {
3240                                    excerpt_range.start <= range.start
3241                                        && excerpt_range.end >= range.end
3242                                })
3243                        });
3244
3245                        if all_edits_within_excerpt {
3246                            return Ok(());
3247                        }
3248                    }
3249                }
3250            }
3251        } else {
3252            return Ok(());
3253        }
3254
3255        let mut ranges_to_highlight = Vec::new();
3256        let excerpt_buffer = cx.add_model(|cx| {
3257            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3258            for (buffer_handle, transaction) in &entries {
3259                let buffer = buffer_handle.read(cx);
3260                ranges_to_highlight.extend(
3261                    multibuffer.push_excerpts_with_context_lines(
3262                        buffer_handle.clone(),
3263                        buffer
3264                            .edited_ranges_for_transaction::<usize>(transaction)
3265                            .collect(),
3266                        1,
3267                        cx,
3268                    ),
3269                );
3270            }
3271            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3272            multibuffer
3273        });
3274
3275        workspace.update(&mut cx, |workspace, cx| {
3276            let project = workspace.project().clone();
3277            let editor =
3278                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3279            workspace.add_item(Box::new(editor.clone()), cx);
3280            editor.update(cx, |editor, cx| {
3281                editor.highlight_background::<Self>(
3282                    ranges_to_highlight,
3283                    |theme| theme.editor.highlighted_line_background,
3284                    cx,
3285                );
3286            });
3287        })?;
3288
3289        Ok(())
3290    }
3291
3292    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3293        let project = self.project.as_ref()?;
3294        let buffer = self.buffer.read(cx);
3295        let newest_selection = self.selections.newest_anchor().clone();
3296        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3297        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3298        if start_buffer != end_buffer {
3299            return None;
3300        }
3301
3302        let actions = project.update(cx, |project, cx| {
3303            project.code_actions(&start_buffer, start..end, cx)
3304        });
3305        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3306            let actions = actions.await;
3307            this.update(&mut cx, |this, cx| {
3308                this.available_code_actions = actions.log_err().and_then(|actions| {
3309                    if actions.is_empty() {
3310                        None
3311                    } else {
3312                        Some((start_buffer, actions.into()))
3313                    }
3314                });
3315                cx.notify();
3316            })
3317            .log_err();
3318        }));
3319        None
3320    }
3321
3322    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3323        if self.pending_rename.is_some() {
3324            return None;
3325        }
3326
3327        let project = self.project.as_ref()?;
3328        let buffer = self.buffer.read(cx);
3329        let newest_selection = self.selections.newest_anchor().clone();
3330        let cursor_position = newest_selection.head();
3331        let (cursor_buffer, cursor_buffer_position) =
3332            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3333        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3334        if cursor_buffer != tail_buffer {
3335            return None;
3336        }
3337
3338        let highlights = project.update(cx, |project, cx| {
3339            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3340        });
3341
3342        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3343            if let Some(highlights) = highlights.await.log_err() {
3344                this.update(&mut cx, |this, cx| {
3345                    if this.pending_rename.is_some() {
3346                        return;
3347                    }
3348
3349                    let buffer_id = cursor_position.buffer_id;
3350                    let buffer = this.buffer.read(cx);
3351                    if !buffer
3352                        .text_anchor_for_position(cursor_position, cx)
3353                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3354                    {
3355                        return;
3356                    }
3357
3358                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3359                    let mut write_ranges = Vec::new();
3360                    let mut read_ranges = Vec::new();
3361                    for highlight in highlights {
3362                        for (excerpt_id, excerpt_range) in
3363                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3364                        {
3365                            let start = highlight
3366                                .range
3367                                .start
3368                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3369                            let end = highlight
3370                                .range
3371                                .end
3372                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3373                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3374                                continue;
3375                            }
3376
3377                            let range = Anchor {
3378                                buffer_id,
3379                                excerpt_id: excerpt_id.clone(),
3380                                text_anchor: start,
3381                            }..Anchor {
3382                                buffer_id,
3383                                excerpt_id,
3384                                text_anchor: end,
3385                            };
3386                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3387                                write_ranges.push(range);
3388                            } else {
3389                                read_ranges.push(range);
3390                            }
3391                        }
3392                    }
3393
3394                    this.highlight_background::<DocumentHighlightRead>(
3395                        read_ranges,
3396                        |theme| theme.editor.document_highlight_read_background,
3397                        cx,
3398                    );
3399                    this.highlight_background::<DocumentHighlightWrite>(
3400                        write_ranges,
3401                        |theme| theme.editor.document_highlight_write_background,
3402                        cx,
3403                    );
3404                    cx.notify();
3405                })
3406                .log_err();
3407            }
3408        }));
3409        None
3410    }
3411
3412    fn refresh_copilot_suggestions(
3413        &mut self,
3414        debounce: bool,
3415        cx: &mut ViewContext<Self>,
3416    ) -> Option<()> {
3417        let copilot = Copilot::global(cx)?;
3418        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3419            self.clear_copilot_suggestions(cx);
3420            return None;
3421        }
3422        self.update_visible_copilot_suggestion(cx);
3423
3424        let snapshot = self.buffer.read(cx).snapshot(cx);
3425        let cursor = self.selections.newest_anchor().head();
3426        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3427            self.clear_copilot_suggestions(cx);
3428            return None;
3429        }
3430
3431        let (buffer, buffer_position) =
3432            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3433        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3434            if debounce {
3435                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3436            }
3437
3438            let completions = copilot
3439                .update(&mut cx, |copilot, cx| {
3440                    copilot.completions(&buffer, buffer_position, cx)
3441                })
3442                .await
3443                .log_err()
3444                .into_iter()
3445                .flatten()
3446                .collect_vec();
3447
3448            this.update(&mut cx, |this, cx| {
3449                if !completions.is_empty() {
3450                    this.copilot_state.cycled = false;
3451                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3452                    this.copilot_state.completions.clear();
3453                    this.copilot_state.active_completion_index = 0;
3454                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3455                    for completion in completions {
3456                        this.copilot_state.push_completion(completion);
3457                    }
3458                    this.update_visible_copilot_suggestion(cx);
3459                }
3460            })
3461            .log_err()?;
3462            Some(())
3463        });
3464
3465        Some(())
3466    }
3467
3468    fn cycle_copilot_suggestions(
3469        &mut self,
3470        direction: Direction,
3471        cx: &mut ViewContext<Self>,
3472    ) -> Option<()> {
3473        let copilot = Copilot::global(cx)?;
3474        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3475            return None;
3476        }
3477
3478        if self.copilot_state.cycled {
3479            self.copilot_state.cycle_completions(direction);
3480            self.update_visible_copilot_suggestion(cx);
3481        } else {
3482            let cursor = self.selections.newest_anchor().head();
3483            let (buffer, buffer_position) =
3484                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3485            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3486                let completions = copilot
3487                    .update(&mut cx, |copilot, cx| {
3488                        copilot.completions_cycling(&buffer, buffer_position, cx)
3489                    })
3490                    .await;
3491
3492                this.update(&mut cx, |this, cx| {
3493                    this.copilot_state.cycled = true;
3494                    for completion in completions.log_err().into_iter().flatten() {
3495                        this.copilot_state.push_completion(completion);
3496                    }
3497                    this.copilot_state.cycle_completions(direction);
3498                    this.update_visible_copilot_suggestion(cx);
3499                })
3500                .log_err()?;
3501
3502                Some(())
3503            });
3504        }
3505
3506        Some(())
3507    }
3508
3509    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3510        if !self.has_active_copilot_suggestion(cx) {
3511            self.refresh_copilot_suggestions(false, cx);
3512            return;
3513        }
3514
3515        self.update_visible_copilot_suggestion(cx);
3516    }
3517
3518    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3519        if self.has_active_copilot_suggestion(cx) {
3520            self.cycle_copilot_suggestions(Direction::Next, cx);
3521        } else {
3522            self.refresh_copilot_suggestions(false, cx);
3523        }
3524    }
3525
3526    fn previous_copilot_suggestion(
3527        &mut self,
3528        _: &copilot::PreviousSuggestion,
3529        cx: &mut ViewContext<Self>,
3530    ) {
3531        if self.has_active_copilot_suggestion(cx) {
3532            self.cycle_copilot_suggestions(Direction::Prev, cx);
3533        } else {
3534            self.refresh_copilot_suggestions(false, cx);
3535        }
3536    }
3537
3538    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3539        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3540            if let Some((copilot, completion)) =
3541                Copilot::global(cx).zip(self.copilot_state.active_completion())
3542            {
3543                copilot
3544                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3545                    .detach_and_log_err(cx);
3546
3547                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3548            }
3549            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3550            cx.notify();
3551            true
3552        } else {
3553            false
3554        }
3555    }
3556
3557    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3558        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3559            if let Some(copilot) = Copilot::global(cx) {
3560                copilot
3561                    .update(cx, |copilot, cx| {
3562                        copilot.discard_completions(&self.copilot_state.completions, cx)
3563                    })
3564                    .detach_and_log_err(cx);
3565
3566                self.report_copilot_event(None, false, cx)
3567            }
3568
3569            self.display_map.update(cx, |map, cx| {
3570                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
3571            });
3572            cx.notify();
3573            true
3574        } else {
3575            false
3576        }
3577    }
3578
3579    fn is_copilot_enabled_at(
3580        &self,
3581        location: Anchor,
3582        snapshot: &MultiBufferSnapshot,
3583        cx: &mut ViewContext<Self>,
3584    ) -> bool {
3585        let file = snapshot.file_at(location);
3586        let language = snapshot.language_at(location);
3587        let settings = all_language_settings(file, cx);
3588        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3589    }
3590
3591    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3592        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3593            let buffer = self.buffer.read(cx).read(cx);
3594            suggestion.position.is_valid(&buffer)
3595        } else {
3596            false
3597        }
3598    }
3599
3600    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3601        let suggestion = self.copilot_state.suggestion.take()?;
3602        self.display_map.update(cx, |map, cx| {
3603            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
3604        });
3605        let buffer = self.buffer.read(cx).read(cx);
3606
3607        if suggestion.position.is_valid(&buffer) {
3608            Some(suggestion)
3609        } else {
3610            None
3611        }
3612    }
3613
3614    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3615        let snapshot = self.buffer.read(cx).snapshot(cx);
3616        let selection = self.selections.newest_anchor();
3617        let cursor = selection.head();
3618
3619        if self.context_menu.is_some()
3620            || !self.completion_tasks.is_empty()
3621            || selection.start != selection.end
3622        {
3623            self.discard_copilot_suggestion(cx);
3624        } else if let Some(text) = self
3625            .copilot_state
3626            .text_for_active_completion(cursor, &snapshot)
3627        {
3628            let text = Rope::from(text);
3629            let mut to_remove = Vec::new();
3630            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3631                to_remove.push(suggestion.id);
3632            }
3633
3634            let suggestion_inlay =
3635                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
3636            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
3637            self.display_map.update(cx, move |map, cx| {
3638                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
3639            });
3640            cx.notify();
3641        } else {
3642            self.discard_copilot_suggestion(cx);
3643        }
3644    }
3645
3646    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3647        self.copilot_state = Default::default();
3648        self.discard_copilot_suggestion(cx);
3649    }
3650
3651    pub fn render_code_actions_indicator(
3652        &self,
3653        style: &EditorStyle,
3654        is_active: bool,
3655        cx: &mut ViewContext<Self>,
3656    ) -> Option<AnyElement<Self>> {
3657        if self.available_code_actions.is_some() {
3658            enum CodeActions {}
3659            Some(
3660                MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
3661                    Svg::new("icons/bolt_8.svg").with_color(
3662                        style
3663                            .code_actions
3664                            .indicator
3665                            .in_state(is_active)
3666                            .style_for(state)
3667                            .color,
3668                    )
3669                })
3670                .with_cursor_style(CursorStyle::PointingHand)
3671                .with_padding(Padding::uniform(3.))
3672                .on_down(MouseButton::Left, |_, this, cx| {
3673                    this.toggle_code_actions(
3674                        &ToggleCodeActions {
3675                            deployed_from_indicator: true,
3676                        },
3677                        cx,
3678                    );
3679                })
3680                .into_any(),
3681            )
3682        } else {
3683            None
3684        }
3685    }
3686
3687    pub fn render_fold_indicators(
3688        &self,
3689        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3690        style: &EditorStyle,
3691        gutter_hovered: bool,
3692        line_height: f32,
3693        gutter_margin: f32,
3694        cx: &mut ViewContext<Self>,
3695    ) -> Vec<Option<AnyElement<Self>>> {
3696        enum FoldIndicators {}
3697
3698        let style = style.folds.clone();
3699
3700        fold_data
3701            .iter()
3702            .enumerate()
3703            .map(|(ix, fold_data)| {
3704                fold_data
3705                    .map(|(fold_status, buffer_row, active)| {
3706                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3707                            MouseEventHandler::new::<FoldIndicators, _>(
3708                                ix as usize,
3709                                cx,
3710                                |mouse_state, _| {
3711                                    Svg::new(match fold_status {
3712                                        FoldStatus::Folded => style.folded_icon.clone(),
3713                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3714                                    })
3715                                    .with_color(
3716                                        style
3717                                            .indicator
3718                                            .in_state(fold_status == FoldStatus::Folded)
3719                                            .style_for(mouse_state)
3720                                            .color,
3721                                    )
3722                                    .constrained()
3723                                    .with_width(gutter_margin * style.icon_margin_scale)
3724                                    .aligned()
3725                                    .constrained()
3726                                    .with_height(line_height)
3727                                    .with_width(gutter_margin)
3728                                    .aligned()
3729                                },
3730                            )
3731                            .with_cursor_style(CursorStyle::PointingHand)
3732                            .with_padding(Padding::uniform(3.))
3733                            .on_click(MouseButton::Left, {
3734                                move |_, editor, cx| match fold_status {
3735                                    FoldStatus::Folded => {
3736                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3737                                    }
3738                                    FoldStatus::Foldable => {
3739                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3740                                    }
3741                                }
3742                            })
3743                            .into_any()
3744                        })
3745                    })
3746                    .flatten()
3747            })
3748            .collect()
3749    }
3750
3751    pub fn context_menu_visible(&self) -> bool {
3752        self.context_menu
3753            .as_ref()
3754            .map_or(false, |menu| menu.visible())
3755    }
3756
3757    pub fn render_context_menu(
3758        &self,
3759        cursor_position: DisplayPoint,
3760        style: EditorStyle,
3761        cx: &mut ViewContext<Editor>,
3762    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3763        self.context_menu
3764            .as_ref()
3765            .map(|menu| menu.render(cursor_position, style, cx))
3766    }
3767
3768    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3769        if !matches!(menu, ContextMenu::Completions(_)) {
3770            self.completion_tasks.clear();
3771        }
3772        self.context_menu = Some(menu);
3773        self.discard_copilot_suggestion(cx);
3774        cx.notify();
3775    }
3776
3777    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3778        cx.notify();
3779        self.completion_tasks.clear();
3780        let context_menu = self.context_menu.take();
3781        if context_menu.is_some() {
3782            self.update_visible_copilot_suggestion(cx);
3783        }
3784        context_menu
3785    }
3786
3787    pub fn insert_snippet(
3788        &mut self,
3789        insertion_ranges: &[Range<usize>],
3790        snippet: Snippet,
3791        cx: &mut ViewContext<Self>,
3792    ) -> Result<()> {
3793        let tabstops = self.buffer.update(cx, |buffer, cx| {
3794            let snippet_text: Arc<str> = snippet.text.clone().into();
3795            buffer.edit(
3796                insertion_ranges
3797                    .iter()
3798                    .cloned()
3799                    .map(|range| (range, snippet_text.clone())),
3800                Some(AutoindentMode::EachLine),
3801                cx,
3802            );
3803
3804            let snapshot = &*buffer.read(cx);
3805            let snippet = &snippet;
3806            snippet
3807                .tabstops
3808                .iter()
3809                .map(|tabstop| {
3810                    let mut tabstop_ranges = tabstop
3811                        .iter()
3812                        .flat_map(|tabstop_range| {
3813                            let mut delta = 0_isize;
3814                            insertion_ranges.iter().map(move |insertion_range| {
3815                                let insertion_start = insertion_range.start as isize + delta;
3816                                delta +=
3817                                    snippet.text.len() as isize - insertion_range.len() as isize;
3818
3819                                let start = snapshot.anchor_before(
3820                                    (insertion_start + tabstop_range.start) as usize,
3821                                );
3822                                let end = snapshot
3823                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3824                                start..end
3825                            })
3826                        })
3827                        .collect::<Vec<_>>();
3828                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3829                    tabstop_ranges
3830                })
3831                .collect::<Vec<_>>()
3832        });
3833
3834        if let Some(tabstop) = tabstops.first() {
3835            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3836                s.select_ranges(tabstop.iter().cloned());
3837            });
3838            self.snippet_stack.push(SnippetState {
3839                active_index: 0,
3840                ranges: tabstops,
3841            });
3842        }
3843
3844        Ok(())
3845    }
3846
3847    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3848        self.move_to_snippet_tabstop(Bias::Right, cx)
3849    }
3850
3851    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3852        self.move_to_snippet_tabstop(Bias::Left, cx)
3853    }
3854
3855    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3856        if let Some(mut snippet) = self.snippet_stack.pop() {
3857            match bias {
3858                Bias::Left => {
3859                    if snippet.active_index > 0 {
3860                        snippet.active_index -= 1;
3861                    } else {
3862                        self.snippet_stack.push(snippet);
3863                        return false;
3864                    }
3865                }
3866                Bias::Right => {
3867                    if snippet.active_index + 1 < snippet.ranges.len() {
3868                        snippet.active_index += 1;
3869                    } else {
3870                        self.snippet_stack.push(snippet);
3871                        return false;
3872                    }
3873                }
3874            }
3875            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3876                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3877                    s.select_anchor_ranges(current_ranges.iter().cloned())
3878                });
3879                // If snippet state is not at the last tabstop, push it back on the stack
3880                if snippet.active_index + 1 < snippet.ranges.len() {
3881                    self.snippet_stack.push(snippet);
3882                }
3883                return true;
3884            }
3885        }
3886
3887        false
3888    }
3889
3890    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3891        self.transact(cx, |this, cx| {
3892            this.select_all(&SelectAll, cx);
3893            this.insert("", cx);
3894        });
3895    }
3896
3897    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3898        self.transact(cx, |this, cx| {
3899            this.select_autoclose_pair(cx);
3900            let mut selections = this.selections.all::<Point>(cx);
3901            if !this.selections.line_mode {
3902                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3903                for selection in &mut selections {
3904                    if selection.is_empty() {
3905                        let old_head = selection.head();
3906                        let mut new_head =
3907                            movement::left(&display_map, old_head.to_display_point(&display_map))
3908                                .to_point(&display_map);
3909                        if let Some((buffer, line_buffer_range)) = display_map
3910                            .buffer_snapshot
3911                            .buffer_line_for_row(old_head.row)
3912                        {
3913                            let indent_size =
3914                                buffer.indent_size_for_line(line_buffer_range.start.row);
3915                            let indent_len = match indent_size.kind {
3916                                IndentKind::Space => {
3917                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3918                                }
3919                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3920                            };
3921                            if old_head.column <= indent_size.len && old_head.column > 0 {
3922                                let indent_len = indent_len.get();
3923                                new_head = cmp::min(
3924                                    new_head,
3925                                    Point::new(
3926                                        old_head.row,
3927                                        ((old_head.column - 1) / indent_len) * indent_len,
3928                                    ),
3929                                );
3930                            }
3931                        }
3932
3933                        selection.set_head(new_head, SelectionGoal::None);
3934                    }
3935                }
3936            }
3937
3938            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3939            this.insert("", cx);
3940            this.refresh_copilot_suggestions(true, cx);
3941        });
3942    }
3943
3944    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3945        self.transact(cx, |this, cx| {
3946            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3947                let line_mode = s.line_mode;
3948                s.move_with(|map, selection| {
3949                    if selection.is_empty() && !line_mode {
3950                        let cursor = movement::right(map, selection.head());
3951                        selection.end = cursor;
3952                        selection.reversed = true;
3953                        selection.goal = SelectionGoal::None;
3954                    }
3955                })
3956            });
3957            this.insert("", cx);
3958            this.refresh_copilot_suggestions(true, cx);
3959        });
3960    }
3961
3962    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3963        if self.move_to_prev_snippet_tabstop(cx) {
3964            return;
3965        }
3966
3967        self.outdent(&Outdent, cx);
3968    }
3969
3970    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3971        if self.move_to_next_snippet_tabstop(cx) {
3972            return;
3973        }
3974
3975        let mut selections = self.selections.all_adjusted(cx);
3976        let buffer = self.buffer.read(cx);
3977        let snapshot = buffer.snapshot(cx);
3978        let rows_iter = selections.iter().map(|s| s.head().row);
3979        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3980
3981        let mut edits = Vec::new();
3982        let mut prev_edited_row = 0;
3983        let mut row_delta = 0;
3984        for selection in &mut selections {
3985            if selection.start.row != prev_edited_row {
3986                row_delta = 0;
3987            }
3988            prev_edited_row = selection.end.row;
3989
3990            // If the selection is non-empty, then increase the indentation of the selected lines.
3991            if !selection.is_empty() {
3992                row_delta =
3993                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3994                continue;
3995            }
3996
3997            // If the selection is empty and the cursor is in the leading whitespace before the
3998            // suggested indentation, then auto-indent the line.
3999            let cursor = selection.head();
4000            let current_indent = snapshot.indent_size_for_line(cursor.row);
4001            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
4002                if cursor.column < suggested_indent.len
4003                    && cursor.column <= current_indent.len
4004                    && current_indent.len <= suggested_indent.len
4005                {
4006                    selection.start = Point::new(cursor.row, suggested_indent.len);
4007                    selection.end = selection.start;
4008                    if row_delta == 0 {
4009                        edits.extend(Buffer::edit_for_indent_size_adjustment(
4010                            cursor.row,
4011                            current_indent,
4012                            suggested_indent,
4013                        ));
4014                        row_delta = suggested_indent.len - current_indent.len;
4015                    }
4016                    continue;
4017                }
4018            }
4019
4020            // Accept copilot suggestion if there is only one selection and the cursor is not
4021            // in the leading whitespace.
4022            if self.selections.count() == 1
4023                && cursor.column >= current_indent.len
4024                && self.has_active_copilot_suggestion(cx)
4025            {
4026                self.accept_copilot_suggestion(cx);
4027                return;
4028            }
4029
4030            // Otherwise, insert a hard or soft tab.
4031            let settings = buffer.settings_at(cursor, cx);
4032            let tab_size = if settings.hard_tabs {
4033                IndentSize::tab()
4034            } else {
4035                let tab_size = settings.tab_size.get();
4036                let char_column = snapshot
4037                    .text_for_range(Point::new(cursor.row, 0)..cursor)
4038                    .flat_map(str::chars)
4039                    .count()
4040                    + row_delta as usize;
4041                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
4042                IndentSize::spaces(chars_to_next_tab_stop)
4043            };
4044            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
4045            selection.end = selection.start;
4046            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
4047            row_delta += tab_size.len;
4048        }
4049
4050        self.transact(cx, |this, cx| {
4051            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4052            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4053            this.refresh_copilot_suggestions(true, cx);
4054        });
4055    }
4056
4057    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
4058        let mut selections = self.selections.all::<Point>(cx);
4059        let mut prev_edited_row = 0;
4060        let mut row_delta = 0;
4061        let mut edits = Vec::new();
4062        let buffer = self.buffer.read(cx);
4063        let snapshot = buffer.snapshot(cx);
4064        for selection in &mut selections {
4065            if selection.start.row != prev_edited_row {
4066                row_delta = 0;
4067            }
4068            prev_edited_row = selection.end.row;
4069
4070            row_delta =
4071                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4072        }
4073
4074        self.transact(cx, |this, cx| {
4075            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4076            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4077        });
4078    }
4079
4080    fn indent_selection(
4081        buffer: &MultiBuffer,
4082        snapshot: &MultiBufferSnapshot,
4083        selection: &mut Selection<Point>,
4084        edits: &mut Vec<(Range<Point>, String)>,
4085        delta_for_start_row: u32,
4086        cx: &AppContext,
4087    ) -> u32 {
4088        let settings = buffer.settings_at(selection.start, cx);
4089        let tab_size = settings.tab_size.get();
4090        let indent_kind = if settings.hard_tabs {
4091            IndentKind::Tab
4092        } else {
4093            IndentKind::Space
4094        };
4095        let mut start_row = selection.start.row;
4096        let mut end_row = selection.end.row + 1;
4097
4098        // If a selection ends at the beginning of a line, don't indent
4099        // that last line.
4100        if selection.end.column == 0 {
4101            end_row -= 1;
4102        }
4103
4104        // Avoid re-indenting a row that has already been indented by a
4105        // previous selection, but still update this selection's column
4106        // to reflect that indentation.
4107        if delta_for_start_row > 0 {
4108            start_row += 1;
4109            selection.start.column += delta_for_start_row;
4110            if selection.end.row == selection.start.row {
4111                selection.end.column += delta_for_start_row;
4112            }
4113        }
4114
4115        let mut delta_for_end_row = 0;
4116        for row in start_row..end_row {
4117            let current_indent = snapshot.indent_size_for_line(row);
4118            let indent_delta = match (current_indent.kind, indent_kind) {
4119                (IndentKind::Space, IndentKind::Space) => {
4120                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4121                    IndentSize::spaces(columns_to_next_tab_stop)
4122                }
4123                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4124                (_, IndentKind::Tab) => IndentSize::tab(),
4125            };
4126
4127            let row_start = Point::new(row, 0);
4128            edits.push((
4129                row_start..row_start,
4130                indent_delta.chars().collect::<String>(),
4131            ));
4132
4133            // Update this selection's endpoints to reflect the indentation.
4134            if row == selection.start.row {
4135                selection.start.column += indent_delta.len;
4136            }
4137            if row == selection.end.row {
4138                selection.end.column += indent_delta.len;
4139                delta_for_end_row = indent_delta.len;
4140            }
4141        }
4142
4143        if selection.start.row == selection.end.row {
4144            delta_for_start_row + delta_for_end_row
4145        } else {
4146            delta_for_end_row
4147        }
4148    }
4149
4150    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4151        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4152        let selections = self.selections.all::<Point>(cx);
4153        let mut deletion_ranges = Vec::new();
4154        let mut last_outdent = None;
4155        {
4156            let buffer = self.buffer.read(cx);
4157            let snapshot = buffer.snapshot(cx);
4158            for selection in &selections {
4159                let settings = buffer.settings_at(selection.start, cx);
4160                let tab_size = settings.tab_size.get();
4161                let mut rows = selection.spanned_rows(false, &display_map);
4162
4163                // Avoid re-outdenting a row that has already been outdented by a
4164                // previous selection.
4165                if let Some(last_row) = last_outdent {
4166                    if last_row == rows.start {
4167                        rows.start += 1;
4168                    }
4169                }
4170
4171                for row in rows {
4172                    let indent_size = snapshot.indent_size_for_line(row);
4173                    if indent_size.len > 0 {
4174                        let deletion_len = match indent_size.kind {
4175                            IndentKind::Space => {
4176                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4177                                if columns_to_prev_tab_stop == 0 {
4178                                    tab_size
4179                                } else {
4180                                    columns_to_prev_tab_stop
4181                                }
4182                            }
4183                            IndentKind::Tab => 1,
4184                        };
4185                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4186                        last_outdent = Some(row);
4187                    }
4188                }
4189            }
4190        }
4191
4192        self.transact(cx, |this, cx| {
4193            this.buffer.update(cx, |buffer, cx| {
4194                let empty_str: Arc<str> = "".into();
4195                buffer.edit(
4196                    deletion_ranges
4197                        .into_iter()
4198                        .map(|range| (range, empty_str.clone())),
4199                    None,
4200                    cx,
4201                );
4202            });
4203            let selections = this.selections.all::<usize>(cx);
4204            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4205        });
4206    }
4207
4208    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4209        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4210        let selections = self.selections.all::<Point>(cx);
4211
4212        let mut new_cursors = Vec::new();
4213        let mut edit_ranges = Vec::new();
4214        let mut selections = selections.iter().peekable();
4215        while let Some(selection) = selections.next() {
4216            let mut rows = selection.spanned_rows(false, &display_map);
4217            let goal_display_column = selection.head().to_display_point(&display_map).column();
4218
4219            // Accumulate contiguous regions of rows that we want to delete.
4220            while let Some(next_selection) = selections.peek() {
4221                let next_rows = next_selection.spanned_rows(false, &display_map);
4222                if next_rows.start <= rows.end {
4223                    rows.end = next_rows.end;
4224                    selections.next().unwrap();
4225                } else {
4226                    break;
4227                }
4228            }
4229
4230            let buffer = &display_map.buffer_snapshot;
4231            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4232            let edit_end;
4233            let cursor_buffer_row;
4234            if buffer.max_point().row >= rows.end {
4235                // If there's a line after the range, delete the \n from the end of the row range
4236                // and position the cursor on the next line.
4237                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4238                cursor_buffer_row = rows.end;
4239            } else {
4240                // If there isn't a line after the range, delete the \n from the line before the
4241                // start of the row range and position the cursor there.
4242                edit_start = edit_start.saturating_sub(1);
4243                edit_end = buffer.len();
4244                cursor_buffer_row = rows.start.saturating_sub(1);
4245            }
4246
4247            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4248            *cursor.column_mut() =
4249                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4250
4251            new_cursors.push((
4252                selection.id,
4253                buffer.anchor_after(cursor.to_point(&display_map)),
4254            ));
4255            edit_ranges.push(edit_start..edit_end);
4256        }
4257
4258        self.transact(cx, |this, cx| {
4259            let buffer = this.buffer.update(cx, |buffer, cx| {
4260                let empty_str: Arc<str> = "".into();
4261                buffer.edit(
4262                    edit_ranges
4263                        .into_iter()
4264                        .map(|range| (range, empty_str.clone())),
4265                    None,
4266                    cx,
4267                );
4268                buffer.snapshot(cx)
4269            });
4270            let new_selections = new_cursors
4271                .into_iter()
4272                .map(|(id, cursor)| {
4273                    let cursor = cursor.to_point(&buffer);
4274                    Selection {
4275                        id,
4276                        start: cursor,
4277                        end: cursor,
4278                        reversed: false,
4279                        goal: SelectionGoal::None,
4280                    }
4281                })
4282                .collect();
4283
4284            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4285                s.select(new_selections);
4286            });
4287        });
4288    }
4289
4290    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4291        let mut row_ranges = Vec::<Range<u32>>::new();
4292        for selection in self.selections.all::<Point>(cx) {
4293            let start = selection.start.row;
4294            let end = if selection.start.row == selection.end.row {
4295                selection.start.row + 1
4296            } else {
4297                selection.end.row
4298            };
4299
4300            if let Some(last_row_range) = row_ranges.last_mut() {
4301                if start <= last_row_range.end {
4302                    last_row_range.end = end;
4303                    continue;
4304                }
4305            }
4306            row_ranges.push(start..end);
4307        }
4308
4309        let snapshot = self.buffer.read(cx).snapshot(cx);
4310        let mut cursor_positions = Vec::new();
4311        for row_range in &row_ranges {
4312            let anchor = snapshot.anchor_before(Point::new(
4313                row_range.end - 1,
4314                snapshot.line_len(row_range.end - 1),
4315            ));
4316            cursor_positions.push(anchor.clone()..anchor);
4317        }
4318
4319        self.transact(cx, |this, cx| {
4320            for row_range in row_ranges.into_iter().rev() {
4321                for row in row_range.rev() {
4322                    let end_of_line = Point::new(row, snapshot.line_len(row));
4323                    let indent = snapshot.indent_size_for_line(row + 1);
4324                    let start_of_next_line = Point::new(row + 1, indent.len);
4325
4326                    let replace = if snapshot.line_len(row + 1) > indent.len {
4327                        " "
4328                    } else {
4329                        ""
4330                    };
4331
4332                    this.buffer.update(cx, |buffer, cx| {
4333                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4334                    });
4335                }
4336            }
4337
4338            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4339                s.select_anchor_ranges(cursor_positions)
4340            });
4341        });
4342    }
4343
4344    pub fn sort_lines_case_sensitive(
4345        &mut self,
4346        _: &SortLinesCaseSensitive,
4347        cx: &mut ViewContext<Self>,
4348    ) {
4349        self.manipulate_lines(cx, |lines| lines.sort())
4350    }
4351
4352    pub fn sort_lines_case_insensitive(
4353        &mut self,
4354        _: &SortLinesCaseInsensitive,
4355        cx: &mut ViewContext<Self>,
4356    ) {
4357        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4358    }
4359
4360    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4361        self.manipulate_lines(cx, |lines| lines.reverse())
4362    }
4363
4364    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4365        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4366    }
4367
4368    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4369    where
4370        Fn: FnMut(&mut [&str]),
4371    {
4372        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4373        let buffer = self.buffer.read(cx).snapshot(cx);
4374
4375        let mut edits = Vec::new();
4376
4377        let selections = self.selections.all::<Point>(cx);
4378        let mut selections = selections.iter().peekable();
4379        let mut contiguous_row_selections = Vec::new();
4380        let mut new_selections = Vec::new();
4381
4382        while let Some(selection) = selections.next() {
4383            let (start_row, end_row) = consume_contiguous_rows(
4384                &mut contiguous_row_selections,
4385                selection,
4386                &display_map,
4387                &mut selections,
4388            );
4389
4390            let start_point = Point::new(start_row, 0);
4391            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4392            let text = buffer
4393                .text_for_range(start_point..end_point)
4394                .collect::<String>();
4395            let mut lines = text.split("\n").collect_vec();
4396
4397            let lines_len = lines.len();
4398            callback(&mut lines);
4399
4400            // This is a current limitation with selections.
4401            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4402            debug_assert!(
4403                lines.len() == lines_len,
4404                "callback should not change the number of lines"
4405            );
4406
4407            edits.push((start_point..end_point, lines.join("\n")));
4408            let start_anchor = buffer.anchor_after(start_point);
4409            let end_anchor = buffer.anchor_before(end_point);
4410
4411            // Make selection and push
4412            new_selections.push(Selection {
4413                id: selection.id,
4414                start: start_anchor.to_offset(&buffer),
4415                end: end_anchor.to_offset(&buffer),
4416                goal: SelectionGoal::None,
4417                reversed: selection.reversed,
4418            });
4419        }
4420
4421        self.transact(cx, |this, cx| {
4422            this.buffer.update(cx, |buffer, cx| {
4423                buffer.edit(edits, None, cx);
4424            });
4425
4426            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4427                s.select(new_selections);
4428            });
4429
4430            this.request_autoscroll(Autoscroll::fit(), cx);
4431        });
4432    }
4433
4434    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
4435        self.manipulate_text(cx, |text| text.to_uppercase())
4436    }
4437
4438    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
4439        self.manipulate_text(cx, |text| text.to_lowercase())
4440    }
4441
4442    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
4443        self.manipulate_text(cx, |text| text.to_case(Case::Title))
4444    }
4445
4446    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
4447        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
4448    }
4449
4450    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
4451        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
4452    }
4453
4454    pub fn convert_to_upper_camel_case(
4455        &mut self,
4456        _: &ConvertToUpperCamelCase,
4457        cx: &mut ViewContext<Self>,
4458    ) {
4459        self.manipulate_text(cx, |text| text.to_case(Case::UpperCamel))
4460    }
4461
4462    pub fn convert_to_lower_camel_case(
4463        &mut self,
4464        _: &ConvertToLowerCamelCase,
4465        cx: &mut ViewContext<Self>,
4466    ) {
4467        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
4468    }
4469
4470    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4471    where
4472        Fn: FnMut(&str) -> String,
4473    {
4474        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4475        let buffer = self.buffer.read(cx).snapshot(cx);
4476
4477        let mut new_selections = Vec::new();
4478        let mut edits = Vec::new();
4479        let mut selection_adjustment = 0i32;
4480
4481        for selection in self.selections.all::<usize>(cx) {
4482            let selection_is_empty = selection.is_empty();
4483
4484            let (start, end) = if selection_is_empty {
4485                let word_range = movement::surrounding_word(
4486                    &display_map,
4487                    selection.start.to_display_point(&display_map),
4488                );
4489                let start = word_range.start.to_offset(&display_map, Bias::Left);
4490                let end = word_range.end.to_offset(&display_map, Bias::Left);
4491                (start, end)
4492            } else {
4493                (selection.start, selection.end)
4494            };
4495
4496            let text = buffer.text_for_range(start..end).collect::<String>();
4497            let old_length = text.len() as i32;
4498            let text = callback(&text);
4499
4500            new_selections.push(Selection {
4501                start: (start as i32 - selection_adjustment) as usize,
4502                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
4503                goal: SelectionGoal::None,
4504                ..selection
4505            });
4506
4507            selection_adjustment += old_length - text.len() as i32;
4508
4509            edits.push((start..end, text));
4510        }
4511
4512        self.transact(cx, |this, cx| {
4513            this.buffer.update(cx, |buffer, cx| {
4514                buffer.edit(edits, None, cx);
4515            });
4516
4517            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4518                s.select(new_selections);
4519            });
4520
4521            this.request_autoscroll(Autoscroll::fit(), cx);
4522        });
4523    }
4524
4525    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4526        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4527        let buffer = &display_map.buffer_snapshot;
4528        let selections = self.selections.all::<Point>(cx);
4529
4530        let mut edits = Vec::new();
4531        let mut selections_iter = selections.iter().peekable();
4532        while let Some(selection) = selections_iter.next() {
4533            // Avoid duplicating the same lines twice.
4534            let mut rows = selection.spanned_rows(false, &display_map);
4535
4536            while let Some(next_selection) = selections_iter.peek() {
4537                let next_rows = next_selection.spanned_rows(false, &display_map);
4538                if next_rows.start < rows.end {
4539                    rows.end = next_rows.end;
4540                    selections_iter.next().unwrap();
4541                } else {
4542                    break;
4543                }
4544            }
4545
4546            // Copy the text from the selected row region and splice it at the start of the region.
4547            let start = Point::new(rows.start, 0);
4548            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4549            let text = buffer
4550                .text_for_range(start..end)
4551                .chain(Some("\n"))
4552                .collect::<String>();
4553            edits.push((start..start, text));
4554        }
4555
4556        self.transact(cx, |this, cx| {
4557            this.buffer.update(cx, |buffer, cx| {
4558                buffer.edit(edits, None, cx);
4559            });
4560
4561            this.request_autoscroll(Autoscroll::fit(), cx);
4562        });
4563    }
4564
4565    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4566        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4567        let buffer = self.buffer.read(cx).snapshot(cx);
4568
4569        let mut edits = Vec::new();
4570        let mut unfold_ranges = Vec::new();
4571        let mut refold_ranges = Vec::new();
4572
4573        let selections = self.selections.all::<Point>(cx);
4574        let mut selections = selections.iter().peekable();
4575        let mut contiguous_row_selections = Vec::new();
4576        let mut new_selections = Vec::new();
4577
4578        while let Some(selection) = selections.next() {
4579            // Find all the selections that span a contiguous row range
4580            let (start_row, end_row) = consume_contiguous_rows(
4581                &mut contiguous_row_selections,
4582                selection,
4583                &display_map,
4584                &mut selections,
4585            );
4586
4587            // Move the text spanned by the row range to be before the line preceding the row range
4588            if start_row > 0 {
4589                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4590                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4591                let insertion_point = display_map
4592                    .prev_line_boundary(Point::new(start_row - 1, 0))
4593                    .0;
4594
4595                // Don't move lines across excerpts
4596                if buffer
4597                    .excerpt_boundaries_in_range((
4598                        Bound::Excluded(insertion_point),
4599                        Bound::Included(range_to_move.end),
4600                    ))
4601                    .next()
4602                    .is_none()
4603                {
4604                    let text = buffer
4605                        .text_for_range(range_to_move.clone())
4606                        .flat_map(|s| s.chars())
4607                        .skip(1)
4608                        .chain(['\n'])
4609                        .collect::<String>();
4610
4611                    edits.push((
4612                        buffer.anchor_after(range_to_move.start)
4613                            ..buffer.anchor_before(range_to_move.end),
4614                        String::new(),
4615                    ));
4616                    let insertion_anchor = buffer.anchor_after(insertion_point);
4617                    edits.push((insertion_anchor..insertion_anchor, text));
4618
4619                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4620
4621                    // Move selections up
4622                    new_selections.extend(contiguous_row_selections.drain(..).map(
4623                        |mut selection| {
4624                            selection.start.row -= row_delta;
4625                            selection.end.row -= row_delta;
4626                            selection
4627                        },
4628                    ));
4629
4630                    // Move folds up
4631                    unfold_ranges.push(range_to_move.clone());
4632                    for fold in display_map.folds_in_range(
4633                        buffer.anchor_before(range_to_move.start)
4634                            ..buffer.anchor_after(range_to_move.end),
4635                    ) {
4636                        let mut start = fold.start.to_point(&buffer);
4637                        let mut end = fold.end.to_point(&buffer);
4638                        start.row -= row_delta;
4639                        end.row -= row_delta;
4640                        refold_ranges.push(start..end);
4641                    }
4642                }
4643            }
4644
4645            // If we didn't move line(s), preserve the existing selections
4646            new_selections.append(&mut contiguous_row_selections);
4647        }
4648
4649        self.transact(cx, |this, cx| {
4650            this.unfold_ranges(unfold_ranges, true, true, cx);
4651            this.buffer.update(cx, |buffer, cx| {
4652                for (range, text) in edits {
4653                    buffer.edit([(range, text)], None, cx);
4654                }
4655            });
4656            this.fold_ranges(refold_ranges, true, cx);
4657            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4658                s.select(new_selections);
4659            })
4660        });
4661    }
4662
4663    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4664        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4665        let buffer = self.buffer.read(cx).snapshot(cx);
4666
4667        let mut edits = Vec::new();
4668        let mut unfold_ranges = Vec::new();
4669        let mut refold_ranges = Vec::new();
4670
4671        let selections = self.selections.all::<Point>(cx);
4672        let mut selections = selections.iter().peekable();
4673        let mut contiguous_row_selections = Vec::new();
4674        let mut new_selections = Vec::new();
4675
4676        while let Some(selection) = selections.next() {
4677            // Find all the selections that span a contiguous row range
4678            let (start_row, end_row) = consume_contiguous_rows(
4679                &mut contiguous_row_selections,
4680                selection,
4681                &display_map,
4682                &mut selections,
4683            );
4684
4685            // Move the text spanned by the row range to be after the last line of the row range
4686            if end_row <= buffer.max_point().row {
4687                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4688                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4689
4690                // Don't move lines across excerpt boundaries
4691                if buffer
4692                    .excerpt_boundaries_in_range((
4693                        Bound::Excluded(range_to_move.start),
4694                        Bound::Included(insertion_point),
4695                    ))
4696                    .next()
4697                    .is_none()
4698                {
4699                    let mut text = String::from("\n");
4700                    text.extend(buffer.text_for_range(range_to_move.clone()));
4701                    text.pop(); // Drop trailing newline
4702                    edits.push((
4703                        buffer.anchor_after(range_to_move.start)
4704                            ..buffer.anchor_before(range_to_move.end),
4705                        String::new(),
4706                    ));
4707                    let insertion_anchor = buffer.anchor_after(insertion_point);
4708                    edits.push((insertion_anchor..insertion_anchor, text));
4709
4710                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4711
4712                    // Move selections down
4713                    new_selections.extend(contiguous_row_selections.drain(..).map(
4714                        |mut selection| {
4715                            selection.start.row += row_delta;
4716                            selection.end.row += row_delta;
4717                            selection
4718                        },
4719                    ));
4720
4721                    // Move folds down
4722                    unfold_ranges.push(range_to_move.clone());
4723                    for fold in display_map.folds_in_range(
4724                        buffer.anchor_before(range_to_move.start)
4725                            ..buffer.anchor_after(range_to_move.end),
4726                    ) {
4727                        let mut start = fold.start.to_point(&buffer);
4728                        let mut end = fold.end.to_point(&buffer);
4729                        start.row += row_delta;
4730                        end.row += row_delta;
4731                        refold_ranges.push(start..end);
4732                    }
4733                }
4734            }
4735
4736            // If we didn't move line(s), preserve the existing selections
4737            new_selections.append(&mut contiguous_row_selections);
4738        }
4739
4740        self.transact(cx, |this, cx| {
4741            this.unfold_ranges(unfold_ranges, true, true, cx);
4742            this.buffer.update(cx, |buffer, cx| {
4743                for (range, text) in edits {
4744                    buffer.edit([(range, text)], None, cx);
4745                }
4746            });
4747            this.fold_ranges(refold_ranges, true, cx);
4748            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4749        });
4750    }
4751
4752    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4753        self.transact(cx, |this, cx| {
4754            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4755                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4756                let line_mode = s.line_mode;
4757                s.move_with(|display_map, selection| {
4758                    if !selection.is_empty() || line_mode {
4759                        return;
4760                    }
4761
4762                    let mut head = selection.head();
4763                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4764                    if head.column() == display_map.line_len(head.row()) {
4765                        transpose_offset = display_map
4766                            .buffer_snapshot
4767                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4768                    }
4769
4770                    if transpose_offset == 0 {
4771                        return;
4772                    }
4773
4774                    *head.column_mut() += 1;
4775                    head = display_map.clip_point(head, Bias::Right);
4776                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4777
4778                    let transpose_start = display_map
4779                        .buffer_snapshot
4780                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4781                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4782                        let transpose_end = display_map
4783                            .buffer_snapshot
4784                            .clip_offset(transpose_offset + 1, Bias::Right);
4785                        if let Some(ch) =
4786                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4787                        {
4788                            edits.push((transpose_start..transpose_offset, String::new()));
4789                            edits.push((transpose_end..transpose_end, ch.to_string()));
4790                        }
4791                    }
4792                });
4793                edits
4794            });
4795            this.buffer
4796                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4797            let selections = this.selections.all::<usize>(cx);
4798            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4799                s.select(selections);
4800            });
4801        });
4802    }
4803
4804    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4805        let mut text = String::new();
4806        let buffer = self.buffer.read(cx).snapshot(cx);
4807        let mut selections = self.selections.all::<Point>(cx);
4808        let mut clipboard_selections = Vec::with_capacity(selections.len());
4809        {
4810            let max_point = buffer.max_point();
4811            let mut is_first = true;
4812            for selection in &mut selections {
4813                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4814                if is_entire_line {
4815                    selection.start = Point::new(selection.start.row, 0);
4816                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4817                    selection.goal = SelectionGoal::None;
4818                }
4819                if is_first {
4820                    is_first = false;
4821                } else {
4822                    text += "\n";
4823                }
4824                let mut len = 0;
4825                for chunk in buffer.text_for_range(selection.start..selection.end) {
4826                    text.push_str(chunk);
4827                    len += chunk.len();
4828                }
4829                clipboard_selections.push(ClipboardSelection {
4830                    len,
4831                    is_entire_line,
4832                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4833                });
4834            }
4835        }
4836
4837        self.transact(cx, |this, cx| {
4838            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4839                s.select(selections);
4840            });
4841            this.insert("", cx);
4842            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4843        });
4844    }
4845
4846    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4847        let selections = self.selections.all::<Point>(cx);
4848        let buffer = self.buffer.read(cx).read(cx);
4849        let mut text = String::new();
4850
4851        let mut clipboard_selections = Vec::with_capacity(selections.len());
4852        {
4853            let max_point = buffer.max_point();
4854            let mut is_first = true;
4855            for selection in selections.iter() {
4856                let mut start = selection.start;
4857                let mut end = selection.end;
4858                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4859                if is_entire_line {
4860                    start = Point::new(start.row, 0);
4861                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4862                }
4863                if is_first {
4864                    is_first = false;
4865                } else {
4866                    text += "\n";
4867                }
4868                let mut len = 0;
4869                for chunk in buffer.text_for_range(start..end) {
4870                    text.push_str(chunk);
4871                    len += chunk.len();
4872                }
4873                clipboard_selections.push(ClipboardSelection {
4874                    len,
4875                    is_entire_line,
4876                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4877                });
4878            }
4879        }
4880
4881        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4882    }
4883
4884    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4885        self.transact(cx, |this, cx| {
4886            if let Some(item) = cx.read_from_clipboard() {
4887                let clipboard_text = Cow::Borrowed(item.text());
4888                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4889                    let old_selections = this.selections.all::<usize>(cx);
4890                    let all_selections_were_entire_line =
4891                        clipboard_selections.iter().all(|s| s.is_entire_line);
4892                    let first_selection_indent_column =
4893                        clipboard_selections.first().map(|s| s.first_line_indent);
4894                    if clipboard_selections.len() != old_selections.len() {
4895                        clipboard_selections.drain(..);
4896                    }
4897
4898                    this.buffer.update(cx, |buffer, cx| {
4899                        let snapshot = buffer.read(cx);
4900                        let mut start_offset = 0;
4901                        let mut edits = Vec::new();
4902                        let mut original_indent_columns = Vec::new();
4903                        let line_mode = this.selections.line_mode;
4904                        for (ix, selection) in old_selections.iter().enumerate() {
4905                            let to_insert;
4906                            let entire_line;
4907                            let original_indent_column;
4908                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4909                                let end_offset = start_offset + clipboard_selection.len;
4910                                to_insert = &clipboard_text[start_offset..end_offset];
4911                                entire_line = clipboard_selection.is_entire_line;
4912                                start_offset = end_offset + 1;
4913                                original_indent_column =
4914                                    Some(clipboard_selection.first_line_indent);
4915                            } else {
4916                                to_insert = clipboard_text.as_str();
4917                                entire_line = all_selections_were_entire_line;
4918                                original_indent_column = first_selection_indent_column
4919                            }
4920
4921                            // If the corresponding selection was empty when this slice of the
4922                            // clipboard text was written, then the entire line containing the
4923                            // selection was copied. If this selection is also currently empty,
4924                            // then paste the line before the current line of the buffer.
4925                            let range = if selection.is_empty() && !line_mode && entire_line {
4926                                let column = selection.start.to_point(&snapshot).column as usize;
4927                                let line_start = selection.start - column;
4928                                line_start..line_start
4929                            } else {
4930                                selection.range()
4931                            };
4932
4933                            edits.push((range, to_insert));
4934                            original_indent_columns.extend(original_indent_column);
4935                        }
4936                        drop(snapshot);
4937
4938                        buffer.edit(
4939                            edits,
4940                            Some(AutoindentMode::Block {
4941                                original_indent_columns,
4942                            }),
4943                            cx,
4944                        );
4945                    });
4946
4947                    let selections = this.selections.all::<usize>(cx);
4948                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4949                } else {
4950                    this.insert(&clipboard_text, cx);
4951                }
4952            }
4953        });
4954    }
4955
4956    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4957        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4958            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4959                self.change_selections(None, cx, |s| {
4960                    s.select_anchors(selections.to_vec());
4961                });
4962            }
4963            self.request_autoscroll(Autoscroll::fit(), cx);
4964            self.unmark_text(cx);
4965            self.refresh_copilot_suggestions(true, cx);
4966            cx.emit(Event::Edited);
4967        }
4968    }
4969
4970    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4971        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4972            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4973            {
4974                self.change_selections(None, cx, |s| {
4975                    s.select_anchors(selections.to_vec());
4976                });
4977            }
4978            self.request_autoscroll(Autoscroll::fit(), cx);
4979            self.unmark_text(cx);
4980            self.refresh_copilot_suggestions(true, cx);
4981            cx.emit(Event::Edited);
4982        }
4983    }
4984
4985    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4986        self.buffer
4987            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4988    }
4989
4990    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4991        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4992            let line_mode = s.line_mode;
4993            s.move_with(|map, selection| {
4994                let cursor = if selection.is_empty() && !line_mode {
4995                    movement::left(map, selection.start)
4996                } else {
4997                    selection.start
4998                };
4999                selection.collapse_to(cursor, SelectionGoal::None);
5000            });
5001        })
5002    }
5003
5004    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
5005        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5006            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
5007        })
5008    }
5009
5010    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
5011        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5012            let line_mode = s.line_mode;
5013            s.move_with(|map, selection| {
5014                let cursor = if selection.is_empty() && !line_mode {
5015                    movement::right(map, selection.end)
5016                } else {
5017                    selection.end
5018                };
5019                selection.collapse_to(cursor, SelectionGoal::None)
5020            });
5021        })
5022    }
5023
5024    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
5025        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5026            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
5027        })
5028    }
5029
5030    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
5031        if self.take_rename(true, cx).is_some() {
5032            return;
5033        }
5034
5035        if let Some(context_menu) = self.context_menu.as_mut() {
5036            if context_menu.select_prev(cx) {
5037                return;
5038            }
5039        }
5040
5041        if matches!(self.mode, EditorMode::SingleLine) {
5042            cx.propagate_action();
5043            return;
5044        }
5045
5046        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5047            let line_mode = s.line_mode;
5048            s.move_with(|map, selection| {
5049                if !selection.is_empty() && !line_mode {
5050                    selection.goal = SelectionGoal::None;
5051                }
5052                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
5053                selection.collapse_to(cursor, goal);
5054            });
5055        })
5056    }
5057
5058    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5059        if self.take_rename(true, cx).is_some() {
5060            return;
5061        }
5062
5063        if self
5064            .context_menu
5065            .as_mut()
5066            .map(|menu| menu.select_first(cx))
5067            .unwrap_or(false)
5068        {
5069            return;
5070        }
5071
5072        if matches!(self.mode, EditorMode::SingleLine) {
5073            cx.propagate_action();
5074            return;
5075        }
5076
5077        let row_count = if let Some(row_count) = self.visible_line_count() {
5078            row_count as u32 - 1
5079        } else {
5080            return;
5081        };
5082
5083        let autoscroll = if action.center_cursor {
5084            Autoscroll::center()
5085        } else {
5086            Autoscroll::fit()
5087        };
5088
5089        self.change_selections(Some(autoscroll), cx, |s| {
5090            let line_mode = s.line_mode;
5091            s.move_with(|map, selection| {
5092                if !selection.is_empty() && !line_mode {
5093                    selection.goal = SelectionGoal::None;
5094                }
5095                let (cursor, goal) =
5096                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
5097                selection.collapse_to(cursor, goal);
5098            });
5099        });
5100    }
5101
5102    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5103        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5104            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
5105        })
5106    }
5107
5108    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5109        self.take_rename(true, cx);
5110
5111        if let Some(context_menu) = self.context_menu.as_mut() {
5112            if context_menu.select_next(cx) {
5113                return;
5114            }
5115        }
5116
5117        if self.mode == EditorMode::SingleLine {
5118            cx.propagate_action();
5119            return;
5120        }
5121
5122        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5123            let line_mode = s.line_mode;
5124            s.move_with(|map, selection| {
5125                if !selection.is_empty() && !line_mode {
5126                    selection.goal = SelectionGoal::None;
5127                }
5128                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
5129                selection.collapse_to(cursor, goal);
5130            });
5131        });
5132    }
5133
5134    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5135        if self.take_rename(true, cx).is_some() {
5136            return;
5137        }
5138
5139        if self
5140            .context_menu
5141            .as_mut()
5142            .map(|menu| menu.select_last(cx))
5143            .unwrap_or(false)
5144        {
5145            return;
5146        }
5147
5148        if matches!(self.mode, EditorMode::SingleLine) {
5149            cx.propagate_action();
5150            return;
5151        }
5152
5153        let row_count = if let Some(row_count) = self.visible_line_count() {
5154            row_count as u32 - 1
5155        } else {
5156            return;
5157        };
5158
5159        let autoscroll = if action.center_cursor {
5160            Autoscroll::center()
5161        } else {
5162            Autoscroll::fit()
5163        };
5164
5165        self.change_selections(Some(autoscroll), cx, |s| {
5166            let line_mode = s.line_mode;
5167            s.move_with(|map, selection| {
5168                if !selection.is_empty() && !line_mode {
5169                    selection.goal = SelectionGoal::None;
5170                }
5171                let (cursor, goal) =
5172                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
5173                selection.collapse_to(cursor, goal);
5174            });
5175        });
5176    }
5177
5178    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5179        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5180            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
5181        });
5182    }
5183
5184    pub fn move_to_previous_word_start(
5185        &mut self,
5186        _: &MoveToPreviousWordStart,
5187        cx: &mut ViewContext<Self>,
5188    ) {
5189        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5190            s.move_cursors_with(|map, head, _| {
5191                (
5192                    movement::previous_word_start(map, head),
5193                    SelectionGoal::None,
5194                )
5195            });
5196        })
5197    }
5198
5199    pub fn move_to_previous_subword_start(
5200        &mut self,
5201        _: &MoveToPreviousSubwordStart,
5202        cx: &mut ViewContext<Self>,
5203    ) {
5204        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5205            s.move_cursors_with(|map, head, _| {
5206                (
5207                    movement::previous_subword_start(map, head),
5208                    SelectionGoal::None,
5209                )
5210            });
5211        })
5212    }
5213
5214    pub fn select_to_previous_word_start(
5215        &mut self,
5216        _: &SelectToPreviousWordStart,
5217        cx: &mut ViewContext<Self>,
5218    ) {
5219        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5220            s.move_heads_with(|map, head, _| {
5221                (
5222                    movement::previous_word_start(map, head),
5223                    SelectionGoal::None,
5224                )
5225            });
5226        })
5227    }
5228
5229    pub fn select_to_previous_subword_start(
5230        &mut self,
5231        _: &SelectToPreviousSubwordStart,
5232        cx: &mut ViewContext<Self>,
5233    ) {
5234        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5235            s.move_heads_with(|map, head, _| {
5236                (
5237                    movement::previous_subword_start(map, head),
5238                    SelectionGoal::None,
5239                )
5240            });
5241        })
5242    }
5243
5244    pub fn delete_to_previous_word_start(
5245        &mut self,
5246        _: &DeleteToPreviousWordStart,
5247        cx: &mut ViewContext<Self>,
5248    ) {
5249        self.transact(cx, |this, cx| {
5250            this.select_autoclose_pair(cx);
5251            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5252                let line_mode = s.line_mode;
5253                s.move_with(|map, selection| {
5254                    if selection.is_empty() && !line_mode {
5255                        let cursor = movement::previous_word_start(map, selection.head());
5256                        selection.set_head(cursor, SelectionGoal::None);
5257                    }
5258                });
5259            });
5260            this.insert("", cx);
5261        });
5262    }
5263
5264    pub fn delete_to_previous_subword_start(
5265        &mut self,
5266        _: &DeleteToPreviousSubwordStart,
5267        cx: &mut ViewContext<Self>,
5268    ) {
5269        self.transact(cx, |this, cx| {
5270            this.select_autoclose_pair(cx);
5271            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5272                let line_mode = s.line_mode;
5273                s.move_with(|map, selection| {
5274                    if selection.is_empty() && !line_mode {
5275                        let cursor = movement::previous_subword_start(map, selection.head());
5276                        selection.set_head(cursor, SelectionGoal::None);
5277                    }
5278                });
5279            });
5280            this.insert("", cx);
5281        });
5282    }
5283
5284    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5285        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5286            s.move_cursors_with(|map, head, _| {
5287                (movement::next_word_end(map, head), SelectionGoal::None)
5288            });
5289        })
5290    }
5291
5292    pub fn move_to_next_subword_end(
5293        &mut self,
5294        _: &MoveToNextSubwordEnd,
5295        cx: &mut ViewContext<Self>,
5296    ) {
5297        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5298            s.move_cursors_with(|map, head, _| {
5299                (movement::next_subword_end(map, head), SelectionGoal::None)
5300            });
5301        })
5302    }
5303
5304    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5305        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5306            s.move_heads_with(|map, head, _| {
5307                (movement::next_word_end(map, head), SelectionGoal::None)
5308            });
5309        })
5310    }
5311
5312    pub fn select_to_next_subword_end(
5313        &mut self,
5314        _: &SelectToNextSubwordEnd,
5315        cx: &mut ViewContext<Self>,
5316    ) {
5317        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5318            s.move_heads_with(|map, head, _| {
5319                (movement::next_subword_end(map, head), SelectionGoal::None)
5320            });
5321        })
5322    }
5323
5324    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5325        self.transact(cx, |this, cx| {
5326            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5327                let line_mode = s.line_mode;
5328                s.move_with(|map, selection| {
5329                    if selection.is_empty() && !line_mode {
5330                        let cursor = movement::next_word_end(map, selection.head());
5331                        selection.set_head(cursor, SelectionGoal::None);
5332                    }
5333                });
5334            });
5335            this.insert("", cx);
5336        });
5337    }
5338
5339    pub fn delete_to_next_subword_end(
5340        &mut self,
5341        _: &DeleteToNextSubwordEnd,
5342        cx: &mut ViewContext<Self>,
5343    ) {
5344        self.transact(cx, |this, cx| {
5345            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5346                s.move_with(|map, selection| {
5347                    if selection.is_empty() {
5348                        let cursor = movement::next_subword_end(map, selection.head());
5349                        selection.set_head(cursor, SelectionGoal::None);
5350                    }
5351                });
5352            });
5353            this.insert("", cx);
5354        });
5355    }
5356
5357    pub fn move_to_beginning_of_line(
5358        &mut self,
5359        _: &MoveToBeginningOfLine,
5360        cx: &mut ViewContext<Self>,
5361    ) {
5362        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5363            s.move_cursors_with(|map, head, _| {
5364                (
5365                    movement::indented_line_beginning(map, head, true),
5366                    SelectionGoal::None,
5367                )
5368            });
5369        })
5370    }
5371
5372    pub fn select_to_beginning_of_line(
5373        &mut self,
5374        action: &SelectToBeginningOfLine,
5375        cx: &mut ViewContext<Self>,
5376    ) {
5377        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5378            s.move_heads_with(|map, head, _| {
5379                (
5380                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5381                    SelectionGoal::None,
5382                )
5383            });
5384        });
5385    }
5386
5387    pub fn delete_to_beginning_of_line(
5388        &mut self,
5389        _: &DeleteToBeginningOfLine,
5390        cx: &mut ViewContext<Self>,
5391    ) {
5392        self.transact(cx, |this, cx| {
5393            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5394                s.move_with(|_, selection| {
5395                    selection.reversed = true;
5396                });
5397            });
5398
5399            this.select_to_beginning_of_line(
5400                &SelectToBeginningOfLine {
5401                    stop_at_soft_wraps: false,
5402                },
5403                cx,
5404            );
5405            this.backspace(&Backspace, cx);
5406        });
5407    }
5408
5409    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5410        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5411            s.move_cursors_with(|map, head, _| {
5412                (movement::line_end(map, head, true), SelectionGoal::None)
5413            });
5414        })
5415    }
5416
5417    pub fn select_to_end_of_line(
5418        &mut self,
5419        action: &SelectToEndOfLine,
5420        cx: &mut ViewContext<Self>,
5421    ) {
5422        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5423            s.move_heads_with(|map, head, _| {
5424                (
5425                    movement::line_end(map, head, action.stop_at_soft_wraps),
5426                    SelectionGoal::None,
5427                )
5428            });
5429        })
5430    }
5431
5432    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5433        self.transact(cx, |this, cx| {
5434            this.select_to_end_of_line(
5435                &SelectToEndOfLine {
5436                    stop_at_soft_wraps: false,
5437                },
5438                cx,
5439            );
5440            this.delete(&Delete, cx);
5441        });
5442    }
5443
5444    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5445        self.transact(cx, |this, cx| {
5446            this.select_to_end_of_line(
5447                &SelectToEndOfLine {
5448                    stop_at_soft_wraps: false,
5449                },
5450                cx,
5451            );
5452            this.cut(&Cut, cx);
5453        });
5454    }
5455
5456    pub fn move_to_start_of_paragraph(
5457        &mut self,
5458        _: &MoveToStartOfParagraph,
5459        cx: &mut ViewContext<Self>,
5460    ) {
5461        if matches!(self.mode, EditorMode::SingleLine) {
5462            cx.propagate_action();
5463            return;
5464        }
5465
5466        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5467            s.move_with(|map, selection| {
5468                selection.collapse_to(
5469                    movement::start_of_paragraph(map, selection.head(), 1),
5470                    SelectionGoal::None,
5471                )
5472            });
5473        })
5474    }
5475
5476    pub fn move_to_end_of_paragraph(
5477        &mut self,
5478        _: &MoveToEndOfParagraph,
5479        cx: &mut ViewContext<Self>,
5480    ) {
5481        if matches!(self.mode, EditorMode::SingleLine) {
5482            cx.propagate_action();
5483            return;
5484        }
5485
5486        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5487            s.move_with(|map, selection| {
5488                selection.collapse_to(
5489                    movement::end_of_paragraph(map, selection.head(), 1),
5490                    SelectionGoal::None,
5491                )
5492            });
5493        })
5494    }
5495
5496    pub fn select_to_start_of_paragraph(
5497        &mut self,
5498        _: &SelectToStartOfParagraph,
5499        cx: &mut ViewContext<Self>,
5500    ) {
5501        if matches!(self.mode, EditorMode::SingleLine) {
5502            cx.propagate_action();
5503            return;
5504        }
5505
5506        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5507            s.move_heads_with(|map, head, _| {
5508                (
5509                    movement::start_of_paragraph(map, head, 1),
5510                    SelectionGoal::None,
5511                )
5512            });
5513        })
5514    }
5515
5516    pub fn select_to_end_of_paragraph(
5517        &mut self,
5518        _: &SelectToEndOfParagraph,
5519        cx: &mut ViewContext<Self>,
5520    ) {
5521        if matches!(self.mode, EditorMode::SingleLine) {
5522            cx.propagate_action();
5523            return;
5524        }
5525
5526        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5527            s.move_heads_with(|map, head, _| {
5528                (
5529                    movement::end_of_paragraph(map, head, 1),
5530                    SelectionGoal::None,
5531                )
5532            });
5533        })
5534    }
5535
5536    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5537        if matches!(self.mode, EditorMode::SingleLine) {
5538            cx.propagate_action();
5539            return;
5540        }
5541
5542        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5543            s.select_ranges(vec![0..0]);
5544        });
5545    }
5546
5547    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5548        let mut selection = self.selections.last::<Point>(cx);
5549        selection.set_head(Point::zero(), SelectionGoal::None);
5550
5551        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5552            s.select(vec![selection]);
5553        });
5554    }
5555
5556    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5557        if matches!(self.mode, EditorMode::SingleLine) {
5558            cx.propagate_action();
5559            return;
5560        }
5561
5562        let cursor = self.buffer.read(cx).read(cx).len();
5563        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5564            s.select_ranges(vec![cursor..cursor])
5565        });
5566    }
5567
5568    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5569        self.nav_history = nav_history;
5570    }
5571
5572    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5573        self.nav_history.as_ref()
5574    }
5575
5576    fn push_to_nav_history(
5577        &mut self,
5578        cursor_anchor: Anchor,
5579        new_position: Option<Point>,
5580        cx: &mut ViewContext<Self>,
5581    ) {
5582        if let Some(nav_history) = self.nav_history.as_mut() {
5583            let buffer = self.buffer.read(cx).read(cx);
5584            let cursor_position = cursor_anchor.to_point(&buffer);
5585            let scroll_state = self.scroll_manager.anchor();
5586            let scroll_top_row = scroll_state.top_row(&buffer);
5587            drop(buffer);
5588
5589            if let Some(new_position) = new_position {
5590                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5591                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5592                    return;
5593                }
5594            }
5595
5596            nav_history.push(
5597                Some(NavigationData {
5598                    cursor_anchor,
5599                    cursor_position,
5600                    scroll_anchor: scroll_state,
5601                    scroll_top_row,
5602                }),
5603                cx,
5604            );
5605        }
5606    }
5607
5608    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5609        let buffer = self.buffer.read(cx).snapshot(cx);
5610        let mut selection = self.selections.first::<usize>(cx);
5611        selection.set_head(buffer.len(), SelectionGoal::None);
5612        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5613            s.select(vec![selection]);
5614        });
5615    }
5616
5617    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5618        let end = self.buffer.read(cx).read(cx).len();
5619        self.change_selections(None, cx, |s| {
5620            s.select_ranges(vec![0..end]);
5621        });
5622    }
5623
5624    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5625        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5626        let mut selections = self.selections.all::<Point>(cx);
5627        let max_point = display_map.buffer_snapshot.max_point();
5628        for selection in &mut selections {
5629            let rows = selection.spanned_rows(true, &display_map);
5630            selection.start = Point::new(rows.start, 0);
5631            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5632            selection.reversed = false;
5633        }
5634        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5635            s.select(selections);
5636        });
5637    }
5638
5639    pub fn split_selection_into_lines(
5640        &mut self,
5641        _: &SplitSelectionIntoLines,
5642        cx: &mut ViewContext<Self>,
5643    ) {
5644        let mut to_unfold = Vec::new();
5645        let mut new_selection_ranges = Vec::new();
5646        {
5647            let selections = self.selections.all::<Point>(cx);
5648            let buffer = self.buffer.read(cx).read(cx);
5649            for selection in selections {
5650                for row in selection.start.row..selection.end.row {
5651                    let cursor = Point::new(row, buffer.line_len(row));
5652                    new_selection_ranges.push(cursor..cursor);
5653                }
5654                new_selection_ranges.push(selection.end..selection.end);
5655                to_unfold.push(selection.start..selection.end);
5656            }
5657        }
5658        self.unfold_ranges(to_unfold, true, true, cx);
5659        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5660            s.select_ranges(new_selection_ranges);
5661        });
5662    }
5663
5664    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5665        self.add_selection(true, cx);
5666    }
5667
5668    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5669        self.add_selection(false, cx);
5670    }
5671
5672    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5673        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5674        let mut selections = self.selections.all::<Point>(cx);
5675        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5676            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5677            let range = oldest_selection.display_range(&display_map).sorted();
5678            let columns = cmp::min(range.start.column(), range.end.column())
5679                ..cmp::max(range.start.column(), range.end.column());
5680
5681            selections.clear();
5682            let mut stack = Vec::new();
5683            for row in range.start.row()..=range.end.row() {
5684                if let Some(selection) = self.selections.build_columnar_selection(
5685                    &display_map,
5686                    row,
5687                    &columns,
5688                    oldest_selection.reversed,
5689                ) {
5690                    stack.push(selection.id);
5691                    selections.push(selection);
5692                }
5693            }
5694
5695            if above {
5696                stack.reverse();
5697            }
5698
5699            AddSelectionsState { above, stack }
5700        });
5701
5702        let last_added_selection = *state.stack.last().unwrap();
5703        let mut new_selections = Vec::new();
5704        if above == state.above {
5705            let end_row = if above {
5706                0
5707            } else {
5708                display_map.max_point().row()
5709            };
5710
5711            'outer: for selection in selections {
5712                if selection.id == last_added_selection {
5713                    let range = selection.display_range(&display_map).sorted();
5714                    debug_assert_eq!(range.start.row(), range.end.row());
5715                    let mut row = range.start.row();
5716                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5717                    {
5718                        start..end
5719                    } else {
5720                        cmp::min(range.start.column(), range.end.column())
5721                            ..cmp::max(range.start.column(), range.end.column())
5722                    };
5723
5724                    while row != end_row {
5725                        if above {
5726                            row -= 1;
5727                        } else {
5728                            row += 1;
5729                        }
5730
5731                        if let Some(new_selection) = self.selections.build_columnar_selection(
5732                            &display_map,
5733                            row,
5734                            &columns,
5735                            selection.reversed,
5736                        ) {
5737                            state.stack.push(new_selection.id);
5738                            if above {
5739                                new_selections.push(new_selection);
5740                                new_selections.push(selection);
5741                            } else {
5742                                new_selections.push(selection);
5743                                new_selections.push(new_selection);
5744                            }
5745
5746                            continue 'outer;
5747                        }
5748                    }
5749                }
5750
5751                new_selections.push(selection);
5752            }
5753        } else {
5754            new_selections = selections;
5755            new_selections.retain(|s| s.id != last_added_selection);
5756            state.stack.pop();
5757        }
5758
5759        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5760            s.select(new_selections);
5761        });
5762        if state.stack.len() > 1 {
5763            self.add_selections_state = Some(state);
5764        }
5765    }
5766
5767    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5768        self.push_to_selection_history();
5769        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5770        let buffer = &display_map.buffer_snapshot;
5771        let mut selections = self.selections.all::<usize>(cx);
5772        if let Some(mut select_next_state) = self.select_next_state.take() {
5773            let query = &select_next_state.query;
5774            if !select_next_state.done {
5775                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5776                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5777                let mut next_selected_range = None;
5778
5779                let bytes_after_last_selection =
5780                    buffer.bytes_in_range(last_selection.end..buffer.len());
5781                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5782                let query_matches = query
5783                    .stream_find_iter(bytes_after_last_selection)
5784                    .map(|result| (last_selection.end, result))
5785                    .chain(
5786                        query
5787                            .stream_find_iter(bytes_before_first_selection)
5788                            .map(|result| (0, result)),
5789                    );
5790                for (start_offset, query_match) in query_matches {
5791                    let query_match = query_match.unwrap(); // can only fail due to I/O
5792                    let offset_range =
5793                        start_offset + query_match.start()..start_offset + query_match.end();
5794                    let display_range = offset_range.start.to_display_point(&display_map)
5795                        ..offset_range.end.to_display_point(&display_map);
5796
5797                    if !select_next_state.wordwise
5798                        || (!movement::is_inside_word(&display_map, display_range.start)
5799                            && !movement::is_inside_word(&display_map, display_range.end))
5800                    {
5801                        next_selected_range = Some(offset_range);
5802                        break;
5803                    }
5804                }
5805
5806                if let Some(next_selected_range) = next_selected_range {
5807                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5808                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5809                        if action.replace_newest {
5810                            s.delete(s.newest_anchor().id);
5811                        }
5812                        s.insert_range(next_selected_range);
5813                    });
5814                } else {
5815                    select_next_state.done = true;
5816                }
5817            }
5818
5819            self.select_next_state = Some(select_next_state);
5820        } else if selections.len() == 1 {
5821            let selection = selections.last_mut().unwrap();
5822            if selection.start == selection.end {
5823                let word_range = movement::surrounding_word(
5824                    &display_map,
5825                    selection.start.to_display_point(&display_map),
5826                );
5827                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5828                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5829                selection.goal = SelectionGoal::None;
5830                selection.reversed = false;
5831
5832                let query = buffer
5833                    .text_for_range(selection.start..selection.end)
5834                    .collect::<String>();
5835                let select_state = SelectNextState {
5836                    query: AhoCorasick::new_auto_configured(&[query]),
5837                    wordwise: true,
5838                    done: false,
5839                };
5840                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5841                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5842                    s.select(selections);
5843                });
5844                self.select_next_state = Some(select_state);
5845            } else {
5846                let query = buffer
5847                    .text_for_range(selection.start..selection.end)
5848                    .collect::<String>();
5849                self.select_next_state = Some(SelectNextState {
5850                    query: AhoCorasick::new_auto_configured(&[query]),
5851                    wordwise: false,
5852                    done: false,
5853                });
5854                self.select_next(action, cx);
5855            }
5856        }
5857    }
5858
5859    pub fn select_previous(&mut self, action: &SelectPrevious, cx: &mut ViewContext<Self>) {
5860        self.push_to_selection_history();
5861        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5862        let buffer = &display_map.buffer_snapshot;
5863        let mut selections = self.selections.all::<usize>(cx);
5864        if let Some(mut select_prev_state) = self.select_prev_state.take() {
5865            let query = &select_prev_state.query;
5866            if !select_prev_state.done {
5867                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5868                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5869                let mut next_selected_range = None;
5870                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
5871                let bytes_before_last_selection =
5872                    buffer.reversed_bytes_in_range(0..last_selection.start);
5873                let bytes_after_first_selection =
5874                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
5875                let query_matches = query
5876                    .stream_find_iter(bytes_before_last_selection)
5877                    .map(|result| (last_selection.start, result))
5878                    .chain(
5879                        query
5880                            .stream_find_iter(bytes_after_first_selection)
5881                            .map(|result| (buffer.len(), result)),
5882                    );
5883                for (end_offset, query_match) in query_matches {
5884                    let query_match = query_match.unwrap(); // can only fail due to I/O
5885                    let offset_range =
5886                        end_offset - query_match.end()..end_offset - query_match.start();
5887                    let display_range = offset_range.start.to_display_point(&display_map)
5888                        ..offset_range.end.to_display_point(&display_map);
5889
5890                    if !select_prev_state.wordwise
5891                        || (!movement::is_inside_word(&display_map, display_range.start)
5892                            && !movement::is_inside_word(&display_map, display_range.end))
5893                    {
5894                        next_selected_range = Some(offset_range);
5895                        break;
5896                    }
5897                }
5898
5899                if let Some(next_selected_range) = next_selected_range {
5900                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5901                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5902                        if action.replace_newest {
5903                            s.delete(s.newest_anchor().id);
5904                        }
5905                        s.insert_range(next_selected_range);
5906                    });
5907                } else {
5908                    select_prev_state.done = true;
5909                }
5910            }
5911
5912            self.select_prev_state = Some(select_prev_state);
5913        } else if selections.len() == 1 {
5914            let selection = selections.last_mut().unwrap();
5915            if selection.start == selection.end {
5916                let word_range = movement::surrounding_word(
5917                    &display_map,
5918                    selection.start.to_display_point(&display_map),
5919                );
5920                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5921                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5922                selection.goal = SelectionGoal::None;
5923                selection.reversed = false;
5924
5925                let query = buffer
5926                    .text_for_range(selection.start..selection.end)
5927                    .collect::<String>();
5928                let query = query.chars().rev().collect::<String>();
5929                let select_state = SelectNextState {
5930                    query: AhoCorasick::new_auto_configured(&[query]),
5931                    wordwise: true,
5932                    done: false,
5933                };
5934                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5935                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5936                    s.select(selections);
5937                });
5938                self.select_prev_state = Some(select_state);
5939            } else {
5940                let query = buffer
5941                    .text_for_range(selection.start..selection.end)
5942                    .collect::<String>();
5943                let query = query.chars().rev().collect::<String>();
5944                self.select_prev_state = Some(SelectNextState {
5945                    query: AhoCorasick::new_auto_configured(&[query]),
5946                    wordwise: false,
5947                    done: false,
5948                });
5949                self.select_previous(action, cx);
5950            }
5951        }
5952    }
5953
5954    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5955        self.transact(cx, |this, cx| {
5956            let mut selections = this.selections.all::<Point>(cx);
5957            let mut edits = Vec::new();
5958            let mut selection_edit_ranges = Vec::new();
5959            let mut last_toggled_row = None;
5960            let snapshot = this.buffer.read(cx).read(cx);
5961            let empty_str: Arc<str> = "".into();
5962            let mut suffixes_inserted = Vec::new();
5963
5964            fn comment_prefix_range(
5965                snapshot: &MultiBufferSnapshot,
5966                row: u32,
5967                comment_prefix: &str,
5968                comment_prefix_whitespace: &str,
5969            ) -> Range<Point> {
5970                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5971
5972                let mut line_bytes = snapshot
5973                    .bytes_in_range(start..snapshot.max_point())
5974                    .flatten()
5975                    .copied();
5976
5977                // If this line currently begins with the line comment prefix, then record
5978                // the range containing the prefix.
5979                if line_bytes
5980                    .by_ref()
5981                    .take(comment_prefix.len())
5982                    .eq(comment_prefix.bytes())
5983                {
5984                    // Include any whitespace that matches the comment prefix.
5985                    let matching_whitespace_len = line_bytes
5986                        .zip(comment_prefix_whitespace.bytes())
5987                        .take_while(|(a, b)| a == b)
5988                        .count() as u32;
5989                    let end = Point::new(
5990                        start.row,
5991                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5992                    );
5993                    start..end
5994                } else {
5995                    start..start
5996                }
5997            }
5998
5999            fn comment_suffix_range(
6000                snapshot: &MultiBufferSnapshot,
6001                row: u32,
6002                comment_suffix: &str,
6003                comment_suffix_has_leading_space: bool,
6004            ) -> Range<Point> {
6005                let end = Point::new(row, snapshot.line_len(row));
6006                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6007
6008                let mut line_end_bytes = snapshot
6009                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6010                    .flatten()
6011                    .copied();
6012
6013                let leading_space_len = if suffix_start_column > 0
6014                    && line_end_bytes.next() == Some(b' ')
6015                    && comment_suffix_has_leading_space
6016                {
6017                    1
6018                } else {
6019                    0
6020                };
6021
6022                // If this line currently begins with the line comment prefix, then record
6023                // the range containing the prefix.
6024                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6025                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6026                    start..end
6027                } else {
6028                    end..end
6029                }
6030            }
6031
6032            // TODO: Handle selections that cross excerpts
6033            for selection in &mut selections {
6034                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6035                let language = if let Some(language) =
6036                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6037                {
6038                    language
6039                } else {
6040                    continue;
6041                };
6042
6043                selection_edit_ranges.clear();
6044
6045                // If multiple selections contain a given row, avoid processing that
6046                // row more than once.
6047                let mut start_row = selection.start.row;
6048                if last_toggled_row == Some(start_row) {
6049                    start_row += 1;
6050                }
6051                let end_row =
6052                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6053                        selection.end.row - 1
6054                    } else {
6055                        selection.end.row
6056                    };
6057                last_toggled_row = Some(end_row);
6058
6059                if start_row > end_row {
6060                    continue;
6061                }
6062
6063                // If the language has line comments, toggle those.
6064                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6065                    // Split the comment prefix's trailing whitespace into a separate string,
6066                    // as that portion won't be used for detecting if a line is a comment.
6067                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6068                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6069                    let mut all_selection_lines_are_comments = true;
6070
6071                    for row in start_row..=end_row {
6072                        if snapshot.is_line_blank(row) && start_row < end_row {
6073                            continue;
6074                        }
6075
6076                        let prefix_range = comment_prefix_range(
6077                            snapshot.deref(),
6078                            row,
6079                            comment_prefix,
6080                            comment_prefix_whitespace,
6081                        );
6082                        if prefix_range.is_empty() {
6083                            all_selection_lines_are_comments = false;
6084                        }
6085                        selection_edit_ranges.push(prefix_range);
6086                    }
6087
6088                    if all_selection_lines_are_comments {
6089                        edits.extend(
6090                            selection_edit_ranges
6091                                .iter()
6092                                .cloned()
6093                                .map(|range| (range, empty_str.clone())),
6094                        );
6095                    } else {
6096                        let min_column = selection_edit_ranges
6097                            .iter()
6098                            .map(|r| r.start.column)
6099                            .min()
6100                            .unwrap_or(0);
6101                        edits.extend(selection_edit_ranges.iter().map(|range| {
6102                            let position = Point::new(range.start.row, min_column);
6103                            (position..position, full_comment_prefix.clone())
6104                        }));
6105                    }
6106                } else if let Some((full_comment_prefix, comment_suffix)) =
6107                    language.block_comment_delimiters()
6108                {
6109                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6110                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6111                    let prefix_range = comment_prefix_range(
6112                        snapshot.deref(),
6113                        start_row,
6114                        comment_prefix,
6115                        comment_prefix_whitespace,
6116                    );
6117                    let suffix_range = comment_suffix_range(
6118                        snapshot.deref(),
6119                        end_row,
6120                        comment_suffix.trim_start_matches(' '),
6121                        comment_suffix.starts_with(' '),
6122                    );
6123
6124                    if prefix_range.is_empty() || suffix_range.is_empty() {
6125                        edits.push((
6126                            prefix_range.start..prefix_range.start,
6127                            full_comment_prefix.clone(),
6128                        ));
6129                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6130                        suffixes_inserted.push((end_row, comment_suffix.len()));
6131                    } else {
6132                        edits.push((prefix_range, empty_str.clone()));
6133                        edits.push((suffix_range, empty_str.clone()));
6134                    }
6135                } else {
6136                    continue;
6137                }
6138            }
6139
6140            drop(snapshot);
6141            this.buffer.update(cx, |buffer, cx| {
6142                buffer.edit(edits, None, cx);
6143            });
6144
6145            // Adjust selections so that they end before any comment suffixes that
6146            // were inserted.
6147            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6148            let mut selections = this.selections.all::<Point>(cx);
6149            let snapshot = this.buffer.read(cx).read(cx);
6150            for selection in &mut selections {
6151                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6152                    match row.cmp(&selection.end.row) {
6153                        Ordering::Less => {
6154                            suffixes_inserted.next();
6155                            continue;
6156                        }
6157                        Ordering::Greater => break,
6158                        Ordering::Equal => {
6159                            if selection.end.column == snapshot.line_len(row) {
6160                                if selection.is_empty() {
6161                                    selection.start.column -= suffix_len as u32;
6162                                }
6163                                selection.end.column -= suffix_len as u32;
6164                            }
6165                            break;
6166                        }
6167                    }
6168                }
6169            }
6170
6171            drop(snapshot);
6172            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6173
6174            let selections = this.selections.all::<Point>(cx);
6175            let selections_on_single_row = selections.windows(2).all(|selections| {
6176                selections[0].start.row == selections[1].start.row
6177                    && selections[0].end.row == selections[1].end.row
6178                    && selections[0].start.row == selections[0].end.row
6179            });
6180            let selections_selecting = selections
6181                .iter()
6182                .any(|selection| selection.start != selection.end);
6183            let advance_downwards = action.advance_downwards
6184                && selections_on_single_row
6185                && !selections_selecting
6186                && this.mode != EditorMode::SingleLine;
6187
6188            if advance_downwards {
6189                let snapshot = this.buffer.read(cx).snapshot(cx);
6190
6191                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6192                    s.move_cursors_with(|display_snapshot, display_point, _| {
6193                        let mut point = display_point.to_point(display_snapshot);
6194                        point.row += 1;
6195                        point = snapshot.clip_point(point, Bias::Left);
6196                        let display_point = point.to_display_point(display_snapshot);
6197                        (display_point, SelectionGoal::Column(display_point.column()))
6198                    })
6199                });
6200            }
6201        });
6202    }
6203
6204    pub fn select_larger_syntax_node(
6205        &mut self,
6206        _: &SelectLargerSyntaxNode,
6207        cx: &mut ViewContext<Self>,
6208    ) {
6209        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6210        let buffer = self.buffer.read(cx).snapshot(cx);
6211        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6212
6213        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6214        let mut selected_larger_node = false;
6215        let new_selections = old_selections
6216            .iter()
6217            .map(|selection| {
6218                let old_range = selection.start..selection.end;
6219                let mut new_range = old_range.clone();
6220                while let Some(containing_range) =
6221                    buffer.range_for_syntax_ancestor(new_range.clone())
6222                {
6223                    new_range = containing_range;
6224                    if !display_map.intersects_fold(new_range.start)
6225                        && !display_map.intersects_fold(new_range.end)
6226                    {
6227                        break;
6228                    }
6229                }
6230
6231                selected_larger_node |= new_range != old_range;
6232                Selection {
6233                    id: selection.id,
6234                    start: new_range.start,
6235                    end: new_range.end,
6236                    goal: SelectionGoal::None,
6237                    reversed: selection.reversed,
6238                }
6239            })
6240            .collect::<Vec<_>>();
6241
6242        if selected_larger_node {
6243            stack.push(old_selections);
6244            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6245                s.select(new_selections);
6246            });
6247        }
6248        self.select_larger_syntax_node_stack = stack;
6249    }
6250
6251    pub fn select_smaller_syntax_node(
6252        &mut self,
6253        _: &SelectSmallerSyntaxNode,
6254        cx: &mut ViewContext<Self>,
6255    ) {
6256        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6257        if let Some(selections) = stack.pop() {
6258            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6259                s.select(selections.to_vec());
6260            });
6261        }
6262        self.select_larger_syntax_node_stack = stack;
6263    }
6264
6265    pub fn move_to_enclosing_bracket(
6266        &mut self,
6267        _: &MoveToEnclosingBracket,
6268        cx: &mut ViewContext<Self>,
6269    ) {
6270        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6271            s.move_offsets_with(|snapshot, selection| {
6272                let Some(enclosing_bracket_ranges) =
6273                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6274                else {
6275                    return;
6276                };
6277
6278                let mut best_length = usize::MAX;
6279                let mut best_inside = false;
6280                let mut best_in_bracket_range = false;
6281                let mut best_destination = None;
6282                for (open, close) in enclosing_bracket_ranges {
6283                    let close = close.to_inclusive();
6284                    let length = close.end() - open.start;
6285                    let inside = selection.start >= open.end && selection.end <= *close.start();
6286                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6287                        || close.contains(&selection.head());
6288
6289                    // If best is next to a bracket and current isn't, skip
6290                    if !in_bracket_range && best_in_bracket_range {
6291                        continue;
6292                    }
6293
6294                    // Prefer smaller lengths unless best is inside and current isn't
6295                    if length > best_length && (best_inside || !inside) {
6296                        continue;
6297                    }
6298
6299                    best_length = length;
6300                    best_inside = inside;
6301                    best_in_bracket_range = in_bracket_range;
6302                    best_destination = Some(
6303                        if close.contains(&selection.start) && close.contains(&selection.end) {
6304                            if inside {
6305                                open.end
6306                            } else {
6307                                open.start
6308                            }
6309                        } else {
6310                            if inside {
6311                                *close.start()
6312                            } else {
6313                                *close.end()
6314                            }
6315                        },
6316                    );
6317                }
6318
6319                if let Some(destination) = best_destination {
6320                    selection.collapse_to(destination, SelectionGoal::None);
6321                }
6322            })
6323        });
6324    }
6325
6326    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6327        self.end_selection(cx);
6328        self.selection_history.mode = SelectionHistoryMode::Undoing;
6329        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6330            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6331            self.select_next_state = entry.select_next_state;
6332            self.select_prev_state = entry.select_prev_state;
6333            self.add_selections_state = entry.add_selections_state;
6334            self.request_autoscroll(Autoscroll::newest(), cx);
6335        }
6336        self.selection_history.mode = SelectionHistoryMode::Normal;
6337    }
6338
6339    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6340        self.end_selection(cx);
6341        self.selection_history.mode = SelectionHistoryMode::Redoing;
6342        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6343            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6344            self.select_next_state = entry.select_next_state;
6345            self.select_prev_state = entry.select_prev_state;
6346            self.add_selections_state = entry.add_selections_state;
6347            self.request_autoscroll(Autoscroll::newest(), cx);
6348        }
6349        self.selection_history.mode = SelectionHistoryMode::Normal;
6350    }
6351
6352    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6353        self.go_to_diagnostic_impl(Direction::Next, cx)
6354    }
6355
6356    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6357        self.go_to_diagnostic_impl(Direction::Prev, cx)
6358    }
6359
6360    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6361        let buffer = self.buffer.read(cx).snapshot(cx);
6362        let selection = self.selections.newest::<usize>(cx);
6363
6364        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
6365        if direction == Direction::Next {
6366            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6367                let (group_id, jump_to) = popover.activation_info();
6368                if self.activate_diagnostics(group_id, cx) {
6369                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6370                        let mut new_selection = s.newest_anchor().clone();
6371                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6372                        s.select_anchors(vec![new_selection.clone()]);
6373                    });
6374                }
6375                return;
6376            }
6377        }
6378
6379        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6380            active_diagnostics
6381                .primary_range
6382                .to_offset(&buffer)
6383                .to_inclusive()
6384        });
6385        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6386            if active_primary_range.contains(&selection.head()) {
6387                *active_primary_range.end()
6388            } else {
6389                selection.head()
6390            }
6391        } else {
6392            selection.head()
6393        };
6394
6395        loop {
6396            let mut diagnostics = if direction == Direction::Prev {
6397                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6398            } else {
6399                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6400            };
6401            let group = diagnostics.find_map(|entry| {
6402                if entry.diagnostic.is_primary
6403                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6404                    && !entry.range.is_empty()
6405                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6406                {
6407                    Some((entry.range, entry.diagnostic.group_id))
6408                } else {
6409                    None
6410                }
6411            });
6412
6413            if let Some((primary_range, group_id)) = group {
6414                if self.activate_diagnostics(group_id, cx) {
6415                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6416                        s.select(vec![Selection {
6417                            id: selection.id,
6418                            start: primary_range.start,
6419                            end: primary_range.start,
6420                            reversed: false,
6421                            goal: SelectionGoal::None,
6422                        }]);
6423                    });
6424                }
6425                break;
6426            } else {
6427                // Cycle around to the start of the buffer, potentially moving back to the start of
6428                // the currently active diagnostic.
6429                active_primary_range.take();
6430                if direction == Direction::Prev {
6431                    if search_start == buffer.len() {
6432                        break;
6433                    } else {
6434                        search_start = buffer.len();
6435                    }
6436                } else if search_start == 0 {
6437                    break;
6438                } else {
6439                    search_start = 0;
6440                }
6441            }
6442        }
6443    }
6444
6445    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6446        let snapshot = self
6447            .display_map
6448            .update(cx, |display_map, cx| display_map.snapshot(cx));
6449        let selection = self.selections.newest::<Point>(cx);
6450
6451        if !self.seek_in_direction(
6452            &snapshot,
6453            selection.head(),
6454            false,
6455            snapshot
6456                .buffer_snapshot
6457                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6458            cx,
6459        ) {
6460            let wrapped_point = Point::zero();
6461            self.seek_in_direction(
6462                &snapshot,
6463                wrapped_point,
6464                true,
6465                snapshot
6466                    .buffer_snapshot
6467                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
6468                cx,
6469            );
6470        }
6471    }
6472
6473    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
6474        let snapshot = self
6475            .display_map
6476            .update(cx, |display_map, cx| display_map.snapshot(cx));
6477        let selection = self.selections.newest::<Point>(cx);
6478
6479        if !self.seek_in_direction(
6480            &snapshot,
6481            selection.head(),
6482            false,
6483            snapshot
6484                .buffer_snapshot
6485                .git_diff_hunks_in_range_rev(0..selection.head().row),
6486            cx,
6487        ) {
6488            let wrapped_point = snapshot.buffer_snapshot.max_point();
6489            self.seek_in_direction(
6490                &snapshot,
6491                wrapped_point,
6492                true,
6493                snapshot
6494                    .buffer_snapshot
6495                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
6496                cx,
6497            );
6498        }
6499    }
6500
6501    fn seek_in_direction(
6502        &mut self,
6503        snapshot: &DisplaySnapshot,
6504        initial_point: Point,
6505        is_wrapped: bool,
6506        hunks: impl Iterator<Item = DiffHunk<u32>>,
6507        cx: &mut ViewContext<Editor>,
6508    ) -> bool {
6509        let display_point = initial_point.to_display_point(snapshot);
6510        let mut hunks = hunks
6511            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
6512            .skip_while(|hunk| {
6513                if is_wrapped {
6514                    false
6515                } else {
6516                    hunk.contains_display_row(display_point.row())
6517                }
6518            })
6519            .dedup();
6520
6521        if let Some(hunk) = hunks.next() {
6522            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6523                let row = hunk.start_display_row();
6524                let point = DisplayPoint::new(row, 0);
6525                s.select_display_ranges([point..point]);
6526            });
6527
6528            true
6529        } else {
6530            false
6531        }
6532    }
6533
6534    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
6535        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
6536    }
6537
6538    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
6539        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
6540    }
6541
6542    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
6543        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
6544    }
6545
6546    pub fn go_to_type_definition_split(
6547        &mut self,
6548        _: &GoToTypeDefinitionSplit,
6549        cx: &mut ViewContext<Self>,
6550    ) {
6551        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
6552    }
6553
6554    fn go_to_definition_of_kind(
6555        &mut self,
6556        kind: GotoDefinitionKind,
6557        split: bool,
6558        cx: &mut ViewContext<Self>,
6559    ) {
6560        let Some(workspace) = self.workspace(cx) else {
6561            return;
6562        };
6563        let buffer = self.buffer.read(cx);
6564        let head = self.selections.newest::<usize>(cx).head();
6565        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
6566            text_anchor
6567        } else {
6568            return;
6569        };
6570
6571        let project = workspace.read(cx).project().clone();
6572        let definitions = project.update(cx, |project, cx| match kind {
6573            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
6574            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
6575        });
6576
6577        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
6578            let definitions = definitions.await?;
6579            editor.update(&mut cx, |editor, cx| {
6580                editor.navigate_to_definitions(
6581                    definitions
6582                        .into_iter()
6583                        .map(GoToDefinitionLink::Text)
6584                        .collect(),
6585                    split,
6586                    cx,
6587                );
6588            })?;
6589            Ok::<(), anyhow::Error>(())
6590        })
6591        .detach_and_log_err(cx);
6592    }
6593
6594    pub fn navigate_to_definitions(
6595        &mut self,
6596        mut definitions: Vec<GoToDefinitionLink>,
6597        split: bool,
6598        cx: &mut ViewContext<Editor>,
6599    ) {
6600        let Some(workspace) = self.workspace(cx) else {
6601            return;
6602        };
6603        let pane = workspace.read(cx).active_pane().clone();
6604        // If there is one definition, just open it directly
6605        if definitions.len() == 1 {
6606            let definition = definitions.pop().unwrap();
6607            let target_task = match definition {
6608                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
6609                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
6610                    self.compute_target_location(lsp_location, server_id, cx)
6611                }
6612            };
6613            cx.spawn(|editor, mut cx| async move {
6614                let target = target_task.await.context("target resolution task")?;
6615                if let Some(target) = target {
6616                    editor.update(&mut cx, |editor, cx| {
6617                        let range = target.range.to_offset(target.buffer.read(cx));
6618                        let range = editor.range_for_match(&range);
6619                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
6620                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
6621                                s.select_ranges([range]);
6622                            });
6623                        } else {
6624                            cx.window_context().defer(move |cx| {
6625                                let target_editor: ViewHandle<Self> =
6626                                    workspace.update(cx, |workspace, cx| {
6627                                        if split {
6628                                            workspace.split_project_item(target.buffer.clone(), cx)
6629                                        } else {
6630                                            workspace.open_project_item(target.buffer.clone(), cx)
6631                                        }
6632                                    });
6633                                target_editor.update(cx, |target_editor, cx| {
6634                                    // When selecting a definition in a different buffer, disable the nav history
6635                                    // to avoid creating a history entry at the previous cursor location.
6636                                    pane.update(cx, |pane, _| pane.disable_history());
6637                                    target_editor.change_selections(
6638                                        Some(Autoscroll::fit()),
6639                                        cx,
6640                                        |s| {
6641                                            s.select_ranges([range]);
6642                                        },
6643                                    );
6644                                    pane.update(cx, |pane, _| pane.enable_history());
6645                                });
6646                            });
6647                        }
6648                    })
6649                } else {
6650                    Ok(())
6651                }
6652            })
6653            .detach_and_log_err(cx);
6654        } else if !definitions.is_empty() {
6655            let replica_id = self.replica_id(cx);
6656            cx.spawn(|editor, mut cx| async move {
6657                let (title, location_tasks) = editor
6658                    .update(&mut cx, |editor, cx| {
6659                        let title = definitions
6660                            .iter()
6661                            .find_map(|definition| match definition {
6662                                GoToDefinitionLink::Text(link) => {
6663                                    link.origin.as_ref().map(|origin| {
6664                                        let buffer = origin.buffer.read(cx);
6665                                        format!(
6666                                            "Definitions for {}",
6667                                            buffer
6668                                                .text_for_range(origin.range.clone())
6669                                                .collect::<String>()
6670                                        )
6671                                    })
6672                                }
6673                                GoToDefinitionLink::InlayHint(_, _) => None,
6674                            })
6675                            .unwrap_or("Definitions".to_string());
6676                        let location_tasks = definitions
6677                            .into_iter()
6678                            .map(|definition| match definition {
6679                                GoToDefinitionLink::Text(link) => {
6680                                    Task::Ready(Some(Ok(Some(link.target))))
6681                                }
6682                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
6683                                    editor.compute_target_location(lsp_location, server_id, cx)
6684                                }
6685                            })
6686                            .collect::<Vec<_>>();
6687                        (title, location_tasks)
6688                    })
6689                    .context("location tasks preparation")?;
6690
6691                let locations = futures::future::join_all(location_tasks)
6692                    .await
6693                    .into_iter()
6694                    .filter_map(|location| location.transpose())
6695                    .collect::<Result<_>>()
6696                    .context("location tasks")?;
6697                workspace.update(&mut cx, |workspace, cx| {
6698                    Self::open_locations_in_multibuffer(
6699                        workspace, locations, replica_id, title, split, cx,
6700                    )
6701                });
6702
6703                anyhow::Ok(())
6704            })
6705            .detach_and_log_err(cx);
6706        }
6707    }
6708
6709    fn compute_target_location(
6710        &self,
6711        lsp_location: lsp::Location,
6712        server_id: LanguageServerId,
6713        cx: &mut ViewContext<Editor>,
6714    ) -> Task<anyhow::Result<Option<Location>>> {
6715        let Some(project) = self.project.clone() else {
6716            return Task::Ready(Some(Ok(None)));
6717        };
6718
6719        cx.spawn(move |editor, mut cx| async move {
6720            let location_task = editor.update(&mut cx, |editor, cx| {
6721                project.update(cx, |project, cx| {
6722                    let language_server_name =
6723                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
6724                            project
6725                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
6726                                .map(|(_, lsp_adapter)| {
6727                                    LanguageServerName(Arc::from(lsp_adapter.name()))
6728                                })
6729                        });
6730                    language_server_name.map(|language_server_name| {
6731                        project.open_local_buffer_via_lsp(
6732                            lsp_location.uri.clone(),
6733                            server_id,
6734                            language_server_name,
6735                            cx,
6736                        )
6737                    })
6738                })
6739            })?;
6740            let location = match location_task {
6741                Some(task) => Some({
6742                    let target_buffer_handle = task.await.context("open local buffer")?;
6743                    let range = {
6744                        target_buffer_handle.update(&mut cx, |target_buffer, _| {
6745                            let target_start = target_buffer.clip_point_utf16(
6746                                point_from_lsp(lsp_location.range.start),
6747                                Bias::Left,
6748                            );
6749                            let target_end = target_buffer.clip_point_utf16(
6750                                point_from_lsp(lsp_location.range.end),
6751                                Bias::Left,
6752                            );
6753                            target_buffer.anchor_after(target_start)
6754                                ..target_buffer.anchor_before(target_end)
6755                        })
6756                    };
6757                    Location {
6758                        buffer: target_buffer_handle,
6759                        range,
6760                    }
6761                }),
6762                None => None,
6763            };
6764            Ok(location)
6765        })
6766    }
6767
6768    pub fn find_all_references(
6769        workspace: &mut Workspace,
6770        _: &FindAllReferences,
6771        cx: &mut ViewContext<Workspace>,
6772    ) -> Option<Task<Result<()>>> {
6773        let active_item = workspace.active_item(cx)?;
6774        let editor_handle = active_item.act_as::<Self>(cx)?;
6775
6776        let editor = editor_handle.read(cx);
6777        let buffer = editor.buffer.read(cx);
6778        let head = editor.selections.newest::<usize>(cx).head();
6779        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
6780        let replica_id = editor.replica_id(cx);
6781
6782        let project = workspace.project().clone();
6783        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
6784        Some(cx.spawn_labeled(
6785            "Finding All References...",
6786            |workspace, mut cx| async move {
6787                let locations = references.await?;
6788                if locations.is_empty() {
6789                    return Ok(());
6790                }
6791
6792                workspace.update(&mut cx, |workspace, cx| {
6793                    let title = locations
6794                        .first()
6795                        .as_ref()
6796                        .map(|location| {
6797                            let buffer = location.buffer.read(cx);
6798                            format!(
6799                                "References to `{}`",
6800                                buffer
6801                                    .text_for_range(location.range.clone())
6802                                    .collect::<String>()
6803                            )
6804                        })
6805                        .unwrap();
6806                    Self::open_locations_in_multibuffer(
6807                        workspace, locations, replica_id, title, false, cx,
6808                    );
6809                })?;
6810
6811                Ok(())
6812            },
6813        ))
6814    }
6815
6816    /// Opens a multibuffer with the given project locations in it
6817    pub fn open_locations_in_multibuffer(
6818        workspace: &mut Workspace,
6819        mut locations: Vec<Location>,
6820        replica_id: ReplicaId,
6821        title: String,
6822        split: bool,
6823        cx: &mut ViewContext<Workspace>,
6824    ) {
6825        // If there are multiple definitions, open them in a multibuffer
6826        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
6827        let mut locations = locations.into_iter().peekable();
6828        let mut ranges_to_highlight = Vec::new();
6829
6830        let excerpt_buffer = cx.add_model(|cx| {
6831            let mut multibuffer = MultiBuffer::new(replica_id);
6832            while let Some(location) = locations.next() {
6833                let buffer = location.buffer.read(cx);
6834                let mut ranges_for_buffer = Vec::new();
6835                let range = location.range.to_offset(buffer);
6836                ranges_for_buffer.push(range.clone());
6837
6838                while let Some(next_location) = locations.peek() {
6839                    if next_location.buffer == location.buffer {
6840                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
6841                        locations.next();
6842                    } else {
6843                        break;
6844                    }
6845                }
6846
6847                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
6848                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
6849                    location.buffer.clone(),
6850                    ranges_for_buffer,
6851                    1,
6852                    cx,
6853                ))
6854            }
6855
6856            multibuffer.with_title(title)
6857        });
6858
6859        let editor = cx.add_view(|cx| {
6860            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
6861        });
6862        editor.update(cx, |editor, cx| {
6863            editor.highlight_background::<Self>(
6864                ranges_to_highlight,
6865                |theme| theme.editor.highlighted_line_background,
6866                cx,
6867            );
6868        });
6869        if split {
6870            workspace.split_item(Box::new(editor), cx);
6871        } else {
6872            workspace.add_item(Box::new(editor), cx);
6873        }
6874    }
6875
6876    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6877        use language::ToOffset as _;
6878
6879        let project = self.project.clone()?;
6880        let selection = self.selections.newest_anchor().clone();
6881        let (cursor_buffer, cursor_buffer_position) = self
6882            .buffer
6883            .read(cx)
6884            .text_anchor_for_position(selection.head(), cx)?;
6885        let (tail_buffer, _) = self
6886            .buffer
6887            .read(cx)
6888            .text_anchor_for_position(selection.tail(), cx)?;
6889        if tail_buffer != cursor_buffer {
6890            return None;
6891        }
6892
6893        let snapshot = cursor_buffer.read(cx).snapshot();
6894        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
6895        let prepare_rename = project.update(cx, |project, cx| {
6896            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
6897        });
6898
6899        Some(cx.spawn(|this, mut cx| async move {
6900            let rename_range = if let Some(range) = prepare_rename.await? {
6901                Some(range)
6902            } else {
6903                this.update(&mut cx, |this, cx| {
6904                    let buffer = this.buffer.read(cx).snapshot(cx);
6905                    let display_snapshot = this
6906                        .display_map
6907                        .update(cx, |display_map, cx| display_map.snapshot(cx));
6908                    let mut buffer_highlights = this
6909                        .document_highlights_for_position(
6910                            selection.head(),
6911                            &buffer,
6912                            &display_snapshot,
6913                        )
6914                        .filter_map(|highlight| highlight.as_text_range())
6915                        .filter(|highlight| {
6916                            highlight.start.excerpt_id() == selection.head().excerpt_id()
6917                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
6918                        });
6919                    buffer_highlights
6920                        .next()
6921                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
6922                })?
6923            };
6924            if let Some(rename_range) = rename_range {
6925                let rename_buffer_range = rename_range.to_offset(&snapshot);
6926                let cursor_offset_in_rename_range =
6927                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
6928
6929                this.update(&mut cx, |this, cx| {
6930                    this.take_rename(false, cx);
6931                    let style = this.style(cx);
6932                    let buffer = this.buffer.read(cx).read(cx);
6933                    let cursor_offset = selection.head().to_offset(&buffer);
6934                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
6935                    let rename_end = rename_start + rename_buffer_range.len();
6936                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
6937                    let mut old_highlight_id = None;
6938                    let old_name: Arc<str> = buffer
6939                        .chunks(rename_start..rename_end, true)
6940                        .map(|chunk| {
6941                            if old_highlight_id.is_none() {
6942                                old_highlight_id = chunk.syntax_highlight_id;
6943                            }
6944                            chunk.text
6945                        })
6946                        .collect::<String>()
6947                        .into();
6948
6949                    drop(buffer);
6950
6951                    // Position the selection in the rename editor so that it matches the current selection.
6952                    this.show_local_selections = false;
6953                    let rename_editor = cx.add_view(|cx| {
6954                        let mut editor = Editor::single_line(None, cx);
6955                        if let Some(old_highlight_id) = old_highlight_id {
6956                            editor.override_text_style =
6957                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6958                        }
6959                        editor.buffer.update(cx, |buffer, cx| {
6960                            buffer.edit([(0..0, old_name.clone())], None, cx)
6961                        });
6962                        editor.select_all(&SelectAll, cx);
6963                        editor
6964                    });
6965
6966                    let ranges = this
6967                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6968                        .into_iter()
6969                        .flat_map(|(_, ranges)| {
6970                            ranges.into_iter().filter_map(|range| range.as_text_range())
6971                        })
6972                        .chain(
6973                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6974                                .into_iter()
6975                                .flat_map(|(_, ranges)| {
6976                                    ranges.into_iter().filter_map(|range| range.as_text_range())
6977                                }),
6978                        )
6979                        .collect();
6980
6981                    this.highlight_text::<Rename>(
6982                        ranges,
6983                        HighlightStyle {
6984                            fade_out: Some(style.rename_fade),
6985                            ..Default::default()
6986                        },
6987                        cx,
6988                    );
6989                    cx.focus(&rename_editor);
6990                    let block_id = this.insert_blocks(
6991                        [BlockProperties {
6992                            style: BlockStyle::Flex,
6993                            position: range.start.clone(),
6994                            height: 1,
6995                            render: Arc::new({
6996                                let editor = rename_editor.clone();
6997                                move |cx: &mut BlockContext| {
6998                                    ChildView::new(&editor, cx)
6999                                        .contained()
7000                                        .with_padding_left(cx.anchor_x)
7001                                        .into_any()
7002                                }
7003                            }),
7004                            disposition: BlockDisposition::Below,
7005                        }],
7006                        Some(Autoscroll::fit()),
7007                        cx,
7008                    )[0];
7009                    this.pending_rename = Some(RenameState {
7010                        range,
7011                        old_name,
7012                        editor: rename_editor,
7013                        block_id,
7014                    });
7015                })?;
7016            }
7017
7018            Ok(())
7019        }))
7020    }
7021
7022    pub fn confirm_rename(
7023        workspace: &mut Workspace,
7024        _: &ConfirmRename,
7025        cx: &mut ViewContext<Workspace>,
7026    ) -> Option<Task<Result<()>>> {
7027        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
7028
7029        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
7030            let rename = editor.take_rename(false, cx)?;
7031            let buffer = editor.buffer.read(cx);
7032            let (start_buffer, start) =
7033                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
7034            let (end_buffer, end) =
7035                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
7036            if start_buffer == end_buffer {
7037                let new_name = rename.editor.read(cx).text(cx);
7038                Some((start_buffer, start..end, rename.old_name, new_name))
7039            } else {
7040                None
7041            }
7042        })?;
7043
7044        let rename = workspace.project().clone().update(cx, |project, cx| {
7045            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7046        });
7047
7048        let editor = editor.downgrade();
7049        Some(cx.spawn(|workspace, mut cx| async move {
7050            let project_transaction = rename.await?;
7051            Self::open_project_transaction(
7052                &editor,
7053                workspace,
7054                project_transaction,
7055                format!("Rename: {}{}", old_name, new_name),
7056                cx.clone(),
7057            )
7058            .await?;
7059
7060            editor.update(&mut cx, |editor, cx| {
7061                editor.refresh_document_highlights(cx);
7062            })?;
7063            Ok(())
7064        }))
7065    }
7066
7067    fn take_rename(
7068        &mut self,
7069        moving_cursor: bool,
7070        cx: &mut ViewContext<Self>,
7071    ) -> Option<RenameState> {
7072        let rename = self.pending_rename.take()?;
7073        self.remove_blocks(
7074            [rename.block_id].into_iter().collect(),
7075            Some(Autoscroll::fit()),
7076            cx,
7077        );
7078        self.clear_text_highlights::<Rename>(cx);
7079        self.show_local_selections = true;
7080
7081        if moving_cursor {
7082            let rename_editor = rename.editor.read(cx);
7083            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7084
7085            // Update the selection to match the position of the selection inside
7086            // the rename editor.
7087            let snapshot = self.buffer.read(cx).read(cx);
7088            let rename_range = rename.range.to_offset(&snapshot);
7089            let cursor_in_editor = snapshot
7090                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7091                .min(rename_range.end);
7092            drop(snapshot);
7093
7094            self.change_selections(None, cx, |s| {
7095                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7096            });
7097        } else {
7098            self.refresh_document_highlights(cx);
7099        }
7100
7101        Some(rename)
7102    }
7103
7104    #[cfg(any(test, feature = "test-support"))]
7105    pub fn pending_rename(&self) -> Option<&RenameState> {
7106        self.pending_rename.as_ref()
7107    }
7108
7109    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7110        let project = match &self.project {
7111            Some(project) => project.clone(),
7112            None => return None,
7113        };
7114
7115        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7116    }
7117
7118    fn perform_format(
7119        &mut self,
7120        project: ModelHandle<Project>,
7121        trigger: FormatTrigger,
7122        cx: &mut ViewContext<Self>,
7123    ) -> Task<Result<()>> {
7124        let buffer = self.buffer().clone();
7125        let buffers = buffer.read(cx).all_buffers();
7126
7127        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
7128        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7129
7130        cx.spawn(|_, mut cx| async move {
7131            let transaction = futures::select_biased! {
7132                _ = timeout => {
7133                    log::warn!("timed out waiting for formatting");
7134                    None
7135                }
7136                transaction = format.log_err().fuse() => transaction,
7137            };
7138
7139            buffer.update(&mut cx, |buffer, cx| {
7140                if let Some(transaction) = transaction {
7141                    if !buffer.is_singleton() {
7142                        buffer.push_transaction(&transaction.0, cx);
7143                    }
7144                }
7145
7146                cx.notify();
7147            });
7148
7149            Ok(())
7150        })
7151    }
7152
7153    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7154        if let Some(project) = self.project.clone() {
7155            self.buffer.update(cx, |multi_buffer, cx| {
7156                project.update(cx, |project, cx| {
7157                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7158                });
7159            })
7160        }
7161    }
7162
7163    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7164        cx.show_character_palette();
7165    }
7166
7167    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7168        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7169            let buffer = self.buffer.read(cx).snapshot(cx);
7170            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7171            let is_valid = buffer
7172                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7173                .any(|entry| {
7174                    entry.diagnostic.is_primary
7175                        && !entry.range.is_empty()
7176                        && entry.range.start == primary_range_start
7177                        && entry.diagnostic.message == active_diagnostics.primary_message
7178                });
7179
7180            if is_valid != active_diagnostics.is_valid {
7181                active_diagnostics.is_valid = is_valid;
7182                let mut new_styles = HashMap::default();
7183                for (block_id, diagnostic) in &active_diagnostics.blocks {
7184                    new_styles.insert(
7185                        *block_id,
7186                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7187                    );
7188                }
7189                self.display_map
7190                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7191            }
7192        }
7193    }
7194
7195    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7196        self.dismiss_diagnostics(cx);
7197        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7198            let buffer = self.buffer.read(cx).snapshot(cx);
7199
7200            let mut primary_range = None;
7201            let mut primary_message = None;
7202            let mut group_end = Point::zero();
7203            let diagnostic_group = buffer
7204                .diagnostic_group::<Point>(group_id)
7205                .map(|entry| {
7206                    if entry.range.end > group_end {
7207                        group_end = entry.range.end;
7208                    }
7209                    if entry.diagnostic.is_primary {
7210                        primary_range = Some(entry.range.clone());
7211                        primary_message = Some(entry.diagnostic.message.clone());
7212                    }
7213                    entry
7214                })
7215                .collect::<Vec<_>>();
7216            let primary_range = primary_range?;
7217            let primary_message = primary_message?;
7218            let primary_range =
7219                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7220
7221            let blocks = display_map
7222                .insert_blocks(
7223                    diagnostic_group.iter().map(|entry| {
7224                        let diagnostic = entry.diagnostic.clone();
7225                        let message_height = diagnostic.message.lines().count() as u8;
7226                        BlockProperties {
7227                            style: BlockStyle::Fixed,
7228                            position: buffer.anchor_after(entry.range.start),
7229                            height: message_height,
7230                            render: diagnostic_block_renderer(diagnostic, true),
7231                            disposition: BlockDisposition::Below,
7232                        }
7233                    }),
7234                    cx,
7235                )
7236                .into_iter()
7237                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7238                .collect();
7239
7240            Some(ActiveDiagnosticGroup {
7241                primary_range,
7242                primary_message,
7243                blocks,
7244                is_valid: true,
7245            })
7246        });
7247        self.active_diagnostics.is_some()
7248    }
7249
7250    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7251        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7252            self.display_map.update(cx, |display_map, cx| {
7253                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7254            });
7255            cx.notify();
7256        }
7257    }
7258
7259    pub fn set_selections_from_remote(
7260        &mut self,
7261        selections: Vec<Selection<Anchor>>,
7262        pending_selection: Option<Selection<Anchor>>,
7263        cx: &mut ViewContext<Self>,
7264    ) {
7265        let old_cursor_position = self.selections.newest_anchor().head();
7266        self.selections.change_with(cx, |s| {
7267            s.select_anchors(selections);
7268            if let Some(pending_selection) = pending_selection {
7269                s.set_pending(pending_selection, SelectMode::Character);
7270            } else {
7271                s.clear_pending();
7272            }
7273        });
7274        self.selections_did_change(false, &old_cursor_position, cx);
7275    }
7276
7277    fn push_to_selection_history(&mut self) {
7278        self.selection_history.push(SelectionHistoryEntry {
7279            selections: self.selections.disjoint_anchors(),
7280            select_next_state: self.select_next_state.clone(),
7281            select_prev_state: self.select_prev_state.clone(),
7282            add_selections_state: self.add_selections_state.clone(),
7283        });
7284    }
7285
7286    pub fn transact(
7287        &mut self,
7288        cx: &mut ViewContext<Self>,
7289        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7290    ) -> Option<TransactionId> {
7291        self.start_transaction_at(Instant::now(), cx);
7292        update(self, cx);
7293        self.end_transaction_at(Instant::now(), cx)
7294    }
7295
7296    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7297        self.end_selection(cx);
7298        if let Some(tx_id) = self
7299            .buffer
7300            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7301        {
7302            self.selection_history
7303                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7304        }
7305    }
7306
7307    fn end_transaction_at(
7308        &mut self,
7309        now: Instant,
7310        cx: &mut ViewContext<Self>,
7311    ) -> Option<TransactionId> {
7312        if let Some(tx_id) = self
7313            .buffer
7314            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7315        {
7316            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7317                *end_selections = Some(self.selections.disjoint_anchors());
7318            } else {
7319                error!("unexpectedly ended a transaction that wasn't started by this editor");
7320            }
7321
7322            cx.emit(Event::Edited);
7323            Some(tx_id)
7324        } else {
7325            None
7326        }
7327    }
7328
7329    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7330        let mut fold_ranges = Vec::new();
7331
7332        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7333
7334        let selections = self.selections.all::<Point>(cx);
7335        for selection in selections {
7336            let range = selection.range().sorted();
7337            let buffer_start_row = range.start.row;
7338
7339            for row in (0..=range.end.row).rev() {
7340                let fold_range = display_map.foldable_range(row);
7341
7342                if let Some(fold_range) = fold_range {
7343                    if fold_range.end.row >= buffer_start_row {
7344                        fold_ranges.push(fold_range);
7345                        if row <= range.start.row {
7346                            break;
7347                        }
7348                    }
7349                }
7350            }
7351        }
7352
7353        self.fold_ranges(fold_ranges, true, cx);
7354    }
7355
7356    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7357        let buffer_row = fold_at.buffer_row;
7358        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7359
7360        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7361            let autoscroll = self
7362                .selections
7363                .all::<Point>(cx)
7364                .iter()
7365                .any(|selection| fold_range.overlaps(&selection.range()));
7366
7367            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7368        }
7369    }
7370
7371    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7372        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7373        let buffer = &display_map.buffer_snapshot;
7374        let selections = self.selections.all::<Point>(cx);
7375        let ranges = selections
7376            .iter()
7377            .map(|s| {
7378                let range = s.display_range(&display_map).sorted();
7379                let mut start = range.start.to_point(&display_map);
7380                let mut end = range.end.to_point(&display_map);
7381                start.column = 0;
7382                end.column = buffer.line_len(end.row);
7383                start..end
7384            })
7385            .collect::<Vec<_>>();
7386
7387        self.unfold_ranges(ranges, true, true, cx);
7388    }
7389
7390    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7391        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7392
7393        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7394            ..Point::new(
7395                unfold_at.buffer_row,
7396                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7397            );
7398
7399        let autoscroll = self
7400            .selections
7401            .all::<Point>(cx)
7402            .iter()
7403            .any(|selection| selection.range().overlaps(&intersection_range));
7404
7405        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7406    }
7407
7408    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7409        let selections = self.selections.all::<Point>(cx);
7410        let ranges = selections.into_iter().map(|s| s.start..s.end);
7411        self.fold_ranges(ranges, true, cx);
7412    }
7413
7414    pub fn fold_ranges<T: ToOffset + Clone>(
7415        &mut self,
7416        ranges: impl IntoIterator<Item = Range<T>>,
7417        auto_scroll: bool,
7418        cx: &mut ViewContext<Self>,
7419    ) {
7420        let mut ranges = ranges.into_iter().peekable();
7421        if ranges.peek().is_some() {
7422            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7423
7424            if auto_scroll {
7425                self.request_autoscroll(Autoscroll::fit(), cx);
7426            }
7427
7428            cx.notify();
7429        }
7430    }
7431
7432    pub fn unfold_ranges<T: ToOffset + Clone>(
7433        &mut self,
7434        ranges: impl IntoIterator<Item = Range<T>>,
7435        inclusive: bool,
7436        auto_scroll: bool,
7437        cx: &mut ViewContext<Self>,
7438    ) {
7439        let mut ranges = ranges.into_iter().peekable();
7440        if ranges.peek().is_some() {
7441            self.display_map
7442                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
7443            if auto_scroll {
7444                self.request_autoscroll(Autoscroll::fit(), cx);
7445            }
7446
7447            cx.notify();
7448        }
7449    }
7450
7451    pub fn gutter_hover(
7452        &mut self,
7453        GutterHover { hovered }: &GutterHover,
7454        cx: &mut ViewContext<Self>,
7455    ) {
7456        self.gutter_hovered = *hovered;
7457        cx.notify();
7458    }
7459
7460    pub fn insert_blocks(
7461        &mut self,
7462        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
7463        autoscroll: Option<Autoscroll>,
7464        cx: &mut ViewContext<Self>,
7465    ) -> Vec<BlockId> {
7466        let blocks = self
7467            .display_map
7468            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
7469        if let Some(autoscroll) = autoscroll {
7470            self.request_autoscroll(autoscroll, cx);
7471        }
7472        blocks
7473    }
7474
7475    pub fn replace_blocks(
7476        &mut self,
7477        blocks: HashMap<BlockId, RenderBlock>,
7478        autoscroll: Option<Autoscroll>,
7479        cx: &mut ViewContext<Self>,
7480    ) {
7481        self.display_map
7482            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
7483        if let Some(autoscroll) = autoscroll {
7484            self.request_autoscroll(autoscroll, cx);
7485        }
7486    }
7487
7488    pub fn remove_blocks(
7489        &mut self,
7490        block_ids: HashSet<BlockId>,
7491        autoscroll: Option<Autoscroll>,
7492        cx: &mut ViewContext<Self>,
7493    ) {
7494        self.display_map.update(cx, |display_map, cx| {
7495            display_map.remove_blocks(block_ids, cx)
7496        });
7497        if let Some(autoscroll) = autoscroll {
7498            self.request_autoscroll(autoscroll, cx);
7499        }
7500    }
7501
7502    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
7503        self.display_map
7504            .update(cx, |map, cx| map.snapshot(cx))
7505            .longest_row()
7506    }
7507
7508    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
7509        self.display_map
7510            .update(cx, |map, cx| map.snapshot(cx))
7511            .max_point()
7512    }
7513
7514    pub fn text(&self, cx: &AppContext) -> String {
7515        self.buffer.read(cx).read(cx).text()
7516    }
7517
7518    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
7519        self.transact(cx, |this, cx| {
7520            this.buffer
7521                .read(cx)
7522                .as_singleton()
7523                .expect("you can only call set_text on editors for singleton buffers")
7524                .update(cx, |buffer, cx| buffer.set_text(text, cx));
7525        });
7526    }
7527
7528    pub fn display_text(&self, cx: &mut AppContext) -> String {
7529        self.display_map
7530            .update(cx, |map, cx| map.snapshot(cx))
7531            .text()
7532    }
7533
7534    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
7535        let mut wrap_guides = smallvec::smallvec![];
7536
7537        if self.show_wrap_guides == Some(false) {
7538            return wrap_guides;
7539        }
7540
7541        let settings = self.buffer.read(cx).settings_at(0, cx);
7542        if settings.show_wrap_guides {
7543            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
7544                wrap_guides.push((soft_wrap as usize, true));
7545            }
7546            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
7547        }
7548
7549        wrap_guides
7550    }
7551
7552    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
7553        let settings = self.buffer.read(cx).settings_at(0, cx);
7554        let mode = self
7555            .soft_wrap_mode_override
7556            .unwrap_or_else(|| settings.soft_wrap);
7557        match mode {
7558            language_settings::SoftWrap::None => SoftWrap::None,
7559            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
7560            language_settings::SoftWrap::PreferredLineLength => {
7561                SoftWrap::Column(settings.preferred_line_length)
7562            }
7563        }
7564    }
7565
7566    pub fn set_soft_wrap_mode(
7567        &mut self,
7568        mode: language_settings::SoftWrap,
7569        cx: &mut ViewContext<Self>,
7570    ) {
7571        self.soft_wrap_mode_override = Some(mode);
7572        cx.notify();
7573    }
7574
7575    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
7576        self.display_map
7577            .update(cx, |map, cx| map.set_wrap_width(width, cx))
7578    }
7579
7580    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
7581        if self.soft_wrap_mode_override.is_some() {
7582            self.soft_wrap_mode_override.take();
7583        } else {
7584            let soft_wrap = match self.soft_wrap_mode(cx) {
7585                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
7586                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
7587            };
7588            self.soft_wrap_mode_override = Some(soft_wrap);
7589        }
7590        cx.notify();
7591    }
7592
7593    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7594        self.show_gutter = show_gutter;
7595        cx.notify();
7596    }
7597
7598    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
7599        self.show_wrap_guides = Some(show_gutter);
7600        cx.notify();
7601    }
7602
7603    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
7604        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7605            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7606                cx.reveal_path(&file.abs_path(cx));
7607            }
7608        }
7609    }
7610
7611    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
7612        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7613            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7614                if let Some(path) = file.abs_path(cx).to_str() {
7615                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7616                }
7617            }
7618        }
7619    }
7620
7621    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
7622        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
7623            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
7624                if let Some(path) = file.path().to_str() {
7625                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
7626                }
7627            }
7628        }
7629    }
7630
7631    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
7632        self.highlighted_rows = rows;
7633    }
7634
7635    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
7636        self.highlighted_rows.clone()
7637    }
7638
7639    pub fn highlight_background<T: 'static>(
7640        &mut self,
7641        ranges: Vec<Range<Anchor>>,
7642        color_fetcher: fn(&Theme) -> Color,
7643        cx: &mut ViewContext<Self>,
7644    ) {
7645        self.background_highlights.insert(
7646            TypeId::of::<T>(),
7647            (
7648                color_fetcher,
7649                ranges.into_iter().map(DocumentRange::Text).collect(),
7650            ),
7651        );
7652        cx.notify();
7653    }
7654
7655    pub fn highlight_inlay_background<T: 'static>(
7656        &mut self,
7657        ranges: Vec<InlayRange>,
7658        color_fetcher: fn(&Theme) -> Color,
7659        cx: &mut ViewContext<Self>,
7660    ) {
7661        self.background_highlights.insert(
7662            TypeId::of::<T>(),
7663            (
7664                color_fetcher,
7665                ranges.into_iter().map(DocumentRange::Inlay).collect(),
7666            ),
7667        );
7668        cx.notify();
7669    }
7670
7671    pub fn clear_background_highlights<T: 'static>(
7672        &mut self,
7673        cx: &mut ViewContext<Self>,
7674    ) -> Option<BackgroundHighlight> {
7675        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
7676        if highlights.is_some() {
7677            cx.notify();
7678        }
7679        highlights
7680    }
7681
7682    #[cfg(feature = "test-support")]
7683    pub fn all_background_highlights(
7684        &mut self,
7685        cx: &mut ViewContext<Self>,
7686    ) -> Vec<(Range<DisplayPoint>, Color)> {
7687        let snapshot = self.snapshot(cx);
7688        let buffer = &snapshot.buffer_snapshot;
7689        let start = buffer.anchor_before(0);
7690        let end = buffer.anchor_after(buffer.len());
7691        let theme = theme::current(cx);
7692        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
7693    }
7694
7695    fn document_highlights_for_position<'a>(
7696        &'a self,
7697        position: Anchor,
7698        buffer: &'a MultiBufferSnapshot,
7699        display_snapshot: &'a DisplaySnapshot,
7700    ) -> impl 'a + Iterator<Item = &DocumentRange> {
7701        let read_highlights = self
7702            .background_highlights
7703            .get(&TypeId::of::<DocumentHighlightRead>())
7704            .map(|h| &h.1);
7705        let write_highlights = self
7706            .background_highlights
7707            .get(&TypeId::of::<DocumentHighlightWrite>())
7708            .map(|h| &h.1);
7709        let left_position = display_snapshot.anchor_to_inlay_offset(position.bias_left(buffer));
7710        let right_position = display_snapshot.anchor_to_inlay_offset(position.bias_right(buffer));
7711        read_highlights
7712            .into_iter()
7713            .chain(write_highlights)
7714            .flat_map(move |ranges| {
7715                let start_ix = match ranges.binary_search_by(|probe| {
7716                    let cmp = document_to_inlay_range(probe, display_snapshot)
7717                        .end
7718                        .cmp(&left_position);
7719                    if cmp.is_ge() {
7720                        Ordering::Greater
7721                    } else {
7722                        Ordering::Less
7723                    }
7724                }) {
7725                    Ok(i) | Err(i) => i,
7726                };
7727
7728                let right_position = right_position.clone();
7729                ranges[start_ix..].iter().take_while(move |range| {
7730                    document_to_inlay_range(range, display_snapshot)
7731                        .start
7732                        .cmp(&right_position)
7733                        .is_le()
7734                })
7735            })
7736    }
7737
7738    pub fn background_highlights_in_range(
7739        &self,
7740        search_range: Range<Anchor>,
7741        display_snapshot: &DisplaySnapshot,
7742        theme: &Theme,
7743    ) -> Vec<(Range<DisplayPoint>, Color)> {
7744        let search_range = display_snapshot.anchor_to_inlay_offset(search_range.start)
7745            ..display_snapshot.anchor_to_inlay_offset(search_range.end);
7746        let mut results = Vec::new();
7747        for (color_fetcher, ranges) in self.background_highlights.values() {
7748            let color = color_fetcher(theme);
7749            let start_ix = match ranges.binary_search_by(|probe| {
7750                let cmp = document_to_inlay_range(probe, display_snapshot)
7751                    .end
7752                    .cmp(&search_range.start);
7753                if cmp.is_gt() {
7754                    Ordering::Greater
7755                } else {
7756                    Ordering::Less
7757                }
7758            }) {
7759                Ok(i) | Err(i) => i,
7760            };
7761            for range in &ranges[start_ix..] {
7762                let range = document_to_inlay_range(range, display_snapshot);
7763                if range.start.cmp(&search_range.end).is_ge() {
7764                    break;
7765                }
7766
7767                let start = display_snapshot.inlay_offset_to_display_point(range.start, Bias::Left);
7768                let end = display_snapshot.inlay_offset_to_display_point(range.end, Bias::Right);
7769                results.push((start..end, color))
7770            }
7771        }
7772        results
7773    }
7774
7775    pub fn background_highlight_row_ranges<T: 'static>(
7776        &self,
7777        search_range: Range<Anchor>,
7778        display_snapshot: &DisplaySnapshot,
7779        count: usize,
7780    ) -> Vec<RangeInclusive<DisplayPoint>> {
7781        let search_range = display_snapshot.anchor_to_inlay_offset(search_range.start)
7782            ..display_snapshot.anchor_to_inlay_offset(search_range.end);
7783        let mut results = Vec::new();
7784        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
7785            return vec![];
7786        };
7787
7788        let start_ix = match ranges.binary_search_by(|probe| {
7789            let cmp = document_to_inlay_range(probe, display_snapshot)
7790                .end
7791                .cmp(&search_range.start);
7792            if cmp.is_gt() {
7793                Ordering::Greater
7794            } else {
7795                Ordering::Less
7796            }
7797        }) {
7798            Ok(i) | Err(i) => i,
7799        };
7800        let mut push_region = |start: Option<Point>, end: Option<Point>| {
7801            if let (Some(start_display), Some(end_display)) = (start, end) {
7802                results.push(
7803                    start_display.to_display_point(display_snapshot)
7804                        ..=end_display.to_display_point(display_snapshot),
7805                );
7806            }
7807        };
7808        let mut start_row: Option<Point> = None;
7809        let mut end_row: Option<Point> = None;
7810        if ranges.len() > count {
7811            return Vec::new();
7812        }
7813        for range in &ranges[start_ix..] {
7814            let range = document_to_inlay_range(range, display_snapshot);
7815            if range.start.cmp(&search_range.end).is_ge() {
7816                break;
7817            }
7818            let end = display_snapshot
7819                .inlay_offset_to_display_point(range.end, Bias::Right)
7820                .to_point(display_snapshot);
7821            if let Some(current_row) = &end_row {
7822                if end.row == current_row.row {
7823                    continue;
7824                }
7825            }
7826            let start = display_snapshot
7827                .inlay_offset_to_display_point(range.start, Bias::Left)
7828                .to_point(display_snapshot);
7829
7830            if start_row.is_none() {
7831                assert_eq!(end_row, None);
7832                start_row = Some(start);
7833                end_row = Some(end);
7834                continue;
7835            }
7836            if let Some(current_end) = end_row.as_mut() {
7837                if start.row > current_end.row + 1 {
7838                    push_region(start_row, end_row);
7839                    start_row = Some(start);
7840                    end_row = Some(end);
7841                } else {
7842                    // Merge two hunks.
7843                    *current_end = end;
7844                }
7845            } else {
7846                unreachable!();
7847            }
7848        }
7849        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
7850        push_region(start_row, end_row);
7851        results
7852    }
7853
7854    pub fn highlight_text<T: 'static>(
7855        &mut self,
7856        ranges: Vec<Range<Anchor>>,
7857        style: HighlightStyle,
7858        cx: &mut ViewContext<Self>,
7859    ) {
7860        self.display_map.update(cx, |map, _| {
7861            map.highlight_text(TypeId::of::<T>(), ranges, style)
7862        });
7863        cx.notify();
7864    }
7865
7866    pub fn highlight_inlays<T: 'static>(
7867        &mut self,
7868        ranges: Vec<InlayRange>,
7869        style: HighlightStyle,
7870        cx: &mut ViewContext<Self>,
7871    ) {
7872        self.display_map.update(cx, |map, _| {
7873            map.highlight_inlays(TypeId::of::<T>(), ranges, style)
7874        });
7875        cx.notify();
7876    }
7877
7878    pub fn text_highlights<'a, T: 'static>(
7879        &'a self,
7880        cx: &'a AppContext,
7881    ) -> Option<(HighlightStyle, &'a [DocumentRange])> {
7882        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
7883    }
7884
7885    pub fn clear_text_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
7886        let text_highlights = self
7887            .display_map
7888            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
7889        if text_highlights.is_some() {
7890            cx.notify();
7891        }
7892    }
7893
7894    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
7895        self.blink_manager.read(cx).visible() && self.focused
7896    }
7897
7898    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
7899        cx.notify();
7900    }
7901
7902    fn on_buffer_event(
7903        &mut self,
7904        multibuffer: ModelHandle<MultiBuffer>,
7905        event: &multi_buffer::Event,
7906        cx: &mut ViewContext<Self>,
7907    ) {
7908        match event {
7909            multi_buffer::Event::Edited {
7910                sigleton_buffer_edited,
7911            } => {
7912                self.refresh_active_diagnostics(cx);
7913                self.refresh_code_actions(cx);
7914                if self.has_active_copilot_suggestion(cx) {
7915                    self.update_visible_copilot_suggestion(cx);
7916                }
7917                cx.emit(Event::BufferEdited);
7918
7919                if *sigleton_buffer_edited {
7920                    if let Some(project) = &self.project {
7921                        let project = project.read(cx);
7922                        let languages_affected = multibuffer
7923                            .read(cx)
7924                            .all_buffers()
7925                            .into_iter()
7926                            .filter_map(|buffer| {
7927                                let buffer = buffer.read(cx);
7928                                let language = buffer.language()?;
7929                                if project.is_local()
7930                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
7931                                {
7932                                    None
7933                                } else {
7934                                    Some(language)
7935                                }
7936                            })
7937                            .cloned()
7938                            .collect::<HashSet<_>>();
7939                        if !languages_affected.is_empty() {
7940                            self.refresh_inlay_hints(
7941                                InlayHintRefreshReason::BufferEdited(languages_affected),
7942                                cx,
7943                            );
7944                        }
7945                    }
7946                }
7947            }
7948            multi_buffer::Event::ExcerptsAdded {
7949                buffer,
7950                predecessor,
7951                excerpts,
7952            } => {
7953                cx.emit(Event::ExcerptsAdded {
7954                    buffer: buffer.clone(),
7955                    predecessor: *predecessor,
7956                    excerpts: excerpts.clone(),
7957                });
7958                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
7959            }
7960            multi_buffer::Event::ExcerptsRemoved { ids } => {
7961                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
7962                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
7963            }
7964            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
7965            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
7966            multi_buffer::Event::Saved => cx.emit(Event::Saved),
7967            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
7968            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
7969            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
7970            multi_buffer::Event::Closed => cx.emit(Event::Closed),
7971            multi_buffer::Event::DiagnosticsUpdated => {
7972                self.refresh_active_diagnostics(cx);
7973            }
7974            _ => {}
7975        };
7976    }
7977
7978    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
7979        cx.notify();
7980    }
7981
7982    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
7983        self.refresh_copilot_suggestions(true, cx);
7984        self.refresh_inlay_hints(
7985            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
7986                self.selections.newest_anchor().head(),
7987                &self.buffer.read(cx).snapshot(cx),
7988                cx,
7989            )),
7990            cx,
7991        );
7992    }
7993
7994    pub fn set_searchable(&mut self, searchable: bool) {
7995        self.searchable = searchable;
7996    }
7997
7998    pub fn searchable(&self) -> bool {
7999        self.searchable
8000    }
8001
8002    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
8003        let active_item = workspace.active_item(cx);
8004        let editor_handle = if let Some(editor) = active_item
8005            .as_ref()
8006            .and_then(|item| item.act_as::<Self>(cx))
8007        {
8008            editor
8009        } else {
8010            cx.propagate_action();
8011            return;
8012        };
8013
8014        let editor = editor_handle.read(cx);
8015        let buffer = editor.buffer.read(cx);
8016        if buffer.is_singleton() {
8017            cx.propagate_action();
8018            return;
8019        }
8020
8021        let mut new_selections_by_buffer = HashMap::default();
8022        for selection in editor.selections.all::<usize>(cx) {
8023            for (buffer, mut range, _) in
8024                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8025            {
8026                if selection.reversed {
8027                    mem::swap(&mut range.start, &mut range.end);
8028                }
8029                new_selections_by_buffer
8030                    .entry(buffer)
8031                    .or_insert(Vec::new())
8032                    .push(range)
8033            }
8034        }
8035
8036        editor_handle.update(cx, |editor, cx| {
8037            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
8038        });
8039        let pane = workspace.active_pane().clone();
8040        pane.update(cx, |pane, _| pane.disable_history());
8041
8042        // We defer the pane interaction because we ourselves are a workspace item
8043        // and activating a new item causes the pane to call a method on us reentrantly,
8044        // which panics if we're on the stack.
8045        cx.defer(move |workspace, cx| {
8046            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8047                let editor = workspace.open_project_item::<Self>(buffer, cx);
8048                editor.update(cx, |editor, cx| {
8049                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8050                        s.select_ranges(ranges);
8051                    });
8052                });
8053            }
8054
8055            pane.update(cx, |pane, _| pane.enable_history());
8056        });
8057    }
8058
8059    fn jump(
8060        workspace: &mut Workspace,
8061        path: ProjectPath,
8062        position: Point,
8063        anchor: language::Anchor,
8064        cx: &mut ViewContext<Workspace>,
8065    ) {
8066        let editor = workspace.open_path(path, None, true, cx);
8067        cx.spawn(|_, mut cx| async move {
8068            let editor = editor
8069                .await?
8070                .downcast::<Editor>()
8071                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8072                .downgrade();
8073            editor.update(&mut cx, |editor, cx| {
8074                let buffer = editor
8075                    .buffer()
8076                    .read(cx)
8077                    .as_singleton()
8078                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8079                let buffer = buffer.read(cx);
8080                let cursor = if buffer.can_resolve(&anchor) {
8081                    language::ToPoint::to_point(&anchor, buffer)
8082                } else {
8083                    buffer.clip_point(position, Bias::Left)
8084                };
8085
8086                let nav_history = editor.nav_history.take();
8087                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8088                    s.select_ranges([cursor..cursor]);
8089                });
8090                editor.nav_history = nav_history;
8091
8092                anyhow::Ok(())
8093            })??;
8094
8095            anyhow::Ok(())
8096        })
8097        .detach_and_log_err(cx);
8098    }
8099
8100    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8101        let snapshot = self.buffer.read(cx).read(cx);
8102        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8103        Some(
8104            ranges
8105                .iter()
8106                .filter_map(|range| range.as_text_range())
8107                .map(move |range| {
8108                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8109                })
8110                .collect(),
8111        )
8112    }
8113
8114    fn selection_replacement_ranges(
8115        &self,
8116        range: Range<OffsetUtf16>,
8117        cx: &AppContext,
8118    ) -> Vec<Range<OffsetUtf16>> {
8119        let selections = self.selections.all::<OffsetUtf16>(cx);
8120        let newest_selection = selections
8121            .iter()
8122            .max_by_key(|selection| selection.id)
8123            .unwrap();
8124        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8125        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8126        let snapshot = self.buffer.read(cx).read(cx);
8127        selections
8128            .into_iter()
8129            .map(|mut selection| {
8130                selection.start.0 =
8131                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8132                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8133                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8134                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8135            })
8136            .collect()
8137    }
8138
8139    fn report_copilot_event(
8140        &self,
8141        suggestion_id: Option<String>,
8142        suggestion_accepted: bool,
8143        cx: &AppContext,
8144    ) {
8145        let Some(project) = &self.project else { return };
8146
8147        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8148        let file_extension = self
8149            .buffer
8150            .read(cx)
8151            .as_singleton()
8152            .and_then(|b| b.read(cx).file())
8153            .and_then(|file| Path::new(file.file_name(cx)).extension())
8154            .and_then(|e| e.to_str())
8155            .map(|a| a.to_string());
8156
8157        let telemetry = project.read(cx).client().telemetry().clone();
8158        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8159
8160        let event = ClickhouseEvent::Copilot {
8161            suggestion_id,
8162            suggestion_accepted,
8163            file_extension,
8164        };
8165        telemetry.report_clickhouse_event(event, telemetry_settings);
8166    }
8167
8168    fn report_editor_event(
8169        &self,
8170        operation: &'static str,
8171        file_extension: Option<String>,
8172        cx: &AppContext,
8173    ) {
8174        let Some(project) = &self.project else { return };
8175
8176        // If None, we are in a file without an extension
8177        let file = self
8178            .buffer
8179            .read(cx)
8180            .as_singleton()
8181            .and_then(|b| b.read(cx).file());
8182        let file_extension = file_extension.or(file
8183            .as_ref()
8184            .and_then(|file| Path::new(file.file_name(cx)).extension())
8185            .and_then(|e| e.to_str())
8186            .map(|a| a.to_string()));
8187
8188        let vim_mode = cx
8189            .global::<SettingsStore>()
8190            .raw_user_settings()
8191            .get("vim_mode")
8192            == Some(&serde_json::Value::Bool(true));
8193        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
8194        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8195        let copilot_enabled_for_language = self
8196            .buffer
8197            .read(cx)
8198            .settings_at(0, cx)
8199            .show_copilot_suggestions;
8200
8201        let telemetry = project.read(cx).client().telemetry().clone();
8202        let event = ClickhouseEvent::Editor {
8203            file_extension,
8204            vim_mode,
8205            operation,
8206            copilot_enabled,
8207            copilot_enabled_for_language,
8208        };
8209        telemetry.report_clickhouse_event(event, telemetry_settings)
8210    }
8211
8212    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8213    /// with each line being an array of {text, highlight} objects.
8214    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8215        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8216            return;
8217        };
8218
8219        #[derive(Serialize)]
8220        struct Chunk<'a> {
8221            text: String,
8222            highlight: Option<&'a str>,
8223        }
8224
8225        let snapshot = buffer.read(cx).snapshot();
8226        let range = self
8227            .selected_text_range(cx)
8228            .and_then(|selected_range| {
8229                if selected_range.is_empty() {
8230                    None
8231                } else {
8232                    Some(selected_range)
8233                }
8234            })
8235            .unwrap_or_else(|| 0..snapshot.len());
8236
8237        let chunks = snapshot.chunks(range, true);
8238        let mut lines = Vec::new();
8239        let mut line: VecDeque<Chunk> = VecDeque::new();
8240
8241        let theme = &theme::current(cx).editor.syntax;
8242
8243        for chunk in chunks {
8244            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
8245            let mut chunk_lines = chunk.text.split("\n").peekable();
8246            while let Some(text) = chunk_lines.next() {
8247                let mut merged_with_last_token = false;
8248                if let Some(last_token) = line.back_mut() {
8249                    if last_token.highlight == highlight {
8250                        last_token.text.push_str(text);
8251                        merged_with_last_token = true;
8252                    }
8253                }
8254
8255                if !merged_with_last_token {
8256                    line.push_back(Chunk {
8257                        text: text.into(),
8258                        highlight,
8259                    });
8260                }
8261
8262                if chunk_lines.peek().is_some() {
8263                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8264                        line.pop_front();
8265                    }
8266                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8267                        line.pop_back();
8268                    }
8269
8270                    lines.push(mem::take(&mut line));
8271                }
8272            }
8273        }
8274
8275        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8276            return;
8277        };
8278        cx.write_to_clipboard(ClipboardItem::new(lines));
8279    }
8280
8281    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8282        &self.inlay_hint_cache
8283    }
8284}
8285
8286fn document_to_inlay_range(
8287    range: &DocumentRange,
8288    snapshot: &DisplaySnapshot,
8289) -> Range<InlayOffset> {
8290    match range {
8291        DocumentRange::Text(text_range) => {
8292            snapshot.anchor_to_inlay_offset(text_range.start)
8293                ..snapshot.anchor_to_inlay_offset(text_range.end)
8294        }
8295        DocumentRange::Inlay(inlay_range) => inlay_range.highlight_start..inlay_range.highlight_end,
8296    }
8297}
8298
8299fn inlay_hint_settings(
8300    location: Anchor,
8301    snapshot: &MultiBufferSnapshot,
8302    cx: &mut ViewContext<'_, '_, Editor>,
8303) -> InlayHintSettings {
8304    let file = snapshot.file_at(location);
8305    let language = snapshot.language_at(location);
8306    let settings = all_language_settings(file, cx);
8307    settings
8308        .language(language.map(|l| l.name()).as_deref())
8309        .inlay_hints
8310}
8311
8312fn consume_contiguous_rows(
8313    contiguous_row_selections: &mut Vec<Selection<Point>>,
8314    selection: &Selection<Point>,
8315    display_map: &DisplaySnapshot,
8316    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
8317) -> (u32, u32) {
8318    contiguous_row_selections.push(selection.clone());
8319    let start_row = selection.start.row;
8320    let mut end_row = ending_row(selection, display_map);
8321
8322    while let Some(next_selection) = selections.peek() {
8323        if next_selection.start.row <= end_row {
8324            end_row = ending_row(next_selection, display_map);
8325            contiguous_row_selections.push(selections.next().unwrap().clone());
8326        } else {
8327            break;
8328        }
8329    }
8330    (start_row, end_row)
8331}
8332
8333fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
8334    if next_selection.end.column > 0 || next_selection.is_empty() {
8335        display_map.next_line_boundary(next_selection.end).0.row + 1
8336    } else {
8337        next_selection.end.row
8338    }
8339}
8340
8341impl EditorSnapshot {
8342    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
8343        self.display_snapshot.buffer_snapshot.language_at(position)
8344    }
8345
8346    pub fn is_focused(&self) -> bool {
8347        self.is_focused
8348    }
8349
8350    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
8351        self.placeholder_text.as_ref()
8352    }
8353
8354    pub fn scroll_position(&self) -> Vector2F {
8355        self.scroll_anchor.scroll_position(&self.display_snapshot)
8356    }
8357}
8358
8359impl Deref for EditorSnapshot {
8360    type Target = DisplaySnapshot;
8361
8362    fn deref(&self) -> &Self::Target {
8363        &self.display_snapshot
8364    }
8365}
8366
8367#[derive(Clone, Debug, PartialEq, Eq)]
8368pub enum Event {
8369    InputIgnored {
8370        text: Arc<str>,
8371    },
8372    ExcerptsAdded {
8373        buffer: ModelHandle<Buffer>,
8374        predecessor: ExcerptId,
8375        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
8376    },
8377    ExcerptsRemoved {
8378        ids: Vec<ExcerptId>,
8379    },
8380    BufferEdited,
8381    Edited,
8382    Reparsed,
8383    Focused,
8384    Blurred,
8385    DirtyChanged,
8386    Saved,
8387    TitleChanged,
8388    DiffBaseChanged,
8389    SelectionsChanged {
8390        local: bool,
8391    },
8392    ScrollPositionChanged {
8393        local: bool,
8394        autoscroll: bool,
8395    },
8396    Closed,
8397}
8398
8399pub struct EditorFocused(pub ViewHandle<Editor>);
8400pub struct EditorBlurred(pub ViewHandle<Editor>);
8401pub struct EditorReleased(pub WeakViewHandle<Editor>);
8402
8403impl Entity for Editor {
8404    type Event = Event;
8405
8406    fn release(&mut self, cx: &mut AppContext) {
8407        cx.emit_global(EditorReleased(self.handle.clone()));
8408    }
8409}
8410
8411impl View for Editor {
8412    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
8413        let style = self.style(cx);
8414        let font_changed = self.display_map.update(cx, |map, cx| {
8415            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
8416            map.set_font(style.text.font_id, style.text.font_size, cx)
8417        });
8418
8419        if font_changed {
8420            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
8421                hide_hover(editor, cx);
8422                hide_link_definition(editor, cx);
8423            });
8424        }
8425
8426        Stack::new()
8427            .with_child(EditorElement::new(style.clone()))
8428            .with_child(ChildView::new(&self.mouse_context_menu, cx))
8429            .into_any()
8430    }
8431
8432    fn ui_name() -> &'static str {
8433        "Editor"
8434    }
8435
8436    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8437        if cx.is_self_focused() {
8438            let focused_event = EditorFocused(cx.handle());
8439            cx.emit(Event::Focused);
8440            cx.emit_global(focused_event);
8441        }
8442        if let Some(rename) = self.pending_rename.as_ref() {
8443            cx.focus(&rename.editor);
8444        } else {
8445            if !self.focused {
8446                self.blink_manager.update(cx, BlinkManager::enable);
8447            }
8448            self.focused = true;
8449            self.buffer.update(cx, |buffer, cx| {
8450                buffer.finalize_last_transaction(cx);
8451                if self.leader_replica_id.is_none() {
8452                    buffer.set_active_selections(
8453                        &self.selections.disjoint_anchors(),
8454                        self.selections.line_mode,
8455                        self.cursor_shape,
8456                        cx,
8457                    );
8458                }
8459            });
8460        }
8461    }
8462
8463    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
8464        let blurred_event = EditorBlurred(cx.handle());
8465        cx.emit_global(blurred_event);
8466        self.focused = false;
8467        self.blink_manager.update(cx, BlinkManager::disable);
8468        self.buffer
8469            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8470        self.hide_context_menu(cx);
8471        hide_hover(self, cx);
8472        cx.emit(Event::Blurred);
8473        cx.notify();
8474    }
8475
8476    fn modifiers_changed(
8477        &mut self,
8478        event: &gpui::platform::ModifiersChangedEvent,
8479        cx: &mut ViewContext<Self>,
8480    ) -> bool {
8481        let pending_selection = self.has_pending_selection();
8482
8483        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
8484            if event.cmd && !pending_selection {
8485                let point = point.clone();
8486                let snapshot = self.snapshot(cx);
8487                let kind = point.definition_kind(event.shift);
8488
8489                show_link_definition(kind, self, point, snapshot, cx);
8490                return false;
8491            }
8492        }
8493
8494        {
8495            if self.link_go_to_definition_state.symbol_range.is_some()
8496                || !self.link_go_to_definition_state.definitions.is_empty()
8497            {
8498                self.link_go_to_definition_state.symbol_range.take();
8499                self.link_go_to_definition_state.definitions.clear();
8500                cx.notify();
8501            }
8502
8503            self.link_go_to_definition_state.task = None;
8504
8505            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
8506        }
8507
8508        false
8509    }
8510
8511    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
8512        Self::reset_to_default_keymap_context(keymap);
8513        let mode = match self.mode {
8514            EditorMode::SingleLine => "single_line",
8515            EditorMode::AutoHeight { .. } => "auto_height",
8516            EditorMode::Full => "full",
8517        };
8518        keymap.add_key("mode", mode);
8519        if self.pending_rename.is_some() {
8520            keymap.add_identifier("renaming");
8521        }
8522        match self.context_menu.as_ref() {
8523            Some(ContextMenu::Completions(_)) => {
8524                keymap.add_identifier("menu");
8525                keymap.add_identifier("showing_completions")
8526            }
8527            Some(ContextMenu::CodeActions(_)) => {
8528                keymap.add_identifier("menu");
8529                keymap.add_identifier("showing_code_actions")
8530            }
8531            None => {}
8532        }
8533        for layer in self.keymap_context_layers.values() {
8534            keymap.extend(layer);
8535        }
8536
8537        if let Some(extension) = self
8538            .buffer
8539            .read(cx)
8540            .as_singleton()
8541            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
8542        {
8543            keymap.add_key("extension", extension.to_string());
8544        }
8545    }
8546
8547    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
8548        Some(
8549            self.buffer
8550                .read(cx)
8551                .read(cx)
8552                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
8553                .collect(),
8554        )
8555    }
8556
8557    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8558        // Prevent the IME menu from appearing when holding down an alphabetic key
8559        // while input is disabled.
8560        if !self.input_enabled {
8561            return None;
8562        }
8563
8564        let range = self.selections.newest::<OffsetUtf16>(cx).range();
8565        Some(range.start.0..range.end.0)
8566    }
8567
8568    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
8569        let snapshot = self.buffer.read(cx).read(cx);
8570        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
8571        let range = range.as_text_range()?;
8572        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
8573    }
8574
8575    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
8576        self.clear_text_highlights::<InputComposition>(cx);
8577        self.ime_transaction.take();
8578    }
8579
8580    fn replace_text_in_range(
8581        &mut self,
8582        range_utf16: Option<Range<usize>>,
8583        text: &str,
8584        cx: &mut ViewContext<Self>,
8585    ) {
8586        self.transact(cx, |this, cx| {
8587            if this.input_enabled {
8588                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
8589                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8590                    Some(this.selection_replacement_ranges(range_utf16, cx))
8591                } else {
8592                    this.marked_text_ranges(cx)
8593                };
8594
8595                if let Some(new_selected_ranges) = new_selected_ranges {
8596                    this.change_selections(None, cx, |selections| {
8597                        selections.select_ranges(new_selected_ranges)
8598                    });
8599                }
8600            }
8601
8602            this.handle_input(text, cx);
8603        });
8604
8605        if !self.input_enabled {
8606            return;
8607        }
8608
8609        if let Some(transaction) = self.ime_transaction {
8610            self.buffer.update(cx, |buffer, cx| {
8611                buffer.group_until_transaction(transaction, cx);
8612            });
8613        }
8614
8615        self.unmark_text(cx);
8616    }
8617
8618    fn replace_and_mark_text_in_range(
8619        &mut self,
8620        range_utf16: Option<Range<usize>>,
8621        text: &str,
8622        new_selected_range_utf16: Option<Range<usize>>,
8623        cx: &mut ViewContext<Self>,
8624    ) {
8625        if !self.input_enabled {
8626            return;
8627        }
8628
8629        let transaction = self.transact(cx, |this, cx| {
8630            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
8631                let snapshot = this.buffer.read(cx).read(cx);
8632                if let Some(relative_range_utf16) = range_utf16.as_ref() {
8633                    for marked_range in &mut marked_ranges {
8634                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
8635                        marked_range.start.0 += relative_range_utf16.start;
8636                        marked_range.start =
8637                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
8638                        marked_range.end =
8639                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
8640                    }
8641                }
8642                Some(marked_ranges)
8643            } else if let Some(range_utf16) = range_utf16 {
8644                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
8645                Some(this.selection_replacement_ranges(range_utf16, cx))
8646            } else {
8647                None
8648            };
8649
8650            if let Some(ranges) = ranges_to_replace {
8651                this.change_selections(None, cx, |s| s.select_ranges(ranges));
8652            }
8653
8654            let marked_ranges = {
8655                let snapshot = this.buffer.read(cx).read(cx);
8656                this.selections
8657                    .disjoint_anchors()
8658                    .iter()
8659                    .map(|selection| {
8660                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
8661                    })
8662                    .collect::<Vec<_>>()
8663            };
8664
8665            if text.is_empty() {
8666                this.unmark_text(cx);
8667            } else {
8668                this.highlight_text::<InputComposition>(
8669                    marked_ranges.clone(),
8670                    this.style(cx).composition_mark,
8671                    cx,
8672                );
8673            }
8674
8675            this.handle_input(text, cx);
8676
8677            if let Some(new_selected_range) = new_selected_range_utf16 {
8678                let snapshot = this.buffer.read(cx).read(cx);
8679                let new_selected_ranges = marked_ranges
8680                    .into_iter()
8681                    .map(|marked_range| {
8682                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
8683                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
8684                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
8685                        snapshot.clip_offset_utf16(new_start, Bias::Left)
8686                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
8687                    })
8688                    .collect::<Vec<_>>();
8689
8690                drop(snapshot);
8691                this.change_selections(None, cx, |selections| {
8692                    selections.select_ranges(new_selected_ranges)
8693                });
8694            }
8695        });
8696
8697        self.ime_transaction = self.ime_transaction.or(transaction);
8698        if let Some(transaction) = self.ime_transaction {
8699            self.buffer.update(cx, |buffer, cx| {
8700                buffer.group_until_transaction(transaction, cx);
8701            });
8702        }
8703
8704        if self.text_highlights::<InputComposition>(cx).is_none() {
8705            self.ime_transaction.take();
8706        }
8707    }
8708}
8709
8710fn build_style(
8711    settings: &ThemeSettings,
8712    get_field_editor_theme: Option<&GetFieldEditorTheme>,
8713    override_text_style: Option<&OverrideTextStyle>,
8714    cx: &AppContext,
8715) -> EditorStyle {
8716    let font_cache = cx.font_cache();
8717    let line_height_scalar = settings.line_height();
8718    let theme_id = settings.theme.meta.id;
8719    let mut theme = settings.theme.editor.clone();
8720    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
8721        let field_editor_theme = get_field_editor_theme(&settings.theme);
8722        theme.text_color = field_editor_theme.text.color;
8723        theme.selection = field_editor_theme.selection;
8724        theme.background = field_editor_theme
8725            .container
8726            .background_color
8727            .unwrap_or_default();
8728        EditorStyle {
8729            text: field_editor_theme.text,
8730            placeholder_text: field_editor_theme.placeholder_text,
8731            line_height_scalar,
8732            theme,
8733            theme_id,
8734        }
8735    } else {
8736        let font_family_id = settings.buffer_font_family;
8737        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
8738        let font_properties = Default::default();
8739        let font_id = font_cache
8740            .select_font(font_family_id, &font_properties)
8741            .unwrap();
8742        let font_size = settings.buffer_font_size(cx);
8743        EditorStyle {
8744            text: TextStyle {
8745                color: settings.theme.editor.text_color,
8746                font_family_name,
8747                font_family_id,
8748                font_id,
8749                font_size,
8750                font_properties,
8751                underline: Default::default(),
8752                soft_wrap: false,
8753            },
8754            placeholder_text: None,
8755            line_height_scalar,
8756            theme,
8757            theme_id,
8758        }
8759    };
8760
8761    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
8762        if let Some(highlighted) = style
8763            .text
8764            .clone()
8765            .highlight(highlight_style, font_cache)
8766            .log_err()
8767        {
8768            style.text = highlighted;
8769        }
8770    }
8771
8772    style
8773}
8774
8775trait SelectionExt {
8776    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
8777    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
8778    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
8779    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
8780        -> Range<u32>;
8781}
8782
8783impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
8784    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
8785        let start = self.start.to_point(buffer);
8786        let end = self.end.to_point(buffer);
8787        if self.reversed {
8788            end..start
8789        } else {
8790            start..end
8791        }
8792    }
8793
8794    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
8795        let start = self.start.to_offset(buffer);
8796        let end = self.end.to_offset(buffer);
8797        if self.reversed {
8798            end..start
8799        } else {
8800            start..end
8801        }
8802    }
8803
8804    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
8805        let start = self
8806            .start
8807            .to_point(&map.buffer_snapshot)
8808            .to_display_point(map);
8809        let end = self
8810            .end
8811            .to_point(&map.buffer_snapshot)
8812            .to_display_point(map);
8813        if self.reversed {
8814            end..start
8815        } else {
8816            start..end
8817        }
8818    }
8819
8820    fn spanned_rows(
8821        &self,
8822        include_end_if_at_line_start: bool,
8823        map: &DisplaySnapshot,
8824    ) -> Range<u32> {
8825        let start = self.start.to_point(&map.buffer_snapshot);
8826        let mut end = self.end.to_point(&map.buffer_snapshot);
8827        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
8828            end.row -= 1;
8829        }
8830
8831        let buffer_start = map.prev_line_boundary(start).0;
8832        let buffer_end = map.next_line_boundary(end).0;
8833        buffer_start.row..buffer_end.row + 1
8834    }
8835}
8836
8837impl<T: InvalidationRegion> InvalidationStack<T> {
8838    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
8839    where
8840        S: Clone + ToOffset,
8841    {
8842        while let Some(region) = self.last() {
8843            let all_selections_inside_invalidation_ranges =
8844                if selections.len() == region.ranges().len() {
8845                    selections
8846                        .iter()
8847                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
8848                        .all(|(selection, invalidation_range)| {
8849                            let head = selection.head().to_offset(buffer);
8850                            invalidation_range.start <= head && invalidation_range.end >= head
8851                        })
8852                } else {
8853                    false
8854                };
8855
8856            if all_selections_inside_invalidation_ranges {
8857                break;
8858            } else {
8859                self.pop();
8860            }
8861        }
8862    }
8863}
8864
8865impl<T> Default for InvalidationStack<T> {
8866    fn default() -> Self {
8867        Self(Default::default())
8868    }
8869}
8870
8871impl<T> Deref for InvalidationStack<T> {
8872    type Target = Vec<T>;
8873
8874    fn deref(&self) -> &Self::Target {
8875        &self.0
8876    }
8877}
8878
8879impl<T> DerefMut for InvalidationStack<T> {
8880    fn deref_mut(&mut self) -> &mut Self::Target {
8881        &mut self.0
8882    }
8883}
8884
8885impl InvalidationRegion for SnippetState {
8886    fn ranges(&self) -> &[Range<Anchor>] {
8887        &self.ranges[self.active_index]
8888    }
8889}
8890
8891impl Deref for EditorStyle {
8892    type Target = theme::Editor;
8893
8894    fn deref(&self) -> &Self::Target {
8895        &self.theme
8896    }
8897}
8898
8899pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
8900    let mut highlighted_lines = Vec::new();
8901
8902    for (index, line) in diagnostic.message.lines().enumerate() {
8903        let line = match &diagnostic.source {
8904            Some(source) if index == 0 => {
8905                let source_highlight = Vec::from_iter(0..source.len());
8906                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
8907            }
8908
8909            _ => highlight_diagnostic_message(Vec::new(), line),
8910        };
8911        highlighted_lines.push(line);
8912    }
8913    let message = diagnostic.message;
8914    Arc::new(move |cx: &mut BlockContext| {
8915        let message = message.clone();
8916        let settings = settings::get::<ThemeSettings>(cx);
8917        let tooltip_style = settings.theme.tooltip.clone();
8918        let theme = &settings.theme.editor;
8919        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
8920        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
8921        let anchor_x = cx.anchor_x;
8922        enum BlockContextToolip {}
8923        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
8924            Flex::column()
8925                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
8926                    Label::new(
8927                        line.clone(),
8928                        style.message.clone().with_font_size(font_size),
8929                    )
8930                    .with_highlights(highlights.clone())
8931                    .contained()
8932                    .with_margin_left(anchor_x)
8933                }))
8934                .aligned()
8935                .left()
8936                .into_any()
8937        })
8938        .with_cursor_style(CursorStyle::PointingHand)
8939        .on_click(MouseButton::Left, move |_, _, cx| {
8940            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
8941        })
8942        // We really need to rethink this ID system...
8943        .with_tooltip::<BlockContextToolip>(
8944            cx.block_id,
8945            "Copy diagnostic message",
8946            None,
8947            tooltip_style,
8948            cx,
8949        )
8950        .into_any()
8951    })
8952}
8953
8954pub fn highlight_diagnostic_message(
8955    initial_highlights: Vec<usize>,
8956    message: &str,
8957) -> (String, Vec<usize>) {
8958    let mut message_without_backticks = String::new();
8959    let mut prev_offset = 0;
8960    let mut inside_block = false;
8961    let mut highlights = initial_highlights;
8962    for (match_ix, (offset, _)) in message
8963        .match_indices('`')
8964        .chain([(message.len(), "")])
8965        .enumerate()
8966    {
8967        message_without_backticks.push_str(&message[prev_offset..offset]);
8968        if inside_block {
8969            highlights.extend(prev_offset - match_ix..offset - match_ix);
8970        }
8971
8972        inside_block = !inside_block;
8973        prev_offset = offset + 1;
8974    }
8975
8976    (message_without_backticks, highlights)
8977}
8978
8979pub fn diagnostic_style(
8980    severity: DiagnosticSeverity,
8981    valid: bool,
8982    theme: &theme::Editor,
8983) -> DiagnosticStyle {
8984    match (severity, valid) {
8985        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
8986        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
8987        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
8988        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
8989        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
8990        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
8991        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
8992        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
8993        _ => theme.invalid_hint_diagnostic.clone(),
8994    }
8995}
8996
8997pub fn combine_syntax_and_fuzzy_match_highlights(
8998    text: &str,
8999    default_style: HighlightStyle,
9000    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
9001    match_indices: &[usize],
9002) -> Vec<(Range<usize>, HighlightStyle)> {
9003    let mut result = Vec::new();
9004    let mut match_indices = match_indices.iter().copied().peekable();
9005
9006    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
9007    {
9008        syntax_highlight.weight = None;
9009
9010        // Add highlights for any fuzzy match characters before the next
9011        // syntax highlight range.
9012        while let Some(&match_index) = match_indices.peek() {
9013            if match_index >= range.start {
9014                break;
9015            }
9016            match_indices.next();
9017            let end_index = char_ix_after(match_index, text);
9018            let mut match_style = default_style;
9019            match_style.weight = Some(fonts::Weight::BOLD);
9020            result.push((match_index..end_index, match_style));
9021        }
9022
9023        if range.start == usize::MAX {
9024            break;
9025        }
9026
9027        // Add highlights for any fuzzy match characters within the
9028        // syntax highlight range.
9029        let mut offset = range.start;
9030        while let Some(&match_index) = match_indices.peek() {
9031            if match_index >= range.end {
9032                break;
9033            }
9034
9035            match_indices.next();
9036            if match_index > offset {
9037                result.push((offset..match_index, syntax_highlight));
9038            }
9039
9040            let mut end_index = char_ix_after(match_index, text);
9041            while let Some(&next_match_index) = match_indices.peek() {
9042                if next_match_index == end_index && next_match_index < range.end {
9043                    end_index = char_ix_after(next_match_index, text);
9044                    match_indices.next();
9045                } else {
9046                    break;
9047                }
9048            }
9049
9050            let mut match_style = syntax_highlight;
9051            match_style.weight = Some(fonts::Weight::BOLD);
9052            result.push((match_index..end_index, match_style));
9053            offset = end_index;
9054        }
9055
9056        if offset < range.end {
9057            result.push((offset..range.end, syntax_highlight));
9058        }
9059    }
9060
9061    fn char_ix_after(ix: usize, text: &str) -> usize {
9062        ix + text[ix..].chars().next().unwrap().len_utf8()
9063    }
9064
9065    result
9066}
9067
9068pub fn styled_runs_for_code_label<'a>(
9069    label: &'a CodeLabel,
9070    syntax_theme: &'a theme::SyntaxTheme,
9071) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9072    let fade_out = HighlightStyle {
9073        fade_out: Some(0.35),
9074        ..Default::default()
9075    };
9076
9077    let mut prev_end = label.filter_range.end;
9078    label
9079        .runs
9080        .iter()
9081        .enumerate()
9082        .flat_map(move |(ix, (range, highlight_id))| {
9083            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9084                style
9085            } else {
9086                return Default::default();
9087            };
9088            let mut muted_style = style;
9089            muted_style.highlight(fade_out);
9090
9091            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9092            if range.start >= label.filter_range.end {
9093                if range.start > prev_end {
9094                    runs.push((prev_end..range.start, fade_out));
9095                }
9096                runs.push((range.clone(), muted_style));
9097            } else if range.end <= label.filter_range.end {
9098                runs.push((range.clone(), style));
9099            } else {
9100                runs.push((range.start..label.filter_range.end, style));
9101                runs.push((label.filter_range.end..range.end, muted_style));
9102            }
9103            prev_end = cmp::max(prev_end, range.end);
9104
9105            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9106                runs.push((prev_end..label.text.len(), fade_out));
9107            }
9108
9109            runs
9110        })
9111}
9112
9113pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9114    let mut index = 0;
9115    let mut codepoints = text.char_indices().peekable();
9116
9117    std::iter::from_fn(move || {
9118        let start_index = index;
9119        while let Some((new_index, codepoint)) = codepoints.next() {
9120            index = new_index + codepoint.len_utf8();
9121            let current_upper = codepoint.is_uppercase();
9122            let next_upper = codepoints
9123                .peek()
9124                .map(|(_, c)| c.is_uppercase())
9125                .unwrap_or(false);
9126
9127            if !current_upper && next_upper {
9128                return Some(&text[start_index..index]);
9129            }
9130        }
9131
9132        index = text.len();
9133        if start_index < text.len() {
9134            return Some(&text[start_index..]);
9135        }
9136        None
9137    })
9138    .flat_map(|word| word.split_inclusive('_'))
9139}
9140
9141trait RangeToAnchorExt {
9142    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9143}
9144
9145impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9146    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9147        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9148    }
9149}