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