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