editor.rs

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