editor.rs

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