editor.rs

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