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