editor.rs

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