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