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        dbg!("undo");
3615        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3616            dbg!(tx_id);
3617            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3618                self.change_selections(None, cx, |s| {
3619                    s.select_anchors(selections.to_vec());
3620                });
3621            }
3622            self.request_autoscroll(Autoscroll::fit(), cx);
3623            self.unmark_text(cx);
3624            cx.emit(Event::Edited);
3625        }
3626    }
3627
3628    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3629        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3630            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3631            {
3632                self.change_selections(None, cx, |s| {
3633                    s.select_anchors(selections.to_vec());
3634                });
3635            }
3636            self.request_autoscroll(Autoscroll::fit(), cx);
3637            self.unmark_text(cx);
3638            cx.emit(Event::Edited);
3639        }
3640    }
3641
3642    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3643        self.buffer
3644            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3645    }
3646
3647    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3648        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3649            let line_mode = s.line_mode;
3650            s.move_with(|map, selection| {
3651                let cursor = if selection.is_empty() && !line_mode {
3652                    movement::left(map, selection.start)
3653                } else {
3654                    selection.start
3655                };
3656                selection.collapse_to(cursor, SelectionGoal::None);
3657            });
3658        })
3659    }
3660
3661    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3662        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3663            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3664        })
3665    }
3666
3667    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3668        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3669            let line_mode = s.line_mode;
3670            s.move_with(|map, selection| {
3671                let cursor = if selection.is_empty() && !line_mode {
3672                    movement::right(map, selection.end)
3673                } else {
3674                    selection.end
3675                };
3676                selection.collapse_to(cursor, SelectionGoal::None)
3677            });
3678        })
3679    }
3680
3681    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3682        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3683            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3684        })
3685    }
3686
3687    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3688        if self.take_rename(true, cx).is_some() {
3689            return;
3690        }
3691
3692        if let Some(context_menu) = self.context_menu.as_mut() {
3693            if context_menu.select_prev(cx) {
3694                return;
3695            }
3696        }
3697
3698        if matches!(self.mode, EditorMode::SingleLine) {
3699            cx.propagate_action();
3700            return;
3701        }
3702
3703        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3704            let line_mode = s.line_mode;
3705            s.move_with(|map, selection| {
3706                if !selection.is_empty() && !line_mode {
3707                    selection.goal = SelectionGoal::None;
3708                }
3709                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
3710                selection.collapse_to(cursor, goal);
3711            });
3712        })
3713    }
3714
3715    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
3716        if self.take_rename(true, cx).is_some() {
3717            return;
3718        }
3719
3720        if self
3721            .context_menu
3722            .as_mut()
3723            .map(|menu| menu.select_first(cx))
3724            .unwrap_or(false)
3725        {
3726            return;
3727        }
3728
3729        if matches!(self.mode, EditorMode::SingleLine) {
3730            cx.propagate_action();
3731            return;
3732        }
3733
3734        let row_count = if let Some(row_count) = self.visible_line_count() {
3735            row_count as u32 - 1
3736        } else {
3737            return;
3738        };
3739
3740        let autoscroll = if action.center_cursor {
3741            Autoscroll::center()
3742        } else {
3743            Autoscroll::fit()
3744        };
3745
3746        self.change_selections(Some(autoscroll), cx, |s| {
3747            let line_mode = s.line_mode;
3748            s.move_with(|map, selection| {
3749                if !selection.is_empty() && !line_mode {
3750                    selection.goal = SelectionGoal::None;
3751                }
3752                let (cursor, goal) =
3753                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
3754                selection.collapse_to(cursor, goal);
3755            });
3756        });
3757    }
3758
3759    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3760        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3761            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3762        })
3763    }
3764
3765    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3766        self.take_rename(true, cx);
3767
3768        if let Some(context_menu) = self.context_menu.as_mut() {
3769            if context_menu.select_next(cx) {
3770                return;
3771            }
3772        }
3773
3774        if matches!(self.mode, EditorMode::SingleLine) {
3775            cx.propagate_action();
3776            return;
3777        }
3778
3779        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3780            let line_mode = s.line_mode;
3781            s.move_with(|map, selection| {
3782                if !selection.is_empty() && !line_mode {
3783                    selection.goal = SelectionGoal::None;
3784                }
3785                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
3786                selection.collapse_to(cursor, goal);
3787            });
3788        });
3789    }
3790
3791    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
3792        if self.take_rename(true, cx).is_some() {
3793            return;
3794        }
3795
3796        if self
3797            .context_menu
3798            .as_mut()
3799            .map(|menu| menu.select_last(cx))
3800            .unwrap_or(false)
3801        {
3802            return;
3803        }
3804
3805        if matches!(self.mode, EditorMode::SingleLine) {
3806            cx.propagate_action();
3807            return;
3808        }
3809
3810        let row_count = if let Some(row_count) = self.visible_line_count() {
3811            row_count as u32 - 1
3812        } else {
3813            return;
3814        };
3815
3816        let autoscroll = if action.center_cursor {
3817            Autoscroll::center()
3818        } else {
3819            Autoscroll::fit()
3820        };
3821
3822        self.change_selections(Some(autoscroll), cx, |s| {
3823            let line_mode = s.line_mode;
3824            s.move_with(|map, selection| {
3825                if !selection.is_empty() && !line_mode {
3826                    selection.goal = SelectionGoal::None;
3827                }
3828                let (cursor, goal) =
3829                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
3830                selection.collapse_to(cursor, goal);
3831            });
3832        });
3833    }
3834
3835    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3836        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3837            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3838        });
3839    }
3840
3841    pub fn move_to_previous_word_start(
3842        &mut self,
3843        _: &MoveToPreviousWordStart,
3844        cx: &mut ViewContext<Self>,
3845    ) {
3846        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3847            s.move_cursors_with(|map, head, _| {
3848                (
3849                    movement::previous_word_start(map, head),
3850                    SelectionGoal::None,
3851                )
3852            });
3853        })
3854    }
3855
3856    pub fn move_to_previous_subword_start(
3857        &mut self,
3858        _: &MoveToPreviousSubwordStart,
3859        cx: &mut ViewContext<Self>,
3860    ) {
3861        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3862            s.move_cursors_with(|map, head, _| {
3863                (
3864                    movement::previous_subword_start(map, head),
3865                    SelectionGoal::None,
3866                )
3867            });
3868        })
3869    }
3870
3871    pub fn select_to_previous_word_start(
3872        &mut self,
3873        _: &SelectToPreviousWordStart,
3874        cx: &mut ViewContext<Self>,
3875    ) {
3876        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3877            s.move_heads_with(|map, head, _| {
3878                (
3879                    movement::previous_word_start(map, head),
3880                    SelectionGoal::None,
3881                )
3882            });
3883        })
3884    }
3885
3886    pub fn select_to_previous_subword_start(
3887        &mut self,
3888        _: &SelectToPreviousSubwordStart,
3889        cx: &mut ViewContext<Self>,
3890    ) {
3891        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3892            s.move_heads_with(|map, head, _| {
3893                (
3894                    movement::previous_subword_start(map, head),
3895                    SelectionGoal::None,
3896                )
3897            });
3898        })
3899    }
3900
3901    pub fn delete_to_previous_word_start(
3902        &mut self,
3903        _: &DeleteToPreviousWordStart,
3904        cx: &mut ViewContext<Self>,
3905    ) {
3906        self.transact(cx, |this, cx| {
3907            this.select_autoclose_pair(cx);
3908            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3909                let line_mode = s.line_mode;
3910                s.move_with(|map, selection| {
3911                    if selection.is_empty() && !line_mode {
3912                        let cursor = movement::previous_word_start(map, selection.head());
3913                        selection.set_head(cursor, SelectionGoal::None);
3914                    }
3915                });
3916            });
3917            this.insert("", cx);
3918        });
3919    }
3920
3921    pub fn delete_to_previous_subword_start(
3922        &mut self,
3923        _: &DeleteToPreviousSubwordStart,
3924        cx: &mut ViewContext<Self>,
3925    ) {
3926        self.transact(cx, |this, cx| {
3927            this.select_autoclose_pair(cx);
3928            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3929                let line_mode = s.line_mode;
3930                s.move_with(|map, selection| {
3931                    if selection.is_empty() && !line_mode {
3932                        let cursor = movement::previous_subword_start(map, selection.head());
3933                        selection.set_head(cursor, SelectionGoal::None);
3934                    }
3935                });
3936            });
3937            this.insert("", cx);
3938        });
3939    }
3940
3941    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
3942        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3943            s.move_cursors_with(|map, head, _| {
3944                (movement::next_word_end(map, head), SelectionGoal::None)
3945            });
3946        })
3947    }
3948
3949    pub fn move_to_next_subword_end(
3950        &mut self,
3951        _: &MoveToNextSubwordEnd,
3952        cx: &mut ViewContext<Self>,
3953    ) {
3954        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3955            s.move_cursors_with(|map, head, _| {
3956                (movement::next_subword_end(map, head), SelectionGoal::None)
3957            });
3958        })
3959    }
3960
3961    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
3962        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3963            s.move_heads_with(|map, head, _| {
3964                (movement::next_word_end(map, head), SelectionGoal::None)
3965            });
3966        })
3967    }
3968
3969    pub fn select_to_next_subword_end(
3970        &mut self,
3971        _: &SelectToNextSubwordEnd,
3972        cx: &mut ViewContext<Self>,
3973    ) {
3974        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3975            s.move_heads_with(|map, head, _| {
3976                (movement::next_subword_end(map, head), SelectionGoal::None)
3977            });
3978        })
3979    }
3980
3981    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
3982        self.transact(cx, |this, cx| {
3983            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3984                let line_mode = s.line_mode;
3985                s.move_with(|map, selection| {
3986                    if selection.is_empty() && !line_mode {
3987                        let cursor = movement::next_word_end(map, selection.head());
3988                        selection.set_head(cursor, SelectionGoal::None);
3989                    }
3990                });
3991            });
3992            this.insert("", cx);
3993        });
3994    }
3995
3996    pub fn delete_to_next_subword_end(
3997        &mut self,
3998        _: &DeleteToNextSubwordEnd,
3999        cx: &mut ViewContext<Self>,
4000    ) {
4001        self.transact(cx, |this, cx| {
4002            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4003                s.move_with(|map, selection| {
4004                    if selection.is_empty() {
4005                        let cursor = movement::next_subword_end(map, selection.head());
4006                        selection.set_head(cursor, SelectionGoal::None);
4007                    }
4008                });
4009            });
4010            this.insert("", cx);
4011        });
4012    }
4013
4014    pub fn move_to_beginning_of_line(
4015        &mut self,
4016        _: &MoveToBeginningOfLine,
4017        cx: &mut ViewContext<Self>,
4018    ) {
4019        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4020            s.move_cursors_with(|map, head, _| {
4021                (
4022                    movement::indented_line_beginning(map, head, true),
4023                    SelectionGoal::None,
4024                )
4025            });
4026        })
4027    }
4028
4029    pub fn select_to_beginning_of_line(
4030        &mut self,
4031        action: &SelectToBeginningOfLine,
4032        cx: &mut ViewContext<Self>,
4033    ) {
4034        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4035            s.move_heads_with(|map, head, _| {
4036                (
4037                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4038                    SelectionGoal::None,
4039                )
4040            });
4041        });
4042    }
4043
4044    pub fn delete_to_beginning_of_line(
4045        &mut self,
4046        _: &DeleteToBeginningOfLine,
4047        cx: &mut ViewContext<Self>,
4048    ) {
4049        self.transact(cx, |this, cx| {
4050            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4051                s.move_with(|_, selection| {
4052                    selection.reversed = true;
4053                });
4054            });
4055
4056            this.select_to_beginning_of_line(
4057                &SelectToBeginningOfLine {
4058                    stop_at_soft_wraps: false,
4059                },
4060                cx,
4061            );
4062            this.backspace(&Backspace, cx);
4063        });
4064    }
4065
4066    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4067        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4068            s.move_cursors_with(|map, head, _| {
4069                (movement::line_end(map, head, true), SelectionGoal::None)
4070            });
4071        })
4072    }
4073
4074    pub fn select_to_end_of_line(
4075        &mut self,
4076        action: &SelectToEndOfLine,
4077        cx: &mut ViewContext<Self>,
4078    ) {
4079        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4080            s.move_heads_with(|map, head, _| {
4081                (
4082                    movement::line_end(map, head, action.stop_at_soft_wraps),
4083                    SelectionGoal::None,
4084                )
4085            });
4086        })
4087    }
4088
4089    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4090        self.transact(cx, |this, cx| {
4091            this.select_to_end_of_line(
4092                &SelectToEndOfLine {
4093                    stop_at_soft_wraps: false,
4094                },
4095                cx,
4096            );
4097            this.delete(&Delete, cx);
4098        });
4099    }
4100
4101    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4102        self.transact(cx, |this, cx| {
4103            this.select_to_end_of_line(
4104                &SelectToEndOfLine {
4105                    stop_at_soft_wraps: false,
4106                },
4107                cx,
4108            );
4109            this.cut(&Cut, cx);
4110        });
4111    }
4112
4113    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4114        if matches!(self.mode, EditorMode::SingleLine) {
4115            cx.propagate_action();
4116            return;
4117        }
4118
4119        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4120            s.select_ranges(vec![0..0]);
4121        });
4122    }
4123
4124    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4125        let mut selection = self.selections.last::<Point>(cx);
4126        selection.set_head(Point::zero(), SelectionGoal::None);
4127
4128        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4129            s.select(vec![selection]);
4130        });
4131    }
4132
4133    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4134        if matches!(self.mode, EditorMode::SingleLine) {
4135            cx.propagate_action();
4136            return;
4137        }
4138
4139        let cursor = self.buffer.read(cx).read(cx).len();
4140        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4141            s.select_ranges(vec![cursor..cursor])
4142        });
4143    }
4144
4145    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4146        self.nav_history = nav_history;
4147    }
4148
4149    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4150        self.nav_history.as_ref()
4151    }
4152
4153    fn push_to_nav_history(
4154        &self,
4155        cursor_anchor: Anchor,
4156        new_position: Option<Point>,
4157        cx: &mut ViewContext<Self>,
4158    ) {
4159        if let Some(nav_history) = &self.nav_history {
4160            let buffer = self.buffer.read(cx).read(cx);
4161            let cursor_position = cursor_anchor.to_point(&buffer);
4162            let scroll_state = self.scroll_manager.anchor();
4163            let scroll_top_row = scroll_state.top_row(&buffer);
4164            drop(buffer);
4165
4166            if let Some(new_position) = new_position {
4167                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4168                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4169                    return;
4170                }
4171            }
4172
4173            nav_history.push(
4174                Some(NavigationData {
4175                    cursor_anchor,
4176                    cursor_position,
4177                    scroll_anchor: scroll_state,
4178                    scroll_top_row,
4179                }),
4180                cx,
4181            );
4182        }
4183    }
4184
4185    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4186        let buffer = self.buffer.read(cx).snapshot(cx);
4187        let mut selection = self.selections.first::<usize>(cx);
4188        selection.set_head(buffer.len(), SelectionGoal::None);
4189        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4190            s.select(vec![selection]);
4191        });
4192    }
4193
4194    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4195        let end = self.buffer.read(cx).read(cx).len();
4196        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4197            s.select_ranges(vec![0..end]);
4198        });
4199    }
4200
4201    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4202        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4203        let mut selections = self.selections.all::<Point>(cx);
4204        let max_point = display_map.buffer_snapshot.max_point();
4205        for selection in &mut selections {
4206            let rows = selection.spanned_rows(true, &display_map);
4207            selection.start = Point::new(rows.start, 0);
4208            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4209            selection.reversed = false;
4210        }
4211        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4212            s.select(selections);
4213        });
4214    }
4215
4216    pub fn split_selection_into_lines(
4217        &mut self,
4218        _: &SplitSelectionIntoLines,
4219        cx: &mut ViewContext<Self>,
4220    ) {
4221        let mut to_unfold = Vec::new();
4222        let mut new_selection_ranges = Vec::new();
4223        {
4224            let selections = self.selections.all::<Point>(cx);
4225            let buffer = self.buffer.read(cx).read(cx);
4226            for selection in selections {
4227                for row in selection.start.row..selection.end.row {
4228                    let cursor = Point::new(row, buffer.line_len(row));
4229                    new_selection_ranges.push(cursor..cursor);
4230                }
4231                new_selection_ranges.push(selection.end..selection.end);
4232                to_unfold.push(selection.start..selection.end);
4233            }
4234        }
4235        self.unfold_ranges(to_unfold, true, cx);
4236        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4237            s.select_ranges(new_selection_ranges);
4238        });
4239    }
4240
4241    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4242        self.add_selection(true, cx);
4243    }
4244
4245    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4246        self.add_selection(false, cx);
4247    }
4248
4249    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4250        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4251        let mut selections = self.selections.all::<Point>(cx);
4252        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4253            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4254            let range = oldest_selection.display_range(&display_map).sorted();
4255            let columns = cmp::min(range.start.column(), range.end.column())
4256                ..cmp::max(range.start.column(), range.end.column());
4257
4258            selections.clear();
4259            let mut stack = Vec::new();
4260            for row in range.start.row()..=range.end.row() {
4261                if let Some(selection) = self.selections.build_columnar_selection(
4262                    &display_map,
4263                    row,
4264                    &columns,
4265                    oldest_selection.reversed,
4266                ) {
4267                    stack.push(selection.id);
4268                    selections.push(selection);
4269                }
4270            }
4271
4272            if above {
4273                stack.reverse();
4274            }
4275
4276            AddSelectionsState { above, stack }
4277        });
4278
4279        let last_added_selection = *state.stack.last().unwrap();
4280        let mut new_selections = Vec::new();
4281        if above == state.above {
4282            let end_row = if above {
4283                0
4284            } else {
4285                display_map.max_point().row()
4286            };
4287
4288            'outer: for selection in selections {
4289                if selection.id == last_added_selection {
4290                    let range = selection.display_range(&display_map).sorted();
4291                    debug_assert_eq!(range.start.row(), range.end.row());
4292                    let mut row = range.start.row();
4293                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4294                    {
4295                        start..end
4296                    } else {
4297                        cmp::min(range.start.column(), range.end.column())
4298                            ..cmp::max(range.start.column(), range.end.column())
4299                    };
4300
4301                    while row != end_row {
4302                        if above {
4303                            row -= 1;
4304                        } else {
4305                            row += 1;
4306                        }
4307
4308                        if let Some(new_selection) = self.selections.build_columnar_selection(
4309                            &display_map,
4310                            row,
4311                            &columns,
4312                            selection.reversed,
4313                        ) {
4314                            state.stack.push(new_selection.id);
4315                            if above {
4316                                new_selections.push(new_selection);
4317                                new_selections.push(selection);
4318                            } else {
4319                                new_selections.push(selection);
4320                                new_selections.push(new_selection);
4321                            }
4322
4323                            continue 'outer;
4324                        }
4325                    }
4326                }
4327
4328                new_selections.push(selection);
4329            }
4330        } else {
4331            new_selections = selections;
4332            new_selections.retain(|s| s.id != last_added_selection);
4333            state.stack.pop();
4334        }
4335
4336        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4337            s.select(new_selections);
4338        });
4339        if state.stack.len() > 1 {
4340            self.add_selections_state = Some(state);
4341        }
4342    }
4343
4344    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4345        self.push_to_selection_history();
4346        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4347        let buffer = &display_map.buffer_snapshot;
4348        let mut selections = self.selections.all::<usize>(cx);
4349        if let Some(mut select_next_state) = self.select_next_state.take() {
4350            let query = &select_next_state.query;
4351            if !select_next_state.done {
4352                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4353                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4354                let mut next_selected_range = None;
4355
4356                let bytes_after_last_selection =
4357                    buffer.bytes_in_range(last_selection.end..buffer.len());
4358                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4359                let query_matches = query
4360                    .stream_find_iter(bytes_after_last_selection)
4361                    .map(|result| (last_selection.end, result))
4362                    .chain(
4363                        query
4364                            .stream_find_iter(bytes_before_first_selection)
4365                            .map(|result| (0, result)),
4366                    );
4367                for (start_offset, query_match) in query_matches {
4368                    let query_match = query_match.unwrap(); // can only fail due to I/O
4369                    let offset_range =
4370                        start_offset + query_match.start()..start_offset + query_match.end();
4371                    let display_range = offset_range.start.to_display_point(&display_map)
4372                        ..offset_range.end.to_display_point(&display_map);
4373
4374                    if !select_next_state.wordwise
4375                        || (!movement::is_inside_word(&display_map, display_range.start)
4376                            && !movement::is_inside_word(&display_map, display_range.end))
4377                    {
4378                        next_selected_range = Some(offset_range);
4379                        break;
4380                    }
4381                }
4382
4383                if let Some(next_selected_range) = next_selected_range {
4384                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4385                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4386                        if action.replace_newest {
4387                            s.delete(s.newest_anchor().id);
4388                        }
4389                        s.insert_range(next_selected_range);
4390                    });
4391                } else {
4392                    select_next_state.done = true;
4393                }
4394            }
4395
4396            self.select_next_state = Some(select_next_state);
4397        } else if selections.len() == 1 {
4398            let selection = selections.last_mut().unwrap();
4399            if selection.start == selection.end {
4400                let word_range = movement::surrounding_word(
4401                    &display_map,
4402                    selection.start.to_display_point(&display_map),
4403                );
4404                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4405                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4406                selection.goal = SelectionGoal::None;
4407                selection.reversed = false;
4408
4409                let query = buffer
4410                    .text_for_range(selection.start..selection.end)
4411                    .collect::<String>();
4412                let select_state = SelectNextState {
4413                    query: AhoCorasick::new_auto_configured(&[query]),
4414                    wordwise: true,
4415                    done: false,
4416                };
4417                self.unfold_ranges([selection.start..selection.end], false, cx);
4418                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4419                    s.select(selections);
4420                });
4421                self.select_next_state = Some(select_state);
4422            } else {
4423                let query = buffer
4424                    .text_for_range(selection.start..selection.end)
4425                    .collect::<String>();
4426                self.select_next_state = Some(SelectNextState {
4427                    query: AhoCorasick::new_auto_configured(&[query]),
4428                    wordwise: false,
4429                    done: false,
4430                });
4431                self.select_next(action, cx);
4432            }
4433        }
4434    }
4435
4436    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4437        self.transact(cx, |this, cx| {
4438            let mut selections = this.selections.all::<Point>(cx);
4439            let mut edits = Vec::new();
4440            let mut selection_edit_ranges = Vec::new();
4441            let mut last_toggled_row = None;
4442            let snapshot = this.buffer.read(cx).read(cx);
4443            let empty_str: Arc<str> = "".into();
4444            let mut suffixes_inserted = Vec::new();
4445
4446            fn comment_prefix_range(
4447                snapshot: &MultiBufferSnapshot,
4448                row: u32,
4449                comment_prefix: &str,
4450                comment_prefix_whitespace: &str,
4451            ) -> Range<Point> {
4452                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4453
4454                let mut line_bytes = snapshot
4455                    .bytes_in_range(start..snapshot.max_point())
4456                    .flatten()
4457                    .copied();
4458
4459                // If this line currently begins with the line comment prefix, then record
4460                // the range containing the prefix.
4461                if line_bytes
4462                    .by_ref()
4463                    .take(comment_prefix.len())
4464                    .eq(comment_prefix.bytes())
4465                {
4466                    // Include any whitespace that matches the comment prefix.
4467                    let matching_whitespace_len = line_bytes
4468                        .zip(comment_prefix_whitespace.bytes())
4469                        .take_while(|(a, b)| a == b)
4470                        .count() as u32;
4471                    let end = Point::new(
4472                        start.row,
4473                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4474                    );
4475                    start..end
4476                } else {
4477                    start..start
4478                }
4479            }
4480
4481            fn comment_suffix_range(
4482                snapshot: &MultiBufferSnapshot,
4483                row: u32,
4484                comment_suffix: &str,
4485                comment_suffix_has_leading_space: bool,
4486            ) -> Range<Point> {
4487                let end = Point::new(row, snapshot.line_len(row));
4488                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4489
4490                let mut line_end_bytes = snapshot
4491                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4492                    .flatten()
4493                    .copied();
4494
4495                let leading_space_len = if suffix_start_column > 0
4496                    && line_end_bytes.next() == Some(b' ')
4497                    && comment_suffix_has_leading_space
4498                {
4499                    1
4500                } else {
4501                    0
4502                };
4503
4504                // If this line currently begins with the line comment prefix, then record
4505                // the range containing the prefix.
4506                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4507                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4508                    start..end
4509                } else {
4510                    end..end
4511                }
4512            }
4513
4514            // TODO: Handle selections that cross excerpts
4515            for selection in &mut selections {
4516                let language = if let Some(language) = snapshot.language_at(selection.start) {
4517                    language
4518                } else {
4519                    continue;
4520                };
4521
4522                selection_edit_ranges.clear();
4523
4524                // If multiple selections contain a given row, avoid processing that
4525                // row more than once.
4526                let mut start_row = selection.start.row;
4527                if last_toggled_row == Some(start_row) {
4528                    start_row += 1;
4529                }
4530                let end_row =
4531                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4532                        selection.end.row - 1
4533                    } else {
4534                        selection.end.row
4535                    };
4536                last_toggled_row = Some(end_row);
4537
4538                if start_row > end_row {
4539                    continue;
4540                }
4541
4542                // If the language has line comments, toggle those.
4543                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4544                    // Split the comment prefix's trailing whitespace into a separate string,
4545                    // as that portion won't be used for detecting if a line is a comment.
4546                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4547                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4548                    let mut all_selection_lines_are_comments = true;
4549
4550                    for row in start_row..=end_row {
4551                        if snapshot.is_line_blank(row) {
4552                            continue;
4553                        }
4554
4555                        let prefix_range = comment_prefix_range(
4556                            snapshot.deref(),
4557                            row,
4558                            comment_prefix,
4559                            comment_prefix_whitespace,
4560                        );
4561                        if prefix_range.is_empty() {
4562                            all_selection_lines_are_comments = false;
4563                        }
4564                        selection_edit_ranges.push(prefix_range);
4565                    }
4566
4567                    if all_selection_lines_are_comments {
4568                        edits.extend(
4569                            selection_edit_ranges
4570                                .iter()
4571                                .cloned()
4572                                .map(|range| (range, empty_str.clone())),
4573                        );
4574                    } else {
4575                        let min_column = selection_edit_ranges
4576                            .iter()
4577                            .map(|r| r.start.column)
4578                            .min()
4579                            .unwrap_or(0);
4580                        edits.extend(selection_edit_ranges.iter().map(|range| {
4581                            let position = Point::new(range.start.row, min_column);
4582                            (position..position, full_comment_prefix.clone())
4583                        }));
4584                    }
4585                } else if let Some((full_comment_prefix, comment_suffix)) =
4586                    language.block_comment_delimiters()
4587                {
4588                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4589                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4590                    let prefix_range = comment_prefix_range(
4591                        snapshot.deref(),
4592                        start_row,
4593                        comment_prefix,
4594                        comment_prefix_whitespace,
4595                    );
4596                    let suffix_range = comment_suffix_range(
4597                        snapshot.deref(),
4598                        end_row,
4599                        comment_suffix.trim_start_matches(' '),
4600                        comment_suffix.starts_with(' '),
4601                    );
4602
4603                    if prefix_range.is_empty() || suffix_range.is_empty() {
4604                        edits.push((
4605                            prefix_range.start..prefix_range.start,
4606                            full_comment_prefix.clone(),
4607                        ));
4608                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4609                        suffixes_inserted.push((end_row, comment_suffix.len()));
4610                    } else {
4611                        edits.push((prefix_range, empty_str.clone()));
4612                        edits.push((suffix_range, empty_str.clone()));
4613                    }
4614                } else {
4615                    continue;
4616                }
4617            }
4618
4619            drop(snapshot);
4620            this.buffer.update(cx, |buffer, cx| {
4621                buffer.edit(edits, None, cx);
4622            });
4623
4624            // Adjust selections so that they end before any comment suffixes that
4625            // were inserted.
4626            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4627            let mut selections = this.selections.all::<Point>(cx);
4628            let snapshot = this.buffer.read(cx).read(cx);
4629            for selection in &mut selections {
4630                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
4631                    match row.cmp(&selection.end.row) {
4632                        Ordering::Less => {
4633                            suffixes_inserted.next();
4634                            continue;
4635                        }
4636                        Ordering::Greater => break,
4637                        Ordering::Equal => {
4638                            if selection.end.column == snapshot.line_len(row) {
4639                                if selection.is_empty() {
4640                                    selection.start.column -= suffix_len as u32;
4641                                }
4642                                selection.end.column -= suffix_len as u32;
4643                            }
4644                            break;
4645                        }
4646                    }
4647                }
4648            }
4649
4650            drop(snapshot);
4651            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4652        });
4653    }
4654
4655    pub fn select_larger_syntax_node(
4656        &mut self,
4657        _: &SelectLargerSyntaxNode,
4658        cx: &mut ViewContext<Self>,
4659    ) {
4660        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4661        let buffer = self.buffer.read(cx).snapshot(cx);
4662        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4663
4664        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4665        let mut selected_larger_node = false;
4666        let new_selections = old_selections
4667            .iter()
4668            .map(|selection| {
4669                let old_range = selection.start..selection.end;
4670                let mut new_range = old_range.clone();
4671                while let Some(containing_range) =
4672                    buffer.range_for_syntax_ancestor(new_range.clone())
4673                {
4674                    new_range = containing_range;
4675                    if !display_map.intersects_fold(new_range.start)
4676                        && !display_map.intersects_fold(new_range.end)
4677                    {
4678                        break;
4679                    }
4680                }
4681
4682                selected_larger_node |= new_range != old_range;
4683                Selection {
4684                    id: selection.id,
4685                    start: new_range.start,
4686                    end: new_range.end,
4687                    goal: SelectionGoal::None,
4688                    reversed: selection.reversed,
4689                }
4690            })
4691            .collect::<Vec<_>>();
4692
4693        if selected_larger_node {
4694            stack.push(old_selections);
4695            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4696                s.select(new_selections);
4697            });
4698        }
4699        self.select_larger_syntax_node_stack = stack;
4700    }
4701
4702    pub fn select_smaller_syntax_node(
4703        &mut self,
4704        _: &SelectSmallerSyntaxNode,
4705        cx: &mut ViewContext<Self>,
4706    ) {
4707        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4708        if let Some(selections) = stack.pop() {
4709            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4710                s.select(selections.to_vec());
4711            });
4712        }
4713        self.select_larger_syntax_node_stack = stack;
4714    }
4715
4716    pub fn move_to_enclosing_bracket(
4717        &mut self,
4718        _: &MoveToEnclosingBracket,
4719        cx: &mut ViewContext<Self>,
4720    ) {
4721        let buffer = self.buffer.read(cx).snapshot(cx);
4722        let mut selections = self.selections.all::<usize>(cx);
4723        for selection in &mut selections {
4724            if let Some((open_range, close_range)) =
4725                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4726            {
4727                let close_range = close_range.to_inclusive();
4728                let destination = if close_range.contains(&selection.start)
4729                    && close_range.contains(&selection.end)
4730                {
4731                    open_range.end
4732                } else {
4733                    *close_range.start()
4734                };
4735                selection.start = destination;
4736                selection.end = destination;
4737            }
4738        }
4739
4740        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4741            s.select(selections);
4742        });
4743    }
4744
4745    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4746        self.end_selection(cx);
4747        self.selection_history.mode = SelectionHistoryMode::Undoing;
4748        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4749            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4750            self.select_next_state = entry.select_next_state;
4751            self.add_selections_state = entry.add_selections_state;
4752            self.request_autoscroll(Autoscroll::newest(), cx);
4753        }
4754        self.selection_history.mode = SelectionHistoryMode::Normal;
4755    }
4756
4757    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4758        self.end_selection(cx);
4759        self.selection_history.mode = SelectionHistoryMode::Redoing;
4760        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4761            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4762            self.select_next_state = entry.select_next_state;
4763            self.add_selections_state = entry.add_selections_state;
4764            self.request_autoscroll(Autoscroll::newest(), cx);
4765        }
4766        self.selection_history.mode = SelectionHistoryMode::Normal;
4767    }
4768
4769    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
4770        self.go_to_diagnostic_impl(Direction::Next, cx)
4771    }
4772
4773    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4774        self.go_to_diagnostic_impl(Direction::Prev, cx)
4775    }
4776
4777    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4778        let buffer = self.buffer.read(cx).snapshot(cx);
4779        let selection = self.selections.newest::<usize>(cx);
4780
4781        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
4782        if direction == Direction::Next {
4783            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
4784                let (group_id, jump_to) = popover.activation_info();
4785                if self.activate_diagnostics(group_id, cx) {
4786                    self.change_selections(Some(Autoscroll::center()), cx, |s| {
4787                        let mut new_selection = s.newest_anchor().clone();
4788                        new_selection.collapse_to(jump_to, SelectionGoal::None);
4789                        s.select_anchors(vec![new_selection.clone()]);
4790                    });
4791                }
4792                return;
4793            }
4794        }
4795
4796        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4797            active_diagnostics
4798                .primary_range
4799                .to_offset(&buffer)
4800                .to_inclusive()
4801        });
4802        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4803            if active_primary_range.contains(&selection.head()) {
4804                *active_primary_range.end()
4805            } else {
4806                selection.head()
4807            }
4808        } else {
4809            selection.head()
4810        };
4811
4812        loop {
4813            let mut diagnostics = if direction == Direction::Prev {
4814                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4815            } else {
4816                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4817            };
4818            let group = diagnostics.find_map(|entry| {
4819                if entry.diagnostic.is_primary
4820                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4821                    && !entry.range.is_empty()
4822                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4823                {
4824                    Some((entry.range, entry.diagnostic.group_id))
4825                } else {
4826                    None
4827                }
4828            });
4829
4830            if let Some((primary_range, group_id)) = group {
4831                if self.activate_diagnostics(group_id, cx) {
4832                    self.change_selections(Some(Autoscroll::center()), cx, |s| {
4833                        s.select(vec![Selection {
4834                            id: selection.id,
4835                            start: primary_range.start,
4836                            end: primary_range.start,
4837                            reversed: false,
4838                            goal: SelectionGoal::None,
4839                        }]);
4840                    });
4841                }
4842                break;
4843            } else {
4844                // Cycle around to the start of the buffer, potentially moving back to the start of
4845                // the currently active diagnostic.
4846                active_primary_range.take();
4847                if direction == Direction::Prev {
4848                    if search_start == buffer.len() {
4849                        break;
4850                    } else {
4851                        search_start = buffer.len();
4852                    }
4853                } else if search_start == 0 {
4854                    break;
4855                } else {
4856                    search_start = 0;
4857                }
4858            }
4859        }
4860    }
4861
4862    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
4863        self.go_to_hunk_impl(Direction::Next, cx)
4864    }
4865
4866    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
4867        self.go_to_hunk_impl(Direction::Prev, cx)
4868    }
4869
4870    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4871        let snapshot = self
4872            .display_map
4873            .update(cx, |display_map, cx| display_map.snapshot(cx));
4874        let selection = self.selections.newest::<Point>(cx);
4875
4876        fn seek_in_direction(
4877            this: &mut Editor,
4878            snapshot: &DisplaySnapshot,
4879            initial_point: Point,
4880            is_wrapped: bool,
4881            direction: Direction,
4882            cx: &mut ViewContext<Editor>,
4883        ) -> bool {
4884            let hunks = if direction == Direction::Next {
4885                snapshot
4886                    .buffer_snapshot
4887                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
4888            } else {
4889                snapshot
4890                    .buffer_snapshot
4891                    .git_diff_hunks_in_range(0..initial_point.row, true)
4892            };
4893
4894            let display_point = initial_point.to_display_point(snapshot);
4895            let mut hunks = hunks
4896                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
4897                .skip_while(|hunk| {
4898                    if is_wrapped {
4899                        false
4900                    } else {
4901                        hunk.contains_display_row(display_point.row())
4902                    }
4903                })
4904                .dedup();
4905
4906            if let Some(hunk) = hunks.next() {
4907                this.change_selections(Some(Autoscroll::center()), cx, |s| {
4908                    let row = hunk.start_display_row();
4909                    let point = DisplayPoint::new(row, 0);
4910                    s.select_display_ranges([point..point]);
4911                });
4912
4913                true
4914            } else {
4915                false
4916            }
4917        }
4918
4919        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
4920            let wrapped_point = match direction {
4921                Direction::Next => Point::zero(),
4922                Direction::Prev => snapshot.buffer_snapshot.max_point(),
4923            };
4924            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
4925        }
4926    }
4927
4928    pub fn go_to_definition(
4929        workspace: &mut Workspace,
4930        _: &GoToDefinition,
4931        cx: &mut ViewContext<Workspace>,
4932    ) {
4933        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
4934    }
4935
4936    pub fn go_to_type_definition(
4937        workspace: &mut Workspace,
4938        _: &GoToTypeDefinition,
4939        cx: &mut ViewContext<Workspace>,
4940    ) {
4941        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
4942    }
4943
4944    fn go_to_definition_of_kind(
4945        kind: GotoDefinitionKind,
4946        workspace: &mut Workspace,
4947        cx: &mut ViewContext<Workspace>,
4948    ) {
4949        let active_item = workspace.active_item(cx);
4950        let editor_handle = if let Some(editor) = active_item
4951            .as_ref()
4952            .and_then(|item| item.act_as::<Self>(cx))
4953        {
4954            editor
4955        } else {
4956            return;
4957        };
4958
4959        let editor = editor_handle.read(cx);
4960        let buffer = editor.buffer.read(cx);
4961        let head = editor.selections.newest::<usize>(cx).head();
4962        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
4963            text_anchor
4964        } else {
4965            return;
4966        };
4967
4968        let project = workspace.project().clone();
4969        let definitions = project.update(cx, |project, cx| match kind {
4970            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
4971            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
4972        });
4973
4974        cx.spawn(|workspace, mut cx| async move {
4975            let definitions = definitions.await?;
4976            workspace.update(&mut cx, |workspace, cx| {
4977                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
4978            });
4979
4980            Ok::<(), anyhow::Error>(())
4981        })
4982        .detach_and_log_err(cx);
4983    }
4984
4985    pub fn navigate_to_definitions(
4986        workspace: &mut Workspace,
4987        editor_handle: ViewHandle<Editor>,
4988        definitions: Vec<LocationLink>,
4989        cx: &mut ViewContext<Workspace>,
4990    ) {
4991        let pane = workspace.active_pane().clone();
4992        for definition in definitions {
4993            let range = definition
4994                .target
4995                .range
4996                .to_offset(definition.target.buffer.read(cx));
4997
4998            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
4999            target_editor_handle.update(cx, |target_editor, cx| {
5000                // When selecting a definition in a different buffer, disable the nav history
5001                // to avoid creating a history entry at the previous cursor location.
5002                if editor_handle != target_editor_handle {
5003                    pane.update(cx, |pane, _| pane.disable_history());
5004                }
5005                target_editor.change_selections(Some(Autoscroll::center()), cx, |s| {
5006                    s.select_ranges([range]);
5007                });
5008
5009                pane.update(cx, |pane, _| pane.enable_history());
5010            });
5011        }
5012    }
5013
5014    pub fn find_all_references(
5015        workspace: &mut Workspace,
5016        _: &FindAllReferences,
5017        cx: &mut ViewContext<Workspace>,
5018    ) -> Option<Task<Result<()>>> {
5019        let active_item = workspace.active_item(cx)?;
5020        let editor_handle = active_item.act_as::<Self>(cx)?;
5021
5022        let editor = editor_handle.read(cx);
5023        let buffer = editor.buffer.read(cx);
5024        let head = editor.selections.newest::<usize>(cx).head();
5025        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5026        let replica_id = editor.replica_id(cx);
5027
5028        let project = workspace.project().clone();
5029        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5030        Some(cx.spawn(|workspace, mut cx| async move {
5031            let mut locations = references.await?;
5032            if locations.is_empty() {
5033                return Ok(());
5034            }
5035
5036            locations.sort_by_key(|location| location.buffer.id());
5037            let mut locations = locations.into_iter().peekable();
5038            let mut ranges_to_highlight = Vec::new();
5039
5040            let excerpt_buffer = cx.add_model(|cx| {
5041                let mut symbol_name = None;
5042                let mut multibuffer = MultiBuffer::new(replica_id);
5043                while let Some(location) = locations.next() {
5044                    let buffer = location.buffer.read(cx);
5045                    let mut ranges_for_buffer = Vec::new();
5046                    let range = location.range.to_offset(buffer);
5047                    ranges_for_buffer.push(range.clone());
5048                    if symbol_name.is_none() {
5049                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
5050                    }
5051
5052                    while let Some(next_location) = locations.peek() {
5053                        if next_location.buffer == location.buffer {
5054                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
5055                            locations.next();
5056                        } else {
5057                            break;
5058                        }
5059                    }
5060
5061                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5062                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5063                        location.buffer.clone(),
5064                        ranges_for_buffer,
5065                        1,
5066                        cx,
5067                    ));
5068                }
5069                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
5070            });
5071
5072            workspace.update(&mut cx, |workspace, cx| {
5073                let editor =
5074                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
5075                editor.update(cx, |editor, cx| {
5076                    editor.highlight_background::<Self>(
5077                        ranges_to_highlight,
5078                        |theme| theme.editor.highlighted_line_background,
5079                        cx,
5080                    );
5081                });
5082                workspace.add_item(Box::new(editor), cx);
5083            });
5084
5085            Ok(())
5086        }))
5087    }
5088
5089    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5090        use language::ToOffset as _;
5091
5092        let project = self.project.clone()?;
5093        let selection = self.selections.newest_anchor().clone();
5094        let (cursor_buffer, cursor_buffer_position) = self
5095            .buffer
5096            .read(cx)
5097            .text_anchor_for_position(selection.head(), cx)?;
5098        let (tail_buffer, _) = self
5099            .buffer
5100            .read(cx)
5101            .text_anchor_for_position(selection.tail(), cx)?;
5102        if tail_buffer != cursor_buffer {
5103            return None;
5104        }
5105
5106        let snapshot = cursor_buffer.read(cx).snapshot();
5107        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5108        let prepare_rename = project.update(cx, |project, cx| {
5109            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5110        });
5111
5112        Some(cx.spawn(|this, mut cx| async move {
5113            let rename_range = if let Some(range) = prepare_rename.await? {
5114                Some(range)
5115            } else {
5116                this.read_with(&cx, |this, cx| {
5117                    let buffer = this.buffer.read(cx).snapshot(cx);
5118                    let mut buffer_highlights = this
5119                        .document_highlights_for_position(selection.head(), &buffer)
5120                        .filter(|highlight| {
5121                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5122                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5123                        });
5124                    buffer_highlights
5125                        .next()
5126                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5127                })
5128            };
5129            if let Some(rename_range) = rename_range {
5130                let rename_buffer_range = rename_range.to_offset(&snapshot);
5131                let cursor_offset_in_rename_range =
5132                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5133
5134                this.update(&mut cx, |this, cx| {
5135                    this.take_rename(false, cx);
5136                    let style = this.style(cx);
5137                    let buffer = this.buffer.read(cx).read(cx);
5138                    let cursor_offset = selection.head().to_offset(&buffer);
5139                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5140                    let rename_end = rename_start + rename_buffer_range.len();
5141                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5142                    let mut old_highlight_id = None;
5143                    let old_name: Arc<str> = buffer
5144                        .chunks(rename_start..rename_end, true)
5145                        .map(|chunk| {
5146                            if old_highlight_id.is_none() {
5147                                old_highlight_id = chunk.syntax_highlight_id;
5148                            }
5149                            chunk.text
5150                        })
5151                        .collect::<String>()
5152                        .into();
5153
5154                    drop(buffer);
5155
5156                    // Position the selection in the rename editor so that it matches the current selection.
5157                    this.show_local_selections = false;
5158                    let rename_editor = cx.add_view(|cx| {
5159                        let mut editor = Editor::single_line(None, cx);
5160                        if let Some(old_highlight_id) = old_highlight_id {
5161                            editor.override_text_style =
5162                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5163                        }
5164                        editor.buffer.update(cx, |buffer, cx| {
5165                            buffer.edit([(0..0, old_name.clone())], None, cx)
5166                        });
5167                        editor.select_all(&SelectAll, cx);
5168                        editor
5169                    });
5170
5171                    let ranges = this
5172                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5173                        .into_iter()
5174                        .flat_map(|(_, ranges)| ranges)
5175                        .chain(
5176                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5177                                .into_iter()
5178                                .flat_map(|(_, ranges)| ranges),
5179                        )
5180                        .collect();
5181
5182                    this.highlight_text::<Rename>(
5183                        ranges,
5184                        HighlightStyle {
5185                            fade_out: Some(style.rename_fade),
5186                            ..Default::default()
5187                        },
5188                        cx,
5189                    );
5190                    cx.focus(&rename_editor);
5191                    let block_id = this.insert_blocks(
5192                        [BlockProperties {
5193                            style: BlockStyle::Flex,
5194                            position: range.start.clone(),
5195                            height: 1,
5196                            render: Arc::new({
5197                                let editor = rename_editor.clone();
5198                                move |cx: &mut BlockContext| {
5199                                    ChildView::new(editor.clone(), cx)
5200                                        .contained()
5201                                        .with_padding_left(cx.anchor_x)
5202                                        .boxed()
5203                                }
5204                            }),
5205                            disposition: BlockDisposition::Below,
5206                        }],
5207                        cx,
5208                    )[0];
5209                    this.pending_rename = Some(RenameState {
5210                        range,
5211                        old_name,
5212                        editor: rename_editor,
5213                        block_id,
5214                    });
5215                });
5216            }
5217
5218            Ok(())
5219        }))
5220    }
5221
5222    pub fn confirm_rename(
5223        workspace: &mut Workspace,
5224        _: &ConfirmRename,
5225        cx: &mut ViewContext<Workspace>,
5226    ) -> Option<Task<Result<()>>> {
5227        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5228
5229        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5230            let rename = editor.take_rename(false, cx)?;
5231            let buffer = editor.buffer.read(cx);
5232            let (start_buffer, start) =
5233                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5234            let (end_buffer, end) =
5235                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5236            if start_buffer == end_buffer {
5237                let new_name = rename.editor.read(cx).text(cx);
5238                Some((start_buffer, start..end, rename.old_name, new_name))
5239            } else {
5240                None
5241            }
5242        })?;
5243
5244        let rename = workspace.project().clone().update(cx, |project, cx| {
5245            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5246        });
5247
5248        Some(cx.spawn(|workspace, mut cx| async move {
5249            let project_transaction = rename.await?;
5250            Self::open_project_transaction(
5251                editor.clone(),
5252                workspace,
5253                project_transaction,
5254                format!("Rename: {}{}", old_name, new_name),
5255                cx.clone(),
5256            )
5257            .await?;
5258
5259            editor.update(&mut cx, |editor, cx| {
5260                editor.refresh_document_highlights(cx);
5261            });
5262            Ok(())
5263        }))
5264    }
5265
5266    fn take_rename(
5267        &mut self,
5268        moving_cursor: bool,
5269        cx: &mut ViewContext<Self>,
5270    ) -> Option<RenameState> {
5271        let rename = self.pending_rename.take()?;
5272        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5273        self.clear_text_highlights::<Rename>(cx);
5274        self.show_local_selections = true;
5275
5276        if moving_cursor {
5277            let rename_editor = rename.editor.read(cx);
5278            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5279
5280            // Update the selection to match the position of the selection inside
5281            // the rename editor.
5282            let snapshot = self.buffer.read(cx).read(cx);
5283            let rename_range = rename.range.to_offset(&snapshot);
5284            let cursor_in_editor = snapshot
5285                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5286                .min(rename_range.end);
5287            drop(snapshot);
5288
5289            self.change_selections(None, cx, |s| {
5290                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5291            });
5292        } else {
5293            self.refresh_document_highlights(cx);
5294        }
5295
5296        Some(rename)
5297    }
5298
5299    #[cfg(any(test, feature = "test-support"))]
5300    pub fn pending_rename(&self) -> Option<&RenameState> {
5301        self.pending_rename.as_ref()
5302    }
5303
5304    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5305        let project = match &self.project {
5306            Some(project) => project.clone(),
5307            None => return None,
5308        };
5309
5310        Some(self.perform_format(project, cx))
5311    }
5312
5313    fn perform_format(
5314        &mut self,
5315        project: ModelHandle<Project>,
5316        cx: &mut ViewContext<'_, Self>,
5317    ) -> Task<Result<()>> {
5318        let buffer = self.buffer().clone();
5319        let buffers = buffer.read(cx).all_buffers();
5320
5321        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5322        let format = project.update(cx, |project, cx| {
5323            project.format(buffers, true, FormatTrigger::Manual, cx)
5324        });
5325
5326        cx.spawn(|_, mut cx| async move {
5327            let transaction = futures::select_biased! {
5328                _ = timeout => {
5329                    log::warn!("timed out waiting for formatting");
5330                    None
5331                }
5332                transaction = format.log_err().fuse() => transaction,
5333            };
5334
5335            buffer.update(&mut cx, |buffer, cx| {
5336                if let Some(transaction) = transaction {
5337                    if !buffer.is_singleton() {
5338                        buffer.push_transaction(&transaction.0);
5339                    }
5340                }
5341
5342                cx.notify();
5343            });
5344
5345            Ok(())
5346        })
5347    }
5348
5349    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5350        if let Some(project) = self.project.clone() {
5351            self.buffer.update(cx, |multi_buffer, cx| {
5352                project.update(cx, |project, cx| {
5353                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5354                });
5355            })
5356        }
5357    }
5358
5359    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5360        cx.show_character_palette();
5361    }
5362
5363    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5364        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5365            let buffer = self.buffer.read(cx).snapshot(cx);
5366            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5367            let is_valid = buffer
5368                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5369                .any(|entry| {
5370                    entry.diagnostic.is_primary
5371                        && !entry.range.is_empty()
5372                        && entry.range.start == primary_range_start
5373                        && entry.diagnostic.message == active_diagnostics.primary_message
5374                });
5375
5376            if is_valid != active_diagnostics.is_valid {
5377                active_diagnostics.is_valid = is_valid;
5378                let mut new_styles = HashMap::default();
5379                for (block_id, diagnostic) in &active_diagnostics.blocks {
5380                    new_styles.insert(
5381                        *block_id,
5382                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5383                    );
5384                }
5385                self.display_map
5386                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5387            }
5388        }
5389    }
5390
5391    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5392        self.dismiss_diagnostics(cx);
5393        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5394            let buffer = self.buffer.read(cx).snapshot(cx);
5395
5396            let mut primary_range = None;
5397            let mut primary_message = None;
5398            let mut group_end = Point::zero();
5399            let diagnostic_group = buffer
5400                .diagnostic_group::<Point>(group_id)
5401                .map(|entry| {
5402                    if entry.range.end > group_end {
5403                        group_end = entry.range.end;
5404                    }
5405                    if entry.diagnostic.is_primary {
5406                        primary_range = Some(entry.range.clone());
5407                        primary_message = Some(entry.diagnostic.message.clone());
5408                    }
5409                    entry
5410                })
5411                .collect::<Vec<_>>();
5412            let primary_range = primary_range?;
5413            let primary_message = primary_message?;
5414            let primary_range =
5415                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5416
5417            let blocks = display_map
5418                .insert_blocks(
5419                    diagnostic_group.iter().map(|entry| {
5420                        let diagnostic = entry.diagnostic.clone();
5421                        let message_height = diagnostic.message.lines().count() as u8;
5422                        BlockProperties {
5423                            style: BlockStyle::Fixed,
5424                            position: buffer.anchor_after(entry.range.start),
5425                            height: message_height,
5426                            render: diagnostic_block_renderer(diagnostic, true),
5427                            disposition: BlockDisposition::Below,
5428                        }
5429                    }),
5430                    cx,
5431                )
5432                .into_iter()
5433                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5434                .collect();
5435
5436            Some(ActiveDiagnosticGroup {
5437                primary_range,
5438                primary_message,
5439                blocks,
5440                is_valid: true,
5441            })
5442        });
5443        self.active_diagnostics.is_some()
5444    }
5445
5446    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5447        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5448            self.display_map.update(cx, |display_map, cx| {
5449                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5450            });
5451            cx.notify();
5452        }
5453    }
5454
5455    pub fn set_selections_from_remote(
5456        &mut self,
5457        selections: Vec<Selection<Anchor>>,
5458        pending_selection: Option<Selection<Anchor>>,
5459        cx: &mut ViewContext<Self>,
5460    ) {
5461        let old_cursor_position = self.selections.newest_anchor().head();
5462        self.selections.change_with(cx, |s| {
5463            s.select_anchors(selections);
5464            if let Some(pending_selection) = pending_selection {
5465                s.set_pending(pending_selection, SelectMode::Character);
5466            } else {
5467                s.clear_pending();
5468            }
5469        });
5470        self.selections_did_change(false, &old_cursor_position, cx);
5471    }
5472
5473    fn push_to_selection_history(&mut self) {
5474        self.selection_history.push(SelectionHistoryEntry {
5475            selections: self.selections.disjoint_anchors(),
5476            select_next_state: self.select_next_state.clone(),
5477            add_selections_state: self.add_selections_state.clone(),
5478        });
5479    }
5480
5481    pub fn transact(
5482        &mut self,
5483        cx: &mut ViewContext<Self>,
5484        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5485    ) -> Option<TransactionId> {
5486        self.start_transaction_at(Instant::now(), cx);
5487        update(self, cx);
5488        self.end_transaction_at(Instant::now(), cx)
5489    }
5490
5491    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5492        self.end_selection(cx);
5493        if let Some(tx_id) = self
5494            .buffer
5495            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5496        {
5497            self.selection_history
5498                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5499        }
5500    }
5501
5502    fn end_transaction_at(
5503        &mut self,
5504        now: Instant,
5505        cx: &mut ViewContext<Self>,
5506    ) -> Option<TransactionId> {
5507        if let Some(tx_id) = self
5508            .buffer
5509            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5510        {
5511            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5512                *end_selections = Some(self.selections.disjoint_anchors());
5513            } else {
5514                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5515            }
5516
5517            cx.emit(Event::Edited);
5518            Some(tx_id)
5519        } else {
5520            None
5521        }
5522    }
5523
5524    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5525        let mut fold_ranges = Vec::new();
5526
5527        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5528        let selections = self.selections.all::<Point>(cx);
5529        for selection in selections {
5530            let range = selection.display_range(&display_map).sorted();
5531            let buffer_start_row = range.start.to_point(&display_map).row;
5532
5533            for row in (0..=range.end.row()).rev() {
5534                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5535                    let fold_range = self.foldable_range_for_line(&display_map, row);
5536                    if fold_range.end.row >= buffer_start_row {
5537                        fold_ranges.push(fold_range);
5538                        if row <= range.start.row() {
5539                            break;
5540                        }
5541                    }
5542                }
5543            }
5544        }
5545
5546        self.fold_ranges(fold_ranges, cx);
5547    }
5548
5549    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5550        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5551        let buffer = &display_map.buffer_snapshot;
5552        let selections = self.selections.all::<Point>(cx);
5553        let ranges = selections
5554            .iter()
5555            .map(|s| {
5556                let range = s.display_range(&display_map).sorted();
5557                let mut start = range.start.to_point(&display_map);
5558                let mut end = range.end.to_point(&display_map);
5559                start.column = 0;
5560                end.column = buffer.line_len(end.row);
5561                start..end
5562            })
5563            .collect::<Vec<_>>();
5564        self.unfold_ranges(ranges, true, cx);
5565    }
5566
5567    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5568        let max_point = display_map.max_point();
5569        if display_row >= max_point.row() {
5570            false
5571        } else {
5572            let (start_indent, is_blank) = display_map.line_indent(display_row);
5573            if is_blank {
5574                false
5575            } else {
5576                for display_row in display_row + 1..=max_point.row() {
5577                    let (indent, is_blank) = display_map.line_indent(display_row);
5578                    if !is_blank {
5579                        return indent > start_indent;
5580                    }
5581                }
5582                false
5583            }
5584        }
5585    }
5586
5587    fn foldable_range_for_line(
5588        &self,
5589        display_map: &DisplaySnapshot,
5590        start_row: u32,
5591    ) -> Range<Point> {
5592        let max_point = display_map.max_point();
5593
5594        let (start_indent, _) = display_map.line_indent(start_row);
5595        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5596        let mut end = None;
5597        for row in start_row + 1..=max_point.row() {
5598            let (indent, is_blank) = display_map.line_indent(row);
5599            if !is_blank && indent <= start_indent {
5600                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5601                break;
5602            }
5603        }
5604
5605        let end = end.unwrap_or(max_point);
5606        start.to_point(display_map)..end.to_point(display_map)
5607    }
5608
5609    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5610        let selections = self.selections.all::<Point>(cx);
5611        let ranges = selections.into_iter().map(|s| s.start..s.end);
5612        self.fold_ranges(ranges, cx);
5613    }
5614
5615    pub fn fold_ranges<T: ToOffset>(
5616        &mut self,
5617        ranges: impl IntoIterator<Item = Range<T>>,
5618        cx: &mut ViewContext<Self>,
5619    ) {
5620        let mut ranges = ranges.into_iter().peekable();
5621        if ranges.peek().is_some() {
5622            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5623            self.request_autoscroll(Autoscroll::fit(), cx);
5624            cx.notify();
5625        }
5626    }
5627
5628    pub fn unfold_ranges<T: ToOffset>(
5629        &mut self,
5630        ranges: impl IntoIterator<Item = Range<T>>,
5631        inclusive: bool,
5632        cx: &mut ViewContext<Self>,
5633    ) {
5634        let mut ranges = ranges.into_iter().peekable();
5635        if ranges.peek().is_some() {
5636            self.display_map
5637                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5638            self.request_autoscroll(Autoscroll::fit(), cx);
5639            cx.notify();
5640        }
5641    }
5642
5643    pub fn insert_blocks(
5644        &mut self,
5645        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5646        cx: &mut ViewContext<Self>,
5647    ) -> Vec<BlockId> {
5648        let blocks = self
5649            .display_map
5650            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5651        self.request_autoscroll(Autoscroll::fit(), cx);
5652        blocks
5653    }
5654
5655    pub fn replace_blocks(
5656        &mut self,
5657        blocks: HashMap<BlockId, RenderBlock>,
5658        cx: &mut ViewContext<Self>,
5659    ) {
5660        self.display_map
5661            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5662        self.request_autoscroll(Autoscroll::fit(), cx);
5663    }
5664
5665    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5666        self.display_map.update(cx, |display_map, cx| {
5667            display_map.remove_blocks(block_ids, cx)
5668        });
5669    }
5670
5671    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5672        self.display_map
5673            .update(cx, |map, cx| map.snapshot(cx))
5674            .longest_row()
5675    }
5676
5677    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5678        self.display_map
5679            .update(cx, |map, cx| map.snapshot(cx))
5680            .max_point()
5681    }
5682
5683    pub fn text(&self, cx: &AppContext) -> String {
5684        self.buffer.read(cx).read(cx).text()
5685    }
5686
5687    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5688        self.transact(cx, |this, cx| {
5689            this.buffer
5690                .read(cx)
5691                .as_singleton()
5692                .expect("you can only call set_text on editors for singleton buffers")
5693                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5694        });
5695    }
5696
5697    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5698        self.display_map
5699            .update(cx, |map, cx| map.snapshot(cx))
5700            .text()
5701    }
5702
5703    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5704        let language_name = self
5705            .buffer
5706            .read(cx)
5707            .as_singleton()
5708            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5709            .map(|l| l.name());
5710
5711        let settings = cx.global::<Settings>();
5712        let mode = self
5713            .soft_wrap_mode_override
5714            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5715        match mode {
5716            settings::SoftWrap::None => SoftWrap::None,
5717            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5718            settings::SoftWrap::PreferredLineLength => {
5719                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5720            }
5721        }
5722    }
5723
5724    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5725        self.soft_wrap_mode_override = Some(mode);
5726        cx.notify();
5727    }
5728
5729    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5730        self.display_map
5731            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5732    }
5733
5734    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5735        self.highlighted_rows = rows;
5736    }
5737
5738    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5739        self.highlighted_rows.clone()
5740    }
5741
5742    pub fn highlight_background<T: 'static>(
5743        &mut self,
5744        ranges: Vec<Range<Anchor>>,
5745        color_fetcher: fn(&Theme) -> Color,
5746        cx: &mut ViewContext<Self>,
5747    ) {
5748        self.background_highlights
5749            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5750        cx.notify();
5751    }
5752
5753    #[allow(clippy::type_complexity)]
5754    pub fn clear_background_highlights<T: 'static>(
5755        &mut self,
5756        cx: &mut ViewContext<Self>,
5757    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5758        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
5759        if highlights.is_some() {
5760            cx.notify();
5761        }
5762        highlights
5763    }
5764
5765    #[cfg(feature = "test-support")]
5766    pub fn all_background_highlights(
5767        &mut self,
5768        cx: &mut ViewContext<Self>,
5769    ) -> Vec<(Range<DisplayPoint>, Color)> {
5770        let snapshot = self.snapshot(cx);
5771        let buffer = &snapshot.buffer_snapshot;
5772        let start = buffer.anchor_before(0);
5773        let end = buffer.anchor_after(buffer.len());
5774        let theme = cx.global::<Settings>().theme.as_ref();
5775        self.background_highlights_in_range(start..end, &snapshot, theme)
5776    }
5777
5778    fn document_highlights_for_position<'a>(
5779        &'a self,
5780        position: Anchor,
5781        buffer: &'a MultiBufferSnapshot,
5782    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5783        let read_highlights = self
5784            .background_highlights
5785            .get(&TypeId::of::<DocumentHighlightRead>())
5786            .map(|h| &h.1);
5787        let write_highlights = self
5788            .background_highlights
5789            .get(&TypeId::of::<DocumentHighlightWrite>())
5790            .map(|h| &h.1);
5791        let left_position = position.bias_left(buffer);
5792        let right_position = position.bias_right(buffer);
5793        read_highlights
5794            .into_iter()
5795            .chain(write_highlights)
5796            .flat_map(move |ranges| {
5797                let start_ix = match ranges.binary_search_by(|probe| {
5798                    let cmp = probe.end.cmp(&left_position, buffer);
5799                    if cmp.is_ge() {
5800                        Ordering::Greater
5801                    } else {
5802                        Ordering::Less
5803                    }
5804                }) {
5805                    Ok(i) | Err(i) => i,
5806                };
5807
5808                let right_position = right_position.clone();
5809                ranges[start_ix..]
5810                    .iter()
5811                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5812            })
5813    }
5814
5815    pub fn background_highlights_in_range(
5816        &self,
5817        search_range: Range<Anchor>,
5818        display_snapshot: &DisplaySnapshot,
5819        theme: &Theme,
5820    ) -> Vec<(Range<DisplayPoint>, Color)> {
5821        let mut results = Vec::new();
5822        let buffer = &display_snapshot.buffer_snapshot;
5823        for (color_fetcher, ranges) in self.background_highlights.values() {
5824            let color = color_fetcher(theme);
5825            let start_ix = match ranges.binary_search_by(|probe| {
5826                let cmp = probe.end.cmp(&search_range.start, buffer);
5827                if cmp.is_gt() {
5828                    Ordering::Greater
5829                } else {
5830                    Ordering::Less
5831                }
5832            }) {
5833                Ok(i) | Err(i) => i,
5834            };
5835            for range in &ranges[start_ix..] {
5836                if range.start.cmp(&search_range.end, buffer).is_ge() {
5837                    break;
5838                }
5839                let start = range
5840                    .start
5841                    .to_point(buffer)
5842                    .to_display_point(display_snapshot);
5843                let end = range
5844                    .end
5845                    .to_point(buffer)
5846                    .to_display_point(display_snapshot);
5847                results.push((start..end, color))
5848            }
5849        }
5850        results
5851    }
5852
5853    pub fn highlight_text<T: 'static>(
5854        &mut self,
5855        ranges: Vec<Range<Anchor>>,
5856        style: HighlightStyle,
5857        cx: &mut ViewContext<Self>,
5858    ) {
5859        self.display_map.update(cx, |map, _| {
5860            map.highlight_text(TypeId::of::<T>(), ranges, style)
5861        });
5862        cx.notify();
5863    }
5864
5865    pub fn text_highlights<'a, T: 'static>(
5866        &'a self,
5867        cx: &'a AppContext,
5868    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
5869        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
5870    }
5871
5872    pub fn clear_text_highlights<T: 'static>(
5873        &mut self,
5874        cx: &mut ViewContext<Self>,
5875    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5876        let highlights = self
5877            .display_map
5878            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
5879        if highlights.is_some() {
5880            cx.notify();
5881        }
5882        highlights
5883    }
5884
5885    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
5886        self.blink_manager.read(cx).visible() && self.focused
5887    }
5888
5889    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5890        cx.notify();
5891    }
5892
5893    fn on_buffer_event(
5894        &mut self,
5895        _: ModelHandle<MultiBuffer>,
5896        event: &multi_buffer::Event,
5897        cx: &mut ViewContext<Self>,
5898    ) {
5899        match event {
5900            multi_buffer::Event::Edited => {
5901                self.refresh_active_diagnostics(cx);
5902                self.refresh_code_actions(cx);
5903                cx.emit(Event::BufferEdited);
5904            }
5905            multi_buffer::Event::ExcerptsAdded {
5906                buffer,
5907                predecessor,
5908                excerpts,
5909            } => cx.emit(Event::ExcerptsAdded {
5910                buffer: buffer.clone(),
5911                predecessor: *predecessor,
5912                excerpts: excerpts.clone(),
5913            }),
5914            multi_buffer::Event::ExcerptsRemoved { ids } => {
5915                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
5916            }
5917            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
5918            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
5919            multi_buffer::Event::Saved => cx.emit(Event::Saved),
5920            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5921            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
5922            multi_buffer::Event::Closed => cx.emit(Event::Closed),
5923            multi_buffer::Event::DiagnosticsUpdated => {
5924                self.refresh_active_diagnostics(cx);
5925            }
5926        }
5927    }
5928
5929    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5930        cx.notify();
5931    }
5932
5933    pub fn set_searchable(&mut self, searchable: bool) {
5934        self.searchable = searchable;
5935    }
5936
5937    pub fn searchable(&self) -> bool {
5938        self.searchable
5939    }
5940
5941    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
5942        let active_item = workspace.active_item(cx);
5943        let editor_handle = if let Some(editor) = active_item
5944            .as_ref()
5945            .and_then(|item| item.act_as::<Self>(cx))
5946        {
5947            editor
5948        } else {
5949            cx.propagate_action();
5950            return;
5951        };
5952
5953        let editor = editor_handle.read(cx);
5954        let buffer = editor.buffer.read(cx);
5955        if buffer.is_singleton() {
5956            cx.propagate_action();
5957            return;
5958        }
5959
5960        let mut new_selections_by_buffer = HashMap::default();
5961        for selection in editor.selections.all::<usize>(cx) {
5962            for (buffer, mut range) in
5963                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
5964            {
5965                if selection.reversed {
5966                    mem::swap(&mut range.start, &mut range.end);
5967                }
5968                new_selections_by_buffer
5969                    .entry(buffer)
5970                    .or_insert(Vec::new())
5971                    .push(range)
5972            }
5973        }
5974
5975        editor_handle.update(cx, |editor, cx| {
5976            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
5977        });
5978        let pane = workspace.active_pane().clone();
5979        pane.update(cx, |pane, _| pane.disable_history());
5980
5981        // We defer the pane interaction because we ourselves are a workspace item
5982        // and activating a new item causes the pane to call a method on us reentrantly,
5983        // which panics if we're on the stack.
5984        cx.defer(move |workspace, cx| {
5985            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
5986                let editor = workspace.open_project_item::<Self>(buffer, cx);
5987                editor.update(cx, |editor, cx| {
5988                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
5989                        s.select_ranges(ranges);
5990                    });
5991                });
5992            }
5993
5994            pane.update(cx, |pane, _| pane.enable_history());
5995        });
5996    }
5997
5998    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
5999        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6000        let position = action.position;
6001        let anchor = action.anchor;
6002        cx.spawn_weak(|_, mut cx| async move {
6003            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6004            editor.update(&mut cx, |editor, cx| {
6005                let buffer = editor.buffer().read(cx).as_singleton()?;
6006                let buffer = buffer.read(cx);
6007                let cursor = if buffer.can_resolve(&anchor) {
6008                    language::ToPoint::to_point(&anchor, buffer)
6009                } else {
6010                    buffer.clip_point(position, Bias::Left)
6011                };
6012
6013                let nav_history = editor.nav_history.take();
6014                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6015                    s.select_ranges([cursor..cursor]);
6016                });
6017                editor.nav_history = nav_history;
6018
6019                Some(())
6020            })?;
6021            Some(())
6022        })
6023        .detach()
6024    }
6025
6026    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6027        let snapshot = self.buffer.read(cx).read(cx);
6028        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6029        Some(
6030            ranges
6031                .iter()
6032                .map(move |range| {
6033                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6034                })
6035                .collect(),
6036        )
6037    }
6038
6039    fn selection_replacement_ranges(
6040        &self,
6041        range: Range<OffsetUtf16>,
6042        cx: &AppContext,
6043    ) -> Vec<Range<OffsetUtf16>> {
6044        let selections = self.selections.all::<OffsetUtf16>(cx);
6045        let newest_selection = selections
6046            .iter()
6047            .max_by_key(|selection| selection.id)
6048            .unwrap();
6049        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6050        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6051        let snapshot = self.buffer.read(cx).read(cx);
6052        selections
6053            .into_iter()
6054            .map(|mut selection| {
6055                selection.start.0 =
6056                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6057                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6058                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6059                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6060            })
6061            .collect()
6062    }
6063
6064    fn report_event(&self, name: &str, cx: &AppContext) {
6065        if let Some((project, file)) = self.project.as_ref().zip(
6066            self.buffer
6067                .read(cx)
6068                .as_singleton()
6069                .and_then(|b| b.read(cx).file()),
6070        ) {
6071            let extension = Path::new(file.file_name(cx))
6072                .extension()
6073                .and_then(|e| e.to_str());
6074            project
6075                .read(cx)
6076                .client()
6077                .report_event(name, json!({ "File Extension": extension }));
6078        }
6079    }
6080}
6081
6082impl EditorSnapshot {
6083    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6084        self.display_snapshot.buffer_snapshot.language_at(position)
6085    }
6086
6087    pub fn is_focused(&self) -> bool {
6088        self.is_focused
6089    }
6090
6091    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6092        self.placeholder_text.as_ref()
6093    }
6094
6095    pub fn scroll_position(&self) -> Vector2F {
6096        self.scroll_anchor.scroll_position(&self.display_snapshot)
6097    }
6098}
6099
6100impl Deref for EditorSnapshot {
6101    type Target = DisplaySnapshot;
6102
6103    fn deref(&self) -> &Self::Target {
6104        &self.display_snapshot
6105    }
6106}
6107
6108#[derive(Clone, Debug, PartialEq, Eq)]
6109pub enum Event {
6110    ExcerptsAdded {
6111        buffer: ModelHandle<Buffer>,
6112        predecessor: ExcerptId,
6113        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6114    },
6115    ExcerptsRemoved {
6116        ids: Vec<ExcerptId>,
6117    },
6118    BufferEdited,
6119    Edited,
6120    Reparsed,
6121    Blurred,
6122    DirtyChanged,
6123    Saved,
6124    TitleChanged,
6125    SelectionsChanged {
6126        local: bool,
6127    },
6128    ScrollPositionChanged {
6129        local: bool,
6130    },
6131    Closed,
6132}
6133
6134pub struct EditorFocused(pub ViewHandle<Editor>);
6135pub struct EditorBlurred(pub ViewHandle<Editor>);
6136pub struct EditorReleased(pub WeakViewHandle<Editor>);
6137
6138impl Entity for Editor {
6139    type Event = Event;
6140
6141    fn release(&mut self, cx: &mut MutableAppContext) {
6142        cx.emit_global(EditorReleased(self.handle.clone()));
6143    }
6144}
6145
6146impl View for Editor {
6147    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6148        let style = self.style(cx);
6149        let font_changed = self.display_map.update(cx, |map, cx| {
6150            map.set_font(style.text.font_id, style.text.font_size, cx)
6151        });
6152
6153        if font_changed {
6154            let handle = self.handle.clone();
6155            cx.defer(move |cx| {
6156                if let Some(editor) = handle.upgrade(cx) {
6157                    editor.update(cx, |editor, cx| {
6158                        hide_hover(editor, cx);
6159                        hide_link_definition(editor, cx);
6160                    })
6161                }
6162            });
6163        }
6164
6165        Stack::new()
6166            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6167            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6168            .boxed()
6169    }
6170
6171    fn ui_name() -> &'static str {
6172        "Editor"
6173    }
6174
6175    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6176        let focused_event = EditorFocused(cx.handle());
6177        cx.emit_global(focused_event);
6178        if let Some(rename) = self.pending_rename.as_ref() {
6179            cx.focus(&rename.editor);
6180        } else {
6181            if !self.focused {
6182                self.blink_manager.update(cx, BlinkManager::enable);
6183            }
6184            self.focused = true;
6185            self.buffer.update(cx, |buffer, cx| {
6186                buffer.finalize_last_transaction(cx);
6187                if self.leader_replica_id.is_none() {
6188                    buffer.set_active_selections(
6189                        &self.selections.disjoint_anchors(),
6190                        self.selections.line_mode,
6191                        self.cursor_shape,
6192                        cx,
6193                    );
6194                }
6195            });
6196        }
6197    }
6198
6199    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6200        let blurred_event = EditorBlurred(cx.handle());
6201        cx.emit_global(blurred_event);
6202        self.focused = false;
6203        self.blink_manager.update(cx, BlinkManager::disable);
6204        self.buffer
6205            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6206        self.hide_context_menu(cx);
6207        hide_hover(self, cx);
6208        cx.emit(Event::Blurred);
6209        cx.notify();
6210    }
6211
6212    fn modifiers_changed(
6213        &mut self,
6214        event: &gpui::ModifiersChangedEvent,
6215        cx: &mut ViewContext<Self>,
6216    ) -> bool {
6217        let pending_selection = self.has_pending_selection();
6218
6219        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6220            if event.cmd && !pending_selection {
6221                let snapshot = self.snapshot(cx);
6222                let kind = if event.shift {
6223                    LinkDefinitionKind::Type
6224                } else {
6225                    LinkDefinitionKind::Symbol
6226                };
6227
6228                show_link_definition(kind, self, point, snapshot, cx);
6229                return false;
6230            }
6231        }
6232
6233        {
6234            if self.link_go_to_definition_state.symbol_range.is_some()
6235                || !self.link_go_to_definition_state.definitions.is_empty()
6236            {
6237                self.link_go_to_definition_state.symbol_range.take();
6238                self.link_go_to_definition_state.definitions.clear();
6239                cx.notify();
6240            }
6241
6242            self.link_go_to_definition_state.task = None;
6243
6244            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6245        }
6246
6247        false
6248    }
6249
6250    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
6251        let mut context = Self::default_keymap_context();
6252        let mode = match self.mode {
6253            EditorMode::SingleLine => "single_line",
6254            EditorMode::AutoHeight { .. } => "auto_height",
6255            EditorMode::Full => "full",
6256        };
6257        context.map.insert("mode".into(), mode.into());
6258        if self.pending_rename.is_some() {
6259            context.set.insert("renaming".into());
6260        }
6261        match self.context_menu.as_ref() {
6262            Some(ContextMenu::Completions(_)) => {
6263                context.set.insert("showing_completions".into());
6264            }
6265            Some(ContextMenu::CodeActions(_)) => {
6266                context.set.insert("showing_code_actions".into());
6267            }
6268            None => {}
6269        }
6270
6271        for layer in self.keymap_context_layers.values() {
6272            context.extend(layer);
6273        }
6274
6275        context
6276    }
6277
6278    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6279        Some(
6280            self.buffer
6281                .read(cx)
6282                .read(cx)
6283                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6284                .collect(),
6285        )
6286    }
6287
6288    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6289        // Prevent the IME menu from appearing when holding down an alphabetic key
6290        // while input is disabled.
6291        if !self.input_enabled {
6292            return None;
6293        }
6294
6295        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6296        Some(range.start.0..range.end.0)
6297    }
6298
6299    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6300        let snapshot = self.buffer.read(cx).read(cx);
6301        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6302        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6303    }
6304
6305    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6306        self.clear_text_highlights::<InputComposition>(cx);
6307        self.ime_transaction.take();
6308    }
6309
6310    fn replace_text_in_range(
6311        &mut self,
6312        range_utf16: Option<Range<usize>>,
6313        text: &str,
6314        cx: &mut ViewContext<Self>,
6315    ) {
6316        if !self.input_enabled {
6317            return;
6318        }
6319
6320        self.transact(cx, |this, cx| {
6321            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6322                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6323                Some(this.selection_replacement_ranges(range_utf16, cx))
6324            } else {
6325                this.marked_text_ranges(cx)
6326            };
6327
6328            if let Some(new_selected_ranges) = new_selected_ranges {
6329                this.change_selections(None, cx, |selections| {
6330                    selections.select_ranges(new_selected_ranges)
6331                });
6332            }
6333            this.handle_input(text, cx);
6334        });
6335
6336        if let Some(transaction) = self.ime_transaction {
6337            self.buffer.update(cx, |buffer, cx| {
6338                buffer.group_until_transaction(transaction, cx);
6339            });
6340        }
6341
6342        self.unmark_text(cx);
6343    }
6344
6345    fn replace_and_mark_text_in_range(
6346        &mut self,
6347        range_utf16: Option<Range<usize>>,
6348        text: &str,
6349        new_selected_range_utf16: Option<Range<usize>>,
6350        cx: &mut ViewContext<Self>,
6351    ) {
6352        if !self.input_enabled {
6353            return;
6354        }
6355
6356        let transaction = self.transact(cx, |this, cx| {
6357            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6358                let snapshot = this.buffer.read(cx).read(cx);
6359                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6360                    for marked_range in &mut marked_ranges {
6361                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6362                        marked_range.start.0 += relative_range_utf16.start;
6363                        marked_range.start =
6364                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6365                        marked_range.end =
6366                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6367                    }
6368                }
6369                Some(marked_ranges)
6370            } else if let Some(range_utf16) = range_utf16 {
6371                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6372                Some(this.selection_replacement_ranges(range_utf16, cx))
6373            } else {
6374                None
6375            };
6376
6377            if let Some(ranges) = ranges_to_replace {
6378                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6379            }
6380
6381            let marked_ranges = {
6382                let snapshot = this.buffer.read(cx).read(cx);
6383                this.selections
6384                    .disjoint_anchors()
6385                    .iter()
6386                    .map(|selection| {
6387                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6388                    })
6389                    .collect::<Vec<_>>()
6390            };
6391
6392            if text.is_empty() {
6393                this.unmark_text(cx);
6394            } else {
6395                this.highlight_text::<InputComposition>(
6396                    marked_ranges.clone(),
6397                    this.style(cx).composition_mark,
6398                    cx,
6399                );
6400            }
6401
6402            this.handle_input(text, cx);
6403
6404            if let Some(new_selected_range) = new_selected_range_utf16 {
6405                let snapshot = this.buffer.read(cx).read(cx);
6406                let new_selected_ranges = marked_ranges
6407                    .into_iter()
6408                    .map(|marked_range| {
6409                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6410                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6411                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6412                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6413                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6414                    })
6415                    .collect::<Vec<_>>();
6416
6417                drop(snapshot);
6418                this.change_selections(None, cx, |selections| {
6419                    selections.select_ranges(new_selected_ranges)
6420                });
6421            }
6422        });
6423
6424        self.ime_transaction = self.ime_transaction.or(transaction);
6425        if let Some(transaction) = self.ime_transaction {
6426            self.buffer.update(cx, |buffer, cx| {
6427                buffer.group_until_transaction(transaction, cx);
6428            });
6429        }
6430
6431        if self.text_highlights::<InputComposition>(cx).is_none() {
6432            self.ime_transaction.take();
6433        }
6434    }
6435}
6436
6437fn build_style(
6438    settings: &Settings,
6439    get_field_editor_theme: Option<&GetFieldEditorTheme>,
6440    override_text_style: Option<&OverrideTextStyle>,
6441    cx: &AppContext,
6442) -> EditorStyle {
6443    let font_cache = cx.font_cache();
6444
6445    let mut theme = settings.theme.editor.clone();
6446    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6447        let field_editor_theme = get_field_editor_theme(&settings.theme);
6448        theme.text_color = field_editor_theme.text.color;
6449        theme.selection = field_editor_theme.selection;
6450        theme.background = field_editor_theme
6451            .container
6452            .background_color
6453            .unwrap_or_default();
6454        EditorStyle {
6455            text: field_editor_theme.text,
6456            placeholder_text: field_editor_theme.placeholder_text,
6457            theme,
6458        }
6459    } else {
6460        let font_family_id = settings.buffer_font_family;
6461        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6462        let font_properties = Default::default();
6463        let font_id = font_cache
6464            .select_font(font_family_id, &font_properties)
6465            .unwrap();
6466        let font_size = settings.buffer_font_size;
6467        EditorStyle {
6468            text: TextStyle {
6469                color: settings.theme.editor.text_color,
6470                font_family_name,
6471                font_family_id,
6472                font_id,
6473                font_size,
6474                font_properties,
6475                underline: Default::default(),
6476            },
6477            placeholder_text: None,
6478            theme,
6479        }
6480    };
6481
6482    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6483        if let Some(highlighted) = style
6484            .text
6485            .clone()
6486            .highlight(highlight_style, font_cache)
6487            .log_err()
6488        {
6489            style.text = highlighted;
6490        }
6491    }
6492
6493    style
6494}
6495
6496trait SelectionExt {
6497    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6498    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6499    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6500    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6501        -> Range<u32>;
6502}
6503
6504impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6505    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6506        let start = self.start.to_point(buffer);
6507        let end = self.end.to_point(buffer);
6508        if self.reversed {
6509            end..start
6510        } else {
6511            start..end
6512        }
6513    }
6514
6515    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6516        let start = self.start.to_offset(buffer);
6517        let end = self.end.to_offset(buffer);
6518        if self.reversed {
6519            end..start
6520        } else {
6521            start..end
6522        }
6523    }
6524
6525    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6526        let start = self
6527            .start
6528            .to_point(&map.buffer_snapshot)
6529            .to_display_point(map);
6530        let end = self
6531            .end
6532            .to_point(&map.buffer_snapshot)
6533            .to_display_point(map);
6534        if self.reversed {
6535            end..start
6536        } else {
6537            start..end
6538        }
6539    }
6540
6541    fn spanned_rows(
6542        &self,
6543        include_end_if_at_line_start: bool,
6544        map: &DisplaySnapshot,
6545    ) -> Range<u32> {
6546        let start = self.start.to_point(&map.buffer_snapshot);
6547        let mut end = self.end.to_point(&map.buffer_snapshot);
6548        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6549            end.row -= 1;
6550        }
6551
6552        let buffer_start = map.prev_line_boundary(start).0;
6553        let buffer_end = map.next_line_boundary(end).0;
6554        buffer_start.row..buffer_end.row + 1
6555    }
6556}
6557
6558impl<T: InvalidationRegion> InvalidationStack<T> {
6559    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6560    where
6561        S: Clone + ToOffset,
6562    {
6563        while let Some(region) = self.last() {
6564            let all_selections_inside_invalidation_ranges =
6565                if selections.len() == region.ranges().len() {
6566                    selections
6567                        .iter()
6568                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6569                        .all(|(selection, invalidation_range)| {
6570                            let head = selection.head().to_offset(buffer);
6571                            invalidation_range.start <= head && invalidation_range.end >= head
6572                        })
6573                } else {
6574                    false
6575                };
6576
6577            if all_selections_inside_invalidation_ranges {
6578                break;
6579            } else {
6580                self.pop();
6581            }
6582        }
6583    }
6584}
6585
6586impl<T> Default for InvalidationStack<T> {
6587    fn default() -> Self {
6588        Self(Default::default())
6589    }
6590}
6591
6592impl<T> Deref for InvalidationStack<T> {
6593    type Target = Vec<T>;
6594
6595    fn deref(&self) -> &Self::Target {
6596        &self.0
6597    }
6598}
6599
6600impl<T> DerefMut for InvalidationStack<T> {
6601    fn deref_mut(&mut self) -> &mut Self::Target {
6602        &mut self.0
6603    }
6604}
6605
6606impl InvalidationRegion for SnippetState {
6607    fn ranges(&self) -> &[Range<Anchor>] {
6608        &self.ranges[self.active_index]
6609    }
6610}
6611
6612impl Deref for EditorStyle {
6613    type Target = theme::Editor;
6614
6615    fn deref(&self) -> &Self::Target {
6616        &self.theme
6617    }
6618}
6619
6620pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6621    let mut highlighted_lines = Vec::new();
6622    for line in diagnostic.message.lines() {
6623        highlighted_lines.push(highlight_diagnostic_message(line));
6624    }
6625
6626    Arc::new(move |cx: &mut BlockContext| {
6627        let settings = cx.global::<Settings>();
6628        let theme = &settings.theme.editor;
6629        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6630        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6631        Flex::column()
6632            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6633                Label::new(
6634                    line.clone(),
6635                    style.message.clone().with_font_size(font_size),
6636                )
6637                .with_highlights(highlights.clone())
6638                .contained()
6639                .with_margin_left(cx.anchor_x)
6640                .boxed()
6641            }))
6642            .aligned()
6643            .left()
6644            .boxed()
6645    })
6646}
6647
6648pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6649    let mut message_without_backticks = String::new();
6650    let mut prev_offset = 0;
6651    let mut inside_block = false;
6652    let mut highlights = Vec::new();
6653    for (match_ix, (offset, _)) in message
6654        .match_indices('`')
6655        .chain([(message.len(), "")])
6656        .enumerate()
6657    {
6658        message_without_backticks.push_str(&message[prev_offset..offset]);
6659        if inside_block {
6660            highlights.extend(prev_offset - match_ix..offset - match_ix);
6661        }
6662
6663        inside_block = !inside_block;
6664        prev_offset = offset + 1;
6665    }
6666
6667    (message_without_backticks, highlights)
6668}
6669
6670pub fn diagnostic_style(
6671    severity: DiagnosticSeverity,
6672    valid: bool,
6673    theme: &theme::Editor,
6674) -> DiagnosticStyle {
6675    match (severity, valid) {
6676        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6677        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6678        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6679        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6680        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6681        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6682        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6683        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6684        _ => theme.invalid_hint_diagnostic.clone(),
6685    }
6686}
6687
6688pub fn combine_syntax_and_fuzzy_match_highlights(
6689    text: &str,
6690    default_style: HighlightStyle,
6691    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6692    match_indices: &[usize],
6693) -> Vec<(Range<usize>, HighlightStyle)> {
6694    let mut result = Vec::new();
6695    let mut match_indices = match_indices.iter().copied().peekable();
6696
6697    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6698    {
6699        syntax_highlight.weight = None;
6700
6701        // Add highlights for any fuzzy match characters before the next
6702        // syntax highlight range.
6703        while let Some(&match_index) = match_indices.peek() {
6704            if match_index >= range.start {
6705                break;
6706            }
6707            match_indices.next();
6708            let end_index = char_ix_after(match_index, text);
6709            let mut match_style = default_style;
6710            match_style.weight = Some(fonts::Weight::BOLD);
6711            result.push((match_index..end_index, match_style));
6712        }
6713
6714        if range.start == usize::MAX {
6715            break;
6716        }
6717
6718        // Add highlights for any fuzzy match characters within the
6719        // syntax highlight range.
6720        let mut offset = range.start;
6721        while let Some(&match_index) = match_indices.peek() {
6722            if match_index >= range.end {
6723                break;
6724            }
6725
6726            match_indices.next();
6727            if match_index > offset {
6728                result.push((offset..match_index, syntax_highlight));
6729            }
6730
6731            let mut end_index = char_ix_after(match_index, text);
6732            while let Some(&next_match_index) = match_indices.peek() {
6733                if next_match_index == end_index && next_match_index < range.end {
6734                    end_index = char_ix_after(next_match_index, text);
6735                    match_indices.next();
6736                } else {
6737                    break;
6738                }
6739            }
6740
6741            let mut match_style = syntax_highlight;
6742            match_style.weight = Some(fonts::Weight::BOLD);
6743            result.push((match_index..end_index, match_style));
6744            offset = end_index;
6745        }
6746
6747        if offset < range.end {
6748            result.push((offset..range.end, syntax_highlight));
6749        }
6750    }
6751
6752    fn char_ix_after(ix: usize, text: &str) -> usize {
6753        ix + text[ix..].chars().next().unwrap().len_utf8()
6754    }
6755
6756    result
6757}
6758
6759pub fn styled_runs_for_code_label<'a>(
6760    label: &'a CodeLabel,
6761    syntax_theme: &'a theme::SyntaxTheme,
6762) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6763    let fade_out = HighlightStyle {
6764        fade_out: Some(0.35),
6765        ..Default::default()
6766    };
6767
6768    let mut prev_end = label.filter_range.end;
6769    label
6770        .runs
6771        .iter()
6772        .enumerate()
6773        .flat_map(move |(ix, (range, highlight_id))| {
6774            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6775                style
6776            } else {
6777                return Default::default();
6778            };
6779            let mut muted_style = style;
6780            muted_style.highlight(fade_out);
6781
6782            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6783            if range.start >= label.filter_range.end {
6784                if range.start > prev_end {
6785                    runs.push((prev_end..range.start, fade_out));
6786                }
6787                runs.push((range.clone(), muted_style));
6788            } else if range.end <= label.filter_range.end {
6789                runs.push((range.clone(), style));
6790            } else {
6791                runs.push((range.start..label.filter_range.end, style));
6792                runs.push((label.filter_range.end..range.end, muted_style));
6793            }
6794            prev_end = cmp::max(prev_end, range.end);
6795
6796            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6797                runs.push((prev_end..label.text.len(), fade_out));
6798            }
6799
6800            runs
6801        })
6802}
6803
6804trait RangeExt<T> {
6805    fn sorted(&self) -> Range<T>;
6806    fn to_inclusive(&self) -> RangeInclusive<T>;
6807}
6808
6809impl<T: Ord + Clone> RangeExt<T> for Range<T> {
6810    fn sorted(&self) -> Self {
6811        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
6812    }
6813
6814    fn to_inclusive(&self) -> RangeInclusive<T> {
6815        self.start.clone()..=self.end.clone()
6816    }
6817}
6818
6819trait RangeToAnchorExt {
6820    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
6821}
6822
6823impl<T: ToOffset> RangeToAnchorExt for Range<T> {
6824    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
6825        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
6826    }
6827}