editor.rs

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