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