editor.rs

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