editor.rs

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