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