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, enabled) in language.brackets() {
1759                    if enabled && 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().any(|(pair, enabled)| {
1928                                let pair_start = pair.start.trim_end();
1929                                let pair_end = pair.end.trim_start();
1930
1931                                enabled
1932                                    && pair.newline
1933                                    && buffer
1934                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
1935                                    && buffer.contains_str_at(
1936                                        (start - leading_whitespace_len)
1937                                            .saturating_sub(pair_start.len()),
1938                                        pair_start,
1939                                    )
1940                            });
1941                        }
1942
1943                        let mut new_text = String::with_capacity(1 + indent.len as usize);
1944                        new_text.push('\n');
1945                        new_text.extend(indent.chars());
1946                        if insert_extra_newline {
1947                            new_text = new_text.repeat(2);
1948                        }
1949
1950                        let anchor = buffer.anchor_after(end);
1951                        let new_selection = selection.map(|_| anchor);
1952                        (
1953                            (start..end, new_text),
1954                            (insert_extra_newline, new_selection),
1955                        )
1956                    })
1957                    .unzip()
1958            };
1959
1960            this.edit_with_autoindent(edits, cx);
1961            let buffer = this.buffer.read(cx).snapshot(cx);
1962            let new_selections = selection_fixup_info
1963                .into_iter()
1964                .map(|(extra_newline_inserted, new_selection)| {
1965                    let mut cursor = new_selection.end.to_point(&buffer);
1966                    if extra_newline_inserted {
1967                        cursor.row -= 1;
1968                        cursor.column = buffer.line_len(cursor.row);
1969                    }
1970                    new_selection.map(|_| cursor)
1971                })
1972                .collect();
1973
1974            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
1975        });
1976    }
1977
1978    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
1979        let buffer = self.buffer.read(cx);
1980        let snapshot = buffer.snapshot(cx);
1981
1982        let mut edits = Vec::new();
1983        let mut rows = Vec::new();
1984        let mut rows_inserted = 0;
1985
1986        for selection in self.selections.all_adjusted(cx) {
1987            let cursor = selection.head();
1988            let row = cursor.row;
1989
1990            let end_of_line = snapshot
1991                .clip_point(Point::new(row, snapshot.line_len(row)), Bias::Left)
1992                .to_point(&snapshot);
1993
1994            let newline = "\n".to_string();
1995            edits.push((end_of_line..end_of_line, newline));
1996
1997            rows_inserted += 1;
1998            rows.push(row + rows_inserted);
1999        }
2000
2001        self.transact(cx, |editor, cx| {
2002            editor.edit_with_autoindent(edits, cx);
2003
2004            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2005                let mut index = 0;
2006                s.move_cursors_with(|map, _, _| {
2007                    let row = rows[index];
2008                    index += 1;
2009
2010                    let point = Point::new(row, 0);
2011                    let boundary = map.next_line_boundary(point).1;
2012                    let clipped = map.clip_point(boundary, Bias::Left);
2013
2014                    (clipped, SelectionGoal::None)
2015                });
2016            });
2017        });
2018    }
2019
2020    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2021        let text: Arc<str> = text.into();
2022        self.transact(cx, |this, cx| {
2023            let old_selections = this.selections.all_adjusted(cx);
2024            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2025                let anchors = {
2026                    let snapshot = buffer.read(cx);
2027                    old_selections
2028                        .iter()
2029                        .map(|s| {
2030                            let anchor = snapshot.anchor_after(s.end);
2031                            s.map(|_| anchor)
2032                        })
2033                        .collect::<Vec<_>>()
2034                };
2035                buffer.edit(
2036                    old_selections
2037                        .iter()
2038                        .map(|s| (s.start..s.end, text.clone())),
2039                    Some(AutoindentMode::Block {
2040                        original_indent_columns: Vec::new(),
2041                    }),
2042                    cx,
2043                );
2044                anchors
2045            });
2046
2047            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2048                s.select_anchors(selection_anchors);
2049            })
2050        });
2051    }
2052
2053    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2054        if !cx.global::<Settings>().show_completions_on_input {
2055            return;
2056        }
2057
2058        let selection = self.selections.newest_anchor();
2059        if self
2060            .buffer
2061            .read(cx)
2062            .is_completion_trigger(selection.head(), text, cx)
2063        {
2064            self.show_completions(&ShowCompletions, cx);
2065        } else {
2066            self.hide_context_menu(cx);
2067        }
2068    }
2069
2070    /// If any empty selections is touching the start of its innermost containing autoclose
2071    /// region, expand it to select the brackets.
2072    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2073        let selections = self.selections.all::<usize>(cx);
2074        let buffer = self.buffer.read(cx).read(cx);
2075        let mut new_selections = Vec::new();
2076        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2077            if let (Some(region), true) = (region, selection.is_empty()) {
2078                let mut range = region.range.to_offset(&buffer);
2079                if selection.start == range.start {
2080                    if range.start >= region.pair.start.len() {
2081                        range.start -= region.pair.start.len();
2082                        if buffer.contains_str_at(range.start, &region.pair.start) {
2083                            if buffer.contains_str_at(range.end, &region.pair.end) {
2084                                range.end += region.pair.end.len();
2085                                selection.start = range.start;
2086                                selection.end = range.end;
2087                            }
2088                        }
2089                    }
2090                }
2091            }
2092            new_selections.push(selection);
2093        }
2094
2095        drop(buffer);
2096        self.change_selections(None, cx, |selections| selections.select(new_selections));
2097    }
2098
2099    /// Iterate the given selections, and for each one, find the smallest surrounding
2100    /// autoclose region. This uses the ordering of the selections and the autoclose
2101    /// regions to avoid repeated comparisons.
2102    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2103        &'a self,
2104        selections: impl IntoIterator<Item = Selection<D>>,
2105        buffer: &'a MultiBufferSnapshot,
2106    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2107        let mut i = 0;
2108        let mut regions = self.autoclose_regions.as_slice();
2109        selections.into_iter().map(move |selection| {
2110            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2111
2112            let mut enclosing = None;
2113            while let Some(pair_state) = regions.get(i) {
2114                if pair_state.range.end.to_offset(buffer) < range.start {
2115                    regions = &regions[i + 1..];
2116                    i = 0;
2117                } else if pair_state.range.start.to_offset(buffer) > range.end {
2118                    break;
2119                } else if pair_state.selection_id == selection.id {
2120                    enclosing = Some(pair_state);
2121                    i += 1;
2122                }
2123            }
2124
2125            (selection.clone(), enclosing)
2126        })
2127    }
2128
2129    /// Remove any autoclose regions that no longer contain their selection.
2130    fn invalidate_autoclose_regions(
2131        &mut self,
2132        mut selections: &[Selection<Anchor>],
2133        buffer: &MultiBufferSnapshot,
2134    ) {
2135        self.autoclose_regions.retain(|state| {
2136            let mut i = 0;
2137            while let Some(selection) = selections.get(i) {
2138                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2139                    selections = &selections[1..];
2140                    continue;
2141                }
2142                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2143                    break;
2144                }
2145                if selection.id == state.selection_id {
2146                    return true;
2147                } else {
2148                    i += 1;
2149                }
2150            }
2151            false
2152        });
2153    }
2154
2155    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2156        let offset = position.to_offset(buffer);
2157        let (word_range, kind) = buffer.surrounding_word(offset);
2158        if offset > word_range.start && kind == Some(CharKind::Word) {
2159            Some(
2160                buffer
2161                    .text_for_range(word_range.start..offset)
2162                    .collect::<String>(),
2163            )
2164        } else {
2165            None
2166        }
2167    }
2168
2169    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2170        if self.pending_rename.is_some() {
2171            return;
2172        }
2173
2174        let project = if let Some(project) = self.project.clone() {
2175            project
2176        } else {
2177            return;
2178        };
2179
2180        let position = self.selections.newest_anchor().head();
2181        let (buffer, buffer_position) = if let Some(output) = self
2182            .buffer
2183            .read(cx)
2184            .text_anchor_for_position(position.clone(), cx)
2185        {
2186            output
2187        } else {
2188            return;
2189        };
2190
2191        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2192        let completions = project.update(cx, |project, cx| {
2193            project.completions(&buffer, buffer_position, cx)
2194        });
2195
2196        let id = post_inc(&mut self.next_completion_id);
2197        let task = cx.spawn_weak(|this, mut cx| {
2198            async move {
2199                let completions = completions.await?;
2200                if completions.is_empty() {
2201                    return Ok(());
2202                }
2203
2204                let mut menu = CompletionsMenu {
2205                    id,
2206                    initial_position: position,
2207                    match_candidates: completions
2208                        .iter()
2209                        .enumerate()
2210                        .map(|(id, completion)| {
2211                            StringMatchCandidate::new(
2212                                id,
2213                                completion.label.text[completion.label.filter_range.clone()].into(),
2214                            )
2215                        })
2216                        .collect(),
2217                    buffer,
2218                    completions: completions.into(),
2219                    matches: Vec::new().into(),
2220                    selected_item: 0,
2221                    list: Default::default(),
2222                };
2223
2224                menu.filter(query.as_deref(), cx.background()).await;
2225
2226                if let Some(this) = this.upgrade(&cx) {
2227                    this.update(&mut cx, |this, cx| {
2228                        match this.context_menu.as_ref() {
2229                            None => {}
2230                            Some(ContextMenu::Completions(prev_menu)) => {
2231                                if prev_menu.id > menu.id {
2232                                    return;
2233                                }
2234                            }
2235                            _ => return,
2236                        }
2237
2238                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
2239                        if this.focused {
2240                            this.show_context_menu(ContextMenu::Completions(menu), cx);
2241                        }
2242
2243                        cx.notify();
2244                    });
2245                }
2246                Ok::<_, anyhow::Error>(())
2247            }
2248            .log_err()
2249        });
2250        self.completion_tasks.push((id, task));
2251    }
2252
2253    pub fn confirm_completion(
2254        &mut self,
2255        action: &ConfirmCompletion,
2256        cx: &mut ViewContext<Self>,
2257    ) -> Option<Task<Result<()>>> {
2258        use language::ToOffset as _;
2259
2260        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2261            menu
2262        } else {
2263            return None;
2264        };
2265
2266        let mat = completions_menu
2267            .matches
2268            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2269        let buffer_handle = completions_menu.buffer;
2270        let completion = completions_menu.completions.get(mat.candidate_id)?;
2271
2272        let snippet;
2273        let text;
2274        if completion.is_snippet() {
2275            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2276            text = snippet.as_ref().unwrap().text.clone();
2277        } else {
2278            snippet = None;
2279            text = completion.new_text.clone();
2280        };
2281        let selections = self.selections.all::<usize>(cx);
2282        let buffer = buffer_handle.read(cx);
2283        let old_range = completion.old_range.to_offset(buffer);
2284        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2285
2286        let newest_selection = self.selections.newest_anchor();
2287        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
2288            return None;
2289        }
2290
2291        let lookbehind = newest_selection
2292            .start
2293            .text_anchor
2294            .to_offset(buffer)
2295            .saturating_sub(old_range.start);
2296        let lookahead = old_range
2297            .end
2298            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2299        let mut common_prefix_len = old_text
2300            .bytes()
2301            .zip(text.bytes())
2302            .take_while(|(a, b)| a == b)
2303            .count();
2304
2305        let snapshot = self.buffer.read(cx).snapshot(cx);
2306        let mut ranges = Vec::new();
2307        for selection in &selections {
2308            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2309                let start = selection.start.saturating_sub(lookbehind);
2310                let end = selection.end + lookahead;
2311                ranges.push(start + common_prefix_len..end);
2312            } else {
2313                common_prefix_len = 0;
2314                ranges.clear();
2315                ranges.extend(selections.iter().map(|s| {
2316                    if s.id == newest_selection.id {
2317                        old_range.clone()
2318                    } else {
2319                        s.start..s.end
2320                    }
2321                }));
2322                break;
2323            }
2324        }
2325        let text = &text[common_prefix_len..];
2326
2327        self.transact(cx, |this, cx| {
2328            if let Some(mut snippet) = snippet {
2329                snippet.text = text.to_string();
2330                for tabstop in snippet.tabstops.iter_mut().flatten() {
2331                    tabstop.start -= common_prefix_len as isize;
2332                    tabstop.end -= common_prefix_len as isize;
2333                }
2334
2335                this.insert_snippet(&ranges, snippet, cx).log_err();
2336            } else {
2337                this.buffer.update(cx, |buffer, cx| {
2338                    buffer.edit(
2339                        ranges.iter().map(|range| (range.clone(), text)),
2340                        Some(AutoindentMode::EachLine),
2341                        cx,
2342                    );
2343                });
2344            }
2345        });
2346
2347        let project = self.project.clone()?;
2348        let apply_edits = project.update(cx, |project, cx| {
2349            project.apply_additional_edits_for_completion(
2350                buffer_handle,
2351                completion.clone(),
2352                true,
2353                cx,
2354            )
2355        });
2356        Some(cx.foreground().spawn(async move {
2357            apply_edits.await?;
2358            Ok(())
2359        }))
2360    }
2361
2362    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2363        if matches!(
2364            self.context_menu.as_ref(),
2365            Some(ContextMenu::CodeActions(_))
2366        ) {
2367            self.context_menu.take();
2368            cx.notify();
2369            return;
2370        }
2371
2372        let deployed_from_indicator = action.deployed_from_indicator;
2373        let mut task = self.code_actions_task.take();
2374        cx.spawn_weak(|this, mut cx| async move {
2375            while let Some(prev_task) = task {
2376                prev_task.await;
2377                task = this
2378                    .upgrade(&cx)
2379                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
2380            }
2381
2382            if let Some(this) = this.upgrade(&cx) {
2383                this.update(&mut cx, |this, cx| {
2384                    if this.focused {
2385                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
2386                            this.show_context_menu(
2387                                ContextMenu::CodeActions(CodeActionsMenu {
2388                                    buffer,
2389                                    actions,
2390                                    selected_item: Default::default(),
2391                                    list: Default::default(),
2392                                    deployed_from_indicator,
2393                                }),
2394                                cx,
2395                            );
2396                        }
2397                    }
2398                })
2399            }
2400            Ok::<_, anyhow::Error>(())
2401        })
2402        .detach_and_log_err(cx);
2403    }
2404
2405    pub fn confirm_code_action(
2406        workspace: &mut Workspace,
2407        action: &ConfirmCodeAction,
2408        cx: &mut ViewContext<Workspace>,
2409    ) -> Option<Task<Result<()>>> {
2410        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2411        let actions_menu = if let ContextMenu::CodeActions(menu) =
2412            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2413        {
2414            menu
2415        } else {
2416            return None;
2417        };
2418        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2419        let action = actions_menu.actions.get(action_ix)?.clone();
2420        let title = action.lsp_action.title.clone();
2421        let buffer = actions_menu.buffer;
2422
2423        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2424            project.apply_code_action(buffer, action, true, cx)
2425        });
2426        Some(cx.spawn(|workspace, cx| async move {
2427            let project_transaction = apply_code_actions.await?;
2428            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
2429        }))
2430    }
2431
2432    async fn open_project_transaction(
2433        this: ViewHandle<Editor>,
2434        workspace: ViewHandle<Workspace>,
2435        transaction: ProjectTransaction,
2436        title: String,
2437        mut cx: AsyncAppContext,
2438    ) -> Result<()> {
2439        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
2440
2441        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2442        entries.sort_unstable_by_key(|(buffer, _)| {
2443            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2444        });
2445
2446        // If the project transaction's edits are all contained within this editor, then
2447        // avoid opening a new editor to display them.
2448
2449        if let Some((buffer, transaction)) = entries.first() {
2450            if entries.len() == 1 {
2451                let excerpt = this.read_with(&cx, |editor, cx| {
2452                    editor
2453                        .buffer()
2454                        .read(cx)
2455                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2456                });
2457                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2458                    if excerpted_buffer == *buffer {
2459                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2460                            let excerpt_range = excerpt_range.to_offset(buffer);
2461                            buffer
2462                                .edited_ranges_for_transaction::<usize>(transaction)
2463                                .all(|range| {
2464                                    excerpt_range.start <= range.start
2465                                        && excerpt_range.end >= range.end
2466                                })
2467                        });
2468
2469                        if all_edits_within_excerpt {
2470                            return Ok(());
2471                        }
2472                    }
2473                }
2474            }
2475        } else {
2476            return Ok(());
2477        }
2478
2479        let mut ranges_to_highlight = Vec::new();
2480        let excerpt_buffer = cx.add_model(|cx| {
2481            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2482            for (buffer_handle, transaction) in &entries {
2483                let buffer = buffer_handle.read(cx);
2484                ranges_to_highlight.extend(
2485                    multibuffer.push_excerpts_with_context_lines(
2486                        buffer_handle.clone(),
2487                        buffer
2488                            .edited_ranges_for_transaction::<usize>(transaction)
2489                            .collect(),
2490                        1,
2491                        cx,
2492                    ),
2493                );
2494            }
2495            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
2496            multibuffer
2497        });
2498
2499        workspace.update(&mut cx, |workspace, cx| {
2500            let project = workspace.project().clone();
2501            let editor =
2502                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2503            workspace.add_item(Box::new(editor.clone()), cx);
2504            editor.update(cx, |editor, cx| {
2505                editor.highlight_background::<Self>(
2506                    ranges_to_highlight,
2507                    |theme| theme.editor.highlighted_line_background,
2508                    cx,
2509                );
2510            });
2511        });
2512
2513        Ok(())
2514    }
2515
2516    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2517        let project = self.project.as_ref()?;
2518        let buffer = self.buffer.read(cx);
2519        let newest_selection = self.selections.newest_anchor().clone();
2520        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2521        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2522        if start_buffer != end_buffer {
2523            return None;
2524        }
2525
2526        let actions = project.update(cx, |project, cx| {
2527            project.code_actions(&start_buffer, start..end, cx)
2528        });
2529        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
2530            let actions = actions.await;
2531            if let Some(this) = this.upgrade(&cx) {
2532                this.update(&mut cx, |this, cx| {
2533                    this.available_code_actions = actions.log_err().and_then(|actions| {
2534                        if actions.is_empty() {
2535                            None
2536                        } else {
2537                            Some((start_buffer, actions.into()))
2538                        }
2539                    });
2540                    cx.notify();
2541                })
2542            }
2543        }));
2544        None
2545    }
2546
2547    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2548        if self.pending_rename.is_some() {
2549            return None;
2550        }
2551
2552        let project = self.project.as_ref()?;
2553        let buffer = self.buffer.read(cx);
2554        let newest_selection = self.selections.newest_anchor().clone();
2555        let cursor_position = newest_selection.head();
2556        let (cursor_buffer, cursor_buffer_position) =
2557            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2558        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2559        if cursor_buffer != tail_buffer {
2560            return None;
2561        }
2562
2563        let highlights = project.update(cx, |project, cx| {
2564            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2565        });
2566
2567        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
2568            let highlights = highlights.log_err().await;
2569            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
2570                this.update(&mut cx, |this, cx| {
2571                    if this.pending_rename.is_some() {
2572                        return;
2573                    }
2574
2575                    let buffer_id = cursor_position.buffer_id;
2576                    let buffer = this.buffer.read(cx);
2577                    if !buffer
2578                        .text_anchor_for_position(cursor_position, cx)
2579                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2580                    {
2581                        return;
2582                    }
2583
2584                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2585                    let mut write_ranges = Vec::new();
2586                    let mut read_ranges = Vec::new();
2587                    for highlight in highlights {
2588                        for (excerpt_id, excerpt_range) in
2589                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2590                        {
2591                            let start = highlight
2592                                .range
2593                                .start
2594                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
2595                            let end = highlight
2596                                .range
2597                                .end
2598                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
2599                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2600                                continue;
2601                            }
2602
2603                            let range = Anchor {
2604                                buffer_id,
2605                                excerpt_id: excerpt_id.clone(),
2606                                text_anchor: start,
2607                            }..Anchor {
2608                                buffer_id,
2609                                excerpt_id,
2610                                text_anchor: end,
2611                            };
2612                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2613                                write_ranges.push(range);
2614                            } else {
2615                                read_ranges.push(range);
2616                            }
2617                        }
2618                    }
2619
2620                    this.highlight_background::<DocumentHighlightRead>(
2621                        read_ranges,
2622                        |theme| theme.editor.document_highlight_read_background,
2623                        cx,
2624                    );
2625                    this.highlight_background::<DocumentHighlightWrite>(
2626                        write_ranges,
2627                        |theme| theme.editor.document_highlight_write_background,
2628                        cx,
2629                    );
2630                    cx.notify();
2631                });
2632            }
2633        }));
2634        None
2635    }
2636
2637    pub fn render_code_actions_indicator(
2638        &self,
2639        style: &EditorStyle,
2640        cx: &mut RenderContext<Self>,
2641    ) -> Option<ElementBox> {
2642        if self.available_code_actions.is_some() {
2643            enum Tag {}
2644            Some(
2645                MouseEventHandler::<Tag>::new(0, cx, |_, _| {
2646                    Svg::new("icons/bolt_8.svg")
2647                        .with_color(style.code_actions.indicator)
2648                        .boxed()
2649                })
2650                .with_cursor_style(CursorStyle::PointingHand)
2651                .with_padding(Padding::uniform(3.))
2652                .on_down(MouseButton::Left, |_, cx| {
2653                    cx.dispatch_action(ToggleCodeActions {
2654                        deployed_from_indicator: true,
2655                    });
2656                })
2657                .boxed(),
2658            )
2659        } else {
2660            None
2661        }
2662    }
2663
2664    pub fn context_menu_visible(&self) -> bool {
2665        self.context_menu
2666            .as_ref()
2667            .map_or(false, |menu| menu.visible())
2668    }
2669
2670    pub fn render_context_menu(
2671        &self,
2672        cursor_position: DisplayPoint,
2673        style: EditorStyle,
2674        cx: &mut RenderContext<Editor>,
2675    ) -> Option<(DisplayPoint, ElementBox)> {
2676        self.context_menu
2677            .as_ref()
2678            .map(|menu| menu.render(cursor_position, style, cx))
2679    }
2680
2681    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
2682        if !matches!(menu, ContextMenu::Completions(_)) {
2683            self.completion_tasks.clear();
2684        }
2685        self.context_menu = Some(menu);
2686        cx.notify();
2687    }
2688
2689    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
2690        cx.notify();
2691        self.completion_tasks.clear();
2692        self.context_menu.take()
2693    }
2694
2695    pub fn insert_snippet(
2696        &mut self,
2697        insertion_ranges: &[Range<usize>],
2698        snippet: Snippet,
2699        cx: &mut ViewContext<Self>,
2700    ) -> Result<()> {
2701        let tabstops = self.buffer.update(cx, |buffer, cx| {
2702            let snippet_text: Arc<str> = snippet.text.clone().into();
2703            buffer.edit(
2704                insertion_ranges
2705                    .iter()
2706                    .cloned()
2707                    .map(|range| (range, snippet_text.clone())),
2708                Some(AutoindentMode::EachLine),
2709                cx,
2710            );
2711
2712            let snapshot = &*buffer.read(cx);
2713            let snippet = &snippet;
2714            snippet
2715                .tabstops
2716                .iter()
2717                .map(|tabstop| {
2718                    let mut tabstop_ranges = tabstop
2719                        .iter()
2720                        .flat_map(|tabstop_range| {
2721                            let mut delta = 0_isize;
2722                            insertion_ranges.iter().map(move |insertion_range| {
2723                                let insertion_start = insertion_range.start as isize + delta;
2724                                delta +=
2725                                    snippet.text.len() as isize - insertion_range.len() as isize;
2726
2727                                let start = snapshot.anchor_before(
2728                                    (insertion_start + tabstop_range.start) as usize,
2729                                );
2730                                let end = snapshot
2731                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
2732                                start..end
2733                            })
2734                        })
2735                        .collect::<Vec<_>>();
2736                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
2737                    tabstop_ranges
2738                })
2739                .collect::<Vec<_>>()
2740        });
2741
2742        if let Some(tabstop) = tabstops.first() {
2743            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
2744                s.select_ranges(tabstop.iter().cloned());
2745            });
2746            self.snippet_stack.push(SnippetState {
2747                active_index: 0,
2748                ranges: tabstops,
2749            });
2750        }
2751
2752        Ok(())
2753    }
2754
2755    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2756        self.move_to_snippet_tabstop(Bias::Right, cx)
2757    }
2758
2759    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2760        self.move_to_snippet_tabstop(Bias::Left, cx)
2761    }
2762
2763    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
2764        if let Some(mut snippet) = self.snippet_stack.pop() {
2765            match bias {
2766                Bias::Left => {
2767                    if snippet.active_index > 0 {
2768                        snippet.active_index -= 1;
2769                    } else {
2770                        self.snippet_stack.push(snippet);
2771                        return false;
2772                    }
2773                }
2774                Bias::Right => {
2775                    if snippet.active_index + 1 < snippet.ranges.len() {
2776                        snippet.active_index += 1;
2777                    } else {
2778                        self.snippet_stack.push(snippet);
2779                        return false;
2780                    }
2781                }
2782            }
2783            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
2784                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
2785                    s.select_anchor_ranges(current_ranges.iter().cloned())
2786                });
2787                // If snippet state is not at the last tabstop, push it back on the stack
2788                if snippet.active_index + 1 < snippet.ranges.len() {
2789                    self.snippet_stack.push(snippet);
2790                }
2791                return true;
2792            }
2793        }
2794
2795        false
2796    }
2797
2798    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
2799        self.transact(cx, |this, cx| {
2800            this.select_all(&SelectAll, cx);
2801            this.insert("", cx);
2802        });
2803    }
2804
2805    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
2806        self.transact(cx, |this, cx| {
2807            this.select_autoclose_pair(cx);
2808            let mut selections = this.selections.all::<Point>(cx);
2809            if !this.selections.line_mode {
2810                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
2811                for selection in &mut selections {
2812                    if selection.is_empty() {
2813                        let old_head = selection.head();
2814                        let mut new_head =
2815                            movement::left(&display_map, old_head.to_display_point(&display_map))
2816                                .to_point(&display_map);
2817                        if let Some((buffer, line_buffer_range)) = display_map
2818                            .buffer_snapshot
2819                            .buffer_line_for_row(old_head.row)
2820                        {
2821                            let indent_size =
2822                                buffer.indent_size_for_line(line_buffer_range.start.row);
2823                            let language_name = buffer
2824                                .language_at(line_buffer_range.start)
2825                                .map(|language| language.name());
2826                            let indent_len = match indent_size.kind {
2827                                IndentKind::Space => {
2828                                    cx.global::<Settings>().tab_size(language_name.as_deref())
2829                                }
2830                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
2831                            };
2832                            if old_head.column <= indent_size.len && old_head.column > 0 {
2833                                let indent_len = indent_len.get();
2834                                new_head = cmp::min(
2835                                    new_head,
2836                                    Point::new(
2837                                        old_head.row,
2838                                        ((old_head.column - 1) / indent_len) * indent_len,
2839                                    ),
2840                                );
2841                            }
2842                        }
2843
2844                        selection.set_head(new_head, SelectionGoal::None);
2845                    }
2846                }
2847            }
2848
2849            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
2850            this.insert("", cx);
2851        });
2852    }
2853
2854    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
2855        self.transact(cx, |this, cx| {
2856            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2857                let line_mode = s.line_mode;
2858                s.move_with(|map, selection| {
2859                    if selection.is_empty() && !line_mode {
2860                        let cursor = movement::right(map, selection.head());
2861                        selection.set_head(cursor, SelectionGoal::None);
2862                    }
2863                })
2864            });
2865            this.insert("", cx);
2866        });
2867    }
2868
2869    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
2870        if self.move_to_prev_snippet_tabstop(cx) {
2871            return;
2872        }
2873
2874        self.outdent(&Outdent, cx);
2875    }
2876
2877    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
2878        if self.move_to_next_snippet_tabstop(cx) {
2879            return;
2880        }
2881
2882        let mut selections = self.selections.all_adjusted(cx);
2883        let buffer = self.buffer.read(cx);
2884        let snapshot = buffer.snapshot(cx);
2885        let rows_iter = selections.iter().map(|s| s.head().row);
2886        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
2887
2888        let mut edits = Vec::new();
2889        let mut prev_edited_row = 0;
2890        let mut row_delta = 0;
2891        for selection in &mut selections {
2892            if selection.start.row != prev_edited_row {
2893                row_delta = 0;
2894            }
2895            prev_edited_row = selection.end.row;
2896
2897            // If the selection is non-empty, then increase the indentation of the selected lines.
2898            if !selection.is_empty() {
2899                row_delta =
2900                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
2901                continue;
2902            }
2903
2904            // If the selection is empty and the cursor is in the leading whitespace before the
2905            // suggested indentation, then auto-indent the line.
2906            let cursor = selection.head();
2907            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
2908                let current_indent = snapshot.indent_size_for_line(cursor.row);
2909                if cursor.column < suggested_indent.len
2910                    && cursor.column <= current_indent.len
2911                    && current_indent.len <= suggested_indent.len
2912                {
2913                    selection.start = Point::new(cursor.row, suggested_indent.len);
2914                    selection.end = selection.start;
2915                    if row_delta == 0 {
2916                        edits.extend(Buffer::edit_for_indent_size_adjustment(
2917                            cursor.row,
2918                            current_indent,
2919                            suggested_indent,
2920                        ));
2921                        row_delta = suggested_indent.len - current_indent.len;
2922                    }
2923                    continue;
2924                }
2925            }
2926
2927            // Otherwise, insert a hard or soft tab.
2928            let settings = cx.global::<Settings>();
2929            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
2930            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
2931                IndentSize::tab()
2932            } else {
2933                let tab_size = settings.tab_size(language_name.as_deref()).get();
2934                let char_column = snapshot
2935                    .text_for_range(Point::new(cursor.row, 0)..cursor)
2936                    .flat_map(str::chars)
2937                    .count()
2938                    + row_delta as usize;
2939                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
2940                IndentSize::spaces(chars_to_next_tab_stop)
2941            };
2942            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
2943            selection.end = selection.start;
2944            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
2945            row_delta += tab_size.len;
2946        }
2947
2948        self.transact(cx, |this, cx| {
2949            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
2950            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections))
2951        });
2952    }
2953
2954    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
2955        let mut selections = self.selections.all::<Point>(cx);
2956        let mut prev_edited_row = 0;
2957        let mut row_delta = 0;
2958        let mut edits = Vec::new();
2959        let buffer = self.buffer.read(cx);
2960        let snapshot = buffer.snapshot(cx);
2961        for selection in &mut selections {
2962            if selection.start.row != prev_edited_row {
2963                row_delta = 0;
2964            }
2965            prev_edited_row = selection.end.row;
2966
2967            row_delta =
2968                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
2969        }
2970
2971        self.transact(cx, |this, cx| {
2972            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
2973            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
2974        });
2975    }
2976
2977    fn indent_selection(
2978        buffer: &MultiBuffer,
2979        snapshot: &MultiBufferSnapshot,
2980        selection: &mut Selection<Point>,
2981        edits: &mut Vec<(Range<Point>, String)>,
2982        delta_for_start_row: u32,
2983        cx: &AppContext,
2984    ) -> u32 {
2985        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
2986        let settings = cx.global::<Settings>();
2987        let tab_size = settings.tab_size(language_name.as_deref()).get();
2988        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
2989            IndentKind::Tab
2990        } else {
2991            IndentKind::Space
2992        };
2993        let mut start_row = selection.start.row;
2994        let mut end_row = selection.end.row + 1;
2995
2996        // If a selection ends at the beginning of a line, don't indent
2997        // that last line.
2998        if selection.end.column == 0 {
2999            end_row -= 1;
3000        }
3001
3002        // Avoid re-indenting a row that has already been indented by a
3003        // previous selection, but still update this selection's column
3004        // to reflect that indentation.
3005        if delta_for_start_row > 0 {
3006            start_row += 1;
3007            selection.start.column += delta_for_start_row;
3008            if selection.end.row == selection.start.row {
3009                selection.end.column += delta_for_start_row;
3010            }
3011        }
3012
3013        let mut delta_for_end_row = 0;
3014        for row in start_row..end_row {
3015            let current_indent = snapshot.indent_size_for_line(row);
3016            let indent_delta = match (current_indent.kind, indent_kind) {
3017                (IndentKind::Space, IndentKind::Space) => {
3018                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3019                    IndentSize::spaces(columns_to_next_tab_stop)
3020                }
3021                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3022                (_, IndentKind::Tab) => IndentSize::tab(),
3023            };
3024
3025            let row_start = Point::new(row, 0);
3026            edits.push((
3027                row_start..row_start,
3028                indent_delta.chars().collect::<String>(),
3029            ));
3030
3031            // Update this selection's endpoints to reflect the indentation.
3032            if row == selection.start.row {
3033                selection.start.column += indent_delta.len;
3034            }
3035            if row == selection.end.row {
3036                selection.end.column += indent_delta.len;
3037                delta_for_end_row = indent_delta.len;
3038            }
3039        }
3040
3041        if selection.start.row == selection.end.row {
3042            delta_for_start_row + delta_for_end_row
3043        } else {
3044            delta_for_end_row
3045        }
3046    }
3047
3048    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3049        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3050        let selections = self.selections.all::<Point>(cx);
3051        let mut deletion_ranges = Vec::new();
3052        let mut last_outdent = None;
3053        {
3054            let buffer = self.buffer.read(cx);
3055            let snapshot = buffer.snapshot(cx);
3056            for selection in &selections {
3057                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3058                let tab_size = cx
3059                    .global::<Settings>()
3060                    .tab_size(language_name.as_deref())
3061                    .get();
3062                let mut rows = selection.spanned_rows(false, &display_map);
3063
3064                // Avoid re-outdenting a row that has already been outdented by a
3065                // previous selection.
3066                if let Some(last_row) = last_outdent {
3067                    if last_row == rows.start {
3068                        rows.start += 1;
3069                    }
3070                }
3071
3072                for row in rows {
3073                    let indent_size = snapshot.indent_size_for_line(row);
3074                    if indent_size.len > 0 {
3075                        let deletion_len = match indent_size.kind {
3076                            IndentKind::Space => {
3077                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3078                                if columns_to_prev_tab_stop == 0 {
3079                                    tab_size
3080                                } else {
3081                                    columns_to_prev_tab_stop
3082                                }
3083                            }
3084                            IndentKind::Tab => 1,
3085                        };
3086                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3087                        last_outdent = Some(row);
3088                    }
3089                }
3090            }
3091        }
3092
3093        self.transact(cx, |this, cx| {
3094            this.buffer.update(cx, |buffer, cx| {
3095                let empty_str: Arc<str> = "".into();
3096                buffer.edit(
3097                    deletion_ranges
3098                        .into_iter()
3099                        .map(|range| (range, empty_str.clone())),
3100                    None,
3101                    cx,
3102                );
3103            });
3104            let selections = this.selections.all::<usize>(cx);
3105            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3106        });
3107    }
3108
3109    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3110        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3111        let selections = self.selections.all::<Point>(cx);
3112
3113        let mut new_cursors = Vec::new();
3114        let mut edit_ranges = Vec::new();
3115        let mut selections = selections.iter().peekable();
3116        while let Some(selection) = selections.next() {
3117            let mut rows = selection.spanned_rows(false, &display_map);
3118            let goal_display_column = selection.head().to_display_point(&display_map).column();
3119
3120            // Accumulate contiguous regions of rows that we want to delete.
3121            while let Some(next_selection) = selections.peek() {
3122                let next_rows = next_selection.spanned_rows(false, &display_map);
3123                if next_rows.start <= rows.end {
3124                    rows.end = next_rows.end;
3125                    selections.next().unwrap();
3126                } else {
3127                    break;
3128                }
3129            }
3130
3131            let buffer = &display_map.buffer_snapshot;
3132            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3133            let edit_end;
3134            let cursor_buffer_row;
3135            if buffer.max_point().row >= rows.end {
3136                // If there's a line after the range, delete the \n from the end of the row range
3137                // and position the cursor on the next line.
3138                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3139                cursor_buffer_row = rows.end;
3140            } else {
3141                // If there isn't a line after the range, delete the \n from the line before the
3142                // start of the row range and position the cursor there.
3143                edit_start = edit_start.saturating_sub(1);
3144                edit_end = buffer.len();
3145                cursor_buffer_row = rows.start.saturating_sub(1);
3146            }
3147
3148            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3149            *cursor.column_mut() =
3150                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3151
3152            new_cursors.push((
3153                selection.id,
3154                buffer.anchor_after(cursor.to_point(&display_map)),
3155            ));
3156            edit_ranges.push(edit_start..edit_end);
3157        }
3158
3159        self.transact(cx, |this, cx| {
3160            let buffer = this.buffer.update(cx, |buffer, cx| {
3161                let empty_str: Arc<str> = "".into();
3162                buffer.edit(
3163                    edit_ranges
3164                        .into_iter()
3165                        .map(|range| (range, empty_str.clone())),
3166                    None,
3167                    cx,
3168                );
3169                buffer.snapshot(cx)
3170            });
3171            let new_selections = new_cursors
3172                .into_iter()
3173                .map(|(id, cursor)| {
3174                    let cursor = cursor.to_point(&buffer);
3175                    Selection {
3176                        id,
3177                        start: cursor,
3178                        end: cursor,
3179                        reversed: false,
3180                        goal: SelectionGoal::None,
3181                    }
3182                })
3183                .collect();
3184
3185            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3186                s.select(new_selections);
3187            });
3188        });
3189    }
3190
3191    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3192        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3193        let buffer = &display_map.buffer_snapshot;
3194        let selections = self.selections.all::<Point>(cx);
3195
3196        let mut edits = Vec::new();
3197        let mut selections_iter = selections.iter().peekable();
3198        while let Some(selection) = selections_iter.next() {
3199            // Avoid duplicating the same lines twice.
3200            let mut rows = selection.spanned_rows(false, &display_map);
3201
3202            while let Some(next_selection) = selections_iter.peek() {
3203                let next_rows = next_selection.spanned_rows(false, &display_map);
3204                if next_rows.start < rows.end {
3205                    rows.end = next_rows.end;
3206                    selections_iter.next().unwrap();
3207                } else {
3208                    break;
3209                }
3210            }
3211
3212            // Copy the text from the selected row region and splice it at the start of the region.
3213            let start = Point::new(rows.start, 0);
3214            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3215            let text = buffer
3216                .text_for_range(start..end)
3217                .chain(Some("\n"))
3218                .collect::<String>();
3219            edits.push((start..start, text));
3220        }
3221
3222        self.transact(cx, |this, cx| {
3223            this.buffer.update(cx, |buffer, cx| {
3224                buffer.edit(edits, None, cx);
3225            });
3226
3227            this.request_autoscroll(Autoscroll::fit(), cx);
3228        });
3229    }
3230
3231    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3232        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3233        let buffer = self.buffer.read(cx).snapshot(cx);
3234
3235        let mut edits = Vec::new();
3236        let mut unfold_ranges = Vec::new();
3237        let mut refold_ranges = Vec::new();
3238
3239        let selections = self.selections.all::<Point>(cx);
3240        let mut selections = selections.iter().peekable();
3241        let mut contiguous_row_selections = Vec::new();
3242        let mut new_selections = Vec::new();
3243
3244        while let Some(selection) = selections.next() {
3245            // Find all the selections that span a contiguous row range
3246            contiguous_row_selections.push(selection.clone());
3247            let start_row = selection.start.row;
3248            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3249                display_map.next_line_boundary(selection.end).0.row + 1
3250            } else {
3251                selection.end.row
3252            };
3253
3254            while let Some(next_selection) = selections.peek() {
3255                if next_selection.start.row <= end_row {
3256                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3257                        display_map.next_line_boundary(next_selection.end).0.row + 1
3258                    } else {
3259                        next_selection.end.row
3260                    };
3261                    contiguous_row_selections.push(selections.next().unwrap().clone());
3262                } else {
3263                    break;
3264                }
3265            }
3266
3267            // Move the text spanned by the row range to be before the line preceding the row range
3268            if start_row > 0 {
3269                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3270                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3271                let insertion_point = display_map
3272                    .prev_line_boundary(Point::new(start_row - 1, 0))
3273                    .0;
3274
3275                // Don't move lines across excerpts
3276                if buffer
3277                    .excerpt_boundaries_in_range((
3278                        Bound::Excluded(insertion_point),
3279                        Bound::Included(range_to_move.end),
3280                    ))
3281                    .next()
3282                    .is_none()
3283                {
3284                    let text = buffer
3285                        .text_for_range(range_to_move.clone())
3286                        .flat_map(|s| s.chars())
3287                        .skip(1)
3288                        .chain(['\n'])
3289                        .collect::<String>();
3290
3291                    edits.push((
3292                        buffer.anchor_after(range_to_move.start)
3293                            ..buffer.anchor_before(range_to_move.end),
3294                        String::new(),
3295                    ));
3296                    let insertion_anchor = buffer.anchor_after(insertion_point);
3297                    edits.push((insertion_anchor..insertion_anchor, text));
3298
3299                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3300
3301                    // Move selections up
3302                    new_selections.extend(contiguous_row_selections.drain(..).map(
3303                        |mut selection| {
3304                            selection.start.row -= row_delta;
3305                            selection.end.row -= row_delta;
3306                            selection
3307                        },
3308                    ));
3309
3310                    // Move folds up
3311                    unfold_ranges.push(range_to_move.clone());
3312                    for fold in display_map.folds_in_range(
3313                        buffer.anchor_before(range_to_move.start)
3314                            ..buffer.anchor_after(range_to_move.end),
3315                    ) {
3316                        let mut start = fold.start.to_point(&buffer);
3317                        let mut end = fold.end.to_point(&buffer);
3318                        start.row -= row_delta;
3319                        end.row -= row_delta;
3320                        refold_ranges.push(start..end);
3321                    }
3322                }
3323            }
3324
3325            // If we didn't move line(s), preserve the existing selections
3326            new_selections.append(&mut contiguous_row_selections);
3327        }
3328
3329        self.transact(cx, |this, cx| {
3330            this.unfold_ranges(unfold_ranges, true, cx);
3331            this.buffer.update(cx, |buffer, cx| {
3332                for (range, text) in edits {
3333                    buffer.edit([(range, text)], None, cx);
3334                }
3335            });
3336            this.fold_ranges(refold_ranges, cx);
3337            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3338                s.select(new_selections);
3339            })
3340        });
3341    }
3342
3343    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3344        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3345        let buffer = self.buffer.read(cx).snapshot(cx);
3346
3347        let mut edits = Vec::new();
3348        let mut unfold_ranges = Vec::new();
3349        let mut refold_ranges = Vec::new();
3350
3351        let selections = self.selections.all::<Point>(cx);
3352        let mut selections = selections.iter().peekable();
3353        let mut contiguous_row_selections = Vec::new();
3354        let mut new_selections = Vec::new();
3355
3356        while let Some(selection) = selections.next() {
3357            // Find all the selections that span a contiguous row range
3358            contiguous_row_selections.push(selection.clone());
3359            let start_row = selection.start.row;
3360            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3361                display_map.next_line_boundary(selection.end).0.row + 1
3362            } else {
3363                selection.end.row
3364            };
3365
3366            while let Some(next_selection) = selections.peek() {
3367                if next_selection.start.row <= end_row {
3368                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3369                        display_map.next_line_boundary(next_selection.end).0.row + 1
3370                    } else {
3371                        next_selection.end.row
3372                    };
3373                    contiguous_row_selections.push(selections.next().unwrap().clone());
3374                } else {
3375                    break;
3376                }
3377            }
3378
3379            // Move the text spanned by the row range to be after the last line of the row range
3380            if end_row <= buffer.max_point().row {
3381                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3382                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3383
3384                // Don't move lines across excerpt boundaries
3385                if buffer
3386                    .excerpt_boundaries_in_range((
3387                        Bound::Excluded(range_to_move.start),
3388                        Bound::Included(insertion_point),
3389                    ))
3390                    .next()
3391                    .is_none()
3392                {
3393                    let mut text = String::from("\n");
3394                    text.extend(buffer.text_for_range(range_to_move.clone()));
3395                    text.pop(); // Drop trailing newline
3396                    edits.push((
3397                        buffer.anchor_after(range_to_move.start)
3398                            ..buffer.anchor_before(range_to_move.end),
3399                        String::new(),
3400                    ));
3401                    let insertion_anchor = buffer.anchor_after(insertion_point);
3402                    edits.push((insertion_anchor..insertion_anchor, text));
3403
3404                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3405
3406                    // Move selections down
3407                    new_selections.extend(contiguous_row_selections.drain(..).map(
3408                        |mut selection| {
3409                            selection.start.row += row_delta;
3410                            selection.end.row += row_delta;
3411                            selection
3412                        },
3413                    ));
3414
3415                    // Move folds down
3416                    unfold_ranges.push(range_to_move.clone());
3417                    for fold in display_map.folds_in_range(
3418                        buffer.anchor_before(range_to_move.start)
3419                            ..buffer.anchor_after(range_to_move.end),
3420                    ) {
3421                        let mut start = fold.start.to_point(&buffer);
3422                        let mut end = fold.end.to_point(&buffer);
3423                        start.row += row_delta;
3424                        end.row += row_delta;
3425                        refold_ranges.push(start..end);
3426                    }
3427                }
3428            }
3429
3430            // If we didn't move line(s), preserve the existing selections
3431            new_selections.append(&mut contiguous_row_selections);
3432        }
3433
3434        self.transact(cx, |this, cx| {
3435            this.unfold_ranges(unfold_ranges, true, cx);
3436            this.buffer.update(cx, |buffer, cx| {
3437                for (range, text) in edits {
3438                    buffer.edit([(range, text)], None, cx);
3439                }
3440            });
3441            this.fold_ranges(refold_ranges, cx);
3442            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
3443        });
3444    }
3445
3446    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3447        self.transact(cx, |this, cx| {
3448            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3449                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3450                let line_mode = s.line_mode;
3451                s.move_with(|display_map, selection| {
3452                    if !selection.is_empty() || line_mode {
3453                        return;
3454                    }
3455
3456                    let mut head = selection.head();
3457                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3458                    if head.column() == display_map.line_len(head.row()) {
3459                        transpose_offset = display_map
3460                            .buffer_snapshot
3461                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3462                    }
3463
3464                    if transpose_offset == 0 {
3465                        return;
3466                    }
3467
3468                    *head.column_mut() += 1;
3469                    head = display_map.clip_point(head, Bias::Right);
3470                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3471
3472                    let transpose_start = display_map
3473                        .buffer_snapshot
3474                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3475                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3476                        let transpose_end = display_map
3477                            .buffer_snapshot
3478                            .clip_offset(transpose_offset + 1, Bias::Right);
3479                        if let Some(ch) =
3480                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3481                        {
3482                            edits.push((transpose_start..transpose_offset, String::new()));
3483                            edits.push((transpose_end..transpose_end, ch.to_string()));
3484                        }
3485                    }
3486                });
3487                edits
3488            });
3489            this.buffer
3490                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3491            let selections = this.selections.all::<usize>(cx);
3492            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3493                s.select(selections);
3494            });
3495        });
3496    }
3497
3498    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3499        let mut text = String::new();
3500        let buffer = self.buffer.read(cx).snapshot(cx);
3501        let mut selections = self.selections.all::<Point>(cx);
3502        let mut clipboard_selections = Vec::with_capacity(selections.len());
3503        {
3504            let max_point = buffer.max_point();
3505            for selection in &mut selections {
3506                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3507                if is_entire_line {
3508                    selection.start = Point::new(selection.start.row, 0);
3509                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3510                    selection.goal = SelectionGoal::None;
3511                }
3512                let mut len = 0;
3513                for chunk in buffer.text_for_range(selection.start..selection.end) {
3514                    text.push_str(chunk);
3515                    len += chunk.len();
3516                }
3517                clipboard_selections.push(ClipboardSelection {
3518                    len,
3519                    is_entire_line,
3520                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3521                });
3522            }
3523        }
3524
3525        self.transact(cx, |this, cx| {
3526            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3527                s.select(selections);
3528            });
3529            this.insert("", cx);
3530            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3531        });
3532    }
3533
3534    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3535        let selections = self.selections.all::<Point>(cx);
3536        let buffer = self.buffer.read(cx).read(cx);
3537        let mut text = String::new();
3538
3539        let mut clipboard_selections = Vec::with_capacity(selections.len());
3540        {
3541            let max_point = buffer.max_point();
3542            for selection in selections.iter() {
3543                let mut start = selection.start;
3544                let mut end = selection.end;
3545                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3546                if is_entire_line {
3547                    start = Point::new(start.row, 0);
3548                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3549                }
3550                let mut len = 0;
3551                for chunk in buffer.text_for_range(start..end) {
3552                    text.push_str(chunk);
3553                    len += chunk.len();
3554                }
3555                clipboard_selections.push(ClipboardSelection {
3556                    len,
3557                    is_entire_line,
3558                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3559                });
3560            }
3561        }
3562
3563        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3564    }
3565
3566    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3567        self.transact(cx, |this, cx| {
3568            if let Some(item) = cx.as_mut().read_from_clipboard() {
3569                let mut clipboard_text = Cow::Borrowed(item.text());
3570                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3571                    let old_selections = this.selections.all::<usize>(cx);
3572                    let all_selections_were_entire_line =
3573                        clipboard_selections.iter().all(|s| s.is_entire_line);
3574                    let first_selection_indent_column =
3575                        clipboard_selections.first().map(|s| s.first_line_indent);
3576                    if clipboard_selections.len() != old_selections.len() {
3577                        let mut newline_separated_text = String::new();
3578                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3579                        let mut ix = 0;
3580                        while let Some(clipboard_selection) = clipboard_selections.next() {
3581                            newline_separated_text
3582                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3583                            ix += clipboard_selection.len;
3584                            if clipboard_selections.peek().is_some() {
3585                                newline_separated_text.push('\n');
3586                            }
3587                        }
3588                        clipboard_text = Cow::Owned(newline_separated_text);
3589                    }
3590
3591                    this.buffer.update(cx, |buffer, cx| {
3592                        let snapshot = buffer.read(cx);
3593                        let mut start_offset = 0;
3594                        let mut edits = Vec::new();
3595                        let mut original_indent_columns = Vec::new();
3596                        let line_mode = this.selections.line_mode;
3597                        for (ix, selection) in old_selections.iter().enumerate() {
3598                            let to_insert;
3599                            let entire_line;
3600                            let original_indent_column;
3601                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3602                                let end_offset = start_offset + clipboard_selection.len;
3603                                to_insert = &clipboard_text[start_offset..end_offset];
3604                                entire_line = clipboard_selection.is_entire_line;
3605                                start_offset = end_offset;
3606                                original_indent_column =
3607                                    Some(clipboard_selection.first_line_indent);
3608                            } else {
3609                                to_insert = clipboard_text.as_str();
3610                                entire_line = all_selections_were_entire_line;
3611                                original_indent_column = first_selection_indent_column
3612                            }
3613
3614                            // If the corresponding selection was empty when this slice of the
3615                            // clipboard text was written, then the entire line containing the
3616                            // selection was copied. If this selection is also currently empty,
3617                            // then paste the line before the current line of the buffer.
3618                            let range = if selection.is_empty() && !line_mode && entire_line {
3619                                let column = selection.start.to_point(&snapshot).column as usize;
3620                                let line_start = selection.start - column;
3621                                line_start..line_start
3622                            } else {
3623                                selection.range()
3624                            };
3625
3626                            edits.push((range, to_insert));
3627                            original_indent_columns.extend(original_indent_column);
3628                        }
3629                        drop(snapshot);
3630
3631                        buffer.edit(
3632                            edits,
3633                            Some(AutoindentMode::Block {
3634                                original_indent_columns,
3635                            }),
3636                            cx,
3637                        );
3638                    });
3639
3640                    let selections = this.selections.all::<usize>(cx);
3641                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3642                } else {
3643                    this.insert(&clipboard_text, cx);
3644                }
3645            }
3646        });
3647    }
3648
3649    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3650        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3651            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3652                self.change_selections(None, cx, |s| {
3653                    s.select_anchors(selections.to_vec());
3654                });
3655            }
3656            self.request_autoscroll(Autoscroll::fit(), cx);
3657            self.unmark_text(cx);
3658            cx.emit(Event::Edited);
3659        }
3660    }
3661
3662    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3663        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3664            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3665            {
3666                self.change_selections(None, cx, |s| {
3667                    s.select_anchors(selections.to_vec());
3668                });
3669            }
3670            self.request_autoscroll(Autoscroll::fit(), cx);
3671            self.unmark_text(cx);
3672            cx.emit(Event::Edited);
3673        }
3674    }
3675
3676    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3677        self.buffer
3678            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3679    }
3680
3681    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3682        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3683            let line_mode = s.line_mode;
3684            s.move_with(|map, selection| {
3685                let cursor = if selection.is_empty() && !line_mode {
3686                    movement::left(map, selection.start)
3687                } else {
3688                    selection.start
3689                };
3690                selection.collapse_to(cursor, SelectionGoal::None);
3691            });
3692        })
3693    }
3694
3695    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3696        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3697            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3698        })
3699    }
3700
3701    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3702        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3703            let line_mode = s.line_mode;
3704            s.move_with(|map, selection| {
3705                let cursor = if selection.is_empty() && !line_mode {
3706                    movement::right(map, selection.end)
3707                } else {
3708                    selection.end
3709                };
3710                selection.collapse_to(cursor, SelectionGoal::None)
3711            });
3712        })
3713    }
3714
3715    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3716        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3717            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3718        })
3719    }
3720
3721    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3722        if self.take_rename(true, cx).is_some() {
3723            return;
3724        }
3725
3726        if let Some(context_menu) = self.context_menu.as_mut() {
3727            if context_menu.select_prev(cx) {
3728                return;
3729            }
3730        }
3731
3732        if matches!(self.mode, EditorMode::SingleLine) {
3733            cx.propagate_action();
3734            return;
3735        }
3736
3737        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3738            let line_mode = s.line_mode;
3739            s.move_with(|map, selection| {
3740                if !selection.is_empty() && !line_mode {
3741                    selection.goal = SelectionGoal::None;
3742                }
3743                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
3744                selection.collapse_to(cursor, goal);
3745            });
3746        })
3747    }
3748
3749    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
3750        if self.take_rename(true, cx).is_some() {
3751            return;
3752        }
3753
3754        if self
3755            .context_menu
3756            .as_mut()
3757            .map(|menu| menu.select_first(cx))
3758            .unwrap_or(false)
3759        {
3760            return;
3761        }
3762
3763        if matches!(self.mode, EditorMode::SingleLine) {
3764            cx.propagate_action();
3765            return;
3766        }
3767
3768        let row_count = if let Some(row_count) = self.visible_line_count() {
3769            row_count as u32 - 1
3770        } else {
3771            return;
3772        };
3773
3774        let autoscroll = if action.center_cursor {
3775            Autoscroll::center()
3776        } else {
3777            Autoscroll::fit()
3778        };
3779
3780        self.change_selections(Some(autoscroll), cx, |s| {
3781            let line_mode = s.line_mode;
3782            s.move_with(|map, selection| {
3783                if !selection.is_empty() && !line_mode {
3784                    selection.goal = SelectionGoal::None;
3785                }
3786                let (cursor, goal) =
3787                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
3788                selection.collapse_to(cursor, goal);
3789            });
3790        });
3791    }
3792
3793    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3794        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3795            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3796        })
3797    }
3798
3799    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3800        self.take_rename(true, cx);
3801
3802        if let Some(context_menu) = self.context_menu.as_mut() {
3803            if context_menu.select_next(cx) {
3804                return;
3805            }
3806        }
3807
3808        if matches!(self.mode, EditorMode::SingleLine) {
3809            cx.propagate_action();
3810            return;
3811        }
3812
3813        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3814            let line_mode = s.line_mode;
3815            s.move_with(|map, selection| {
3816                if !selection.is_empty() && !line_mode {
3817                    selection.goal = SelectionGoal::None;
3818                }
3819                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
3820                selection.collapse_to(cursor, goal);
3821            });
3822        });
3823    }
3824
3825    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
3826        if self.take_rename(true, cx).is_some() {
3827            return;
3828        }
3829
3830        if self
3831            .context_menu
3832            .as_mut()
3833            .map(|menu| menu.select_last(cx))
3834            .unwrap_or(false)
3835        {
3836            return;
3837        }
3838
3839        if matches!(self.mode, EditorMode::SingleLine) {
3840            cx.propagate_action();
3841            return;
3842        }
3843
3844        let row_count = if let Some(row_count) = self.visible_line_count() {
3845            row_count as u32 - 1
3846        } else {
3847            return;
3848        };
3849
3850        let autoscroll = if action.center_cursor {
3851            Autoscroll::center()
3852        } else {
3853            Autoscroll::fit()
3854        };
3855
3856        self.change_selections(Some(autoscroll), cx, |s| {
3857            let line_mode = s.line_mode;
3858            s.move_with(|map, selection| {
3859                if !selection.is_empty() && !line_mode {
3860                    selection.goal = SelectionGoal::None;
3861                }
3862                let (cursor, goal) =
3863                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
3864                selection.collapse_to(cursor, goal);
3865            });
3866        });
3867    }
3868
3869    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3870        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3871            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3872        });
3873    }
3874
3875    pub fn move_to_previous_word_start(
3876        &mut self,
3877        _: &MoveToPreviousWordStart,
3878        cx: &mut ViewContext<Self>,
3879    ) {
3880        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3881            s.move_cursors_with(|map, head, _| {
3882                (
3883                    movement::previous_word_start(map, head),
3884                    SelectionGoal::None,
3885                )
3886            });
3887        })
3888    }
3889
3890    pub fn move_to_previous_subword_start(
3891        &mut self,
3892        _: &MoveToPreviousSubwordStart,
3893        cx: &mut ViewContext<Self>,
3894    ) {
3895        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3896            s.move_cursors_with(|map, head, _| {
3897                (
3898                    movement::previous_subword_start(map, head),
3899                    SelectionGoal::None,
3900                )
3901            });
3902        })
3903    }
3904
3905    pub fn select_to_previous_word_start(
3906        &mut self,
3907        _: &SelectToPreviousWordStart,
3908        cx: &mut ViewContext<Self>,
3909    ) {
3910        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3911            s.move_heads_with(|map, head, _| {
3912                (
3913                    movement::previous_word_start(map, head),
3914                    SelectionGoal::None,
3915                )
3916            });
3917        })
3918    }
3919
3920    pub fn select_to_previous_subword_start(
3921        &mut self,
3922        _: &SelectToPreviousSubwordStart,
3923        cx: &mut ViewContext<Self>,
3924    ) {
3925        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3926            s.move_heads_with(|map, head, _| {
3927                (
3928                    movement::previous_subword_start(map, head),
3929                    SelectionGoal::None,
3930                )
3931            });
3932        })
3933    }
3934
3935    pub fn delete_to_previous_word_start(
3936        &mut self,
3937        _: &DeleteToPreviousWordStart,
3938        cx: &mut ViewContext<Self>,
3939    ) {
3940        self.transact(cx, |this, cx| {
3941            this.select_autoclose_pair(cx);
3942            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3943                let line_mode = s.line_mode;
3944                s.move_with(|map, selection| {
3945                    if selection.is_empty() && !line_mode {
3946                        let cursor = movement::previous_word_start(map, selection.head());
3947                        selection.set_head(cursor, SelectionGoal::None);
3948                    }
3949                });
3950            });
3951            this.insert("", cx);
3952        });
3953    }
3954
3955    pub fn delete_to_previous_subword_start(
3956        &mut self,
3957        _: &DeleteToPreviousSubwordStart,
3958        cx: &mut ViewContext<Self>,
3959    ) {
3960        self.transact(cx, |this, cx| {
3961            this.select_autoclose_pair(cx);
3962            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3963                let line_mode = s.line_mode;
3964                s.move_with(|map, selection| {
3965                    if selection.is_empty() && !line_mode {
3966                        let cursor = movement::previous_subword_start(map, selection.head());
3967                        selection.set_head(cursor, SelectionGoal::None);
3968                    }
3969                });
3970            });
3971            this.insert("", cx);
3972        });
3973    }
3974
3975    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3976        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3977            s.move_cursors_with(|map, head, _| {
3978                (movement::next_word_end(map, head), SelectionGoal::None)
3979            });
3980        })
3981    }
3982
3983    pub fn move_to_next_subword_end(
3984        &mut self,
3985        _: &MoveToNextSubwordEnd,
3986        cx: &mut ViewContext<Self>,
3987    ) {
3988        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3989            s.move_cursors_with(|map, head, _| {
3990                (movement::next_subword_end(map, head), SelectionGoal::None)
3991            });
3992        })
3993    }
3994
3995    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
3996        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3997            s.move_heads_with(|map, head, _| {
3998                (movement::next_word_end(map, head), SelectionGoal::None)
3999            });
4000        })
4001    }
4002
4003    pub fn select_to_next_subword_end(
4004        &mut self,
4005        _: &SelectToNextSubwordEnd,
4006        cx: &mut ViewContext<Self>,
4007    ) {
4008        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4009            s.move_heads_with(|map, head, _| {
4010                (movement::next_subword_end(map, head), SelectionGoal::None)
4011            });
4012        })
4013    }
4014
4015    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4016        self.transact(cx, |this, cx| {
4017            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4018                let line_mode = s.line_mode;
4019                s.move_with(|map, selection| {
4020                    if selection.is_empty() && !line_mode {
4021                        let cursor = movement::next_word_end(map, selection.head());
4022                        selection.set_head(cursor, SelectionGoal::None);
4023                    }
4024                });
4025            });
4026            this.insert("", cx);
4027        });
4028    }
4029
4030    pub fn delete_to_next_subword_end(
4031        &mut self,
4032        _: &DeleteToNextSubwordEnd,
4033        cx: &mut ViewContext<Self>,
4034    ) {
4035        self.transact(cx, |this, cx| {
4036            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4037                s.move_with(|map, selection| {
4038                    if selection.is_empty() {
4039                        let cursor = movement::next_subword_end(map, selection.head());
4040                        selection.set_head(cursor, SelectionGoal::None);
4041                    }
4042                });
4043            });
4044            this.insert("", cx);
4045        });
4046    }
4047
4048    pub fn move_to_beginning_of_line(
4049        &mut self,
4050        _: &MoveToBeginningOfLine,
4051        cx: &mut ViewContext<Self>,
4052    ) {
4053        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4054            s.move_cursors_with(|map, head, _| {
4055                (
4056                    movement::indented_line_beginning(map, head, true),
4057                    SelectionGoal::None,
4058                )
4059            });
4060        })
4061    }
4062
4063    pub fn select_to_beginning_of_line(
4064        &mut self,
4065        action: &SelectToBeginningOfLine,
4066        cx: &mut ViewContext<Self>,
4067    ) {
4068        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4069            s.move_heads_with(|map, head, _| {
4070                (
4071                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4072                    SelectionGoal::None,
4073                )
4074            });
4075        });
4076    }
4077
4078    pub fn delete_to_beginning_of_line(
4079        &mut self,
4080        _: &DeleteToBeginningOfLine,
4081        cx: &mut ViewContext<Self>,
4082    ) {
4083        self.transact(cx, |this, cx| {
4084            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4085                s.move_with(|_, selection| {
4086                    selection.reversed = true;
4087                });
4088            });
4089
4090            this.select_to_beginning_of_line(
4091                &SelectToBeginningOfLine {
4092                    stop_at_soft_wraps: false,
4093                },
4094                cx,
4095            );
4096            this.backspace(&Backspace, cx);
4097        });
4098    }
4099
4100    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4101        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4102            s.move_cursors_with(|map, head, _| {
4103                (movement::line_end(map, head, true), SelectionGoal::None)
4104            });
4105        })
4106    }
4107
4108    pub fn select_to_end_of_line(
4109        &mut self,
4110        action: &SelectToEndOfLine,
4111        cx: &mut ViewContext<Self>,
4112    ) {
4113        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4114            s.move_heads_with(|map, head, _| {
4115                (
4116                    movement::line_end(map, head, action.stop_at_soft_wraps),
4117                    SelectionGoal::None,
4118                )
4119            });
4120        })
4121    }
4122
4123    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4124        self.transact(cx, |this, cx| {
4125            this.select_to_end_of_line(
4126                &SelectToEndOfLine {
4127                    stop_at_soft_wraps: false,
4128                },
4129                cx,
4130            );
4131            this.delete(&Delete, cx);
4132        });
4133    }
4134
4135    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4136        self.transact(cx, |this, cx| {
4137            this.select_to_end_of_line(
4138                &SelectToEndOfLine {
4139                    stop_at_soft_wraps: false,
4140                },
4141                cx,
4142            );
4143            this.cut(&Cut, cx);
4144        });
4145    }
4146
4147    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4148        if matches!(self.mode, EditorMode::SingleLine) {
4149            cx.propagate_action();
4150            return;
4151        }
4152
4153        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4154            s.select_ranges(vec![0..0]);
4155        });
4156    }
4157
4158    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4159        let mut selection = self.selections.last::<Point>(cx);
4160        selection.set_head(Point::zero(), SelectionGoal::None);
4161
4162        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4163            s.select(vec![selection]);
4164        });
4165    }
4166
4167    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4168        if matches!(self.mode, EditorMode::SingleLine) {
4169            cx.propagate_action();
4170            return;
4171        }
4172
4173        let cursor = self.buffer.read(cx).read(cx).len();
4174        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4175            s.select_ranges(vec![cursor..cursor])
4176        });
4177    }
4178
4179    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4180        self.nav_history = nav_history;
4181    }
4182
4183    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4184        self.nav_history.as_ref()
4185    }
4186
4187    fn push_to_nav_history(
4188        &self,
4189        cursor_anchor: Anchor,
4190        new_position: Option<Point>,
4191        cx: &mut ViewContext<Self>,
4192    ) {
4193        if let Some(nav_history) = &self.nav_history {
4194            let buffer = self.buffer.read(cx).read(cx);
4195            let cursor_position = cursor_anchor.to_point(&buffer);
4196            let scroll_state = self.scroll_manager.anchor();
4197            let scroll_top_row = scroll_state.top_row(&buffer);
4198            drop(buffer);
4199
4200            if let Some(new_position) = new_position {
4201                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4202                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4203                    return;
4204                }
4205            }
4206
4207            nav_history.push(
4208                Some(NavigationData {
4209                    cursor_anchor,
4210                    cursor_position,
4211                    scroll_anchor: scroll_state,
4212                    scroll_top_row,
4213                }),
4214                cx,
4215            );
4216        }
4217    }
4218
4219    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4220        let buffer = self.buffer.read(cx).snapshot(cx);
4221        let mut selection = self.selections.first::<usize>(cx);
4222        selection.set_head(buffer.len(), SelectionGoal::None);
4223        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4224            s.select(vec![selection]);
4225        });
4226    }
4227
4228    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4229        let end = self.buffer.read(cx).read(cx).len();
4230        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4231            s.select_ranges(vec![0..end]);
4232        });
4233    }
4234
4235    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4236        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4237        let mut selections = self.selections.all::<Point>(cx);
4238        let max_point = display_map.buffer_snapshot.max_point();
4239        for selection in &mut selections {
4240            let rows = selection.spanned_rows(true, &display_map);
4241            selection.start = Point::new(rows.start, 0);
4242            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4243            selection.reversed = false;
4244        }
4245        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4246            s.select(selections);
4247        });
4248    }
4249
4250    pub fn split_selection_into_lines(
4251        &mut self,
4252        _: &SplitSelectionIntoLines,
4253        cx: &mut ViewContext<Self>,
4254    ) {
4255        let mut to_unfold = Vec::new();
4256        let mut new_selection_ranges = Vec::new();
4257        {
4258            let selections = self.selections.all::<Point>(cx);
4259            let buffer = self.buffer.read(cx).read(cx);
4260            for selection in selections {
4261                for row in selection.start.row..selection.end.row {
4262                    let cursor = Point::new(row, buffer.line_len(row));
4263                    new_selection_ranges.push(cursor..cursor);
4264                }
4265                new_selection_ranges.push(selection.end..selection.end);
4266                to_unfold.push(selection.start..selection.end);
4267            }
4268        }
4269        self.unfold_ranges(to_unfold, true, cx);
4270        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4271            s.select_ranges(new_selection_ranges);
4272        });
4273    }
4274
4275    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4276        self.add_selection(true, cx);
4277    }
4278
4279    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4280        self.add_selection(false, cx);
4281    }
4282
4283    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4284        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4285        let mut selections = self.selections.all::<Point>(cx);
4286        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4287            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4288            let range = oldest_selection.display_range(&display_map).sorted();
4289            let columns = cmp::min(range.start.column(), range.end.column())
4290                ..cmp::max(range.start.column(), range.end.column());
4291
4292            selections.clear();
4293            let mut stack = Vec::new();
4294            for row in range.start.row()..=range.end.row() {
4295                if let Some(selection) = self.selections.build_columnar_selection(
4296                    &display_map,
4297                    row,
4298                    &columns,
4299                    oldest_selection.reversed,
4300                ) {
4301                    stack.push(selection.id);
4302                    selections.push(selection);
4303                }
4304            }
4305
4306            if above {
4307                stack.reverse();
4308            }
4309
4310            AddSelectionsState { above, stack }
4311        });
4312
4313        let last_added_selection = *state.stack.last().unwrap();
4314        let mut new_selections = Vec::new();
4315        if above == state.above {
4316            let end_row = if above {
4317                0
4318            } else {
4319                display_map.max_point().row()
4320            };
4321
4322            'outer: for selection in selections {
4323                if selection.id == last_added_selection {
4324                    let range = selection.display_range(&display_map).sorted();
4325                    debug_assert_eq!(range.start.row(), range.end.row());
4326                    let mut row = range.start.row();
4327                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4328                    {
4329                        start..end
4330                    } else {
4331                        cmp::min(range.start.column(), range.end.column())
4332                            ..cmp::max(range.start.column(), range.end.column())
4333                    };
4334
4335                    while row != end_row {
4336                        if above {
4337                            row -= 1;
4338                        } else {
4339                            row += 1;
4340                        }
4341
4342                        if let Some(new_selection) = self.selections.build_columnar_selection(
4343                            &display_map,
4344                            row,
4345                            &columns,
4346                            selection.reversed,
4347                        ) {
4348                            state.stack.push(new_selection.id);
4349                            if above {
4350                                new_selections.push(new_selection);
4351                                new_selections.push(selection);
4352                            } else {
4353                                new_selections.push(selection);
4354                                new_selections.push(new_selection);
4355                            }
4356
4357                            continue 'outer;
4358                        }
4359                    }
4360                }
4361
4362                new_selections.push(selection);
4363            }
4364        } else {
4365            new_selections = selections;
4366            new_selections.retain(|s| s.id != last_added_selection);
4367            state.stack.pop();
4368        }
4369
4370        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4371            s.select(new_selections);
4372        });
4373        if state.stack.len() > 1 {
4374            self.add_selections_state = Some(state);
4375        }
4376    }
4377
4378    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4379        self.push_to_selection_history();
4380        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4381        let buffer = &display_map.buffer_snapshot;
4382        let mut selections = self.selections.all::<usize>(cx);
4383        if let Some(mut select_next_state) = self.select_next_state.take() {
4384            let query = &select_next_state.query;
4385            if !select_next_state.done {
4386                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4387                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4388                let mut next_selected_range = None;
4389
4390                let bytes_after_last_selection =
4391                    buffer.bytes_in_range(last_selection.end..buffer.len());
4392                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4393                let query_matches = query
4394                    .stream_find_iter(bytes_after_last_selection)
4395                    .map(|result| (last_selection.end, result))
4396                    .chain(
4397                        query
4398                            .stream_find_iter(bytes_before_first_selection)
4399                            .map(|result| (0, result)),
4400                    );
4401                for (start_offset, query_match) in query_matches {
4402                    let query_match = query_match.unwrap(); // can only fail due to I/O
4403                    let offset_range =
4404                        start_offset + query_match.start()..start_offset + query_match.end();
4405                    let display_range = offset_range.start.to_display_point(&display_map)
4406                        ..offset_range.end.to_display_point(&display_map);
4407
4408                    if !select_next_state.wordwise
4409                        || (!movement::is_inside_word(&display_map, display_range.start)
4410                            && !movement::is_inside_word(&display_map, display_range.end))
4411                    {
4412                        next_selected_range = Some(offset_range);
4413                        break;
4414                    }
4415                }
4416
4417                if let Some(next_selected_range) = next_selected_range {
4418                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4419                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4420                        if action.replace_newest {
4421                            s.delete(s.newest_anchor().id);
4422                        }
4423                        s.insert_range(next_selected_range);
4424                    });
4425                } else {
4426                    select_next_state.done = true;
4427                }
4428            }
4429
4430            self.select_next_state = Some(select_next_state);
4431        } else if selections.len() == 1 {
4432            let selection = selections.last_mut().unwrap();
4433            if selection.start == selection.end {
4434                let word_range = movement::surrounding_word(
4435                    &display_map,
4436                    selection.start.to_display_point(&display_map),
4437                );
4438                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4439                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4440                selection.goal = SelectionGoal::None;
4441                selection.reversed = false;
4442
4443                let query = buffer
4444                    .text_for_range(selection.start..selection.end)
4445                    .collect::<String>();
4446                let select_state = SelectNextState {
4447                    query: AhoCorasick::new_auto_configured(&[query]),
4448                    wordwise: true,
4449                    done: false,
4450                };
4451                self.unfold_ranges([selection.start..selection.end], false, cx);
4452                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4453                    s.select(selections);
4454                });
4455                self.select_next_state = Some(select_state);
4456            } else {
4457                let query = buffer
4458                    .text_for_range(selection.start..selection.end)
4459                    .collect::<String>();
4460                self.select_next_state = Some(SelectNextState {
4461                    query: AhoCorasick::new_auto_configured(&[query]),
4462                    wordwise: false,
4463                    done: false,
4464                });
4465                self.select_next(action, cx);
4466            }
4467        }
4468    }
4469
4470    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4471        self.transact(cx, |this, cx| {
4472            let mut selections = this.selections.all::<Point>(cx);
4473            let mut edits = Vec::new();
4474            let mut selection_edit_ranges = Vec::new();
4475            let mut last_toggled_row = None;
4476            let snapshot = this.buffer.read(cx).read(cx);
4477            let empty_str: Arc<str> = "".into();
4478            let mut suffixes_inserted = Vec::new();
4479
4480            fn comment_prefix_range(
4481                snapshot: &MultiBufferSnapshot,
4482                row: u32,
4483                comment_prefix: &str,
4484                comment_prefix_whitespace: &str,
4485            ) -> Range<Point> {
4486                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4487
4488                let mut line_bytes = snapshot
4489                    .bytes_in_range(start..snapshot.max_point())
4490                    .flatten()
4491                    .copied();
4492
4493                // If this line currently begins with the line comment prefix, then record
4494                // the range containing the prefix.
4495                if line_bytes
4496                    .by_ref()
4497                    .take(comment_prefix.len())
4498                    .eq(comment_prefix.bytes())
4499                {
4500                    // Include any whitespace that matches the comment prefix.
4501                    let matching_whitespace_len = line_bytes
4502                        .zip(comment_prefix_whitespace.bytes())
4503                        .take_while(|(a, b)| a == b)
4504                        .count() as u32;
4505                    let end = Point::new(
4506                        start.row,
4507                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4508                    );
4509                    start..end
4510                } else {
4511                    start..start
4512                }
4513            }
4514
4515            fn comment_suffix_range(
4516                snapshot: &MultiBufferSnapshot,
4517                row: u32,
4518                comment_suffix: &str,
4519                comment_suffix_has_leading_space: bool,
4520            ) -> Range<Point> {
4521                let end = Point::new(row, snapshot.line_len(row));
4522                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4523
4524                let mut line_end_bytes = snapshot
4525                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4526                    .flatten()
4527                    .copied();
4528
4529                let leading_space_len = if suffix_start_column > 0
4530                    && line_end_bytes.next() == Some(b' ')
4531                    && comment_suffix_has_leading_space
4532                {
4533                    1
4534                } else {
4535                    0
4536                };
4537
4538                // If this line currently begins with the line comment prefix, then record
4539                // the range containing the prefix.
4540                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4541                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4542                    start..end
4543                } else {
4544                    end..end
4545                }
4546            }
4547
4548            // TODO: Handle selections that cross excerpts
4549            for selection in &mut selections {
4550                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
4551                let language = if let Some(language) =
4552                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
4553                {
4554                    language
4555                } else {
4556                    continue;
4557                };
4558
4559                selection_edit_ranges.clear();
4560
4561                // If multiple selections contain a given row, avoid processing that
4562                // row more than once.
4563                let mut start_row = selection.start.row;
4564                if last_toggled_row == Some(start_row) {
4565                    start_row += 1;
4566                }
4567                let end_row =
4568                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4569                        selection.end.row - 1
4570                    } else {
4571                        selection.end.row
4572                    };
4573                last_toggled_row = Some(end_row);
4574
4575                if start_row > end_row {
4576                    continue;
4577                }
4578
4579                // If the language has line comments, toggle those.
4580                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4581                    // Split the comment prefix's trailing whitespace into a separate string,
4582                    // as that portion won't be used for detecting if a line is a comment.
4583                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4584                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4585                    let mut all_selection_lines_are_comments = true;
4586
4587                    for row in start_row..=end_row {
4588                        if snapshot.is_line_blank(row) {
4589                            continue;
4590                        }
4591
4592                        let prefix_range = comment_prefix_range(
4593                            snapshot.deref(),
4594                            row,
4595                            comment_prefix,
4596                            comment_prefix_whitespace,
4597                        );
4598                        if prefix_range.is_empty() {
4599                            all_selection_lines_are_comments = false;
4600                        }
4601                        selection_edit_ranges.push(prefix_range);
4602                    }
4603
4604                    if all_selection_lines_are_comments {
4605                        edits.extend(
4606                            selection_edit_ranges
4607                                .iter()
4608                                .cloned()
4609                                .map(|range| (range, empty_str.clone())),
4610                        );
4611                    } else {
4612                        let min_column = selection_edit_ranges
4613                            .iter()
4614                            .map(|r| r.start.column)
4615                            .min()
4616                            .unwrap_or(0);
4617                        edits.extend(selection_edit_ranges.iter().map(|range| {
4618                            let position = Point::new(range.start.row, min_column);
4619                            (position..position, full_comment_prefix.clone())
4620                        }));
4621                    }
4622                } else if let Some((full_comment_prefix, comment_suffix)) =
4623                    language.block_comment_delimiters()
4624                {
4625                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4626                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4627                    let prefix_range = comment_prefix_range(
4628                        snapshot.deref(),
4629                        start_row,
4630                        comment_prefix,
4631                        comment_prefix_whitespace,
4632                    );
4633                    let suffix_range = comment_suffix_range(
4634                        snapshot.deref(),
4635                        end_row,
4636                        comment_suffix.trim_start_matches(' '),
4637                        comment_suffix.starts_with(' '),
4638                    );
4639
4640                    if prefix_range.is_empty() || suffix_range.is_empty() {
4641                        edits.push((
4642                            prefix_range.start..prefix_range.start,
4643                            full_comment_prefix.clone(),
4644                        ));
4645                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4646                        suffixes_inserted.push((end_row, comment_suffix.len()));
4647                    } else {
4648                        edits.push((prefix_range, empty_str.clone()));
4649                        edits.push((suffix_range, empty_str.clone()));
4650                    }
4651                } else {
4652                    continue;
4653                }
4654            }
4655
4656            drop(snapshot);
4657            this.buffer.update(cx, |buffer, cx| {
4658                buffer.edit(edits, None, cx);
4659            });
4660
4661            // Adjust selections so that they end before any comment suffixes that
4662            // were inserted.
4663            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4664            let mut selections = this.selections.all::<Point>(cx);
4665            let snapshot = this.buffer.read(cx).read(cx);
4666            for selection in &mut selections {
4667                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
4668                    match row.cmp(&selection.end.row) {
4669                        Ordering::Less => {
4670                            suffixes_inserted.next();
4671                            continue;
4672                        }
4673                        Ordering::Greater => break,
4674                        Ordering::Equal => {
4675                            if selection.end.column == snapshot.line_len(row) {
4676                                if selection.is_empty() {
4677                                    selection.start.column -= suffix_len as u32;
4678                                }
4679                                selection.end.column -= suffix_len as u32;
4680                            }
4681                            break;
4682                        }
4683                    }
4684                }
4685            }
4686
4687            drop(snapshot);
4688            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4689        });
4690    }
4691
4692    pub fn select_larger_syntax_node(
4693        &mut self,
4694        _: &SelectLargerSyntaxNode,
4695        cx: &mut ViewContext<Self>,
4696    ) {
4697        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4698        let buffer = self.buffer.read(cx).snapshot(cx);
4699        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4700
4701        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4702        let mut selected_larger_node = false;
4703        let new_selections = old_selections
4704            .iter()
4705            .map(|selection| {
4706                let old_range = selection.start..selection.end;
4707                let mut new_range = old_range.clone();
4708                while let Some(containing_range) =
4709                    buffer.range_for_syntax_ancestor(new_range.clone())
4710                {
4711                    new_range = containing_range;
4712                    if !display_map.intersects_fold(new_range.start)
4713                        && !display_map.intersects_fold(new_range.end)
4714                    {
4715                        break;
4716                    }
4717                }
4718
4719                selected_larger_node |= new_range != old_range;
4720                Selection {
4721                    id: selection.id,
4722                    start: new_range.start,
4723                    end: new_range.end,
4724                    goal: SelectionGoal::None,
4725                    reversed: selection.reversed,
4726                }
4727            })
4728            .collect::<Vec<_>>();
4729
4730        if selected_larger_node {
4731            stack.push(old_selections);
4732            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4733                s.select(new_selections);
4734            });
4735        }
4736        self.select_larger_syntax_node_stack = stack;
4737    }
4738
4739    pub fn select_smaller_syntax_node(
4740        &mut self,
4741        _: &SelectSmallerSyntaxNode,
4742        cx: &mut ViewContext<Self>,
4743    ) {
4744        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4745        if let Some(selections) = stack.pop() {
4746            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4747                s.select(selections.to_vec());
4748            });
4749        }
4750        self.select_larger_syntax_node_stack = stack;
4751    }
4752
4753    pub fn move_to_enclosing_bracket(
4754        &mut self,
4755        _: &MoveToEnclosingBracket,
4756        cx: &mut ViewContext<Self>,
4757    ) {
4758        let buffer = self.buffer.read(cx).snapshot(cx);
4759        let mut selections = self.selections.all::<usize>(cx);
4760        for selection in &mut selections {
4761            if let Some((open_range, close_range)) =
4762                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4763            {
4764                let close_range = close_range.to_inclusive();
4765                let destination = if close_range.contains(&selection.start)
4766                    && close_range.contains(&selection.end)
4767                {
4768                    open_range.end
4769                } else {
4770                    *close_range.start()
4771                };
4772                selection.start = destination;
4773                selection.end = destination;
4774            }
4775        }
4776
4777        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4778            s.select(selections);
4779        });
4780    }
4781
4782    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4783        self.end_selection(cx);
4784        self.selection_history.mode = SelectionHistoryMode::Undoing;
4785        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4786            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4787            self.select_next_state = entry.select_next_state;
4788            self.add_selections_state = entry.add_selections_state;
4789            self.request_autoscroll(Autoscroll::newest(), cx);
4790        }
4791        self.selection_history.mode = SelectionHistoryMode::Normal;
4792    }
4793
4794    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4795        self.end_selection(cx);
4796        self.selection_history.mode = SelectionHistoryMode::Redoing;
4797        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4798            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4799            self.select_next_state = entry.select_next_state;
4800            self.add_selections_state = entry.add_selections_state;
4801            self.request_autoscroll(Autoscroll::newest(), cx);
4802        }
4803        self.selection_history.mode = SelectionHistoryMode::Normal;
4804    }
4805
4806    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
4807        self.go_to_diagnostic_impl(Direction::Next, cx)
4808    }
4809
4810    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4811        self.go_to_diagnostic_impl(Direction::Prev, cx)
4812    }
4813
4814    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4815        let buffer = self.buffer.read(cx).snapshot(cx);
4816        let selection = self.selections.newest::<usize>(cx);
4817
4818        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
4819        if direction == Direction::Next {
4820            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
4821                let (group_id, jump_to) = popover.activation_info();
4822                if self.activate_diagnostics(group_id, cx) {
4823                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4824                        let mut new_selection = s.newest_anchor().clone();
4825                        new_selection.collapse_to(jump_to, SelectionGoal::None);
4826                        s.select_anchors(vec![new_selection.clone()]);
4827                    });
4828                }
4829                return;
4830            }
4831        }
4832
4833        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4834            active_diagnostics
4835                .primary_range
4836                .to_offset(&buffer)
4837                .to_inclusive()
4838        });
4839        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4840            if active_primary_range.contains(&selection.head()) {
4841                *active_primary_range.end()
4842            } else {
4843                selection.head()
4844            }
4845        } else {
4846            selection.head()
4847        };
4848
4849        loop {
4850            let mut diagnostics = if direction == Direction::Prev {
4851                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4852            } else {
4853                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4854            };
4855            let group = diagnostics.find_map(|entry| {
4856                if entry.diagnostic.is_primary
4857                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4858                    && !entry.range.is_empty()
4859                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4860                {
4861                    Some((entry.range, entry.diagnostic.group_id))
4862                } else {
4863                    None
4864                }
4865            });
4866
4867            if let Some((primary_range, group_id)) = group {
4868                if self.activate_diagnostics(group_id, cx) {
4869                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4870                        s.select(vec![Selection {
4871                            id: selection.id,
4872                            start: primary_range.start,
4873                            end: primary_range.start,
4874                            reversed: false,
4875                            goal: SelectionGoal::None,
4876                        }]);
4877                    });
4878                }
4879                break;
4880            } else {
4881                // Cycle around to the start of the buffer, potentially moving back to the start of
4882                // the currently active diagnostic.
4883                active_primary_range.take();
4884                if direction == Direction::Prev {
4885                    if search_start == buffer.len() {
4886                        break;
4887                    } else {
4888                        search_start = buffer.len();
4889                    }
4890                } else if search_start == 0 {
4891                    break;
4892                } else {
4893                    search_start = 0;
4894                }
4895            }
4896        }
4897    }
4898
4899    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
4900        self.go_to_hunk_impl(Direction::Next, cx)
4901    }
4902
4903    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
4904        self.go_to_hunk_impl(Direction::Prev, cx)
4905    }
4906
4907    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4908        let snapshot = self
4909            .display_map
4910            .update(cx, |display_map, cx| display_map.snapshot(cx));
4911        let selection = self.selections.newest::<Point>(cx);
4912
4913        fn seek_in_direction(
4914            this: &mut Editor,
4915            snapshot: &DisplaySnapshot,
4916            initial_point: Point,
4917            is_wrapped: bool,
4918            direction: Direction,
4919            cx: &mut ViewContext<Editor>,
4920        ) -> bool {
4921            let hunks = if direction == Direction::Next {
4922                snapshot
4923                    .buffer_snapshot
4924                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
4925            } else {
4926                snapshot
4927                    .buffer_snapshot
4928                    .git_diff_hunks_in_range(0..initial_point.row, true)
4929            };
4930
4931            let display_point = initial_point.to_display_point(snapshot);
4932            let mut hunks = hunks
4933                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
4934                .skip_while(|hunk| {
4935                    if is_wrapped {
4936                        false
4937                    } else {
4938                        hunk.contains_display_row(display_point.row())
4939                    }
4940                })
4941                .dedup();
4942
4943            if let Some(hunk) = hunks.next() {
4944                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4945                    let row = hunk.start_display_row();
4946                    let point = DisplayPoint::new(row, 0);
4947                    s.select_display_ranges([point..point]);
4948                });
4949
4950                true
4951            } else {
4952                false
4953            }
4954        }
4955
4956        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
4957            let wrapped_point = match direction {
4958                Direction::Next => Point::zero(),
4959                Direction::Prev => snapshot.buffer_snapshot.max_point(),
4960            };
4961            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
4962        }
4963    }
4964
4965    pub fn go_to_definition(
4966        workspace: &mut Workspace,
4967        _: &GoToDefinition,
4968        cx: &mut ViewContext<Workspace>,
4969    ) {
4970        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
4971    }
4972
4973    pub fn go_to_type_definition(
4974        workspace: &mut Workspace,
4975        _: &GoToTypeDefinition,
4976        cx: &mut ViewContext<Workspace>,
4977    ) {
4978        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
4979    }
4980
4981    fn go_to_definition_of_kind(
4982        kind: GotoDefinitionKind,
4983        workspace: &mut Workspace,
4984        cx: &mut ViewContext<Workspace>,
4985    ) {
4986        let active_item = workspace.active_item(cx);
4987        let editor_handle = if let Some(editor) = active_item
4988            .as_ref()
4989            .and_then(|item| item.act_as::<Self>(cx))
4990        {
4991            editor
4992        } else {
4993            return;
4994        };
4995
4996        let editor = editor_handle.read(cx);
4997        let buffer = editor.buffer.read(cx);
4998        let head = editor.selections.newest::<usize>(cx).head();
4999        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5000            text_anchor
5001        } else {
5002            return;
5003        };
5004
5005        let project = workspace.project().clone();
5006        let definitions = project.update(cx, |project, cx| match kind {
5007            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5008            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5009        });
5010
5011        cx.spawn(|workspace, mut cx| async move {
5012            let definitions = definitions.await?;
5013            workspace.update(&mut cx, |workspace, cx| {
5014                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5015            });
5016
5017            Ok::<(), anyhow::Error>(())
5018        })
5019        .detach_and_log_err(cx);
5020    }
5021
5022    pub fn navigate_to_definitions(
5023        workspace: &mut Workspace,
5024        editor_handle: ViewHandle<Editor>,
5025        definitions: Vec<LocationLink>,
5026        cx: &mut ViewContext<Workspace>,
5027    ) {
5028        let pane = workspace.active_pane().clone();
5029        // If there is one definition, just open it directly
5030        if let [definition] = definitions.as_slice() {
5031            let range = definition
5032                .target
5033                .range
5034                .to_offset(definition.target.buffer.read(cx));
5035
5036            let target_editor_handle =
5037                workspace.open_project_item(definition.target.buffer.clone(), cx);
5038            target_editor_handle.update(cx, |target_editor, cx| {
5039                // When selecting a definition in a different buffer, disable the nav history
5040                // to avoid creating a history entry at the previous cursor location.
5041                if editor_handle != target_editor_handle {
5042                    pane.update(cx, |pane, _| pane.disable_history());
5043                }
5044                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5045                    s.select_ranges([range]);
5046                });
5047
5048                pane.update(cx, |pane, _| pane.enable_history());
5049            });
5050        } else if !definitions.is_empty() {
5051            let replica_id = editor_handle.read(cx).replica_id(cx);
5052            let title = definitions
5053                .iter()
5054                .find(|definition| definition.origin.is_some())
5055                .and_then(|definition| {
5056                    definition.origin.as_ref().map(|origin| {
5057                        let buffer = origin.buffer.read(cx);
5058                        format!(
5059                            "Definitions for {}",
5060                            buffer
5061                                .text_for_range(origin.range.clone())
5062                                .collect::<String>()
5063                        )
5064                    })
5065                })
5066                .unwrap_or("Definitions".to_owned());
5067            let locations = definitions
5068                .into_iter()
5069                .map(|definition| definition.target)
5070                .collect();
5071            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5072        }
5073    }
5074
5075    pub fn find_all_references(
5076        workspace: &mut Workspace,
5077        _: &FindAllReferences,
5078        cx: &mut ViewContext<Workspace>,
5079    ) -> Option<Task<Result<()>>> {
5080        let active_item = workspace.active_item(cx)?;
5081        let editor_handle = active_item.act_as::<Self>(cx)?;
5082
5083        let editor = editor_handle.read(cx);
5084        let buffer = editor.buffer.read(cx);
5085        let head = editor.selections.newest::<usize>(cx).head();
5086        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5087        let replica_id = editor.replica_id(cx);
5088
5089        let project = workspace.project().clone();
5090        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5091        Some(cx.spawn(|workspace, mut cx| async move {
5092            let locations = references.await?;
5093            if locations.is_empty() {
5094                return Ok(());
5095            }
5096
5097            workspace.update(&mut cx, |workspace, cx| {
5098                let title = locations
5099                    .first()
5100                    .as_ref()
5101                    .map(|location| {
5102                        let buffer = location.buffer.read(cx);
5103                        format!(
5104                            "References to `{}`",
5105                            buffer
5106                                .text_for_range(location.range.clone())
5107                                .collect::<String>()
5108                        )
5109                    })
5110                    .unwrap();
5111                Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx);
5112            });
5113
5114            Ok(())
5115        }))
5116    }
5117
5118    /// Opens a multibuffer with the given project locations in it
5119    pub fn open_locations_in_multibuffer(
5120        workspace: &mut Workspace,
5121        mut locations: Vec<Location>,
5122        replica_id: ReplicaId,
5123        title: String,
5124        cx: &mut ViewContext<Workspace>,
5125    ) {
5126        // If there are multiple definitions, open them in a multibuffer
5127        locations.sort_by_key(|location| location.buffer.id());
5128        let mut locations = locations.into_iter().peekable();
5129        let mut ranges_to_highlight = Vec::new();
5130
5131        let excerpt_buffer = cx.add_model(|cx| {
5132            let mut multibuffer = MultiBuffer::new(replica_id);
5133            while let Some(location) = locations.next() {
5134                let buffer = location.buffer.read(cx);
5135                let mut ranges_for_buffer = Vec::new();
5136                let range = location.range.to_offset(buffer);
5137                ranges_for_buffer.push(range.clone());
5138
5139                while let Some(next_location) = locations.peek() {
5140                    if next_location.buffer == location.buffer {
5141                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5142                        locations.next();
5143                    } else {
5144                        break;
5145                    }
5146                }
5147
5148                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5149                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5150                    location.buffer.clone(),
5151                    ranges_for_buffer,
5152                    1,
5153                    cx,
5154                ))
5155            }
5156
5157            multibuffer.with_title(title)
5158        });
5159
5160        let editor = cx.add_view(|cx| {
5161            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5162        });
5163        editor.update(cx, |editor, cx| {
5164            editor.highlight_background::<Self>(
5165                ranges_to_highlight,
5166                |theme| theme.editor.highlighted_line_background,
5167                cx,
5168            );
5169        });
5170        workspace.add_item(Box::new(editor), cx);
5171    }
5172
5173    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5174        use language::ToOffset as _;
5175
5176        let project = self.project.clone()?;
5177        let selection = self.selections.newest_anchor().clone();
5178        let (cursor_buffer, cursor_buffer_position) = self
5179            .buffer
5180            .read(cx)
5181            .text_anchor_for_position(selection.head(), cx)?;
5182        let (tail_buffer, _) = self
5183            .buffer
5184            .read(cx)
5185            .text_anchor_for_position(selection.tail(), cx)?;
5186        if tail_buffer != cursor_buffer {
5187            return None;
5188        }
5189
5190        let snapshot = cursor_buffer.read(cx).snapshot();
5191        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5192        let prepare_rename = project.update(cx, |project, cx| {
5193            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5194        });
5195
5196        Some(cx.spawn(|this, mut cx| async move {
5197            let rename_range = if let Some(range) = prepare_rename.await? {
5198                Some(range)
5199            } else {
5200                this.read_with(&cx, |this, cx| {
5201                    let buffer = this.buffer.read(cx).snapshot(cx);
5202                    let mut buffer_highlights = this
5203                        .document_highlights_for_position(selection.head(), &buffer)
5204                        .filter(|highlight| {
5205                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5206                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5207                        });
5208                    buffer_highlights
5209                        .next()
5210                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5211                })
5212            };
5213            if let Some(rename_range) = rename_range {
5214                let rename_buffer_range = rename_range.to_offset(&snapshot);
5215                let cursor_offset_in_rename_range =
5216                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5217
5218                this.update(&mut cx, |this, cx| {
5219                    this.take_rename(false, cx);
5220                    let style = this.style(cx);
5221                    let buffer = this.buffer.read(cx).read(cx);
5222                    let cursor_offset = selection.head().to_offset(&buffer);
5223                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5224                    let rename_end = rename_start + rename_buffer_range.len();
5225                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5226                    let mut old_highlight_id = None;
5227                    let old_name: Arc<str> = buffer
5228                        .chunks(rename_start..rename_end, true)
5229                        .map(|chunk| {
5230                            if old_highlight_id.is_none() {
5231                                old_highlight_id = chunk.syntax_highlight_id;
5232                            }
5233                            chunk.text
5234                        })
5235                        .collect::<String>()
5236                        .into();
5237
5238                    drop(buffer);
5239
5240                    // Position the selection in the rename editor so that it matches the current selection.
5241                    this.show_local_selections = false;
5242                    let rename_editor = cx.add_view(|cx| {
5243                        let mut editor = Editor::single_line(None, cx);
5244                        if let Some(old_highlight_id) = old_highlight_id {
5245                            editor.override_text_style =
5246                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5247                        }
5248                        editor.buffer.update(cx, |buffer, cx| {
5249                            buffer.edit([(0..0, old_name.clone())], None, cx)
5250                        });
5251                        editor.select_all(&SelectAll, cx);
5252                        editor
5253                    });
5254
5255                    let ranges = this
5256                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5257                        .into_iter()
5258                        .flat_map(|(_, ranges)| ranges)
5259                        .chain(
5260                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5261                                .into_iter()
5262                                .flat_map(|(_, ranges)| ranges),
5263                        )
5264                        .collect();
5265
5266                    this.highlight_text::<Rename>(
5267                        ranges,
5268                        HighlightStyle {
5269                            fade_out: Some(style.rename_fade),
5270                            ..Default::default()
5271                        },
5272                        cx,
5273                    );
5274                    cx.focus(&rename_editor);
5275                    let block_id = this.insert_blocks(
5276                        [BlockProperties {
5277                            style: BlockStyle::Flex,
5278                            position: range.start.clone(),
5279                            height: 1,
5280                            render: Arc::new({
5281                                let editor = rename_editor.clone();
5282                                move |cx: &mut BlockContext| {
5283                                    ChildView::new(editor.clone(), cx)
5284                                        .contained()
5285                                        .with_padding_left(cx.anchor_x)
5286                                        .boxed()
5287                                }
5288                            }),
5289                            disposition: BlockDisposition::Below,
5290                        }],
5291                        cx,
5292                    )[0];
5293                    this.pending_rename = Some(RenameState {
5294                        range,
5295                        old_name,
5296                        editor: rename_editor,
5297                        block_id,
5298                    });
5299                });
5300            }
5301
5302            Ok(())
5303        }))
5304    }
5305
5306    pub fn confirm_rename(
5307        workspace: &mut Workspace,
5308        _: &ConfirmRename,
5309        cx: &mut ViewContext<Workspace>,
5310    ) -> Option<Task<Result<()>>> {
5311        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5312
5313        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5314            let rename = editor.take_rename(false, cx)?;
5315            let buffer = editor.buffer.read(cx);
5316            let (start_buffer, start) =
5317                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5318            let (end_buffer, end) =
5319                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5320            if start_buffer == end_buffer {
5321                let new_name = rename.editor.read(cx).text(cx);
5322                Some((start_buffer, start..end, rename.old_name, new_name))
5323            } else {
5324                None
5325            }
5326        })?;
5327
5328        let rename = workspace.project().clone().update(cx, |project, cx| {
5329            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5330        });
5331
5332        Some(cx.spawn(|workspace, mut cx| async move {
5333            let project_transaction = rename.await?;
5334            Self::open_project_transaction(
5335                editor.clone(),
5336                workspace,
5337                project_transaction,
5338                format!("Rename: {}{}", old_name, new_name),
5339                cx.clone(),
5340            )
5341            .await?;
5342
5343            editor.update(&mut cx, |editor, cx| {
5344                editor.refresh_document_highlights(cx);
5345            });
5346            Ok(())
5347        }))
5348    }
5349
5350    fn take_rename(
5351        &mut self,
5352        moving_cursor: bool,
5353        cx: &mut ViewContext<Self>,
5354    ) -> Option<RenameState> {
5355        let rename = self.pending_rename.take()?;
5356        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5357        self.clear_text_highlights::<Rename>(cx);
5358        self.show_local_selections = true;
5359
5360        if moving_cursor {
5361            let rename_editor = rename.editor.read(cx);
5362            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5363
5364            // Update the selection to match the position of the selection inside
5365            // the rename editor.
5366            let snapshot = self.buffer.read(cx).read(cx);
5367            let rename_range = rename.range.to_offset(&snapshot);
5368            let cursor_in_editor = snapshot
5369                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5370                .min(rename_range.end);
5371            drop(snapshot);
5372
5373            self.change_selections(None, cx, |s| {
5374                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5375            });
5376        } else {
5377            self.refresh_document_highlights(cx);
5378        }
5379
5380        Some(rename)
5381    }
5382
5383    #[cfg(any(test, feature = "test-support"))]
5384    pub fn pending_rename(&self) -> Option<&RenameState> {
5385        self.pending_rename.as_ref()
5386    }
5387
5388    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5389        let project = match &self.project {
5390            Some(project) => project.clone(),
5391            None => return None,
5392        };
5393
5394        Some(self.perform_format(project, cx))
5395    }
5396
5397    fn perform_format(
5398        &mut self,
5399        project: ModelHandle<Project>,
5400        cx: &mut ViewContext<'_, Self>,
5401    ) -> Task<Result<()>> {
5402        let buffer = self.buffer().clone();
5403        let buffers = buffer.read(cx).all_buffers();
5404
5405        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5406        let format = project.update(cx, |project, cx| {
5407            project.format(buffers, true, FormatTrigger::Manual, cx)
5408        });
5409
5410        cx.spawn(|_, mut cx| async move {
5411            let transaction = futures::select_biased! {
5412                _ = timeout => {
5413                    log::warn!("timed out waiting for formatting");
5414                    None
5415                }
5416                transaction = format.log_err().fuse() => transaction,
5417            };
5418
5419            buffer.update(&mut cx, |buffer, cx| {
5420                if let Some(transaction) = transaction {
5421                    if !buffer.is_singleton() {
5422                        buffer.push_transaction(&transaction.0);
5423                    }
5424                }
5425
5426                cx.notify();
5427            });
5428
5429            Ok(())
5430        })
5431    }
5432
5433    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5434        if let Some(project) = self.project.clone() {
5435            self.buffer.update(cx, |multi_buffer, cx| {
5436                project.update(cx, |project, cx| {
5437                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5438                });
5439            })
5440        }
5441    }
5442
5443    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5444        cx.show_character_palette();
5445    }
5446
5447    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5448        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5449            let buffer = self.buffer.read(cx).snapshot(cx);
5450            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5451            let is_valid = buffer
5452                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5453                .any(|entry| {
5454                    entry.diagnostic.is_primary
5455                        && !entry.range.is_empty()
5456                        && entry.range.start == primary_range_start
5457                        && entry.diagnostic.message == active_diagnostics.primary_message
5458                });
5459
5460            if is_valid != active_diagnostics.is_valid {
5461                active_diagnostics.is_valid = is_valid;
5462                let mut new_styles = HashMap::default();
5463                for (block_id, diagnostic) in &active_diagnostics.blocks {
5464                    new_styles.insert(
5465                        *block_id,
5466                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5467                    );
5468                }
5469                self.display_map
5470                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5471            }
5472        }
5473    }
5474
5475    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5476        self.dismiss_diagnostics(cx);
5477        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5478            let buffer = self.buffer.read(cx).snapshot(cx);
5479
5480            let mut primary_range = None;
5481            let mut primary_message = None;
5482            let mut group_end = Point::zero();
5483            let diagnostic_group = buffer
5484                .diagnostic_group::<Point>(group_id)
5485                .map(|entry| {
5486                    if entry.range.end > group_end {
5487                        group_end = entry.range.end;
5488                    }
5489                    if entry.diagnostic.is_primary {
5490                        primary_range = Some(entry.range.clone());
5491                        primary_message = Some(entry.diagnostic.message.clone());
5492                    }
5493                    entry
5494                })
5495                .collect::<Vec<_>>();
5496            let primary_range = primary_range?;
5497            let primary_message = primary_message?;
5498            let primary_range =
5499                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5500
5501            let blocks = display_map
5502                .insert_blocks(
5503                    diagnostic_group.iter().map(|entry| {
5504                        let diagnostic = entry.diagnostic.clone();
5505                        let message_height = diagnostic.message.lines().count() as u8;
5506                        BlockProperties {
5507                            style: BlockStyle::Fixed,
5508                            position: buffer.anchor_after(entry.range.start),
5509                            height: message_height,
5510                            render: diagnostic_block_renderer(diagnostic, true),
5511                            disposition: BlockDisposition::Below,
5512                        }
5513                    }),
5514                    cx,
5515                )
5516                .into_iter()
5517                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5518                .collect();
5519
5520            Some(ActiveDiagnosticGroup {
5521                primary_range,
5522                primary_message,
5523                blocks,
5524                is_valid: true,
5525            })
5526        });
5527        self.active_diagnostics.is_some()
5528    }
5529
5530    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5531        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5532            self.display_map.update(cx, |display_map, cx| {
5533                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5534            });
5535            cx.notify();
5536        }
5537    }
5538
5539    pub fn set_selections_from_remote(
5540        &mut self,
5541        selections: Vec<Selection<Anchor>>,
5542        pending_selection: Option<Selection<Anchor>>,
5543        cx: &mut ViewContext<Self>,
5544    ) {
5545        let old_cursor_position = self.selections.newest_anchor().head();
5546        self.selections.change_with(cx, |s| {
5547            s.select_anchors(selections);
5548            if let Some(pending_selection) = pending_selection {
5549                s.set_pending(pending_selection, SelectMode::Character);
5550            } else {
5551                s.clear_pending();
5552            }
5553        });
5554        self.selections_did_change(false, &old_cursor_position, cx);
5555    }
5556
5557    fn push_to_selection_history(&mut self) {
5558        self.selection_history.push(SelectionHistoryEntry {
5559            selections: self.selections.disjoint_anchors(),
5560            select_next_state: self.select_next_state.clone(),
5561            add_selections_state: self.add_selections_state.clone(),
5562        });
5563    }
5564
5565    pub fn transact(
5566        &mut self,
5567        cx: &mut ViewContext<Self>,
5568        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5569    ) -> Option<TransactionId> {
5570        self.start_transaction_at(Instant::now(), cx);
5571        update(self, cx);
5572        self.end_transaction_at(Instant::now(), cx)
5573    }
5574
5575    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5576        self.end_selection(cx);
5577        if let Some(tx_id) = self
5578            .buffer
5579            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5580        {
5581            self.selection_history
5582                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5583        }
5584    }
5585
5586    fn end_transaction_at(
5587        &mut self,
5588        now: Instant,
5589        cx: &mut ViewContext<Self>,
5590    ) -> Option<TransactionId> {
5591        if let Some(tx_id) = self
5592            .buffer
5593            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5594        {
5595            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5596                *end_selections = Some(self.selections.disjoint_anchors());
5597            } else {
5598                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5599            }
5600
5601            cx.emit(Event::Edited);
5602            Some(tx_id)
5603        } else {
5604            None
5605        }
5606    }
5607
5608    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5609        let mut fold_ranges = Vec::new();
5610
5611        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5612        let selections = self.selections.all::<Point>(cx);
5613        for selection in selections {
5614            let range = selection.display_range(&display_map).sorted();
5615            let buffer_start_row = range.start.to_point(&display_map).row;
5616
5617            for row in (0..=range.end.row()).rev() {
5618                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5619                    let fold_range = self.foldable_range_for_line(&display_map, row);
5620                    if fold_range.end.row >= buffer_start_row {
5621                        fold_ranges.push(fold_range);
5622                        if row <= range.start.row() {
5623                            break;
5624                        }
5625                    }
5626                }
5627            }
5628        }
5629
5630        self.fold_ranges(fold_ranges, cx);
5631    }
5632
5633    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5634        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5635        let buffer = &display_map.buffer_snapshot;
5636        let selections = self.selections.all::<Point>(cx);
5637        let ranges = selections
5638            .iter()
5639            .map(|s| {
5640                let range = s.display_range(&display_map).sorted();
5641                let mut start = range.start.to_point(&display_map);
5642                let mut end = range.end.to_point(&display_map);
5643                start.column = 0;
5644                end.column = buffer.line_len(end.row);
5645                start..end
5646            })
5647            .collect::<Vec<_>>();
5648        self.unfold_ranges(ranges, true, cx);
5649    }
5650
5651    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5652        let max_point = display_map.max_point();
5653        if display_row >= max_point.row() {
5654            false
5655        } else {
5656            let (start_indent, is_blank) = display_map.line_indent(display_row);
5657            if is_blank {
5658                false
5659            } else {
5660                for display_row in display_row + 1..=max_point.row() {
5661                    let (indent, is_blank) = display_map.line_indent(display_row);
5662                    if !is_blank {
5663                        return indent > start_indent;
5664                    }
5665                }
5666                false
5667            }
5668        }
5669    }
5670
5671    fn foldable_range_for_line(
5672        &self,
5673        display_map: &DisplaySnapshot,
5674        start_row: u32,
5675    ) -> Range<Point> {
5676        let max_point = display_map.max_point();
5677
5678        let (start_indent, _) = display_map.line_indent(start_row);
5679        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5680        let mut end = None;
5681        for row in start_row + 1..=max_point.row() {
5682            let (indent, is_blank) = display_map.line_indent(row);
5683            if !is_blank && indent <= start_indent {
5684                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5685                break;
5686            }
5687        }
5688
5689        let end = end.unwrap_or(max_point);
5690        start.to_point(display_map)..end.to_point(display_map)
5691    }
5692
5693    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5694        let selections = self.selections.all::<Point>(cx);
5695        let ranges = selections.into_iter().map(|s| s.start..s.end);
5696        self.fold_ranges(ranges, cx);
5697    }
5698
5699    pub fn fold_ranges<T: ToOffset>(
5700        &mut self,
5701        ranges: impl IntoIterator<Item = Range<T>>,
5702        cx: &mut ViewContext<Self>,
5703    ) {
5704        let mut ranges = ranges.into_iter().peekable();
5705        if ranges.peek().is_some() {
5706            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5707            self.request_autoscroll(Autoscroll::fit(), cx);
5708            cx.notify();
5709        }
5710    }
5711
5712    pub fn unfold_ranges<T: ToOffset>(
5713        &mut self,
5714        ranges: impl IntoIterator<Item = Range<T>>,
5715        inclusive: bool,
5716        cx: &mut ViewContext<Self>,
5717    ) {
5718        let mut ranges = ranges.into_iter().peekable();
5719        if ranges.peek().is_some() {
5720            self.display_map
5721                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5722            self.request_autoscroll(Autoscroll::fit(), cx);
5723            cx.notify();
5724        }
5725    }
5726
5727    pub fn insert_blocks(
5728        &mut self,
5729        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5730        cx: &mut ViewContext<Self>,
5731    ) -> Vec<BlockId> {
5732        let blocks = self
5733            .display_map
5734            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5735        self.request_autoscroll(Autoscroll::fit(), cx);
5736        blocks
5737    }
5738
5739    pub fn replace_blocks(
5740        &mut self,
5741        blocks: HashMap<BlockId, RenderBlock>,
5742        cx: &mut ViewContext<Self>,
5743    ) {
5744        self.display_map
5745            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5746        self.request_autoscroll(Autoscroll::fit(), cx);
5747    }
5748
5749    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5750        self.display_map.update(cx, |display_map, cx| {
5751            display_map.remove_blocks(block_ids, cx)
5752        });
5753    }
5754
5755    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5756        self.display_map
5757            .update(cx, |map, cx| map.snapshot(cx))
5758            .longest_row()
5759    }
5760
5761    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5762        self.display_map
5763            .update(cx, |map, cx| map.snapshot(cx))
5764            .max_point()
5765    }
5766
5767    pub fn text(&self, cx: &AppContext) -> String {
5768        self.buffer.read(cx).read(cx).text()
5769    }
5770
5771    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5772        self.transact(cx, |this, cx| {
5773            this.buffer
5774                .read(cx)
5775                .as_singleton()
5776                .expect("you can only call set_text on editors for singleton buffers")
5777                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5778        });
5779    }
5780
5781    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5782        self.display_map
5783            .update(cx, |map, cx| map.snapshot(cx))
5784            .text()
5785    }
5786
5787    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5788        let language_name = self
5789            .buffer
5790            .read(cx)
5791            .as_singleton()
5792            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5793            .map(|l| l.name());
5794
5795        let settings = cx.global::<Settings>();
5796        let mode = self
5797            .soft_wrap_mode_override
5798            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5799        match mode {
5800            settings::SoftWrap::None => SoftWrap::None,
5801            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5802            settings::SoftWrap::PreferredLineLength => {
5803                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5804            }
5805        }
5806    }
5807
5808    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5809        self.soft_wrap_mode_override = Some(mode);
5810        cx.notify();
5811    }
5812
5813    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5814        self.display_map
5815            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5816    }
5817
5818    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
5819        if self.soft_wrap_mode_override.is_some() {
5820            self.soft_wrap_mode_override.take();
5821        } else {
5822            let soft_wrap = match self.soft_wrap_mode(cx) {
5823                SoftWrap::None => settings::SoftWrap::EditorWidth,
5824                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
5825            };
5826            self.soft_wrap_mode_override = Some(soft_wrap);
5827        }
5828        cx.notify();
5829    }
5830
5831    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5832        self.highlighted_rows = rows;
5833    }
5834
5835    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5836        self.highlighted_rows.clone()
5837    }
5838
5839    pub fn highlight_background<T: 'static>(
5840        &mut self,
5841        ranges: Vec<Range<Anchor>>,
5842        color_fetcher: fn(&Theme) -> Color,
5843        cx: &mut ViewContext<Self>,
5844    ) {
5845        self.background_highlights
5846            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5847        cx.notify();
5848    }
5849
5850    #[allow(clippy::type_complexity)]
5851    pub fn clear_background_highlights<T: 'static>(
5852        &mut self,
5853        cx: &mut ViewContext<Self>,
5854    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5855        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
5856        if highlights.is_some() {
5857            cx.notify();
5858        }
5859        highlights
5860    }
5861
5862    #[cfg(feature = "test-support")]
5863    pub fn all_background_highlights(
5864        &mut self,
5865        cx: &mut ViewContext<Self>,
5866    ) -> Vec<(Range<DisplayPoint>, Color)> {
5867        let snapshot = self.snapshot(cx);
5868        let buffer = &snapshot.buffer_snapshot;
5869        let start = buffer.anchor_before(0);
5870        let end = buffer.anchor_after(buffer.len());
5871        let theme = cx.global::<Settings>().theme.as_ref();
5872        self.background_highlights_in_range(start..end, &snapshot, theme)
5873    }
5874
5875    fn document_highlights_for_position<'a>(
5876        &'a self,
5877        position: Anchor,
5878        buffer: &'a MultiBufferSnapshot,
5879    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5880        let read_highlights = self
5881            .background_highlights
5882            .get(&TypeId::of::<DocumentHighlightRead>())
5883            .map(|h| &h.1);
5884        let write_highlights = self
5885            .background_highlights
5886            .get(&TypeId::of::<DocumentHighlightWrite>())
5887            .map(|h| &h.1);
5888        let left_position = position.bias_left(buffer);
5889        let right_position = position.bias_right(buffer);
5890        read_highlights
5891            .into_iter()
5892            .chain(write_highlights)
5893            .flat_map(move |ranges| {
5894                let start_ix = match ranges.binary_search_by(|probe| {
5895                    let cmp = probe.end.cmp(&left_position, buffer);
5896                    if cmp.is_ge() {
5897                        Ordering::Greater
5898                    } else {
5899                        Ordering::Less
5900                    }
5901                }) {
5902                    Ok(i) | Err(i) => i,
5903                };
5904
5905                let right_position = right_position.clone();
5906                ranges[start_ix..]
5907                    .iter()
5908                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5909            })
5910    }
5911
5912    pub fn background_highlights_in_range(
5913        &self,
5914        search_range: Range<Anchor>,
5915        display_snapshot: &DisplaySnapshot,
5916        theme: &Theme,
5917    ) -> Vec<(Range<DisplayPoint>, Color)> {
5918        let mut results = Vec::new();
5919        let buffer = &display_snapshot.buffer_snapshot;
5920        for (color_fetcher, ranges) in self.background_highlights.values() {
5921            let color = color_fetcher(theme);
5922            let start_ix = match ranges.binary_search_by(|probe| {
5923                let cmp = probe.end.cmp(&search_range.start, buffer);
5924                if cmp.is_gt() {
5925                    Ordering::Greater
5926                } else {
5927                    Ordering::Less
5928                }
5929            }) {
5930                Ok(i) | Err(i) => i,
5931            };
5932            for range in &ranges[start_ix..] {
5933                if range.start.cmp(&search_range.end, buffer).is_ge() {
5934                    break;
5935                }
5936                let start = range
5937                    .start
5938                    .to_point(buffer)
5939                    .to_display_point(display_snapshot);
5940                let end = range
5941                    .end
5942                    .to_point(buffer)
5943                    .to_display_point(display_snapshot);
5944                results.push((start..end, color))
5945            }
5946        }
5947        results
5948    }
5949
5950    pub fn highlight_text<T: 'static>(
5951        &mut self,
5952        ranges: Vec<Range<Anchor>>,
5953        style: HighlightStyle,
5954        cx: &mut ViewContext<Self>,
5955    ) {
5956        self.display_map.update(cx, |map, _| {
5957            map.highlight_text(TypeId::of::<T>(), ranges, style)
5958        });
5959        cx.notify();
5960    }
5961
5962    pub fn text_highlights<'a, T: 'static>(
5963        &'a self,
5964        cx: &'a AppContext,
5965    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
5966        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
5967    }
5968
5969    pub fn clear_text_highlights<T: 'static>(
5970        &mut self,
5971        cx: &mut ViewContext<Self>,
5972    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5973        let highlights = self
5974            .display_map
5975            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
5976        if highlights.is_some() {
5977            cx.notify();
5978        }
5979        highlights
5980    }
5981
5982    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
5983        self.blink_manager.read(cx).visible() && self.focused
5984    }
5985
5986    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5987        cx.notify();
5988    }
5989
5990    fn on_buffer_event(
5991        &mut self,
5992        _: ModelHandle<MultiBuffer>,
5993        event: &multi_buffer::Event,
5994        cx: &mut ViewContext<Self>,
5995    ) {
5996        match event {
5997            multi_buffer::Event::Edited => {
5998                self.refresh_active_diagnostics(cx);
5999                self.refresh_code_actions(cx);
6000                cx.emit(Event::BufferEdited);
6001            }
6002            multi_buffer::Event::ExcerptsAdded {
6003                buffer,
6004                predecessor,
6005                excerpts,
6006            } => cx.emit(Event::ExcerptsAdded {
6007                buffer: buffer.clone(),
6008                predecessor: *predecessor,
6009                excerpts: excerpts.clone(),
6010            }),
6011            multi_buffer::Event::ExcerptsRemoved { ids } => {
6012                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6013            }
6014            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6015            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6016            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6017            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6018            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6019            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6020            multi_buffer::Event::DiagnosticsUpdated => {
6021                self.refresh_active_diagnostics(cx);
6022            }
6023        }
6024    }
6025
6026    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6027        cx.notify();
6028    }
6029
6030    pub fn set_searchable(&mut self, searchable: bool) {
6031        self.searchable = searchable;
6032    }
6033
6034    pub fn searchable(&self) -> bool {
6035        self.searchable
6036    }
6037
6038    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6039        let active_item = workspace.active_item(cx);
6040        let editor_handle = if let Some(editor) = active_item
6041            .as_ref()
6042            .and_then(|item| item.act_as::<Self>(cx))
6043        {
6044            editor
6045        } else {
6046            cx.propagate_action();
6047            return;
6048        };
6049
6050        let editor = editor_handle.read(cx);
6051        let buffer = editor.buffer.read(cx);
6052        if buffer.is_singleton() {
6053            cx.propagate_action();
6054            return;
6055        }
6056
6057        let mut new_selections_by_buffer = HashMap::default();
6058        for selection in editor.selections.all::<usize>(cx) {
6059            for (buffer, mut range) in
6060                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6061            {
6062                if selection.reversed {
6063                    mem::swap(&mut range.start, &mut range.end);
6064                }
6065                new_selections_by_buffer
6066                    .entry(buffer)
6067                    .or_insert(Vec::new())
6068                    .push(range)
6069            }
6070        }
6071
6072        editor_handle.update(cx, |editor, cx| {
6073            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6074        });
6075        let pane = workspace.active_pane().clone();
6076        pane.update(cx, |pane, _| pane.disable_history());
6077
6078        // We defer the pane interaction because we ourselves are a workspace item
6079        // and activating a new item causes the pane to call a method on us reentrantly,
6080        // which panics if we're on the stack.
6081        cx.defer(move |workspace, cx| {
6082            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6083                let editor = workspace.open_project_item::<Self>(buffer, cx);
6084                editor.update(cx, |editor, cx| {
6085                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6086                        s.select_ranges(ranges);
6087                    });
6088                });
6089            }
6090
6091            pane.update(cx, |pane, _| pane.enable_history());
6092        });
6093    }
6094
6095    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6096        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6097        let position = action.position;
6098        let anchor = action.anchor;
6099        cx.spawn_weak(|_, mut cx| async move {
6100            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6101            editor.update(&mut cx, |editor, cx| {
6102                let buffer = editor.buffer().read(cx).as_singleton()?;
6103                let buffer = buffer.read(cx);
6104                let cursor = if buffer.can_resolve(&anchor) {
6105                    language::ToPoint::to_point(&anchor, buffer)
6106                } else {
6107                    buffer.clip_point(position, Bias::Left)
6108                };
6109
6110                let nav_history = editor.nav_history.take();
6111                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6112                    s.select_ranges([cursor..cursor]);
6113                });
6114                editor.nav_history = nav_history;
6115
6116                Some(())
6117            })?;
6118            Some(())
6119        })
6120        .detach()
6121    }
6122
6123    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6124        let snapshot = self.buffer.read(cx).read(cx);
6125        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6126        Some(
6127            ranges
6128                .iter()
6129                .map(move |range| {
6130                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6131                })
6132                .collect(),
6133        )
6134    }
6135
6136    fn selection_replacement_ranges(
6137        &self,
6138        range: Range<OffsetUtf16>,
6139        cx: &AppContext,
6140    ) -> Vec<Range<OffsetUtf16>> {
6141        let selections = self.selections.all::<OffsetUtf16>(cx);
6142        let newest_selection = selections
6143            .iter()
6144            .max_by_key(|selection| selection.id)
6145            .unwrap();
6146        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6147        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6148        let snapshot = self.buffer.read(cx).read(cx);
6149        selections
6150            .into_iter()
6151            .map(|mut selection| {
6152                selection.start.0 =
6153                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6154                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6155                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6156                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6157            })
6158            .collect()
6159    }
6160
6161    fn report_event(&self, name: &str, cx: &AppContext) {
6162        if let Some((project, file)) = self.project.as_ref().zip(
6163            self.buffer
6164                .read(cx)
6165                .as_singleton()
6166                .and_then(|b| b.read(cx).file()),
6167        ) {
6168            let extension = Path::new(file.file_name(cx))
6169                .extension()
6170                .and_then(|e| e.to_str());
6171            project.read(cx).client().report_event(
6172                name,
6173                json!({ "File Extension": extension }),
6174                cx.global::<Settings>().telemetry(),
6175            );
6176        }
6177    }
6178}
6179
6180impl EditorSnapshot {
6181    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6182        self.display_snapshot.buffer_snapshot.language_at(position)
6183    }
6184
6185    pub fn is_focused(&self) -> bool {
6186        self.is_focused
6187    }
6188
6189    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6190        self.placeholder_text.as_ref()
6191    }
6192
6193    pub fn scroll_position(&self) -> Vector2F {
6194        self.scroll_anchor.scroll_position(&self.display_snapshot)
6195    }
6196}
6197
6198impl Deref for EditorSnapshot {
6199    type Target = DisplaySnapshot;
6200
6201    fn deref(&self) -> &Self::Target {
6202        &self.display_snapshot
6203    }
6204}
6205
6206#[derive(Clone, Debug, PartialEq, Eq)]
6207pub enum Event {
6208    InputIgnored {
6209        text: Arc<str>,
6210    },
6211    ExcerptsAdded {
6212        buffer: ModelHandle<Buffer>,
6213        predecessor: ExcerptId,
6214        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6215    },
6216    ExcerptsRemoved {
6217        ids: Vec<ExcerptId>,
6218    },
6219    BufferEdited,
6220    Edited,
6221    Reparsed,
6222    Blurred,
6223    DirtyChanged,
6224    Saved,
6225    TitleChanged,
6226    SelectionsChanged {
6227        local: bool,
6228    },
6229    ScrollPositionChanged {
6230        local: bool,
6231    },
6232    Closed,
6233}
6234
6235pub struct EditorFocused(pub ViewHandle<Editor>);
6236pub struct EditorBlurred(pub ViewHandle<Editor>);
6237pub struct EditorReleased(pub WeakViewHandle<Editor>);
6238
6239impl Entity for Editor {
6240    type Event = Event;
6241
6242    fn release(&mut self, cx: &mut MutableAppContext) {
6243        cx.emit_global(EditorReleased(self.handle.clone()));
6244    }
6245}
6246
6247impl View for Editor {
6248    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6249        let style = self.style(cx);
6250        let font_changed = self.display_map.update(cx, |map, cx| {
6251            map.set_font(style.text.font_id, style.text.font_size, cx)
6252        });
6253
6254        if font_changed {
6255            let handle = self.handle.clone();
6256            cx.defer(move |cx| {
6257                if let Some(editor) = handle.upgrade(cx) {
6258                    editor.update(cx, |editor, cx| {
6259                        hide_hover(editor, &HideHover, cx);
6260                        hide_link_definition(editor, cx);
6261                    })
6262                }
6263            });
6264        }
6265
6266        Stack::new()
6267            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6268            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6269            .boxed()
6270    }
6271
6272    fn ui_name() -> &'static str {
6273        "Editor"
6274    }
6275
6276    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6277        if cx.is_self_focused() {
6278            let focused_event = EditorFocused(cx.handle());
6279            cx.emit_global(focused_event);
6280        }
6281        if let Some(rename) = self.pending_rename.as_ref() {
6282            cx.focus(&rename.editor);
6283        } else {
6284            if !self.focused {
6285                self.blink_manager.update(cx, BlinkManager::enable);
6286            }
6287            self.focused = true;
6288            self.buffer.update(cx, |buffer, cx| {
6289                buffer.finalize_last_transaction(cx);
6290                if self.leader_replica_id.is_none() {
6291                    buffer.set_active_selections(
6292                        &self.selections.disjoint_anchors(),
6293                        self.selections.line_mode,
6294                        self.cursor_shape,
6295                        cx,
6296                    );
6297                }
6298            });
6299        }
6300    }
6301
6302    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6303        let blurred_event = EditorBlurred(cx.handle());
6304        cx.emit_global(blurred_event);
6305        self.focused = false;
6306        self.blink_manager.update(cx, BlinkManager::disable);
6307        self.buffer
6308            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6309        self.hide_context_menu(cx);
6310        hide_hover(self, &HideHover, cx);
6311        cx.emit(Event::Blurred);
6312        cx.notify();
6313    }
6314
6315    fn modifiers_changed(
6316        &mut self,
6317        event: &gpui::ModifiersChangedEvent,
6318        cx: &mut ViewContext<Self>,
6319    ) -> bool {
6320        let pending_selection = self.has_pending_selection();
6321
6322        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6323            if event.cmd && !pending_selection {
6324                let snapshot = self.snapshot(cx);
6325                let kind = if event.shift {
6326                    LinkDefinitionKind::Type
6327                } else {
6328                    LinkDefinitionKind::Symbol
6329                };
6330
6331                show_link_definition(kind, self, point, snapshot, cx);
6332                return false;
6333            }
6334        }
6335
6336        {
6337            if self.link_go_to_definition_state.symbol_range.is_some()
6338                || !self.link_go_to_definition_state.definitions.is_empty()
6339            {
6340                self.link_go_to_definition_state.symbol_range.take();
6341                self.link_go_to_definition_state.definitions.clear();
6342                cx.notify();
6343            }
6344
6345            self.link_go_to_definition_state.task = None;
6346
6347            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6348        }
6349
6350        false
6351    }
6352
6353    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6354        let mut context = Self::default_keymap_context();
6355        let mode = match self.mode {
6356            EditorMode::SingleLine => "single_line",
6357            EditorMode::AutoHeight { .. } => "auto_height",
6358            EditorMode::Full => "full",
6359        };
6360        context.map.insert("mode".into(), mode.into());
6361        if self.pending_rename.is_some() {
6362            context.set.insert("renaming".into());
6363        }
6364        match self.context_menu.as_ref() {
6365            Some(ContextMenu::Completions(_)) => {
6366                context.set.insert("showing_completions".into());
6367            }
6368            Some(ContextMenu::CodeActions(_)) => {
6369                context.set.insert("showing_code_actions".into());
6370            }
6371            None => {}
6372        }
6373
6374        for layer in self.keymap_context_layers.values() {
6375            context.extend(layer);
6376        }
6377
6378        context
6379    }
6380
6381    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6382        Some(
6383            self.buffer
6384                .read(cx)
6385                .read(cx)
6386                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6387                .collect(),
6388        )
6389    }
6390
6391    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6392        // Prevent the IME menu from appearing when holding down an alphabetic key
6393        // while input is disabled.
6394        if !self.input_enabled {
6395            return None;
6396        }
6397
6398        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6399        Some(range.start.0..range.end.0)
6400    }
6401
6402    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6403        let snapshot = self.buffer.read(cx).read(cx);
6404        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6405        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6406    }
6407
6408    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6409        self.clear_text_highlights::<InputComposition>(cx);
6410        self.ime_transaction.take();
6411    }
6412
6413    fn replace_text_in_range(
6414        &mut self,
6415        range_utf16: Option<Range<usize>>,
6416        text: &str,
6417        cx: &mut ViewContext<Self>,
6418    ) {
6419        self.transact(cx, |this, cx| {
6420            if this.input_enabled {
6421                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6422                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6423                    Some(this.selection_replacement_ranges(range_utf16, cx))
6424                } else {
6425                    this.marked_text_ranges(cx)
6426                };
6427
6428                if let Some(new_selected_ranges) = new_selected_ranges {
6429                    this.change_selections(None, cx, |selections| {
6430                        selections.select_ranges(new_selected_ranges)
6431                    });
6432                }
6433            }
6434
6435            this.handle_input(text, cx);
6436        });
6437
6438        if !self.input_enabled {
6439            return;
6440        }
6441
6442        if let Some(transaction) = self.ime_transaction {
6443            self.buffer.update(cx, |buffer, cx| {
6444                buffer.group_until_transaction(transaction, cx);
6445            });
6446        }
6447
6448        self.unmark_text(cx);
6449    }
6450
6451    fn replace_and_mark_text_in_range(
6452        &mut self,
6453        range_utf16: Option<Range<usize>>,
6454        text: &str,
6455        new_selected_range_utf16: Option<Range<usize>>,
6456        cx: &mut ViewContext<Self>,
6457    ) {
6458        if !self.input_enabled {
6459            return;
6460        }
6461
6462        let transaction = self.transact(cx, |this, cx| {
6463            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6464                let snapshot = this.buffer.read(cx).read(cx);
6465                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6466                    for marked_range in &mut marked_ranges {
6467                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6468                        marked_range.start.0 += relative_range_utf16.start;
6469                        marked_range.start =
6470                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6471                        marked_range.end =
6472                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6473                    }
6474                }
6475                Some(marked_ranges)
6476            } else if let Some(range_utf16) = range_utf16 {
6477                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6478                Some(this.selection_replacement_ranges(range_utf16, cx))
6479            } else {
6480                None
6481            };
6482
6483            if let Some(ranges) = ranges_to_replace {
6484                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6485            }
6486
6487            let marked_ranges = {
6488                let snapshot = this.buffer.read(cx).read(cx);
6489                this.selections
6490                    .disjoint_anchors()
6491                    .iter()
6492                    .map(|selection| {
6493                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6494                    })
6495                    .collect::<Vec<_>>()
6496            };
6497
6498            if text.is_empty() {
6499                this.unmark_text(cx);
6500            } else {
6501                this.highlight_text::<InputComposition>(
6502                    marked_ranges.clone(),
6503                    this.style(cx).composition_mark,
6504                    cx,
6505                );
6506            }
6507
6508            this.handle_input(text, cx);
6509
6510            if let Some(new_selected_range) = new_selected_range_utf16 {
6511                let snapshot = this.buffer.read(cx).read(cx);
6512                let new_selected_ranges = marked_ranges
6513                    .into_iter()
6514                    .map(|marked_range| {
6515                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6516                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6517                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6518                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6519                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6520                    })
6521                    .collect::<Vec<_>>();
6522
6523                drop(snapshot);
6524                this.change_selections(None, cx, |selections| {
6525                    selections.select_ranges(new_selected_ranges)
6526                });
6527            }
6528        });
6529
6530        self.ime_transaction = self.ime_transaction.or(transaction);
6531        if let Some(transaction) = self.ime_transaction {
6532            self.buffer.update(cx, |buffer, cx| {
6533                buffer.group_until_transaction(transaction, cx);
6534            });
6535        }
6536
6537        if self.text_highlights::<InputComposition>(cx).is_none() {
6538            self.ime_transaction.take();
6539        }
6540    }
6541}
6542
6543fn build_style(
6544    settings: &Settings,
6545    get_field_editor_theme: Option<&GetFieldEditorTheme>,
6546    override_text_style: Option<&OverrideTextStyle>,
6547    cx: &AppContext,
6548) -> EditorStyle {
6549    let font_cache = cx.font_cache();
6550
6551    let mut theme = settings.theme.editor.clone();
6552    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6553        let field_editor_theme = get_field_editor_theme(&settings.theme);
6554        theme.text_color = field_editor_theme.text.color;
6555        theme.selection = field_editor_theme.selection;
6556        theme.background = field_editor_theme
6557            .container
6558            .background_color
6559            .unwrap_or_default();
6560        EditorStyle {
6561            text: field_editor_theme.text,
6562            placeholder_text: field_editor_theme.placeholder_text,
6563            theme,
6564        }
6565    } else {
6566        let font_family_id = settings.buffer_font_family;
6567        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6568        let font_properties = Default::default();
6569        let font_id = font_cache
6570            .select_font(font_family_id, &font_properties)
6571            .unwrap();
6572        let font_size = settings.buffer_font_size;
6573        EditorStyle {
6574            text: TextStyle {
6575                color: settings.theme.editor.text_color,
6576                font_family_name,
6577                font_family_id,
6578                font_id,
6579                font_size,
6580                font_properties,
6581                underline: Default::default(),
6582            },
6583            placeholder_text: None,
6584            theme,
6585        }
6586    };
6587
6588    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6589        if let Some(highlighted) = style
6590            .text
6591            .clone()
6592            .highlight(highlight_style, font_cache)
6593            .log_err()
6594        {
6595            style.text = highlighted;
6596        }
6597    }
6598
6599    style
6600}
6601
6602trait SelectionExt {
6603    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6604    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6605    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6606    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6607        -> Range<u32>;
6608}
6609
6610impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6611    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6612        let start = self.start.to_point(buffer);
6613        let end = self.end.to_point(buffer);
6614        if self.reversed {
6615            end..start
6616        } else {
6617            start..end
6618        }
6619    }
6620
6621    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6622        let start = self.start.to_offset(buffer);
6623        let end = self.end.to_offset(buffer);
6624        if self.reversed {
6625            end..start
6626        } else {
6627            start..end
6628        }
6629    }
6630
6631    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6632        let start = self
6633            .start
6634            .to_point(&map.buffer_snapshot)
6635            .to_display_point(map);
6636        let end = self
6637            .end
6638            .to_point(&map.buffer_snapshot)
6639            .to_display_point(map);
6640        if self.reversed {
6641            end..start
6642        } else {
6643            start..end
6644        }
6645    }
6646
6647    fn spanned_rows(
6648        &self,
6649        include_end_if_at_line_start: bool,
6650        map: &DisplaySnapshot,
6651    ) -> Range<u32> {
6652        let start = self.start.to_point(&map.buffer_snapshot);
6653        let mut end = self.end.to_point(&map.buffer_snapshot);
6654        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6655            end.row -= 1;
6656        }
6657
6658        let buffer_start = map.prev_line_boundary(start).0;
6659        let buffer_end = map.next_line_boundary(end).0;
6660        buffer_start.row..buffer_end.row + 1
6661    }
6662}
6663
6664impl<T: InvalidationRegion> InvalidationStack<T> {
6665    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6666    where
6667        S: Clone + ToOffset,
6668    {
6669        while let Some(region) = self.last() {
6670            let all_selections_inside_invalidation_ranges =
6671                if selections.len() == region.ranges().len() {
6672                    selections
6673                        .iter()
6674                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6675                        .all(|(selection, invalidation_range)| {
6676                            let head = selection.head().to_offset(buffer);
6677                            invalidation_range.start <= head && invalidation_range.end >= head
6678                        })
6679                } else {
6680                    false
6681                };
6682
6683            if all_selections_inside_invalidation_ranges {
6684                break;
6685            } else {
6686                self.pop();
6687            }
6688        }
6689    }
6690}
6691
6692impl<T> Default for InvalidationStack<T> {
6693    fn default() -> Self {
6694        Self(Default::default())
6695    }
6696}
6697
6698impl<T> Deref for InvalidationStack<T> {
6699    type Target = Vec<T>;
6700
6701    fn deref(&self) -> &Self::Target {
6702        &self.0
6703    }
6704}
6705
6706impl<T> DerefMut for InvalidationStack<T> {
6707    fn deref_mut(&mut self) -> &mut Self::Target {
6708        &mut self.0
6709    }
6710}
6711
6712impl InvalidationRegion for SnippetState {
6713    fn ranges(&self) -> &[Range<Anchor>] {
6714        &self.ranges[self.active_index]
6715    }
6716}
6717
6718impl Deref for EditorStyle {
6719    type Target = theme::Editor;
6720
6721    fn deref(&self) -> &Self::Target {
6722        &self.theme
6723    }
6724}
6725
6726pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6727    let mut highlighted_lines = Vec::new();
6728    for line in diagnostic.message.lines() {
6729        highlighted_lines.push(highlight_diagnostic_message(line));
6730    }
6731
6732    Arc::new(move |cx: &mut BlockContext| {
6733        let settings = cx.global::<Settings>();
6734        let theme = &settings.theme.editor;
6735        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6736        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6737        Flex::column()
6738            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6739                Label::new(
6740                    line.clone(),
6741                    style.message.clone().with_font_size(font_size),
6742                )
6743                .with_highlights(highlights.clone())
6744                .contained()
6745                .with_margin_left(cx.anchor_x)
6746                .boxed()
6747            }))
6748            .aligned()
6749            .left()
6750            .boxed()
6751    })
6752}
6753
6754pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6755    let mut message_without_backticks = String::new();
6756    let mut prev_offset = 0;
6757    let mut inside_block = false;
6758    let mut highlights = Vec::new();
6759    for (match_ix, (offset, _)) in message
6760        .match_indices('`')
6761        .chain([(message.len(), "")])
6762        .enumerate()
6763    {
6764        message_without_backticks.push_str(&message[prev_offset..offset]);
6765        if inside_block {
6766            highlights.extend(prev_offset - match_ix..offset - match_ix);
6767        }
6768
6769        inside_block = !inside_block;
6770        prev_offset = offset + 1;
6771    }
6772
6773    (message_without_backticks, highlights)
6774}
6775
6776pub fn diagnostic_style(
6777    severity: DiagnosticSeverity,
6778    valid: bool,
6779    theme: &theme::Editor,
6780) -> DiagnosticStyle {
6781    match (severity, valid) {
6782        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6783        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6784        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6785        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6786        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6787        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6788        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6789        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6790        _ => theme.invalid_hint_diagnostic.clone(),
6791    }
6792}
6793
6794pub fn combine_syntax_and_fuzzy_match_highlights(
6795    text: &str,
6796    default_style: HighlightStyle,
6797    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6798    match_indices: &[usize],
6799) -> Vec<(Range<usize>, HighlightStyle)> {
6800    let mut result = Vec::new();
6801    let mut match_indices = match_indices.iter().copied().peekable();
6802
6803    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6804    {
6805        syntax_highlight.weight = None;
6806
6807        // Add highlights for any fuzzy match characters before the next
6808        // syntax highlight range.
6809        while let Some(&match_index) = match_indices.peek() {
6810            if match_index >= range.start {
6811                break;
6812            }
6813            match_indices.next();
6814            let end_index = char_ix_after(match_index, text);
6815            let mut match_style = default_style;
6816            match_style.weight = Some(fonts::Weight::BOLD);
6817            result.push((match_index..end_index, match_style));
6818        }
6819
6820        if range.start == usize::MAX {
6821            break;
6822        }
6823
6824        // Add highlights for any fuzzy match characters within the
6825        // syntax highlight range.
6826        let mut offset = range.start;
6827        while let Some(&match_index) = match_indices.peek() {
6828            if match_index >= range.end {
6829                break;
6830            }
6831
6832            match_indices.next();
6833            if match_index > offset {
6834                result.push((offset..match_index, syntax_highlight));
6835            }
6836
6837            let mut end_index = char_ix_after(match_index, text);
6838            while let Some(&next_match_index) = match_indices.peek() {
6839                if next_match_index == end_index && next_match_index < range.end {
6840                    end_index = char_ix_after(next_match_index, text);
6841                    match_indices.next();
6842                } else {
6843                    break;
6844                }
6845            }
6846
6847            let mut match_style = syntax_highlight;
6848            match_style.weight = Some(fonts::Weight::BOLD);
6849            result.push((match_index..end_index, match_style));
6850            offset = end_index;
6851        }
6852
6853        if offset < range.end {
6854            result.push((offset..range.end, syntax_highlight));
6855        }
6856    }
6857
6858    fn char_ix_after(ix: usize, text: &str) -> usize {
6859        ix + text[ix..].chars().next().unwrap().len_utf8()
6860    }
6861
6862    result
6863}
6864
6865pub fn styled_runs_for_code_label<'a>(
6866    label: &'a CodeLabel,
6867    syntax_theme: &'a theme::SyntaxTheme,
6868) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6869    let fade_out = HighlightStyle {
6870        fade_out: Some(0.35),
6871        ..Default::default()
6872    };
6873
6874    let mut prev_end = label.filter_range.end;
6875    label
6876        .runs
6877        .iter()
6878        .enumerate()
6879        .flat_map(move |(ix, (range, highlight_id))| {
6880            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6881                style
6882            } else {
6883                return Default::default();
6884            };
6885            let mut muted_style = style;
6886            muted_style.highlight(fade_out);
6887
6888            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6889            if range.start >= label.filter_range.end {
6890                if range.start > prev_end {
6891                    runs.push((prev_end..range.start, fade_out));
6892                }
6893                runs.push((range.clone(), muted_style));
6894            } else if range.end <= label.filter_range.end {
6895                runs.push((range.clone(), style));
6896            } else {
6897                runs.push((range.start..label.filter_range.end, style));
6898                runs.push((label.filter_range.end..range.end, muted_style));
6899            }
6900            prev_end = cmp::max(prev_end, range.end);
6901
6902            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6903                runs.push((prev_end..label.text.len(), fade_out));
6904            }
6905
6906            runs
6907        })
6908}
6909
6910pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
6911    let mut index = 0;
6912    let mut codepoints = text.char_indices().peekable();
6913
6914    std::iter::from_fn(move || {
6915        let start_index = index;
6916        while let Some((new_index, codepoint)) = codepoints.next() {
6917            index = new_index + codepoint.len_utf8();
6918            let current_upper = codepoint.is_uppercase();
6919            let next_upper = codepoints
6920                .peek()
6921                .map(|(_, c)| c.is_uppercase())
6922                .unwrap_or(false);
6923
6924            if !current_upper && next_upper {
6925                return Some(&text[start_index..index]);
6926            }
6927        }
6928
6929        index = text.len();
6930        if start_index < text.len() {
6931            return Some(&text[start_index..]);
6932        }
6933        None
6934    })
6935    .flat_map(|word| word.split_inclusive('_'))
6936}
6937
6938trait RangeExt<T> {
6939    fn sorted(&self) -> Range<T>;
6940    fn to_inclusive(&self) -> RangeInclusive<T>;
6941}
6942
6943impl<T: Ord + Clone> RangeExt<T> for Range<T> {
6944    fn sorted(&self) -> Self {
6945        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
6946    }
6947
6948    fn to_inclusive(&self) -> RangeInclusive<T> {
6949        self.start.clone()..=self.end.clone()
6950    }
6951}
6952
6953trait RangeToAnchorExt {
6954    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
6955}
6956
6957impl<T: ToOffset> RangeToAnchorExt for Range<T> {
6958    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
6959        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
6960    }
6961}