editor.rs

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