editor.rs

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