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