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