editor.rs

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