editor.rs

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