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, OffsetUtf16, Point,
  47    Selection, SelectionGoal, 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 selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  58use serde::{Deserialize, Serialize};
  59use settings::Settings;
  60use smallvec::SmallVec;
  61use smol::Timer;
  62use snippet::Snippet;
  63use std::{
  64    any::TypeId,
  65    borrow::Cow,
  66    cmp::{self, Ordering, Reverse},
  67    mem,
  68    num::NonZeroU32,
  69    ops::{Deref, DerefMut, Range, RangeInclusive},
  70    sync::Arc,
  71    time::{Duration, Instant},
  72};
  73pub use sum_tree::Bias;
  74use theme::{DiagnosticStyle, Theme};
  75use util::{post_inc, ResultExt, TryFutureExt};
  76use workspace::{ItemNavHistory, Workspace};
  77
  78const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  79const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
  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    show_scrollbars: bool,
 432    hide_scrollbar_task: Option<Task<()>>,
 433    blink_epoch: usize,
 434    blinking_paused: bool,
 435    mode: EditorMode,
 436    vertical_scroll_margin: f32,
 437    placeholder_text: Option<Arc<str>>,
 438    highlighted_rows: Option<Range<u32>>,
 439    #[allow(clippy::type_complexity)]
 440    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 441    nav_history: Option<ItemNavHistory>,
 442    context_menu: Option<ContextMenu>,
 443    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 444    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 445    next_completion_id: CompletionId,
 446    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 447    code_actions_task: Option<Task<()>>,
 448    document_highlights_task: Option<Task<()>>,
 449    pending_rename: Option<RenameState>,
 450    searchable: bool,
 451    cursor_shape: CursorShape,
 452    keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
 453    input_enabled: bool,
 454    leader_replica_id: Option<u16>,
 455    hover_state: HoverState,
 456    link_go_to_definition_state: LinkGoToDefinitionState,
 457    _subscriptions: Vec<Subscription>,
 458}
 459
 460pub struct EditorSnapshot {
 461    pub mode: EditorMode,
 462    pub display_snapshot: DisplaySnapshot,
 463    pub placeholder_text: Option<Arc<str>>,
 464    is_focused: bool,
 465    scroll_position: Vector2F,
 466    scroll_top_anchor: Anchor,
 467}
 468
 469#[derive(Clone, Debug)]
 470struct SelectionHistoryEntry {
 471    selections: Arc<[Selection<Anchor>]>,
 472    select_next_state: Option<SelectNextState>,
 473    add_selections_state: Option<AddSelectionsState>,
 474}
 475
 476enum SelectionHistoryMode {
 477    Normal,
 478    Undoing,
 479    Redoing,
 480}
 481
 482impl Default for SelectionHistoryMode {
 483    fn default() -> Self {
 484        Self::Normal
 485    }
 486}
 487
 488#[derive(Default)]
 489struct SelectionHistory {
 490    #[allow(clippy::type_complexity)]
 491    selections_by_transaction:
 492        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 493    mode: SelectionHistoryMode,
 494    undo_stack: VecDeque<SelectionHistoryEntry>,
 495    redo_stack: VecDeque<SelectionHistoryEntry>,
 496}
 497
 498impl SelectionHistory {
 499    fn insert_transaction(
 500        &mut self,
 501        transaction_id: TransactionId,
 502        selections: Arc<[Selection<Anchor>]>,
 503    ) {
 504        self.selections_by_transaction
 505            .insert(transaction_id, (selections, None));
 506    }
 507
 508    #[allow(clippy::type_complexity)]
 509    fn transaction(
 510        &self,
 511        transaction_id: TransactionId,
 512    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 513        self.selections_by_transaction.get(&transaction_id)
 514    }
 515
 516    #[allow(clippy::type_complexity)]
 517    fn transaction_mut(
 518        &mut self,
 519        transaction_id: TransactionId,
 520    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 521        self.selections_by_transaction.get_mut(&transaction_id)
 522    }
 523
 524    fn push(&mut self, entry: SelectionHistoryEntry) {
 525        if !entry.selections.is_empty() {
 526            match self.mode {
 527                SelectionHistoryMode::Normal => {
 528                    self.push_undo(entry);
 529                    self.redo_stack.clear();
 530                }
 531                SelectionHistoryMode::Undoing => self.push_redo(entry),
 532                SelectionHistoryMode::Redoing => self.push_undo(entry),
 533            }
 534        }
 535    }
 536
 537    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 538        if self
 539            .undo_stack
 540            .back()
 541            .map_or(true, |e| e.selections != entry.selections)
 542        {
 543            self.undo_stack.push_back(entry);
 544            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 545                self.undo_stack.pop_front();
 546            }
 547        }
 548    }
 549
 550    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 551        if self
 552            .redo_stack
 553            .back()
 554            .map_or(true, |e| e.selections != entry.selections)
 555        {
 556            self.redo_stack.push_back(entry);
 557            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 558                self.redo_stack.pop_front();
 559            }
 560        }
 561    }
 562}
 563
 564#[derive(Clone, Debug)]
 565struct AddSelectionsState {
 566    above: bool,
 567    stack: Vec<usize>,
 568}
 569
 570#[derive(Clone, Debug)]
 571struct SelectNextState {
 572    query: AhoCorasick,
 573    wordwise: bool,
 574    done: bool,
 575}
 576
 577#[derive(Debug)]
 578struct AutocloseRegion {
 579    selection_id: usize,
 580    range: Range<Anchor>,
 581    pair: BracketPair,
 582}
 583
 584#[derive(Debug)]
 585struct SnippetState {
 586    ranges: Vec<Vec<Range<Anchor>>>,
 587    active_index: usize,
 588}
 589
 590pub struct RenameState {
 591    pub range: Range<Anchor>,
 592    pub old_name: Arc<str>,
 593    pub editor: ViewHandle<Editor>,
 594    block_id: BlockId,
 595}
 596
 597struct InvalidationStack<T>(Vec<T>);
 598
 599enum ContextMenu {
 600    Completions(CompletionsMenu),
 601    CodeActions(CodeActionsMenu),
 602}
 603
 604impl ContextMenu {
 605    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 606        if self.visible() {
 607            match self {
 608                ContextMenu::Completions(menu) => menu.select_prev(cx),
 609                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 610            }
 611            true
 612        } else {
 613            false
 614        }
 615    }
 616
 617    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 618        if self.visible() {
 619            match self {
 620                ContextMenu::Completions(menu) => menu.select_next(cx),
 621                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 622            }
 623            true
 624        } else {
 625            false
 626        }
 627    }
 628
 629    fn visible(&self) -> bool {
 630        match self {
 631            ContextMenu::Completions(menu) => menu.visible(),
 632            ContextMenu::CodeActions(menu) => menu.visible(),
 633        }
 634    }
 635
 636    fn render(
 637        &self,
 638        cursor_position: DisplayPoint,
 639        style: EditorStyle,
 640        cx: &mut RenderContext<Editor>,
 641    ) -> (DisplayPoint, ElementBox) {
 642        match self {
 643            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 644            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 645        }
 646    }
 647}
 648
 649struct CompletionsMenu {
 650    id: CompletionId,
 651    initial_position: Anchor,
 652    buffer: ModelHandle<Buffer>,
 653    completions: Arc<[Completion]>,
 654    match_candidates: Vec<StringMatchCandidate>,
 655    matches: Arc<[StringMatch]>,
 656    selected_item: usize,
 657    list: UniformListState,
 658}
 659
 660impl CompletionsMenu {
 661    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 662        if self.selected_item > 0 {
 663            self.selected_item -= 1;
 664            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 665        }
 666        cx.notify();
 667    }
 668
 669    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 670        if self.selected_item + 1 < self.matches.len() {
 671            self.selected_item += 1;
 672            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 673        }
 674        cx.notify();
 675    }
 676
 677    fn visible(&self) -> bool {
 678        !self.matches.is_empty()
 679    }
 680
 681    fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
 682        enum CompletionTag {}
 683
 684        let completions = self.completions.clone();
 685        let matches = self.matches.clone();
 686        let selected_item = self.selected_item;
 687        let container_style = style.autocomplete.container;
 688        UniformList::new(
 689            self.list.clone(),
 690            matches.len(),
 691            cx,
 692            move |_, range, items, cx| {
 693                let start_ix = range.start;
 694                for (ix, mat) in matches[range].iter().enumerate() {
 695                    let completion = &completions[mat.candidate_id];
 696                    let item_ix = start_ix + ix;
 697                    items.push(
 698                        MouseEventHandler::<CompletionTag>::new(
 699                            mat.candidate_id,
 700                            cx,
 701                            |state, _| {
 702                                let item_style = if item_ix == selected_item {
 703                                    style.autocomplete.selected_item
 704                                } else if state.hovered {
 705                                    style.autocomplete.hovered_item
 706                                } else {
 707                                    style.autocomplete.item
 708                                };
 709
 710                                Text::new(completion.label.text.clone(), style.text.clone())
 711                                    .with_soft_wrap(false)
 712                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 713                                        &completion.label.text,
 714                                        style.text.color.into(),
 715                                        styled_runs_for_code_label(
 716                                            &completion.label,
 717                                            &style.syntax,
 718                                        ),
 719                                        &mat.positions,
 720                                    ))
 721                                    .contained()
 722                                    .with_style(item_style)
 723                                    .boxed()
 724                            },
 725                        )
 726                        .with_cursor_style(CursorStyle::PointingHand)
 727                        .on_down(MouseButton::Left, move |_, cx| {
 728                            cx.dispatch_action(ConfirmCompletion {
 729                                item_ix: Some(item_ix),
 730                            });
 731                        })
 732                        .boxed(),
 733                    );
 734                }
 735            },
 736        )
 737        .with_width_from_item(
 738            self.matches
 739                .iter()
 740                .enumerate()
 741                .max_by_key(|(_, mat)| {
 742                    self.completions[mat.candidate_id]
 743                        .label
 744                        .text
 745                        .chars()
 746                        .count()
 747                })
 748                .map(|(ix, _)| ix),
 749        )
 750        .contained()
 751        .with_style(container_style)
 752        .boxed()
 753    }
 754
 755    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 756        let mut matches = if let Some(query) = query {
 757            fuzzy::match_strings(
 758                &self.match_candidates,
 759                query,
 760                false,
 761                100,
 762                &Default::default(),
 763                executor,
 764            )
 765            .await
 766        } else {
 767            self.match_candidates
 768                .iter()
 769                .enumerate()
 770                .map(|(candidate_id, candidate)| StringMatch {
 771                    candidate_id,
 772                    score: Default::default(),
 773                    positions: Default::default(),
 774                    string: candidate.string.clone(),
 775                })
 776                .collect()
 777        };
 778        matches.sort_unstable_by_key(|mat| {
 779            let completion = &self.completions[mat.candidate_id];
 780            (
 781                completion.lsp_completion.sort_text.as_ref(),
 782                Reverse(OrderedFloat(mat.score)),
 783                completion.sort_key(),
 784            )
 785        });
 786
 787        for mat in &mut matches {
 788            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 789            for position in &mut mat.positions {
 790                *position += filter_start;
 791            }
 792        }
 793
 794        self.matches = matches.into();
 795    }
 796}
 797
 798#[derive(Clone)]
 799struct CodeActionsMenu {
 800    actions: Arc<[CodeAction]>,
 801    buffer: ModelHandle<Buffer>,
 802    selected_item: usize,
 803    list: UniformListState,
 804    deployed_from_indicator: bool,
 805}
 806
 807impl CodeActionsMenu {
 808    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 809        if self.selected_item > 0 {
 810            self.selected_item -= 1;
 811            cx.notify()
 812        }
 813    }
 814
 815    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 816        if self.selected_item + 1 < self.actions.len() {
 817            self.selected_item += 1;
 818            cx.notify()
 819        }
 820    }
 821
 822    fn visible(&self) -> bool {
 823        !self.actions.is_empty()
 824    }
 825
 826    fn render(
 827        &self,
 828        mut cursor_position: DisplayPoint,
 829        style: EditorStyle,
 830        cx: &mut RenderContext<Editor>,
 831    ) -> (DisplayPoint, ElementBox) {
 832        enum ActionTag {}
 833
 834        let container_style = style.autocomplete.container;
 835        let actions = self.actions.clone();
 836        let selected_item = self.selected_item;
 837        let element = UniformList::new(
 838            self.list.clone(),
 839            actions.len(),
 840            cx,
 841            move |_, range, items, cx| {
 842                let start_ix = range.start;
 843                for (ix, action) in actions[range].iter().enumerate() {
 844                    let item_ix = start_ix + ix;
 845                    items.push(
 846                        MouseEventHandler::<ActionTag>::new(item_ix, cx, |state, _| {
 847                            let item_style = if item_ix == selected_item {
 848                                style.autocomplete.selected_item
 849                            } else if state.hovered {
 850                                style.autocomplete.hovered_item
 851                            } else {
 852                                style.autocomplete.item
 853                            };
 854
 855                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 856                                .with_soft_wrap(false)
 857                                .contained()
 858                                .with_style(item_style)
 859                                .boxed()
 860                        })
 861                        .with_cursor_style(CursorStyle::PointingHand)
 862                        .on_down(MouseButton::Left, move |_, cx| {
 863                            cx.dispatch_action(ConfirmCodeAction {
 864                                item_ix: Some(item_ix),
 865                            });
 866                        })
 867                        .boxed(),
 868                    );
 869                }
 870            },
 871        )
 872        .with_width_from_item(
 873            self.actions
 874                .iter()
 875                .enumerate()
 876                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 877                .map(|(ix, _)| ix),
 878        )
 879        .contained()
 880        .with_style(container_style)
 881        .boxed();
 882
 883        if self.deployed_from_indicator {
 884            *cursor_position.column_mut() = 0;
 885        }
 886
 887        (cursor_position, element)
 888    }
 889}
 890
 891#[derive(Debug)]
 892struct ActiveDiagnosticGroup {
 893    primary_range: Range<Anchor>,
 894    primary_message: String,
 895    blocks: HashMap<BlockId, Diagnostic>,
 896    is_valid: bool,
 897}
 898
 899#[derive(Serialize, Deserialize)]
 900pub struct ClipboardSelection {
 901    pub len: usize,
 902    pub is_entire_line: bool,
 903    pub first_line_indent: u32,
 904}
 905
 906#[derive(Debug)]
 907pub struct NavigationData {
 908    // Matching offsets for anchor and scroll_top_anchor allows us to recreate the anchor if the buffer
 909    // has since been closed
 910    cursor_anchor: Anchor,
 911    cursor_position: Point,
 912    scroll_position: Vector2F,
 913    scroll_top_anchor: Anchor,
 914    scroll_top_row: u32,
 915}
 916
 917pub struct EditorCreated(pub ViewHandle<Editor>);
 918
 919enum GotoDefinitionKind {
 920    Symbol,
 921    Type,
 922}
 923
 924impl Editor {
 925    pub fn single_line(
 926        field_editor_style: Option<GetFieldEditorTheme>,
 927        cx: &mut ViewContext<Self>,
 928    ) -> Self {
 929        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 930        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 931        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
 932    }
 933
 934    pub fn auto_height(
 935        max_lines: usize,
 936        field_editor_style: Option<GetFieldEditorTheme>,
 937        cx: &mut ViewContext<Self>,
 938    ) -> Self {
 939        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 940        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 941        Self::new(
 942            EditorMode::AutoHeight { max_lines },
 943            buffer,
 944            None,
 945            field_editor_style,
 946            cx,
 947        )
 948    }
 949
 950    pub fn for_buffer(
 951        buffer: ModelHandle<Buffer>,
 952        project: Option<ModelHandle<Project>>,
 953        cx: &mut ViewContext<Self>,
 954    ) -> Self {
 955        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 956        Self::new(EditorMode::Full, buffer, project, None, cx)
 957    }
 958
 959    pub fn for_multibuffer(
 960        buffer: ModelHandle<MultiBuffer>,
 961        project: Option<ModelHandle<Project>>,
 962        cx: &mut ViewContext<Self>,
 963    ) -> Self {
 964        Self::new(EditorMode::Full, buffer, project, None, cx)
 965    }
 966
 967    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 968        let mut clone = Self::new(
 969            self.mode,
 970            self.buffer.clone(),
 971            self.project.clone(),
 972            self.get_field_editor_theme,
 973            cx,
 974        );
 975        self.display_map.update(cx, |display_map, cx| {
 976            let snapshot = display_map.snapshot(cx);
 977            clone.display_map.update(cx, |display_map, cx| {
 978                display_map.set_state(&snapshot, cx);
 979            });
 980        });
 981        clone.selections.set_state(&self.selections);
 982        clone.scroll_position = self.scroll_position;
 983        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
 984        clone.searchable = self.searchable;
 985        clone
 986    }
 987
 988    fn new(
 989        mode: EditorMode,
 990        buffer: ModelHandle<MultiBuffer>,
 991        project: Option<ModelHandle<Project>>,
 992        get_field_editor_theme: Option<GetFieldEditorTheme>,
 993        cx: &mut ViewContext<Self>,
 994    ) -> Self {
 995        let display_map = cx.add_model(|cx| {
 996            let settings = cx.global::<Settings>();
 997            let style = build_style(&*settings, get_field_editor_theme, None, cx);
 998            DisplayMap::new(
 999                buffer.clone(),
1000                style.text.font_id,
1001                style.text.font_size,
1002                None,
1003                2,
1004                1,
1005                cx,
1006            )
1007        });
1008
1009        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1010
1011        let mut this = Self {
1012            handle: cx.weak_handle(),
1013            buffer: buffer.clone(),
1014            display_map: display_map.clone(),
1015            selections,
1016            columnar_selection_tail: None,
1017            add_selections_state: None,
1018            select_next_state: None,
1019            selection_history: Default::default(),
1020            autoclose_regions: Default::default(),
1021            snippet_stack: Default::default(),
1022            select_larger_syntax_node_stack: Vec::new(),
1023            ime_transaction: Default::default(),
1024            active_diagnostics: None,
1025            soft_wrap_mode_override: None,
1026            get_field_editor_theme,
1027            project,
1028            scroll_position: Vector2F::zero(),
1029            scroll_top_anchor: Anchor::min(),
1030            autoscroll_request: None,
1031            focused: false,
1032            show_local_cursors: false,
1033            show_local_selections: true,
1034            show_scrollbars: true,
1035            hide_scrollbar_task: None,
1036            blink_epoch: 0,
1037            blinking_paused: false,
1038            mode,
1039            vertical_scroll_margin: 3.0,
1040            placeholder_text: None,
1041            highlighted_rows: None,
1042            background_highlights: Default::default(),
1043            nav_history: None,
1044            context_menu: None,
1045            mouse_context_menu: cx.add_view(context_menu::ContextMenu::new),
1046            completion_tasks: Default::default(),
1047            next_completion_id: 0,
1048            available_code_actions: Default::default(),
1049            code_actions_task: Default::default(),
1050            document_highlights_task: Default::default(),
1051            pending_rename: Default::default(),
1052            searchable: true,
1053            override_text_style: None,
1054            cursor_shape: Default::default(),
1055            keymap_context_layers: Default::default(),
1056            input_enabled: true,
1057            leader_replica_id: None,
1058            hover_state: Default::default(),
1059            link_go_to_definition_state: Default::default(),
1060            _subscriptions: vec![
1061                cx.observe(&buffer, Self::on_buffer_changed),
1062                cx.subscribe(&buffer, Self::on_buffer_event),
1063                cx.observe(&display_map, Self::on_display_map_changed),
1064            ],
1065        };
1066        this.end_selection(cx);
1067        this.make_scrollbar_visible(cx);
1068
1069        let editor_created_event = EditorCreated(cx.handle());
1070        cx.emit_global(editor_created_event);
1071
1072        this.report_event("open editor", cx);
1073        this
1074    }
1075
1076    pub fn new_file(
1077        workspace: &mut Workspace,
1078        _: &workspace::NewFile,
1079        cx: &mut ViewContext<Workspace>,
1080    ) {
1081        let project = workspace.project().clone();
1082        if project.read(cx).is_remote() {
1083            cx.propagate_action();
1084        } else if let Some(buffer) = project
1085            .update(cx, |project, cx| project.create_buffer("", None, cx))
1086            .log_err()
1087        {
1088            workspace.add_item(
1089                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1090                cx,
1091            );
1092        }
1093    }
1094
1095    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1096        self.buffer.read(cx).replica_id()
1097    }
1098
1099    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1100        self.leader_replica_id
1101    }
1102
1103    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1104        &self.buffer
1105    }
1106
1107    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1108        self.buffer().read(cx).title(cx)
1109    }
1110
1111    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
1112        EditorSnapshot {
1113            mode: self.mode,
1114            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1115            scroll_position: self.scroll_position,
1116            scroll_top_anchor: self.scroll_top_anchor.clone(),
1117            placeholder_text: self.placeholder_text.clone(),
1118            is_focused: self
1119                .handle
1120                .upgrade(cx)
1121                .map_or(false, |handle| handle.is_focused(cx)),
1122        }
1123    }
1124
1125    pub fn language_at<'a, T: ToOffset>(
1126        &self,
1127        point: T,
1128        cx: &'a AppContext,
1129    ) -> Option<Arc<Language>> {
1130        self.buffer.read(cx).language_at(point, cx)
1131    }
1132
1133    fn style(&self, cx: &AppContext) -> EditorStyle {
1134        build_style(
1135            cx.global::<Settings>(),
1136            self.get_field_editor_theme,
1137            self.override_text_style.as_deref(),
1138            cx,
1139        )
1140    }
1141
1142    pub fn mode(&self) -> EditorMode {
1143        self.mode
1144    }
1145
1146    pub fn set_placeholder_text(
1147        &mut self,
1148        placeholder_text: impl Into<Arc<str>>,
1149        cx: &mut ViewContext<Self>,
1150    ) {
1151        self.placeholder_text = Some(placeholder_text.into());
1152        cx.notify();
1153    }
1154
1155    pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
1156        self.vertical_scroll_margin = margin_rows as f32;
1157        cx.notify();
1158    }
1159
1160    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
1161        self.set_scroll_position_internal(scroll_position, true, cx);
1162    }
1163
1164    fn set_scroll_position_internal(
1165        &mut self,
1166        scroll_position: Vector2F,
1167        local: bool,
1168        cx: &mut ViewContext<Self>,
1169    ) {
1170        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1171
1172        if scroll_position.y() == 0. {
1173            self.scroll_top_anchor = Anchor::min();
1174            self.scroll_position = scroll_position;
1175        } else {
1176            let scroll_top_buffer_offset =
1177                DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
1178            let anchor = map
1179                .buffer_snapshot
1180                .anchor_at(scroll_top_buffer_offset, Bias::Right);
1181            self.scroll_position = vec2f(
1182                scroll_position.x(),
1183                scroll_position.y() - anchor.to_display_point(&map).row() as f32,
1184            );
1185            self.scroll_top_anchor = anchor;
1186        }
1187
1188        self.make_scrollbar_visible(cx);
1189        self.autoscroll_request.take();
1190        hide_hover(self, cx);
1191
1192        cx.emit(Event::ScrollPositionChanged { local });
1193        cx.notify();
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.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, _: &mut ViewContext<Self>) {
5525        log::info!("Editor::page_up");
5526    }
5527
5528    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
5529        log::info!("Editor::page_down");
5530    }
5531
5532    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5533        let mut fold_ranges = Vec::new();
5534
5535        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5536        let selections = self.selections.all::<Point>(cx);
5537        for selection in selections {
5538            let range = selection.display_range(&display_map).sorted();
5539            let buffer_start_row = range.start.to_point(&display_map).row;
5540
5541            for row in (0..=range.end.row()).rev() {
5542                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5543                    let fold_range = self.foldable_range_for_line(&display_map, row);
5544                    if fold_range.end.row >= buffer_start_row {
5545                        fold_ranges.push(fold_range);
5546                        if row <= range.start.row() {
5547                            break;
5548                        }
5549                    }
5550                }
5551            }
5552        }
5553
5554        self.fold_ranges(fold_ranges, cx);
5555    }
5556
5557    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5558        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5559        let buffer = &display_map.buffer_snapshot;
5560        let selections = self.selections.all::<Point>(cx);
5561        let ranges = selections
5562            .iter()
5563            .map(|s| {
5564                let range = s.display_range(&display_map).sorted();
5565                let mut start = range.start.to_point(&display_map);
5566                let mut end = range.end.to_point(&display_map);
5567                start.column = 0;
5568                end.column = buffer.line_len(end.row);
5569                start..end
5570            })
5571            .collect::<Vec<_>>();
5572        self.unfold_ranges(ranges, true, cx);
5573    }
5574
5575    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5576        let max_point = display_map.max_point();
5577        if display_row >= max_point.row() {
5578            false
5579        } else {
5580            let (start_indent, is_blank) = display_map.line_indent(display_row);
5581            if is_blank {
5582                false
5583            } else {
5584                for display_row in display_row + 1..=max_point.row() {
5585                    let (indent, is_blank) = display_map.line_indent(display_row);
5586                    if !is_blank {
5587                        return indent > start_indent;
5588                    }
5589                }
5590                false
5591            }
5592        }
5593    }
5594
5595    fn foldable_range_for_line(
5596        &self,
5597        display_map: &DisplaySnapshot,
5598        start_row: u32,
5599    ) -> Range<Point> {
5600        let max_point = display_map.max_point();
5601
5602        let (start_indent, _) = display_map.line_indent(start_row);
5603        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5604        let mut end = None;
5605        for row in start_row + 1..=max_point.row() {
5606            let (indent, is_blank) = display_map.line_indent(row);
5607            if !is_blank && indent <= start_indent {
5608                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5609                break;
5610            }
5611        }
5612
5613        let end = end.unwrap_or(max_point);
5614        start.to_point(display_map)..end.to_point(display_map)
5615    }
5616
5617    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5618        let selections = self.selections.all::<Point>(cx);
5619        let ranges = selections.into_iter().map(|s| s.start..s.end);
5620        self.fold_ranges(ranges, cx);
5621    }
5622
5623    pub fn fold_ranges<T: ToOffset>(
5624        &mut self,
5625        ranges: impl IntoIterator<Item = Range<T>>,
5626        cx: &mut ViewContext<Self>,
5627    ) {
5628        let mut ranges = ranges.into_iter().peekable();
5629        if ranges.peek().is_some() {
5630            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5631            self.request_autoscroll(Autoscroll::Fit, cx);
5632            cx.notify();
5633        }
5634    }
5635
5636    pub fn unfold_ranges<T: ToOffset>(
5637        &mut self,
5638        ranges: impl IntoIterator<Item = Range<T>>,
5639        inclusive: bool,
5640        cx: &mut ViewContext<Self>,
5641    ) {
5642        let mut ranges = ranges.into_iter().peekable();
5643        if ranges.peek().is_some() {
5644            self.display_map
5645                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5646            self.request_autoscroll(Autoscroll::Fit, cx);
5647            cx.notify();
5648        }
5649    }
5650
5651    pub fn insert_blocks(
5652        &mut self,
5653        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5654        cx: &mut ViewContext<Self>,
5655    ) -> Vec<BlockId> {
5656        let blocks = self
5657            .display_map
5658            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5659        self.request_autoscroll(Autoscroll::Fit, cx);
5660        blocks
5661    }
5662
5663    pub fn replace_blocks(
5664        &mut self,
5665        blocks: HashMap<BlockId, RenderBlock>,
5666        cx: &mut ViewContext<Self>,
5667    ) {
5668        self.display_map
5669            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5670        self.request_autoscroll(Autoscroll::Fit, cx);
5671    }
5672
5673    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5674        self.display_map.update(cx, |display_map, cx| {
5675            display_map.remove_blocks(block_ids, cx)
5676        });
5677    }
5678
5679    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5680        self.display_map
5681            .update(cx, |map, cx| map.snapshot(cx))
5682            .longest_row()
5683    }
5684
5685    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5686        self.display_map
5687            .update(cx, |map, cx| map.snapshot(cx))
5688            .max_point()
5689    }
5690
5691    pub fn text(&self, cx: &AppContext) -> String {
5692        self.buffer.read(cx).read(cx).text()
5693    }
5694
5695    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5696        self.transact(cx, |this, cx| {
5697            this.buffer
5698                .read(cx)
5699                .as_singleton()
5700                .expect("you can only call set_text on editors for singleton buffers")
5701                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5702        });
5703    }
5704
5705    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5706        self.display_map
5707            .update(cx, |map, cx| map.snapshot(cx))
5708            .text()
5709    }
5710
5711    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5712        let language_name = self
5713            .buffer
5714            .read(cx)
5715            .as_singleton()
5716            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5717            .map(|l| l.name());
5718
5719        let settings = cx.global::<Settings>();
5720        let mode = self
5721            .soft_wrap_mode_override
5722            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5723        match mode {
5724            settings::SoftWrap::None => SoftWrap::None,
5725            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5726            settings::SoftWrap::PreferredLineLength => {
5727                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5728            }
5729        }
5730    }
5731
5732    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5733        self.soft_wrap_mode_override = Some(mode);
5734        cx.notify();
5735    }
5736
5737    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5738        self.display_map
5739            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5740    }
5741
5742    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5743        self.highlighted_rows = rows;
5744    }
5745
5746    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5747        self.highlighted_rows.clone()
5748    }
5749
5750    pub fn highlight_background<T: 'static>(
5751        &mut self,
5752        ranges: Vec<Range<Anchor>>,
5753        color_fetcher: fn(&Theme) -> Color,
5754        cx: &mut ViewContext<Self>,
5755    ) {
5756        self.background_highlights
5757            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5758        cx.notify();
5759    }
5760
5761    #[allow(clippy::type_complexity)]
5762    pub fn clear_background_highlights<T: 'static>(
5763        &mut self,
5764        cx: &mut ViewContext<Self>,
5765    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5766        cx.notify();
5767        self.background_highlights.remove(&TypeId::of::<T>())
5768    }
5769
5770    #[cfg(feature = "test-support")]
5771    pub fn all_background_highlights(
5772        &mut self,
5773        cx: &mut ViewContext<Self>,
5774    ) -> Vec<(Range<DisplayPoint>, Color)> {
5775        let snapshot = self.snapshot(cx);
5776        let buffer = &snapshot.buffer_snapshot;
5777        let start = buffer.anchor_before(0);
5778        let end = buffer.anchor_after(buffer.len());
5779        let theme = cx.global::<Settings>().theme.as_ref();
5780        self.background_highlights_in_range(start..end, &snapshot, theme)
5781    }
5782
5783    fn document_highlights_for_position<'a>(
5784        &'a self,
5785        position: Anchor,
5786        buffer: &'a MultiBufferSnapshot,
5787    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5788        let read_highlights = self
5789            .background_highlights
5790            .get(&TypeId::of::<DocumentHighlightRead>())
5791            .map(|h| &h.1);
5792        let write_highlights = self
5793            .background_highlights
5794            .get(&TypeId::of::<DocumentHighlightWrite>())
5795            .map(|h| &h.1);
5796        let left_position = position.bias_left(buffer);
5797        let right_position = position.bias_right(buffer);
5798        read_highlights
5799            .into_iter()
5800            .chain(write_highlights)
5801            .flat_map(move |ranges| {
5802                let start_ix = match ranges.binary_search_by(|probe| {
5803                    let cmp = probe.end.cmp(&left_position, buffer);
5804                    if cmp.is_ge() {
5805                        Ordering::Greater
5806                    } else {
5807                        Ordering::Less
5808                    }
5809                }) {
5810                    Ok(i) | Err(i) => i,
5811                };
5812
5813                let right_position = right_position.clone();
5814                ranges[start_ix..]
5815                    .iter()
5816                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5817            })
5818    }
5819
5820    pub fn background_highlights_in_range(
5821        &self,
5822        search_range: Range<Anchor>,
5823        display_snapshot: &DisplaySnapshot,
5824        theme: &Theme,
5825    ) -> Vec<(Range<DisplayPoint>, Color)> {
5826        let mut results = Vec::new();
5827        let buffer = &display_snapshot.buffer_snapshot;
5828        for (color_fetcher, ranges) in self.background_highlights.values() {
5829            let color = color_fetcher(theme);
5830            let start_ix = match ranges.binary_search_by(|probe| {
5831                let cmp = probe.end.cmp(&search_range.start, buffer);
5832                if cmp.is_gt() {
5833                    Ordering::Greater
5834                } else {
5835                    Ordering::Less
5836                }
5837            }) {
5838                Ok(i) | Err(i) => i,
5839            };
5840            for range in &ranges[start_ix..] {
5841                if range.start.cmp(&search_range.end, buffer).is_ge() {
5842                    break;
5843                }
5844                let start = range
5845                    .start
5846                    .to_point(buffer)
5847                    .to_display_point(display_snapshot);
5848                let end = range
5849                    .end
5850                    .to_point(buffer)
5851                    .to_display_point(display_snapshot);
5852                results.push((start..end, color))
5853            }
5854        }
5855        results
5856    }
5857
5858    pub fn highlight_text<T: 'static>(
5859        &mut self,
5860        ranges: Vec<Range<Anchor>>,
5861        style: HighlightStyle,
5862        cx: &mut ViewContext<Self>,
5863    ) {
5864        self.display_map.update(cx, |map, _| {
5865            map.highlight_text(TypeId::of::<T>(), ranges, style)
5866        });
5867        cx.notify();
5868    }
5869
5870    pub fn text_highlights<'a, T: 'static>(
5871        &'a self,
5872        cx: &'a AppContext,
5873    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
5874        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
5875    }
5876
5877    pub fn clear_text_highlights<T: 'static>(
5878        &mut self,
5879        cx: &mut ViewContext<Self>,
5880    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5881        cx.notify();
5882        self.display_map
5883            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
5884    }
5885
5886    fn next_blink_epoch(&mut self) -> usize {
5887        self.blink_epoch += 1;
5888        self.blink_epoch
5889    }
5890
5891    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5892        if !self.focused {
5893            return;
5894        }
5895
5896        self.show_local_cursors = true;
5897        cx.notify();
5898
5899        let epoch = self.next_blink_epoch();
5900        cx.spawn(|this, mut cx| {
5901            let this = this.downgrade();
5902            async move {
5903                Timer::after(CURSOR_BLINK_INTERVAL).await;
5904                if let Some(this) = this.upgrade(&cx) {
5905                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5906                }
5907            }
5908        })
5909        .detach();
5910    }
5911
5912    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5913        if epoch == self.blink_epoch {
5914            self.blinking_paused = false;
5915            self.blink_cursors(epoch, cx);
5916        }
5917    }
5918
5919    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5920        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5921            self.show_local_cursors = !self.show_local_cursors;
5922            cx.notify();
5923
5924            let epoch = self.next_blink_epoch();
5925            cx.spawn(|this, mut cx| {
5926                let this = this.downgrade();
5927                async move {
5928                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5929                    if let Some(this) = this.upgrade(&cx) {
5930                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5931                    }
5932                }
5933            })
5934            .detach();
5935        }
5936    }
5937
5938    pub fn show_local_cursors(&self) -> bool {
5939        self.show_local_cursors && self.focused
5940    }
5941
5942    pub fn show_scrollbars(&self) -> bool {
5943        self.show_scrollbars
5944    }
5945
5946    fn make_scrollbar_visible(&mut self, cx: &mut ViewContext<Self>) {
5947        if !self.show_scrollbars {
5948            self.show_scrollbars = true;
5949            cx.notify();
5950        }
5951
5952        self.hide_scrollbar_task = Some(cx.spawn_weak(|this, mut cx| async move {
5953            Timer::after(SCROLLBAR_SHOW_INTERVAL).await;
5954            if let Some(this) = this.upgrade(&cx) {
5955                this.update(&mut cx, |this, cx| {
5956                    this.show_scrollbars = false;
5957                    cx.notify();
5958                });
5959            }
5960        }));
5961    }
5962
5963    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5964        cx.notify();
5965    }
5966
5967    fn on_buffer_event(
5968        &mut self,
5969        _: ModelHandle<MultiBuffer>,
5970        event: &language::Event,
5971        cx: &mut ViewContext<Self>,
5972    ) {
5973        match event {
5974            language::Event::Edited => {
5975                self.refresh_active_diagnostics(cx);
5976                self.refresh_code_actions(cx);
5977                cx.emit(Event::BufferEdited);
5978            }
5979            language::Event::Reparsed => cx.emit(Event::Reparsed),
5980            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
5981            language::Event::Saved => cx.emit(Event::Saved),
5982            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
5983            language::Event::Reloaded => cx.emit(Event::TitleChanged),
5984            language::Event::Closed => cx.emit(Event::Closed),
5985            language::Event::DiagnosticsUpdated => {
5986                self.refresh_active_diagnostics(cx);
5987            }
5988            _ => {}
5989        }
5990    }
5991
5992    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
5993        cx.notify();
5994    }
5995
5996    pub fn set_searchable(&mut self, searchable: bool) {
5997        self.searchable = searchable;
5998    }
5999
6000    pub fn searchable(&self) -> bool {
6001        self.searchable
6002    }
6003
6004    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6005        let active_item = workspace.active_item(cx);
6006        let editor_handle = if let Some(editor) = active_item
6007            .as_ref()
6008            .and_then(|item| item.act_as::<Self>(cx))
6009        {
6010            editor
6011        } else {
6012            cx.propagate_action();
6013            return;
6014        };
6015
6016        let editor = editor_handle.read(cx);
6017        let buffer = editor.buffer.read(cx);
6018        if buffer.is_singleton() {
6019            cx.propagate_action();
6020            return;
6021        }
6022
6023        let mut new_selections_by_buffer = HashMap::default();
6024        for selection in editor.selections.all::<usize>(cx) {
6025            for (buffer, mut range) in
6026                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6027            {
6028                if selection.reversed {
6029                    mem::swap(&mut range.start, &mut range.end);
6030                }
6031                new_selections_by_buffer
6032                    .entry(buffer)
6033                    .or_insert(Vec::new())
6034                    .push(range)
6035            }
6036        }
6037
6038        editor_handle.update(cx, |editor, cx| {
6039            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6040        });
6041        let pane = workspace.active_pane().clone();
6042        pane.update(cx, |pane, _| pane.disable_history());
6043
6044        // We defer the pane interaction because we ourselves are a workspace item
6045        // and activating a new item causes the pane to call a method on us reentrantly,
6046        // which panics if we're on the stack.
6047        cx.defer(move |workspace, cx| {
6048            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6049                let editor = workspace.open_project_item::<Self>(buffer, cx);
6050                editor.update(cx, |editor, cx| {
6051                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6052                        s.select_ranges(ranges);
6053                    });
6054                });
6055            }
6056
6057            pane.update(cx, |pane, _| pane.enable_history());
6058        });
6059    }
6060
6061    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6062        let editor = workspace.open_path(action.path.clone(), true, cx);
6063        let position = action.position;
6064        let anchor = action.anchor;
6065        cx.spawn_weak(|_, mut cx| async move {
6066            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6067            editor.update(&mut cx, |editor, cx| {
6068                let buffer = editor.buffer().read(cx).as_singleton()?;
6069                let buffer = buffer.read(cx);
6070                let cursor = if buffer.can_resolve(&anchor) {
6071                    language::ToPoint::to_point(&anchor, buffer)
6072                } else {
6073                    buffer.clip_point(position, Bias::Left)
6074                };
6075
6076                let nav_history = editor.nav_history.take();
6077                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6078                    s.select_ranges([cursor..cursor]);
6079                });
6080                editor.nav_history = nav_history;
6081
6082                Some(())
6083            })?;
6084            Some(())
6085        })
6086        .detach()
6087    }
6088
6089    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6090        let snapshot = self.buffer.read(cx).read(cx);
6091        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6092        Some(
6093            ranges
6094                .iter()
6095                .map(move |range| {
6096                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6097                })
6098                .collect(),
6099        )
6100    }
6101
6102    fn selection_replacement_ranges(
6103        &self,
6104        range: Range<OffsetUtf16>,
6105        cx: &AppContext,
6106    ) -> Vec<Range<OffsetUtf16>> {
6107        let selections = self.selections.all::<OffsetUtf16>(cx);
6108        let newest_selection = selections
6109            .iter()
6110            .max_by_key(|selection| selection.id)
6111            .unwrap();
6112        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6113        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6114        let snapshot = self.buffer.read(cx).read(cx);
6115        selections
6116            .into_iter()
6117            .map(|mut selection| {
6118                selection.start.0 =
6119                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6120                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6121                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6122                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6123            })
6124            .collect()
6125    }
6126
6127    fn report_event(&self, name: &str, cx: &AppContext) {
6128        if let Some((project, file)) = self.project.as_ref().zip(
6129            self.buffer
6130                .read(cx)
6131                .as_singleton()
6132                .and_then(|b| b.read(cx).file()),
6133        ) {
6134            project.read(cx).client().report_event(
6135                name,
6136                json!({
6137                    "file_extension": file
6138                        .path()
6139                        .extension()
6140                        .and_then(|e| e.to_str())
6141                }),
6142            );
6143        }
6144    }
6145}
6146
6147impl EditorSnapshot {
6148    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6149        self.display_snapshot.buffer_snapshot.language_at(position)
6150    }
6151
6152    pub fn is_focused(&self) -> bool {
6153        self.is_focused
6154    }
6155
6156    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6157        self.placeholder_text.as_ref()
6158    }
6159
6160    pub fn scroll_position(&self) -> Vector2F {
6161        compute_scroll_position(
6162            &self.display_snapshot,
6163            self.scroll_position,
6164            &self.scroll_top_anchor,
6165        )
6166    }
6167}
6168
6169impl Deref for EditorSnapshot {
6170    type Target = DisplaySnapshot;
6171
6172    fn deref(&self) -> &Self::Target {
6173        &self.display_snapshot
6174    }
6175}
6176
6177fn compute_scroll_position(
6178    snapshot: &DisplaySnapshot,
6179    mut scroll_position: Vector2F,
6180    scroll_top_anchor: &Anchor,
6181) -> Vector2F {
6182    if *scroll_top_anchor != Anchor::min() {
6183        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
6184        scroll_position.set_y(scroll_top + scroll_position.y());
6185    } else {
6186        scroll_position.set_y(0.);
6187    }
6188    scroll_position
6189}
6190
6191#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6192pub enum Event {
6193    BufferEdited,
6194    Edited,
6195    Reparsed,
6196    Blurred,
6197    DirtyChanged,
6198    Saved,
6199    TitleChanged,
6200    SelectionsChanged { local: bool },
6201    ScrollPositionChanged { local: bool },
6202    Closed,
6203    IgnoredInput,
6204}
6205
6206pub struct EditorFocused(pub ViewHandle<Editor>);
6207pub struct EditorBlurred(pub ViewHandle<Editor>);
6208pub struct EditorReleased(pub WeakViewHandle<Editor>);
6209
6210impl Entity for Editor {
6211    type Event = Event;
6212
6213    fn release(&mut self, cx: &mut MutableAppContext) {
6214        cx.emit_global(EditorReleased(self.handle.clone()));
6215    }
6216}
6217
6218impl View for Editor {
6219    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6220        let style = self.style(cx);
6221        let font_changed = self.display_map.update(cx, |map, cx| {
6222            map.set_font(style.text.font_id, style.text.font_size, cx)
6223        });
6224
6225        if font_changed {
6226            let handle = self.handle.clone();
6227            cx.defer(move |cx| {
6228                if let Some(editor) = handle.upgrade(cx) {
6229                    editor.update(cx, |editor, cx| {
6230                        hide_hover(editor, cx);
6231                        hide_link_definition(editor, cx);
6232                    })
6233                }
6234            });
6235        }
6236
6237        Stack::new()
6238            .with_child(
6239                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
6240            )
6241            .with_child(ChildView::new(&self.mouse_context_menu).boxed())
6242            .boxed()
6243    }
6244
6245    fn ui_name() -> &'static str {
6246        "Editor"
6247    }
6248
6249    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6250        let focused_event = EditorFocused(cx.handle());
6251        cx.emit_global(focused_event);
6252        if let Some(rename) = self.pending_rename.as_ref() {
6253            cx.focus(&rename.editor);
6254        } else {
6255            self.focused = true;
6256            self.blink_cursors(self.blink_epoch, cx);
6257            self.buffer.update(cx, |buffer, cx| {
6258                buffer.finalize_last_transaction(cx);
6259                if self.leader_replica_id.is_none() {
6260                    buffer.set_active_selections(
6261                        &self.selections.disjoint_anchors(),
6262                        self.selections.line_mode,
6263                        cx,
6264                    );
6265                }
6266            });
6267        }
6268    }
6269
6270    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6271        let blurred_event = EditorBlurred(cx.handle());
6272        cx.emit_global(blurred_event);
6273        self.focused = false;
6274        self.buffer
6275            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6276        self.hide_context_menu(cx);
6277        hide_hover(self, cx);
6278        cx.emit(Event::Blurred);
6279        cx.notify();
6280    }
6281
6282    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
6283        let mut context = Self::default_keymap_context();
6284        let mode = match self.mode {
6285            EditorMode::SingleLine => "single_line",
6286            EditorMode::AutoHeight { .. } => "auto_height",
6287            EditorMode::Full => "full",
6288        };
6289        context.map.insert("mode".into(), mode.into());
6290        if self.pending_rename.is_some() {
6291            context.set.insert("renaming".into());
6292        }
6293        match self.context_menu.as_ref() {
6294            Some(ContextMenu::Completions(_)) => {
6295                context.set.insert("showing_completions".into());
6296            }
6297            Some(ContextMenu::CodeActions(_)) => {
6298                context.set.insert("showing_code_actions".into());
6299            }
6300            None => {}
6301        }
6302
6303        for layer in self.keymap_context_layers.values() {
6304            context.extend(layer);
6305        }
6306
6307        context
6308    }
6309
6310    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6311        Some(
6312            self.buffer
6313                .read(cx)
6314                .read(cx)
6315                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6316                .collect(),
6317        )
6318    }
6319
6320    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6321        // Prevent the IME menu from appearing when holding down an alphabetic key
6322        // while input is disabled.
6323        if !self.input_enabled {
6324            return None;
6325        }
6326
6327        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6328        Some(range.start.0..range.end.0)
6329    }
6330
6331    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6332        let snapshot = self.buffer.read(cx).read(cx);
6333        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6334        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6335    }
6336
6337    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6338        self.clear_text_highlights::<InputComposition>(cx);
6339        self.ime_transaction.take();
6340    }
6341
6342    fn replace_text_in_range(
6343        &mut self,
6344        range_utf16: Option<Range<usize>>,
6345        text: &str,
6346        cx: &mut ViewContext<Self>,
6347    ) {
6348        if !self.input_enabled {
6349            cx.emit(Event::IgnoredInput);
6350            return;
6351        }
6352
6353        self.transact(cx, |this, cx| {
6354            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6355                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6356                Some(this.selection_replacement_ranges(range_utf16, cx))
6357            } else {
6358                this.marked_text_ranges(cx)
6359            };
6360
6361            if let Some(new_selected_ranges) = new_selected_ranges {
6362                this.change_selections(None, cx, |selections| {
6363                    selections.select_ranges(new_selected_ranges)
6364                });
6365            }
6366            this.handle_input(text, cx);
6367        });
6368
6369        if let Some(transaction) = self.ime_transaction {
6370            self.buffer.update(cx, |buffer, cx| {
6371                buffer.group_until_transaction(transaction, cx);
6372            });
6373        }
6374
6375        self.unmark_text(cx);
6376    }
6377
6378    fn replace_and_mark_text_in_range(
6379        &mut self,
6380        range_utf16: Option<Range<usize>>,
6381        text: &str,
6382        new_selected_range_utf16: Option<Range<usize>>,
6383        cx: &mut ViewContext<Self>,
6384    ) {
6385        if !self.input_enabled {
6386            cx.emit(Event::IgnoredInput);
6387            return;
6388        }
6389
6390        let transaction = self.transact(cx, |this, cx| {
6391            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6392                let snapshot = this.buffer.read(cx).read(cx);
6393                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6394                    for marked_range in &mut marked_ranges {
6395                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6396                        marked_range.start.0 += relative_range_utf16.start;
6397                        marked_range.start =
6398                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6399                        marked_range.end =
6400                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6401                    }
6402                }
6403                Some(marked_ranges)
6404            } else if let Some(range_utf16) = range_utf16 {
6405                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6406                Some(this.selection_replacement_ranges(range_utf16, cx))
6407            } else {
6408                None
6409            };
6410
6411            if let Some(ranges) = ranges_to_replace {
6412                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6413            }
6414
6415            let marked_ranges = {
6416                let snapshot = this.buffer.read(cx).read(cx);
6417                this.selections
6418                    .disjoint_anchors()
6419                    .iter()
6420                    .map(|selection| {
6421                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6422                    })
6423                    .collect::<Vec<_>>()
6424            };
6425
6426            if text.is_empty() {
6427                this.unmark_text(cx);
6428            } else {
6429                this.highlight_text::<InputComposition>(
6430                    marked_ranges.clone(),
6431                    this.style(cx).composition_mark,
6432                    cx,
6433                );
6434            }
6435
6436            this.handle_input(text, cx);
6437
6438            if let Some(new_selected_range) = new_selected_range_utf16 {
6439                let snapshot = this.buffer.read(cx).read(cx);
6440                let new_selected_ranges = marked_ranges
6441                    .into_iter()
6442                    .map(|marked_range| {
6443                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6444                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6445                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6446                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6447                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6448                    })
6449                    .collect::<Vec<_>>();
6450
6451                drop(snapshot);
6452                this.change_selections(None, cx, |selections| {
6453                    selections.select_ranges(new_selected_ranges)
6454                });
6455            }
6456        });
6457
6458        self.ime_transaction = self.ime_transaction.or(transaction);
6459        if let Some(transaction) = self.ime_transaction {
6460            self.buffer.update(cx, |buffer, cx| {
6461                buffer.group_until_transaction(transaction, cx);
6462            });
6463        }
6464
6465        if self.text_highlights::<InputComposition>(cx).is_none() {
6466            self.ime_transaction.take();
6467        }
6468    }
6469}
6470
6471fn build_style(
6472    settings: &Settings,
6473    get_field_editor_theme: Option<GetFieldEditorTheme>,
6474    override_text_style: Option<&OverrideTextStyle>,
6475    cx: &AppContext,
6476) -> EditorStyle {
6477    let font_cache = cx.font_cache();
6478
6479    let mut theme = settings.theme.editor.clone();
6480    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6481        let field_editor_theme = get_field_editor_theme(&settings.theme);
6482        theme.text_color = field_editor_theme.text.color;
6483        theme.selection = field_editor_theme.selection;
6484        theme.background = field_editor_theme
6485            .container
6486            .background_color
6487            .unwrap_or_default();
6488        EditorStyle {
6489            text: field_editor_theme.text,
6490            placeholder_text: field_editor_theme.placeholder_text,
6491            theme,
6492        }
6493    } else {
6494        let font_family_id = settings.buffer_font_family;
6495        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6496        let font_properties = Default::default();
6497        let font_id = font_cache
6498            .select_font(font_family_id, &font_properties)
6499            .unwrap();
6500        let font_size = settings.buffer_font_size;
6501        EditorStyle {
6502            text: TextStyle {
6503                color: settings.theme.editor.text_color,
6504                font_family_name,
6505                font_family_id,
6506                font_id,
6507                font_size,
6508                font_properties,
6509                underline: Default::default(),
6510            },
6511            placeholder_text: None,
6512            theme,
6513        }
6514    };
6515
6516    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6517        if let Some(highlighted) = style
6518            .text
6519            .clone()
6520            .highlight(highlight_style, font_cache)
6521            .log_err()
6522        {
6523            style.text = highlighted;
6524        }
6525    }
6526
6527    style
6528}
6529
6530trait SelectionExt {
6531    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6532    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6533    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6534    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6535        -> Range<u32>;
6536}
6537
6538impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6539    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6540        let start = self.start.to_point(buffer);
6541        let end = self.end.to_point(buffer);
6542        if self.reversed {
6543            end..start
6544        } else {
6545            start..end
6546        }
6547    }
6548
6549    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6550        let start = self.start.to_offset(buffer);
6551        let end = self.end.to_offset(buffer);
6552        if self.reversed {
6553            end..start
6554        } else {
6555            start..end
6556        }
6557    }
6558
6559    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6560        let start = self
6561            .start
6562            .to_point(&map.buffer_snapshot)
6563            .to_display_point(map);
6564        let end = self
6565            .end
6566            .to_point(&map.buffer_snapshot)
6567            .to_display_point(map);
6568        if self.reversed {
6569            end..start
6570        } else {
6571            start..end
6572        }
6573    }
6574
6575    fn spanned_rows(
6576        &self,
6577        include_end_if_at_line_start: bool,
6578        map: &DisplaySnapshot,
6579    ) -> Range<u32> {
6580        let start = self.start.to_point(&map.buffer_snapshot);
6581        let mut end = self.end.to_point(&map.buffer_snapshot);
6582        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6583            end.row -= 1;
6584        }
6585
6586        let buffer_start = map.prev_line_boundary(start).0;
6587        let buffer_end = map.next_line_boundary(end).0;
6588        buffer_start.row..buffer_end.row + 1
6589    }
6590}
6591
6592impl<T: InvalidationRegion> InvalidationStack<T> {
6593    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6594    where
6595        S: Clone + ToOffset,
6596    {
6597        while let Some(region) = self.last() {
6598            let all_selections_inside_invalidation_ranges =
6599                if selections.len() == region.ranges().len() {
6600                    selections
6601                        .iter()
6602                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6603                        .all(|(selection, invalidation_range)| {
6604                            let head = selection.head().to_offset(buffer);
6605                            invalidation_range.start <= head && invalidation_range.end >= head
6606                        })
6607                } else {
6608                    false
6609                };
6610
6611            if all_selections_inside_invalidation_ranges {
6612                break;
6613            } else {
6614                self.pop();
6615            }
6616        }
6617    }
6618}
6619
6620impl<T> Default for InvalidationStack<T> {
6621    fn default() -> Self {
6622        Self(Default::default())
6623    }
6624}
6625
6626impl<T> Deref for InvalidationStack<T> {
6627    type Target = Vec<T>;
6628
6629    fn deref(&self) -> &Self::Target {
6630        &self.0
6631    }
6632}
6633
6634impl<T> DerefMut for InvalidationStack<T> {
6635    fn deref_mut(&mut self) -> &mut Self::Target {
6636        &mut self.0
6637    }
6638}
6639
6640impl InvalidationRegion for SnippetState {
6641    fn ranges(&self) -> &[Range<Anchor>] {
6642        &self.ranges[self.active_index]
6643    }
6644}
6645
6646impl Deref for EditorStyle {
6647    type Target = theme::Editor;
6648
6649    fn deref(&self) -> &Self::Target {
6650        &self.theme
6651    }
6652}
6653
6654pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6655    let mut highlighted_lines = Vec::new();
6656    for line in diagnostic.message.lines() {
6657        highlighted_lines.push(highlight_diagnostic_message(line));
6658    }
6659
6660    Arc::new(move |cx: &mut BlockContext| {
6661        let settings = cx.global::<Settings>();
6662        let theme = &settings.theme.editor;
6663        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6664        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6665        Flex::column()
6666            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6667                Label::new(
6668                    line.clone(),
6669                    style.message.clone().with_font_size(font_size),
6670                )
6671                .with_highlights(highlights.clone())
6672                .contained()
6673                .with_margin_left(cx.anchor_x)
6674                .boxed()
6675            }))
6676            .aligned()
6677            .left()
6678            .boxed()
6679    })
6680}
6681
6682pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6683    let mut message_without_backticks = String::new();
6684    let mut prev_offset = 0;
6685    let mut inside_block = false;
6686    let mut highlights = Vec::new();
6687    for (match_ix, (offset, _)) in message
6688        .match_indices('`')
6689        .chain([(message.len(), "")])
6690        .enumerate()
6691    {
6692        message_without_backticks.push_str(&message[prev_offset..offset]);
6693        if inside_block {
6694            highlights.extend(prev_offset - match_ix..offset - match_ix);
6695        }
6696
6697        inside_block = !inside_block;
6698        prev_offset = offset + 1;
6699    }
6700
6701    (message_without_backticks, highlights)
6702}
6703
6704pub fn diagnostic_style(
6705    severity: DiagnosticSeverity,
6706    valid: bool,
6707    theme: &theme::Editor,
6708) -> DiagnosticStyle {
6709    match (severity, valid) {
6710        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6711        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6712        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6713        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6714        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6715        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6716        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6717        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6718        _ => theme.invalid_hint_diagnostic.clone(),
6719    }
6720}
6721
6722pub fn combine_syntax_and_fuzzy_match_highlights(
6723    text: &str,
6724    default_style: HighlightStyle,
6725    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6726    match_indices: &[usize],
6727) -> Vec<(Range<usize>, HighlightStyle)> {
6728    let mut result = Vec::new();
6729    let mut match_indices = match_indices.iter().copied().peekable();
6730
6731    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6732    {
6733        syntax_highlight.weight = None;
6734
6735        // Add highlights for any fuzzy match characters before the next
6736        // syntax highlight range.
6737        while let Some(&match_index) = match_indices.peek() {
6738            if match_index >= range.start {
6739                break;
6740            }
6741            match_indices.next();
6742            let end_index = char_ix_after(match_index, text);
6743            let mut match_style = default_style;
6744            match_style.weight = Some(fonts::Weight::BOLD);
6745            result.push((match_index..end_index, match_style));
6746        }
6747
6748        if range.start == usize::MAX {
6749            break;
6750        }
6751
6752        // Add highlights for any fuzzy match characters within the
6753        // syntax highlight range.
6754        let mut offset = range.start;
6755        while let Some(&match_index) = match_indices.peek() {
6756            if match_index >= range.end {
6757                break;
6758            }
6759
6760            match_indices.next();
6761            if match_index > offset {
6762                result.push((offset..match_index, syntax_highlight));
6763            }
6764
6765            let mut end_index = char_ix_after(match_index, text);
6766            while let Some(&next_match_index) = match_indices.peek() {
6767                if next_match_index == end_index && next_match_index < range.end {
6768                    end_index = char_ix_after(next_match_index, text);
6769                    match_indices.next();
6770                } else {
6771                    break;
6772                }
6773            }
6774
6775            let mut match_style = syntax_highlight;
6776            match_style.weight = Some(fonts::Weight::BOLD);
6777            result.push((match_index..end_index, match_style));
6778            offset = end_index;
6779        }
6780
6781        if offset < range.end {
6782            result.push((offset..range.end, syntax_highlight));
6783        }
6784    }
6785
6786    fn char_ix_after(ix: usize, text: &str) -> usize {
6787        ix + text[ix..].chars().next().unwrap().len_utf8()
6788    }
6789
6790    result
6791}
6792
6793pub fn styled_runs_for_code_label<'a>(
6794    label: &'a CodeLabel,
6795    syntax_theme: &'a theme::SyntaxTheme,
6796) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6797    let fade_out = HighlightStyle {
6798        fade_out: Some(0.35),
6799        ..Default::default()
6800    };
6801
6802    let mut prev_end = label.filter_range.end;
6803    label
6804        .runs
6805        .iter()
6806        .enumerate()
6807        .flat_map(move |(ix, (range, highlight_id))| {
6808            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6809                style
6810            } else {
6811                return Default::default();
6812            };
6813            let mut muted_style = style;
6814            muted_style.highlight(fade_out);
6815
6816            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6817            if range.start >= label.filter_range.end {
6818                if range.start > prev_end {
6819                    runs.push((prev_end..range.start, fade_out));
6820                }
6821                runs.push((range.clone(), muted_style));
6822            } else if range.end <= label.filter_range.end {
6823                runs.push((range.clone(), style));
6824            } else {
6825                runs.push((range.start..label.filter_range.end, style));
6826                runs.push((label.filter_range.end..range.end, muted_style));
6827            }
6828            prev_end = cmp::max(prev_end, range.end);
6829
6830            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6831                runs.push((prev_end..label.text.len(), fade_out));
6832            }
6833
6834            runs
6835        })
6836}
6837
6838trait RangeExt<T> {
6839    fn sorted(&self) -> Range<T>;
6840    fn to_inclusive(&self) -> RangeInclusive<T>;
6841}
6842
6843impl<T: Ord + Clone> RangeExt<T> for Range<T> {
6844    fn sorted(&self) -> Self {
6845        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
6846    }
6847
6848    fn to_inclusive(&self) -> RangeInclusive<T> {
6849        self.start.clone()..=self.end.clone()
6850    }
6851}
6852
6853trait RangeToAnchorExt {
6854    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
6855}
6856
6857impl<T: ToOffset> RangeToAnchorExt for Range<T> {
6858    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
6859        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
6860    }
6861}