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