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