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