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