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