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