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