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            is_wrapped: bool,
5262            direction: Direction,
5263            cx: &mut ViewContext<Editor>,
5264        ) -> bool {
5265            let hunks = if direction == Direction::Next {
5266                snapshot
5267                    .buffer_snapshot
5268                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
5269            } else {
5270                snapshot
5271                    .buffer_snapshot
5272                    .git_diff_hunks_in_range(0..initial_point.row, true)
5273            };
5274
5275            let display_point = initial_point.to_display_point(snapshot);
5276            let mut hunks = hunks
5277                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5278                .skip_while(|hunk| {
5279                    if is_wrapped {
5280                        false
5281                    } else {
5282                        hunk.contains_display_row(display_point.row())
5283                    }
5284                })
5285                .dedup();
5286
5287            if let Some(hunk) = hunks.next() {
5288                this.change_selections(Some(Autoscroll::Center), cx, |s| {
5289                    let row = hunk.start_display_row();
5290                    let point = DisplayPoint::new(row, 0);
5291                    s.select_display_ranges([point..point]);
5292                });
5293
5294                true
5295            } else {
5296                false
5297            }
5298        }
5299
5300        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5301            let wrapped_point = match direction {
5302                Direction::Next => Point::zero(),
5303                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5304            };
5305            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5306        }
5307    }
5308
5309    pub fn go_to_definition(
5310        workspace: &mut Workspace,
5311        _: &GoToDefinition,
5312        cx: &mut ViewContext<Workspace>,
5313    ) {
5314        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5315    }
5316
5317    pub fn go_to_type_definition(
5318        workspace: &mut Workspace,
5319        _: &GoToTypeDefinition,
5320        cx: &mut ViewContext<Workspace>,
5321    ) {
5322        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5323    }
5324
5325    fn go_to_definition_of_kind(
5326        kind: GotoDefinitionKind,
5327        workspace: &mut Workspace,
5328        cx: &mut ViewContext<Workspace>,
5329    ) {
5330        let active_item = workspace.active_item(cx);
5331        let editor_handle = if let Some(editor) = active_item
5332            .as_ref()
5333            .and_then(|item| item.act_as::<Self>(cx))
5334        {
5335            editor
5336        } else {
5337            return;
5338        };
5339
5340        let editor = editor_handle.read(cx);
5341        let buffer = editor.buffer.read(cx);
5342        let head = editor.selections.newest::<usize>(cx).head();
5343        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5344            text_anchor
5345        } else {
5346            return;
5347        };
5348
5349        let project = workspace.project().clone();
5350        let definitions = project.update(cx, |project, cx| match kind {
5351            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5352            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5353        });
5354
5355        cx.spawn(|workspace, mut cx| async move {
5356            let definitions = definitions.await?;
5357            workspace.update(&mut cx, |workspace, cx| {
5358                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5359            });
5360
5361            Ok::<(), anyhow::Error>(())
5362        })
5363        .detach_and_log_err(cx);
5364    }
5365
5366    pub fn navigate_to_definitions(
5367        workspace: &mut Workspace,
5368        editor_handle: ViewHandle<Editor>,
5369        definitions: Vec<LocationLink>,
5370        cx: &mut ViewContext<Workspace>,
5371    ) {
5372        let pane = workspace.active_pane().clone();
5373        for definition in definitions {
5374            let range = definition
5375                .target
5376                .range
5377                .to_offset(definition.target.buffer.read(cx));
5378
5379            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
5380            target_editor_handle.update(cx, |target_editor, cx| {
5381                // When selecting a definition in a different buffer, disable the nav history
5382                // to avoid creating a history entry at the previous cursor location.
5383                if editor_handle != target_editor_handle {
5384                    pane.update(cx, |pane, _| pane.disable_history());
5385                }
5386                target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
5387                    s.select_ranges([range]);
5388                });
5389
5390                pane.update(cx, |pane, _| pane.enable_history());
5391            });
5392        }
5393    }
5394
5395    pub fn find_all_references(
5396        workspace: &mut Workspace,
5397        _: &FindAllReferences,
5398        cx: &mut ViewContext<Workspace>,
5399    ) -> Option<Task<Result<()>>> {
5400        let active_item = workspace.active_item(cx)?;
5401        let editor_handle = active_item.act_as::<Self>(cx)?;
5402
5403        let editor = editor_handle.read(cx);
5404        let buffer = editor.buffer.read(cx);
5405        let head = editor.selections.newest::<usize>(cx).head();
5406        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5407        let replica_id = editor.replica_id(cx);
5408
5409        let project = workspace.project().clone();
5410        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5411        Some(cx.spawn(|workspace, mut cx| async move {
5412            let mut locations = references.await?;
5413            if locations.is_empty() {
5414                return Ok(());
5415            }
5416
5417            locations.sort_by_key(|location| location.buffer.id());
5418            let mut locations = locations.into_iter().peekable();
5419            let mut ranges_to_highlight = Vec::new();
5420
5421            let excerpt_buffer = cx.add_model(|cx| {
5422                let mut symbol_name = None;
5423                let mut multibuffer = MultiBuffer::new(replica_id);
5424                while let Some(location) = locations.next() {
5425                    let buffer = location.buffer.read(cx);
5426                    let mut ranges_for_buffer = Vec::new();
5427                    let range = location.range.to_offset(buffer);
5428                    ranges_for_buffer.push(range.clone());
5429                    if symbol_name.is_none() {
5430                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
5431                    }
5432
5433                    while let Some(next_location) = locations.peek() {
5434                        if next_location.buffer == location.buffer {
5435                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
5436                            locations.next();
5437                        } else {
5438                            break;
5439                        }
5440                    }
5441
5442                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5443                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5444                        location.buffer.clone(),
5445                        ranges_for_buffer,
5446                        1,
5447                        cx,
5448                    ));
5449                }
5450                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
5451            });
5452
5453            workspace.update(&mut cx, |workspace, cx| {
5454                let editor =
5455                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
5456                editor.update(cx, |editor, cx| {
5457                    editor.highlight_background::<Self>(
5458                        ranges_to_highlight,
5459                        |theme| theme.editor.highlighted_line_background,
5460                        cx,
5461                    );
5462                });
5463                workspace.add_item(Box::new(editor), cx);
5464            });
5465
5466            Ok(())
5467        }))
5468    }
5469
5470    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5471        use language::ToOffset as _;
5472
5473        let project = self.project.clone()?;
5474        let selection = self.selections.newest_anchor().clone();
5475        let (cursor_buffer, cursor_buffer_position) = self
5476            .buffer
5477            .read(cx)
5478            .text_anchor_for_position(selection.head(), cx)?;
5479        let (tail_buffer, _) = self
5480            .buffer
5481            .read(cx)
5482            .text_anchor_for_position(selection.tail(), cx)?;
5483        if tail_buffer != cursor_buffer {
5484            return None;
5485        }
5486
5487        let snapshot = cursor_buffer.read(cx).snapshot();
5488        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5489        let prepare_rename = project.update(cx, |project, cx| {
5490            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5491        });
5492
5493        Some(cx.spawn(|this, mut cx| async move {
5494            let rename_range = if let Some(range) = prepare_rename.await? {
5495                Some(range)
5496            } else {
5497                this.read_with(&cx, |this, cx| {
5498                    let buffer = this.buffer.read(cx).snapshot(cx);
5499                    let mut buffer_highlights = this
5500                        .document_highlights_for_position(selection.head(), &buffer)
5501                        .filter(|highlight| {
5502                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5503                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5504                        });
5505                    buffer_highlights
5506                        .next()
5507                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5508                })
5509            };
5510            if let Some(rename_range) = rename_range {
5511                let rename_buffer_range = rename_range.to_offset(&snapshot);
5512                let cursor_offset_in_rename_range =
5513                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5514
5515                this.update(&mut cx, |this, cx| {
5516                    this.take_rename(false, cx);
5517                    let style = this.style(cx);
5518                    let buffer = this.buffer.read(cx).read(cx);
5519                    let cursor_offset = selection.head().to_offset(&buffer);
5520                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5521                    let rename_end = rename_start + rename_buffer_range.len();
5522                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5523                    let mut old_highlight_id = None;
5524                    let old_name: Arc<str> = buffer
5525                        .chunks(rename_start..rename_end, true)
5526                        .map(|chunk| {
5527                            if old_highlight_id.is_none() {
5528                                old_highlight_id = chunk.syntax_highlight_id;
5529                            }
5530                            chunk.text
5531                        })
5532                        .collect::<String>()
5533                        .into();
5534
5535                    drop(buffer);
5536
5537                    // Position the selection in the rename editor so that it matches the current selection.
5538                    this.show_local_selections = false;
5539                    let rename_editor = cx.add_view(|cx| {
5540                        let mut editor = Editor::single_line(None, cx);
5541                        if let Some(old_highlight_id) = old_highlight_id {
5542                            editor.override_text_style =
5543                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5544                        }
5545                        editor.buffer.update(cx, |buffer, cx| {
5546                            buffer.edit([(0..0, old_name.clone())], None, cx)
5547                        });
5548                        editor.select_all(&SelectAll, cx);
5549                        editor
5550                    });
5551
5552                    let ranges = this
5553                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5554                        .into_iter()
5555                        .flat_map(|(_, ranges)| ranges)
5556                        .chain(
5557                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5558                                .into_iter()
5559                                .flat_map(|(_, ranges)| ranges),
5560                        )
5561                        .collect();
5562
5563                    this.highlight_text::<Rename>(
5564                        ranges,
5565                        HighlightStyle {
5566                            fade_out: Some(style.rename_fade),
5567                            ..Default::default()
5568                        },
5569                        cx,
5570                    );
5571                    cx.focus(&rename_editor);
5572                    let block_id = this.insert_blocks(
5573                        [BlockProperties {
5574                            style: BlockStyle::Flex,
5575                            position: range.start.clone(),
5576                            height: 1,
5577                            render: Arc::new({
5578                                let editor = rename_editor.clone();
5579                                move |cx: &mut BlockContext| {
5580                                    ChildView::new(editor.clone(), cx)
5581                                        .contained()
5582                                        .with_padding_left(cx.anchor_x)
5583                                        .boxed()
5584                                }
5585                            }),
5586                            disposition: BlockDisposition::Below,
5587                        }],
5588                        cx,
5589                    )[0];
5590                    this.pending_rename = Some(RenameState {
5591                        range,
5592                        old_name,
5593                        editor: rename_editor,
5594                        block_id,
5595                    });
5596                });
5597            }
5598
5599            Ok(())
5600        }))
5601    }
5602
5603    pub fn confirm_rename(
5604        workspace: &mut Workspace,
5605        _: &ConfirmRename,
5606        cx: &mut ViewContext<Workspace>,
5607    ) -> Option<Task<Result<()>>> {
5608        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5609
5610        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5611            let rename = editor.take_rename(false, cx)?;
5612            let buffer = editor.buffer.read(cx);
5613            let (start_buffer, start) =
5614                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5615            let (end_buffer, end) =
5616                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5617            if start_buffer == end_buffer {
5618                let new_name = rename.editor.read(cx).text(cx);
5619                Some((start_buffer, start..end, rename.old_name, new_name))
5620            } else {
5621                None
5622            }
5623        })?;
5624
5625        let rename = workspace.project().clone().update(cx, |project, cx| {
5626            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5627        });
5628
5629        Some(cx.spawn(|workspace, mut cx| async move {
5630            let project_transaction = rename.await?;
5631            Self::open_project_transaction(
5632                editor.clone(),
5633                workspace,
5634                project_transaction,
5635                format!("Rename: {}{}", old_name, new_name),
5636                cx.clone(),
5637            )
5638            .await?;
5639
5640            editor.update(&mut cx, |editor, cx| {
5641                editor.refresh_document_highlights(cx);
5642            });
5643            Ok(())
5644        }))
5645    }
5646
5647    fn take_rename(
5648        &mut self,
5649        moving_cursor: bool,
5650        cx: &mut ViewContext<Self>,
5651    ) -> Option<RenameState> {
5652        let rename = self.pending_rename.take()?;
5653        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5654        self.clear_text_highlights::<Rename>(cx);
5655        self.show_local_selections = true;
5656
5657        if moving_cursor {
5658            let rename_editor = rename.editor.read(cx);
5659            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5660
5661            // Update the selection to match the position of the selection inside
5662            // the rename editor.
5663            let snapshot = self.buffer.read(cx).read(cx);
5664            let rename_range = rename.range.to_offset(&snapshot);
5665            let cursor_in_editor = snapshot
5666                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5667                .min(rename_range.end);
5668            drop(snapshot);
5669
5670            self.change_selections(None, cx, |s| {
5671                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5672            });
5673        } else {
5674            self.refresh_document_highlights(cx);
5675        }
5676
5677        Some(rename)
5678    }
5679
5680    #[cfg(any(test, feature = "test-support"))]
5681    pub fn pending_rename(&self) -> Option<&RenameState> {
5682        self.pending_rename.as_ref()
5683    }
5684
5685    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5686        let project = match &self.project {
5687            Some(project) => project.clone(),
5688            None => return None,
5689        };
5690
5691        Some(self.perform_format(project, cx))
5692    }
5693
5694    fn perform_format(
5695        &mut self,
5696        project: ModelHandle<Project>,
5697        cx: &mut ViewContext<'_, Self>,
5698    ) -> Task<Result<()>> {
5699        let buffer = self.buffer().clone();
5700        let buffers = buffer.read(cx).all_buffers();
5701
5702        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5703        let format = project.update(cx, |project, cx| {
5704            project.format(buffers, true, FormatTrigger::Manual, cx)
5705        });
5706
5707        cx.spawn(|_, mut cx| async move {
5708            let transaction = futures::select_biased! {
5709                _ = timeout => {
5710                    log::warn!("timed out waiting for formatting");
5711                    None
5712                }
5713                transaction = format.log_err().fuse() => transaction,
5714            };
5715
5716            buffer.update(&mut cx, |buffer, cx| {
5717                if let Some(transaction) = transaction {
5718                    if !buffer.is_singleton() {
5719                        buffer.push_transaction(&transaction.0);
5720                    }
5721                }
5722
5723                cx.notify();
5724            });
5725
5726            Ok(())
5727        })
5728    }
5729
5730    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5731        if let Some(project) = self.project.clone() {
5732            self.buffer.update(cx, |multi_buffer, cx| {
5733                project.update(cx, |project, cx| {
5734                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5735                });
5736            })
5737        }
5738    }
5739
5740    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5741        cx.show_character_palette();
5742    }
5743
5744    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5745        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5746            let buffer = self.buffer.read(cx).snapshot(cx);
5747            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5748            let is_valid = buffer
5749                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5750                .any(|entry| {
5751                    entry.diagnostic.is_primary
5752                        && !entry.range.is_empty()
5753                        && entry.range.start == primary_range_start
5754                        && entry.diagnostic.message == active_diagnostics.primary_message
5755                });
5756
5757            if is_valid != active_diagnostics.is_valid {
5758                active_diagnostics.is_valid = is_valid;
5759                let mut new_styles = HashMap::default();
5760                for (block_id, diagnostic) in &active_diagnostics.blocks {
5761                    new_styles.insert(
5762                        *block_id,
5763                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5764                    );
5765                }
5766                self.display_map
5767                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5768            }
5769        }
5770    }
5771
5772    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5773        self.dismiss_diagnostics(cx);
5774        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5775            let buffer = self.buffer.read(cx).snapshot(cx);
5776
5777            let mut primary_range = None;
5778            let mut primary_message = None;
5779            let mut group_end = Point::zero();
5780            let diagnostic_group = buffer
5781                .diagnostic_group::<Point>(group_id)
5782                .map(|entry| {
5783                    if entry.range.end > group_end {
5784                        group_end = entry.range.end;
5785                    }
5786                    if entry.diagnostic.is_primary {
5787                        primary_range = Some(entry.range.clone());
5788                        primary_message = Some(entry.diagnostic.message.clone());
5789                    }
5790                    entry
5791                })
5792                .collect::<Vec<_>>();
5793            let primary_range = primary_range?;
5794            let primary_message = primary_message?;
5795            let primary_range =
5796                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5797
5798            let blocks = display_map
5799                .insert_blocks(
5800                    diagnostic_group.iter().map(|entry| {
5801                        let diagnostic = entry.diagnostic.clone();
5802                        let message_height = diagnostic.message.lines().count() as u8;
5803                        BlockProperties {
5804                            style: BlockStyle::Fixed,
5805                            position: buffer.anchor_after(entry.range.start),
5806                            height: message_height,
5807                            render: diagnostic_block_renderer(diagnostic, true),
5808                            disposition: BlockDisposition::Below,
5809                        }
5810                    }),
5811                    cx,
5812                )
5813                .into_iter()
5814                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5815                .collect();
5816
5817            Some(ActiveDiagnosticGroup {
5818                primary_range,
5819                primary_message,
5820                blocks,
5821                is_valid: true,
5822            })
5823        });
5824        self.active_diagnostics.is_some()
5825    }
5826
5827    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5828        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5829            self.display_map.update(cx, |display_map, cx| {
5830                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5831            });
5832            cx.notify();
5833        }
5834    }
5835
5836    pub fn set_selections_from_remote(
5837        &mut self,
5838        selections: Vec<Selection<Anchor>>,
5839        cx: &mut ViewContext<Self>,
5840    ) {
5841        let old_cursor_position = self.selections.newest_anchor().head();
5842        self.selections.change_with(cx, |s| {
5843            s.select_anchors(selections);
5844        });
5845        self.selections_did_change(false, &old_cursor_position, cx);
5846    }
5847
5848    fn push_to_selection_history(&mut self) {
5849        self.selection_history.push(SelectionHistoryEntry {
5850            selections: self.selections.disjoint_anchors(),
5851            select_next_state: self.select_next_state.clone(),
5852            add_selections_state: self.add_selections_state.clone(),
5853        });
5854    }
5855
5856    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5857        self.autoscroll_request = Some((autoscroll, true));
5858        cx.notify();
5859    }
5860
5861    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5862        self.autoscroll_request = Some((autoscroll, false));
5863        cx.notify();
5864    }
5865
5866    pub fn transact(
5867        &mut self,
5868        cx: &mut ViewContext<Self>,
5869        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5870    ) -> Option<TransactionId> {
5871        self.start_transaction_at(Instant::now(), cx);
5872        update(self, cx);
5873        self.end_transaction_at(Instant::now(), cx)
5874    }
5875
5876    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5877        self.end_selection(cx);
5878        if let Some(tx_id) = self
5879            .buffer
5880            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5881        {
5882            self.selection_history
5883                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5884        }
5885    }
5886
5887    fn end_transaction_at(
5888        &mut self,
5889        now: Instant,
5890        cx: &mut ViewContext<Self>,
5891    ) -> Option<TransactionId> {
5892        if let Some(tx_id) = self
5893            .buffer
5894            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5895        {
5896            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5897                *end_selections = Some(self.selections.disjoint_anchors());
5898            } else {
5899                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5900            }
5901
5902            cx.emit(Event::Edited);
5903            Some(tx_id)
5904        } else {
5905            None
5906        }
5907    }
5908
5909    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5910        let mut fold_ranges = Vec::new();
5911
5912        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5913        let selections = self.selections.all::<Point>(cx);
5914        for selection in selections {
5915            let range = selection.display_range(&display_map).sorted();
5916            let buffer_start_row = range.start.to_point(&display_map).row;
5917
5918            for row in (0..=range.end.row()).rev() {
5919                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5920                    let fold_range = self.foldable_range_for_line(&display_map, row);
5921                    if fold_range.end.row >= buffer_start_row {
5922                        fold_ranges.push(fold_range);
5923                        if row <= range.start.row() {
5924                            break;
5925                        }
5926                    }
5927                }
5928            }
5929        }
5930
5931        self.fold_ranges(fold_ranges, cx);
5932    }
5933
5934    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5935        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5936        let buffer = &display_map.buffer_snapshot;
5937        let selections = self.selections.all::<Point>(cx);
5938        let ranges = selections
5939            .iter()
5940            .map(|s| {
5941                let range = s.display_range(&display_map).sorted();
5942                let mut start = range.start.to_point(&display_map);
5943                let mut end = range.end.to_point(&display_map);
5944                start.column = 0;
5945                end.column = buffer.line_len(end.row);
5946                start..end
5947            })
5948            .collect::<Vec<_>>();
5949        self.unfold_ranges(ranges, true, cx);
5950    }
5951
5952    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5953        let max_point = display_map.max_point();
5954        if display_row >= max_point.row() {
5955            false
5956        } else {
5957            let (start_indent, is_blank) = display_map.line_indent(display_row);
5958            if is_blank {
5959                false
5960            } else {
5961                for display_row in display_row + 1..=max_point.row() {
5962                    let (indent, is_blank) = display_map.line_indent(display_row);
5963                    if !is_blank {
5964                        return indent > start_indent;
5965                    }
5966                }
5967                false
5968            }
5969        }
5970    }
5971
5972    fn foldable_range_for_line(
5973        &self,
5974        display_map: &DisplaySnapshot,
5975        start_row: u32,
5976    ) -> Range<Point> {
5977        let max_point = display_map.max_point();
5978
5979        let (start_indent, _) = display_map.line_indent(start_row);
5980        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5981        let mut end = None;
5982        for row in start_row + 1..=max_point.row() {
5983            let (indent, is_blank) = display_map.line_indent(row);
5984            if !is_blank && indent <= start_indent {
5985                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5986                break;
5987            }
5988        }
5989
5990        let end = end.unwrap_or(max_point);
5991        start.to_point(display_map)..end.to_point(display_map)
5992    }
5993
5994    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5995        let selections = self.selections.all::<Point>(cx);
5996        let ranges = selections.into_iter().map(|s| s.start..s.end);
5997        self.fold_ranges(ranges, cx);
5998    }
5999
6000    pub fn fold_ranges<T: ToOffset>(
6001        &mut self,
6002        ranges: impl IntoIterator<Item = Range<T>>,
6003        cx: &mut ViewContext<Self>,
6004    ) {
6005        let mut ranges = ranges.into_iter().peekable();
6006        if ranges.peek().is_some() {
6007            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6008            self.request_autoscroll(Autoscroll::Fit, cx);
6009            cx.notify();
6010        }
6011    }
6012
6013    pub fn unfold_ranges<T: ToOffset>(
6014        &mut self,
6015        ranges: impl IntoIterator<Item = Range<T>>,
6016        inclusive: bool,
6017        cx: &mut ViewContext<Self>,
6018    ) {
6019        let mut ranges = ranges.into_iter().peekable();
6020        if ranges.peek().is_some() {
6021            self.display_map
6022                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6023            self.request_autoscroll(Autoscroll::Fit, cx);
6024            cx.notify();
6025        }
6026    }
6027
6028    pub fn insert_blocks(
6029        &mut self,
6030        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6031        cx: &mut ViewContext<Self>,
6032    ) -> Vec<BlockId> {
6033        let blocks = self
6034            .display_map
6035            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6036        self.request_autoscroll(Autoscroll::Fit, cx);
6037        blocks
6038    }
6039
6040    pub fn replace_blocks(
6041        &mut self,
6042        blocks: HashMap<BlockId, RenderBlock>,
6043        cx: &mut ViewContext<Self>,
6044    ) {
6045        self.display_map
6046            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6047        self.request_autoscroll(Autoscroll::Fit, cx);
6048    }
6049
6050    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6051        self.display_map.update(cx, |display_map, cx| {
6052            display_map.remove_blocks(block_ids, cx)
6053        });
6054    }
6055
6056    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
6057        self.display_map
6058            .update(cx, |map, cx| map.snapshot(cx))
6059            .longest_row()
6060    }
6061
6062    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
6063        self.display_map
6064            .update(cx, |map, cx| map.snapshot(cx))
6065            .max_point()
6066    }
6067
6068    pub fn text(&self, cx: &AppContext) -> String {
6069        self.buffer.read(cx).read(cx).text()
6070    }
6071
6072    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6073        self.transact(cx, |this, cx| {
6074            this.buffer
6075                .read(cx)
6076                .as_singleton()
6077                .expect("you can only call set_text on editors for singleton buffers")
6078                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6079        });
6080    }
6081
6082    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
6083        self.display_map
6084            .update(cx, |map, cx| map.snapshot(cx))
6085            .text()
6086    }
6087
6088    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6089        let language_name = self
6090            .buffer
6091            .read(cx)
6092            .as_singleton()
6093            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6094            .map(|l| l.name());
6095
6096        let settings = cx.global::<Settings>();
6097        let mode = self
6098            .soft_wrap_mode_override
6099            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6100        match mode {
6101            settings::SoftWrap::None => SoftWrap::None,
6102            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6103            settings::SoftWrap::PreferredLineLength => {
6104                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6105            }
6106        }
6107    }
6108
6109    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6110        self.soft_wrap_mode_override = Some(mode);
6111        cx.notify();
6112    }
6113
6114    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
6115        self.display_map
6116            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6117    }
6118
6119    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6120        self.highlighted_rows = rows;
6121    }
6122
6123    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6124        self.highlighted_rows.clone()
6125    }
6126
6127    pub fn highlight_background<T: 'static>(
6128        &mut self,
6129        ranges: Vec<Range<Anchor>>,
6130        color_fetcher: fn(&Theme) -> Color,
6131        cx: &mut ViewContext<Self>,
6132    ) {
6133        self.background_highlights
6134            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6135        cx.notify();
6136    }
6137
6138    #[allow(clippy::type_complexity)]
6139    pub fn clear_background_highlights<T: 'static>(
6140        &mut self,
6141        cx: &mut ViewContext<Self>,
6142    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6143        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6144        if highlights.is_some() {
6145            cx.notify();
6146        }
6147        highlights
6148    }
6149
6150    #[cfg(feature = "test-support")]
6151    pub fn all_background_highlights(
6152        &mut self,
6153        cx: &mut ViewContext<Self>,
6154    ) -> Vec<(Range<DisplayPoint>, Color)> {
6155        let snapshot = self.snapshot(cx);
6156        let buffer = &snapshot.buffer_snapshot;
6157        let start = buffer.anchor_before(0);
6158        let end = buffer.anchor_after(buffer.len());
6159        let theme = cx.global::<Settings>().theme.as_ref();
6160        self.background_highlights_in_range(start..end, &snapshot, theme)
6161    }
6162
6163    fn document_highlights_for_position<'a>(
6164        &'a self,
6165        position: Anchor,
6166        buffer: &'a MultiBufferSnapshot,
6167    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6168        let read_highlights = self
6169            .background_highlights
6170            .get(&TypeId::of::<DocumentHighlightRead>())
6171            .map(|h| &h.1);
6172        let write_highlights = self
6173            .background_highlights
6174            .get(&TypeId::of::<DocumentHighlightWrite>())
6175            .map(|h| &h.1);
6176        let left_position = position.bias_left(buffer);
6177        let right_position = position.bias_right(buffer);
6178        read_highlights
6179            .into_iter()
6180            .chain(write_highlights)
6181            .flat_map(move |ranges| {
6182                let start_ix = match ranges.binary_search_by(|probe| {
6183                    let cmp = probe.end.cmp(&left_position, buffer);
6184                    if cmp.is_ge() {
6185                        Ordering::Greater
6186                    } else {
6187                        Ordering::Less
6188                    }
6189                }) {
6190                    Ok(i) | Err(i) => i,
6191                };
6192
6193                let right_position = right_position.clone();
6194                ranges[start_ix..]
6195                    .iter()
6196                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6197            })
6198    }
6199
6200    pub fn background_highlights_in_range(
6201        &self,
6202        search_range: Range<Anchor>,
6203        display_snapshot: &DisplaySnapshot,
6204        theme: &Theme,
6205    ) -> Vec<(Range<DisplayPoint>, Color)> {
6206        let mut results = Vec::new();
6207        let buffer = &display_snapshot.buffer_snapshot;
6208        for (color_fetcher, ranges) in self.background_highlights.values() {
6209            let color = color_fetcher(theme);
6210            let start_ix = match ranges.binary_search_by(|probe| {
6211                let cmp = probe.end.cmp(&search_range.start, buffer);
6212                if cmp.is_gt() {
6213                    Ordering::Greater
6214                } else {
6215                    Ordering::Less
6216                }
6217            }) {
6218                Ok(i) | Err(i) => i,
6219            };
6220            for range in &ranges[start_ix..] {
6221                if range.start.cmp(&search_range.end, buffer).is_ge() {
6222                    break;
6223                }
6224                let start = range
6225                    .start
6226                    .to_point(buffer)
6227                    .to_display_point(display_snapshot);
6228                let end = range
6229                    .end
6230                    .to_point(buffer)
6231                    .to_display_point(display_snapshot);
6232                results.push((start..end, color))
6233            }
6234        }
6235        results
6236    }
6237
6238    pub fn highlight_text<T: 'static>(
6239        &mut self,
6240        ranges: Vec<Range<Anchor>>,
6241        style: HighlightStyle,
6242        cx: &mut ViewContext<Self>,
6243    ) {
6244        self.display_map.update(cx, |map, _| {
6245            map.highlight_text(TypeId::of::<T>(), ranges, style)
6246        });
6247        cx.notify();
6248    }
6249
6250    pub fn text_highlights<'a, T: 'static>(
6251        &'a self,
6252        cx: &'a AppContext,
6253    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6254        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6255    }
6256
6257    pub fn clear_text_highlights<T: 'static>(
6258        &mut self,
6259        cx: &mut ViewContext<Self>,
6260    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6261        let highlights = self
6262            .display_map
6263            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6264        if highlights.is_some() {
6265            cx.notify();
6266        }
6267        highlights
6268    }
6269
6270    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6271        self.blink_manager.read(cx).visible() && self.focused
6272    }
6273
6274    pub fn show_scrollbars(&self) -> bool {
6275        self.show_scrollbars
6276    }
6277
6278    fn make_scrollbar_visible(&mut self, cx: &mut ViewContext<Self>) {
6279        if !self.show_scrollbars {
6280            self.show_scrollbars = true;
6281            cx.notify();
6282        }
6283
6284        if cx.default_global::<ScrollbarAutoHide>().0 {
6285            self.hide_scrollbar_task = Some(cx.spawn_weak(|this, mut cx| async move {
6286                Timer::after(SCROLLBAR_SHOW_INTERVAL).await;
6287                if let Some(this) = this.upgrade(&cx) {
6288                    this.update(&mut cx, |this, cx| {
6289                        this.show_scrollbars = false;
6290                        cx.notify();
6291                    });
6292                }
6293            }));
6294        } else {
6295            self.hide_scrollbar_task = None;
6296        }
6297    }
6298
6299    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6300        cx.notify();
6301    }
6302
6303    fn on_buffer_event(
6304        &mut self,
6305        _: ModelHandle<MultiBuffer>,
6306        event: &language::Event,
6307        cx: &mut ViewContext<Self>,
6308    ) {
6309        match event {
6310            language::Event::Edited => {
6311                self.refresh_active_diagnostics(cx);
6312                self.refresh_code_actions(cx);
6313                cx.emit(Event::BufferEdited);
6314            }
6315            language::Event::Reparsed => cx.emit(Event::Reparsed),
6316            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6317            language::Event::Saved => cx.emit(Event::Saved),
6318            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6319            language::Event::Reloaded => cx.emit(Event::TitleChanged),
6320            language::Event::Closed => cx.emit(Event::Closed),
6321            language::Event::DiagnosticsUpdated => {
6322                self.refresh_active_diagnostics(cx);
6323            }
6324            _ => {}
6325        }
6326    }
6327
6328    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6329        cx.notify();
6330    }
6331
6332    pub fn set_searchable(&mut self, searchable: bool) {
6333        self.searchable = searchable;
6334    }
6335
6336    pub fn searchable(&self) -> bool {
6337        self.searchable
6338    }
6339
6340    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6341        let active_item = workspace.active_item(cx);
6342        let editor_handle = if let Some(editor) = active_item
6343            .as_ref()
6344            .and_then(|item| item.act_as::<Self>(cx))
6345        {
6346            editor
6347        } else {
6348            cx.propagate_action();
6349            return;
6350        };
6351
6352        let editor = editor_handle.read(cx);
6353        let buffer = editor.buffer.read(cx);
6354        if buffer.is_singleton() {
6355            cx.propagate_action();
6356            return;
6357        }
6358
6359        let mut new_selections_by_buffer = HashMap::default();
6360        for selection in editor.selections.all::<usize>(cx) {
6361            for (buffer, mut range) in
6362                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6363            {
6364                if selection.reversed {
6365                    mem::swap(&mut range.start, &mut range.end);
6366                }
6367                new_selections_by_buffer
6368                    .entry(buffer)
6369                    .or_insert(Vec::new())
6370                    .push(range)
6371            }
6372        }
6373
6374        editor_handle.update(cx, |editor, cx| {
6375            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6376        });
6377        let pane = workspace.active_pane().clone();
6378        pane.update(cx, |pane, _| pane.disable_history());
6379
6380        // We defer the pane interaction because we ourselves are a workspace item
6381        // and activating a new item causes the pane to call a method on us reentrantly,
6382        // which panics if we're on the stack.
6383        cx.defer(move |workspace, cx| {
6384            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6385                let editor = workspace.open_project_item::<Self>(buffer, cx);
6386                editor.update(cx, |editor, cx| {
6387                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6388                        s.select_ranges(ranges);
6389                    });
6390                });
6391            }
6392
6393            pane.update(cx, |pane, _| pane.enable_history());
6394        });
6395    }
6396
6397    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6398        let editor = workspace.open_path(action.path.clone(), true, cx);
6399        let position = action.position;
6400        let anchor = action.anchor;
6401        cx.spawn_weak(|_, mut cx| async move {
6402            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6403            editor.update(&mut cx, |editor, cx| {
6404                let buffer = editor.buffer().read(cx).as_singleton()?;
6405                let buffer = buffer.read(cx);
6406                let cursor = if buffer.can_resolve(&anchor) {
6407                    language::ToPoint::to_point(&anchor, buffer)
6408                } else {
6409                    buffer.clip_point(position, Bias::Left)
6410                };
6411
6412                let nav_history = editor.nav_history.take();
6413                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6414                    s.select_ranges([cursor..cursor]);
6415                });
6416                editor.nav_history = nav_history;
6417
6418                Some(())
6419            })?;
6420            Some(())
6421        })
6422        .detach()
6423    }
6424
6425    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6426        let snapshot = self.buffer.read(cx).read(cx);
6427        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6428        Some(
6429            ranges
6430                .iter()
6431                .map(move |range| {
6432                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6433                })
6434                .collect(),
6435        )
6436    }
6437
6438    fn selection_replacement_ranges(
6439        &self,
6440        range: Range<OffsetUtf16>,
6441        cx: &AppContext,
6442    ) -> Vec<Range<OffsetUtf16>> {
6443        let selections = self.selections.all::<OffsetUtf16>(cx);
6444        let newest_selection = selections
6445            .iter()
6446            .max_by_key(|selection| selection.id)
6447            .unwrap();
6448        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6449        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6450        let snapshot = self.buffer.read(cx).read(cx);
6451        selections
6452            .into_iter()
6453            .map(|mut selection| {
6454                selection.start.0 =
6455                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6456                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6457                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6458                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6459            })
6460            .collect()
6461    }
6462
6463    fn report_event(&self, name: &str, cx: &AppContext) {
6464        if let Some((project, file)) = self.project.as_ref().zip(
6465            self.buffer
6466                .read(cx)
6467                .as_singleton()
6468                .and_then(|b| b.read(cx).file()),
6469        ) {
6470            project.read(cx).client().report_event(
6471                name,
6472                json!({
6473                    "file_extension": file
6474                        .path()
6475                        .extension()
6476                        .and_then(|e| e.to_str())
6477                }),
6478            );
6479        }
6480    }
6481}
6482
6483impl EditorSnapshot {
6484    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6485        self.display_snapshot.buffer_snapshot.language_at(position)
6486    }
6487
6488    pub fn is_focused(&self) -> bool {
6489        self.is_focused
6490    }
6491
6492    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6493        self.placeholder_text.as_ref()
6494    }
6495
6496    pub fn scroll_position(&self) -> Vector2F {
6497        compute_scroll_position(
6498            &self.display_snapshot,
6499            self.scroll_position,
6500            &self.scroll_top_anchor,
6501        )
6502    }
6503}
6504
6505impl Deref for EditorSnapshot {
6506    type Target = DisplaySnapshot;
6507
6508    fn deref(&self) -> &Self::Target {
6509        &self.display_snapshot
6510    }
6511}
6512
6513fn compute_scroll_position(
6514    snapshot: &DisplaySnapshot,
6515    mut scroll_position: Vector2F,
6516    scroll_top_anchor: &Anchor,
6517) -> Vector2F {
6518    if *scroll_top_anchor != Anchor::min() {
6519        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
6520        scroll_position.set_y(scroll_top + scroll_position.y());
6521    } else {
6522        scroll_position.set_y(0.);
6523    }
6524    scroll_position
6525}
6526
6527#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6528pub enum Event {
6529    BufferEdited,
6530    Edited,
6531    Reparsed,
6532    Blurred,
6533    DirtyChanged,
6534    Saved,
6535    TitleChanged,
6536    SelectionsChanged { local: bool },
6537    ScrollPositionChanged { local: bool },
6538    Closed,
6539    IgnoredInput,
6540}
6541
6542pub struct EditorFocused(pub ViewHandle<Editor>);
6543pub struct EditorBlurred(pub ViewHandle<Editor>);
6544pub struct EditorReleased(pub WeakViewHandle<Editor>);
6545
6546impl Entity for Editor {
6547    type Event = Event;
6548
6549    fn release(&mut self, cx: &mut MutableAppContext) {
6550        cx.emit_global(EditorReleased(self.handle.clone()));
6551    }
6552}
6553
6554impl View for Editor {
6555    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6556        let style = self.style(cx);
6557        let font_changed = self.display_map.update(cx, |map, cx| {
6558            map.set_font(style.text.font_id, style.text.font_size, cx)
6559        });
6560
6561        if font_changed {
6562            let handle = self.handle.clone();
6563            cx.defer(move |cx| {
6564                if let Some(editor) = handle.upgrade(cx) {
6565                    editor.update(cx, |editor, cx| {
6566                        hide_hover(editor, cx);
6567                        hide_link_definition(editor, cx);
6568                    })
6569                }
6570            });
6571        }
6572
6573        Stack::new()
6574            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6575            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6576            .boxed()
6577    }
6578
6579    fn ui_name() -> &'static str {
6580        "Editor"
6581    }
6582
6583    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6584        let focused_event = EditorFocused(cx.handle());
6585        cx.emit_global(focused_event);
6586        if let Some(rename) = self.pending_rename.as_ref() {
6587            cx.focus(&rename.editor);
6588        } else {
6589            if !self.focused {
6590                self.blink_manager.update(cx, BlinkManager::enable);
6591            }
6592            self.focused = true;
6593            self.buffer.update(cx, |buffer, cx| {
6594                buffer.finalize_last_transaction(cx);
6595                if self.leader_replica_id.is_none() {
6596                    buffer.set_active_selections(
6597                        &self.selections.disjoint_anchors(),
6598                        self.selections.line_mode,
6599                        self.cursor_shape,
6600                        cx,
6601                    );
6602                }
6603            });
6604        }
6605    }
6606
6607    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6608        let blurred_event = EditorBlurred(cx.handle());
6609        cx.emit_global(blurred_event);
6610        self.focused = false;
6611        self.blink_manager.update(cx, BlinkManager::disable);
6612        self.buffer
6613            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6614        self.hide_context_menu(cx);
6615        hide_hover(self, cx);
6616        cx.emit(Event::Blurred);
6617        cx.notify();
6618    }
6619
6620    fn modifiers_changed(
6621        &mut self,
6622        event: &gpui::ModifiersChangedEvent,
6623        cx: &mut ViewContext<Self>,
6624    ) -> bool {
6625        let pending_selection = self.has_pending_selection();
6626
6627        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6628            if event.cmd && !pending_selection {
6629                let snapshot = self.snapshot(cx);
6630                let kind = if event.shift {
6631                    LinkDefinitionKind::Type
6632                } else {
6633                    LinkDefinitionKind::Symbol
6634                };
6635
6636                show_link_definition(kind, self, point, snapshot, cx);
6637                return false;
6638            }
6639        }
6640
6641        {
6642            if self.link_go_to_definition_state.symbol_range.is_some()
6643                || !self.link_go_to_definition_state.definitions.is_empty()
6644            {
6645                self.link_go_to_definition_state.symbol_range.take();
6646                self.link_go_to_definition_state.definitions.clear();
6647                cx.notify();
6648            }
6649
6650            self.link_go_to_definition_state.task = None;
6651
6652            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6653        }
6654
6655        false
6656    }
6657
6658    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
6659        let mut context = Self::default_keymap_context();
6660        let mode = match self.mode {
6661            EditorMode::SingleLine => "single_line",
6662            EditorMode::AutoHeight { .. } => "auto_height",
6663            EditorMode::Full => "full",
6664        };
6665        context.map.insert("mode".into(), mode.into());
6666        if self.pending_rename.is_some() {
6667            context.set.insert("renaming".into());
6668        }
6669        match self.context_menu.as_ref() {
6670            Some(ContextMenu::Completions(_)) => {
6671                context.set.insert("showing_completions".into());
6672            }
6673            Some(ContextMenu::CodeActions(_)) => {
6674                context.set.insert("showing_code_actions".into());
6675            }
6676            None => {}
6677        }
6678
6679        for layer in self.keymap_context_layers.values() {
6680            context.extend(layer);
6681        }
6682
6683        context
6684    }
6685
6686    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6687        Some(
6688            self.buffer
6689                .read(cx)
6690                .read(cx)
6691                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6692                .collect(),
6693        )
6694    }
6695
6696    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6697        // Prevent the IME menu from appearing when holding down an alphabetic key
6698        // while input is disabled.
6699        if !self.input_enabled {
6700            return None;
6701        }
6702
6703        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6704        Some(range.start.0..range.end.0)
6705    }
6706
6707    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6708        let snapshot = self.buffer.read(cx).read(cx);
6709        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6710        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6711    }
6712
6713    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6714        self.clear_text_highlights::<InputComposition>(cx);
6715        self.ime_transaction.take();
6716    }
6717
6718    fn replace_text_in_range(
6719        &mut self,
6720        range_utf16: Option<Range<usize>>,
6721        text: &str,
6722        cx: &mut ViewContext<Self>,
6723    ) {
6724        if !self.input_enabled {
6725            cx.emit(Event::IgnoredInput);
6726            return;
6727        }
6728
6729        self.transact(cx, |this, cx| {
6730            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6731                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6732                Some(this.selection_replacement_ranges(range_utf16, cx))
6733            } else {
6734                this.marked_text_ranges(cx)
6735            };
6736
6737            if let Some(new_selected_ranges) = new_selected_ranges {
6738                this.change_selections(None, cx, |selections| {
6739                    selections.select_ranges(new_selected_ranges)
6740                });
6741            }
6742            this.handle_input(text, cx);
6743        });
6744
6745        if let Some(transaction) = self.ime_transaction {
6746            self.buffer.update(cx, |buffer, cx| {
6747                buffer.group_until_transaction(transaction, cx);
6748            });
6749        }
6750
6751        self.unmark_text(cx);
6752    }
6753
6754    fn replace_and_mark_text_in_range(
6755        &mut self,
6756        range_utf16: Option<Range<usize>>,
6757        text: &str,
6758        new_selected_range_utf16: Option<Range<usize>>,
6759        cx: &mut ViewContext<Self>,
6760    ) {
6761        if !self.input_enabled {
6762            cx.emit(Event::IgnoredInput);
6763            return;
6764        }
6765
6766        let transaction = self.transact(cx, |this, cx| {
6767            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6768                let snapshot = this.buffer.read(cx).read(cx);
6769                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6770                    for marked_range in &mut marked_ranges {
6771                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6772                        marked_range.start.0 += relative_range_utf16.start;
6773                        marked_range.start =
6774                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6775                        marked_range.end =
6776                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6777                    }
6778                }
6779                Some(marked_ranges)
6780            } else if let Some(range_utf16) = range_utf16 {
6781                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6782                Some(this.selection_replacement_ranges(range_utf16, cx))
6783            } else {
6784                None
6785            };
6786
6787            if let Some(ranges) = ranges_to_replace {
6788                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6789            }
6790
6791            let marked_ranges = {
6792                let snapshot = this.buffer.read(cx).read(cx);
6793                this.selections
6794                    .disjoint_anchors()
6795                    .iter()
6796                    .map(|selection| {
6797                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6798                    })
6799                    .collect::<Vec<_>>()
6800            };
6801
6802            if text.is_empty() {
6803                this.unmark_text(cx);
6804            } else {
6805                this.highlight_text::<InputComposition>(
6806                    marked_ranges.clone(),
6807                    this.style(cx).composition_mark,
6808                    cx,
6809                );
6810            }
6811
6812            this.handle_input(text, cx);
6813
6814            if let Some(new_selected_range) = new_selected_range_utf16 {
6815                let snapshot = this.buffer.read(cx).read(cx);
6816                let new_selected_ranges = marked_ranges
6817                    .into_iter()
6818                    .map(|marked_range| {
6819                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6820                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6821                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6822                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6823                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6824                    })
6825                    .collect::<Vec<_>>();
6826
6827                drop(snapshot);
6828                this.change_selections(None, cx, |selections| {
6829                    selections.select_ranges(new_selected_ranges)
6830                });
6831            }
6832        });
6833
6834        self.ime_transaction = self.ime_transaction.or(transaction);
6835        if let Some(transaction) = self.ime_transaction {
6836            self.buffer.update(cx, |buffer, cx| {
6837                buffer.group_until_transaction(transaction, cx);
6838            });
6839        }
6840
6841        if self.text_highlights::<InputComposition>(cx).is_none() {
6842            self.ime_transaction.take();
6843        }
6844    }
6845}
6846
6847fn build_style(
6848    settings: &Settings,
6849    get_field_editor_theme: Option<GetFieldEditorTheme>,
6850    override_text_style: Option<&OverrideTextStyle>,
6851    cx: &AppContext,
6852) -> EditorStyle {
6853    let font_cache = cx.font_cache();
6854
6855    let mut theme = settings.theme.editor.clone();
6856    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6857        let field_editor_theme = get_field_editor_theme(&settings.theme);
6858        theme.text_color = field_editor_theme.text.color;
6859        theme.selection = field_editor_theme.selection;
6860        theme.background = field_editor_theme
6861            .container
6862            .background_color
6863            .unwrap_or_default();
6864        EditorStyle {
6865            text: field_editor_theme.text,
6866            placeholder_text: field_editor_theme.placeholder_text,
6867            theme,
6868        }
6869    } else {
6870        let font_family_id = settings.buffer_font_family;
6871        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6872        let font_properties = Default::default();
6873        let font_id = font_cache
6874            .select_font(font_family_id, &font_properties)
6875            .unwrap();
6876        let font_size = settings.buffer_font_size;
6877        EditorStyle {
6878            text: TextStyle {
6879                color: settings.theme.editor.text_color,
6880                font_family_name,
6881                font_family_id,
6882                font_id,
6883                font_size,
6884                font_properties,
6885                underline: Default::default(),
6886            },
6887            placeholder_text: None,
6888            theme,
6889        }
6890    };
6891
6892    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6893        if let Some(highlighted) = style
6894            .text
6895            .clone()
6896            .highlight(highlight_style, font_cache)
6897            .log_err()
6898        {
6899            style.text = highlighted;
6900        }
6901    }
6902
6903    style
6904}
6905
6906trait SelectionExt {
6907    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6908    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6909    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6910    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6911        -> Range<u32>;
6912}
6913
6914impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6915    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6916        let start = self.start.to_point(buffer);
6917        let end = self.end.to_point(buffer);
6918        if self.reversed {
6919            end..start
6920        } else {
6921            start..end
6922        }
6923    }
6924
6925    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6926        let start = self.start.to_offset(buffer);
6927        let end = self.end.to_offset(buffer);
6928        if self.reversed {
6929            end..start
6930        } else {
6931            start..end
6932        }
6933    }
6934
6935    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6936        let start = self
6937            .start
6938            .to_point(&map.buffer_snapshot)
6939            .to_display_point(map);
6940        let end = self
6941            .end
6942            .to_point(&map.buffer_snapshot)
6943            .to_display_point(map);
6944        if self.reversed {
6945            end..start
6946        } else {
6947            start..end
6948        }
6949    }
6950
6951    fn spanned_rows(
6952        &self,
6953        include_end_if_at_line_start: bool,
6954        map: &DisplaySnapshot,
6955    ) -> Range<u32> {
6956        let start = self.start.to_point(&map.buffer_snapshot);
6957        let mut end = self.end.to_point(&map.buffer_snapshot);
6958        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6959            end.row -= 1;
6960        }
6961
6962        let buffer_start = map.prev_line_boundary(start).0;
6963        let buffer_end = map.next_line_boundary(end).0;
6964        buffer_start.row..buffer_end.row + 1
6965    }
6966}
6967
6968impl<T: InvalidationRegion> InvalidationStack<T> {
6969    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6970    where
6971        S: Clone + ToOffset,
6972    {
6973        while let Some(region) = self.last() {
6974            let all_selections_inside_invalidation_ranges =
6975                if selections.len() == region.ranges().len() {
6976                    selections
6977                        .iter()
6978                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6979                        .all(|(selection, invalidation_range)| {
6980                            let head = selection.head().to_offset(buffer);
6981                            invalidation_range.start <= head && invalidation_range.end >= head
6982                        })
6983                } else {
6984                    false
6985                };
6986
6987            if all_selections_inside_invalidation_ranges {
6988                break;
6989            } else {
6990                self.pop();
6991            }
6992        }
6993    }
6994}
6995
6996impl<T> Default for InvalidationStack<T> {
6997    fn default() -> Self {
6998        Self(Default::default())
6999    }
7000}
7001
7002impl<T> Deref for InvalidationStack<T> {
7003    type Target = Vec<T>;
7004
7005    fn deref(&self) -> &Self::Target {
7006        &self.0
7007    }
7008}
7009
7010impl<T> DerefMut for InvalidationStack<T> {
7011    fn deref_mut(&mut self) -> &mut Self::Target {
7012        &mut self.0
7013    }
7014}
7015
7016impl InvalidationRegion for SnippetState {
7017    fn ranges(&self) -> &[Range<Anchor>] {
7018        &self.ranges[self.active_index]
7019    }
7020}
7021
7022impl Deref for EditorStyle {
7023    type Target = theme::Editor;
7024
7025    fn deref(&self) -> &Self::Target {
7026        &self.theme
7027    }
7028}
7029
7030pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7031    let mut highlighted_lines = Vec::new();
7032    for line in diagnostic.message.lines() {
7033        highlighted_lines.push(highlight_diagnostic_message(line));
7034    }
7035
7036    Arc::new(move |cx: &mut BlockContext| {
7037        let settings = cx.global::<Settings>();
7038        let theme = &settings.theme.editor;
7039        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7040        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7041        Flex::column()
7042            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7043                Label::new(
7044                    line.clone(),
7045                    style.message.clone().with_font_size(font_size),
7046                )
7047                .with_highlights(highlights.clone())
7048                .contained()
7049                .with_margin_left(cx.anchor_x)
7050                .boxed()
7051            }))
7052            .aligned()
7053            .left()
7054            .boxed()
7055    })
7056}
7057
7058pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
7059    let mut message_without_backticks = String::new();
7060    let mut prev_offset = 0;
7061    let mut inside_block = false;
7062    let mut highlights = Vec::new();
7063    for (match_ix, (offset, _)) in message
7064        .match_indices('`')
7065        .chain([(message.len(), "")])
7066        .enumerate()
7067    {
7068        message_without_backticks.push_str(&message[prev_offset..offset]);
7069        if inside_block {
7070            highlights.extend(prev_offset - match_ix..offset - match_ix);
7071        }
7072
7073        inside_block = !inside_block;
7074        prev_offset = offset + 1;
7075    }
7076
7077    (message_without_backticks, highlights)
7078}
7079
7080pub fn diagnostic_style(
7081    severity: DiagnosticSeverity,
7082    valid: bool,
7083    theme: &theme::Editor,
7084) -> DiagnosticStyle {
7085    match (severity, valid) {
7086        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7087        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7088        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7089        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7090        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7091        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7092        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7093        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7094        _ => theme.invalid_hint_diagnostic.clone(),
7095    }
7096}
7097
7098pub fn combine_syntax_and_fuzzy_match_highlights(
7099    text: &str,
7100    default_style: HighlightStyle,
7101    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7102    match_indices: &[usize],
7103) -> Vec<(Range<usize>, HighlightStyle)> {
7104    let mut result = Vec::new();
7105    let mut match_indices = match_indices.iter().copied().peekable();
7106
7107    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7108    {
7109        syntax_highlight.weight = None;
7110
7111        // Add highlights for any fuzzy match characters before the next
7112        // syntax highlight range.
7113        while let Some(&match_index) = match_indices.peek() {
7114            if match_index >= range.start {
7115                break;
7116            }
7117            match_indices.next();
7118            let end_index = char_ix_after(match_index, text);
7119            let mut match_style = default_style;
7120            match_style.weight = Some(fonts::Weight::BOLD);
7121            result.push((match_index..end_index, match_style));
7122        }
7123
7124        if range.start == usize::MAX {
7125            break;
7126        }
7127
7128        // Add highlights for any fuzzy match characters within the
7129        // syntax highlight range.
7130        let mut offset = range.start;
7131        while let Some(&match_index) = match_indices.peek() {
7132            if match_index >= range.end {
7133                break;
7134            }
7135
7136            match_indices.next();
7137            if match_index > offset {
7138                result.push((offset..match_index, syntax_highlight));
7139            }
7140
7141            let mut end_index = char_ix_after(match_index, text);
7142            while let Some(&next_match_index) = match_indices.peek() {
7143                if next_match_index == end_index && next_match_index < range.end {
7144                    end_index = char_ix_after(next_match_index, text);
7145                    match_indices.next();
7146                } else {
7147                    break;
7148                }
7149            }
7150
7151            let mut match_style = syntax_highlight;
7152            match_style.weight = Some(fonts::Weight::BOLD);
7153            result.push((match_index..end_index, match_style));
7154            offset = end_index;
7155        }
7156
7157        if offset < range.end {
7158            result.push((offset..range.end, syntax_highlight));
7159        }
7160    }
7161
7162    fn char_ix_after(ix: usize, text: &str) -> usize {
7163        ix + text[ix..].chars().next().unwrap().len_utf8()
7164    }
7165
7166    result
7167}
7168
7169pub fn styled_runs_for_code_label<'a>(
7170    label: &'a CodeLabel,
7171    syntax_theme: &'a theme::SyntaxTheme,
7172) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7173    let fade_out = HighlightStyle {
7174        fade_out: Some(0.35),
7175        ..Default::default()
7176    };
7177
7178    let mut prev_end = label.filter_range.end;
7179    label
7180        .runs
7181        .iter()
7182        .enumerate()
7183        .flat_map(move |(ix, (range, highlight_id))| {
7184            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7185                style
7186            } else {
7187                return Default::default();
7188            };
7189            let mut muted_style = style;
7190            muted_style.highlight(fade_out);
7191
7192            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7193            if range.start >= label.filter_range.end {
7194                if range.start > prev_end {
7195                    runs.push((prev_end..range.start, fade_out));
7196                }
7197                runs.push((range.clone(), muted_style));
7198            } else if range.end <= label.filter_range.end {
7199                runs.push((range.clone(), style));
7200            } else {
7201                runs.push((range.start..label.filter_range.end, style));
7202                runs.push((label.filter_range.end..range.end, muted_style));
7203            }
7204            prev_end = cmp::max(prev_end, range.end);
7205
7206            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7207                runs.push((prev_end..label.text.len(), fade_out));
7208            }
7209
7210            runs
7211        })
7212}
7213
7214trait RangeExt<T> {
7215    fn sorted(&self) -> Range<T>;
7216    fn to_inclusive(&self) -> RangeInclusive<T>;
7217}
7218
7219impl<T: Ord + Clone> RangeExt<T> for Range<T> {
7220    fn sorted(&self) -> Self {
7221        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
7222    }
7223
7224    fn to_inclusive(&self) -> RangeInclusive<T> {
7225        self.start.clone()..=self.end.clone()
7226    }
7227}
7228
7229trait RangeToAnchorExt {
7230    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7231}
7232
7233impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7234    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7235        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7236    }
7237}