editor.rs

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