editor.rs

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