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 that closing bracket again; just move the selection
1942                            // past the closing bracket.
1943                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
1944                                && text.as_ref() == region.pair.end.as_str();
1945                            if should_skip {
1946                                let anchor = snapshot.anchor_after(selection.end);
1947                                new_selections.push((
1948                                    selection.map(|_| anchor.clone()),
1949                                    region.pair.end.len(),
1950                                ));
1951                                continue;
1952                            }
1953                        }
1954                    }
1955                    // If an opening bracket is typed while text is selected, then
1956                    // surround that text with the bracket pair.
1957                    else if is_bracket_pair_start {
1958                        edits.push((selection.start..selection.start, text.clone()));
1959                        edits.push((
1960                            selection.end..selection.end,
1961                            bracket_pair.end.as_str().into(),
1962                        ));
1963                        new_selections.push((
1964                            Selection {
1965                                id: selection.id,
1966                                start: snapshot.anchor_after(selection.start),
1967                                end: snapshot.anchor_before(selection.end),
1968                                reversed: selection.reversed,
1969                                goal: selection.goal,
1970                            },
1971                            0,
1972                        ));
1973                        continue;
1974                    }
1975                }
1976            }
1977
1978            // If not handling any auto-close operation, then just replace the selected
1979            // text with the given input and move the selection to the end of the
1980            // newly inserted text.
1981            let anchor = snapshot.anchor_after(selection.end);
1982            new_selections.push((selection.map(|_| anchor.clone()), 0));
1983            edits.push((selection.start..selection.end, text.clone()));
1984        }
1985
1986        drop(snapshot);
1987        self.transact(cx, |this, cx| {
1988            this.buffer.update(cx, |buffer, cx| {
1989                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
1990            });
1991
1992            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
1993            let new_selection_deltas = new_selections.iter().map(|e| e.1);
1994            let snapshot = this.buffer.read(cx).read(cx);
1995            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
1996                .zip(new_selection_deltas)
1997                .map(|(selection, delta)| selection.map(|e| e + delta))
1998                .collect::<Vec<_>>();
1999
2000            let mut i = 0;
2001            for (position, delta, selection_id, pair) in new_autoclose_regions {
2002                let position = position.to_offset(&snapshot) + delta;
2003                let start = snapshot.anchor_before(position);
2004                let end = snapshot.anchor_after(position);
2005                while let Some(existing_state) = this.autoclose_regions.get(i) {
2006                    match existing_state.range.start.cmp(&start, &snapshot) {
2007                        Ordering::Less => i += 1,
2008                        Ordering::Greater => break,
2009                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2010                            Ordering::Less => i += 1,
2011                            Ordering::Equal => break,
2012                            Ordering::Greater => break,
2013                        },
2014                    }
2015                }
2016                this.autoclose_regions.insert(
2017                    i,
2018                    AutocloseRegion {
2019                        selection_id,
2020                        range: start..end,
2021                        pair,
2022                    },
2023                );
2024            }
2025
2026            drop(snapshot);
2027            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
2028            this.trigger_completion_on_input(&text, cx);
2029        });
2030    }
2031
2032    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2033        self.transact(cx, |this, cx| {
2034            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2035                let selections = this.selections.all::<usize>(cx);
2036
2037                let buffer = this.buffer.read(cx).snapshot(cx);
2038                selections
2039                    .iter()
2040                    .map(|selection| {
2041                        let start_point = selection.start.to_point(&buffer);
2042                        let mut indent = buffer.indent_size_for_line(start_point.row);
2043                        indent.len = cmp::min(indent.len, start_point.column);
2044                        let start = selection.start;
2045                        let end = selection.end;
2046
2047                        let mut insert_extra_newline = false;
2048                        if let Some(language) = buffer.language_at(start) {
2049                            let leading_whitespace_len = buffer
2050                                .reversed_chars_at(start)
2051                                .take_while(|c| c.is_whitespace() && *c != '\n')
2052                                .map(|c| c.len_utf8())
2053                                .sum::<usize>();
2054
2055                            let trailing_whitespace_len = buffer
2056                                .chars_at(end)
2057                                .take_while(|c| c.is_whitespace() && *c != '\n')
2058                                .map(|c| c.len_utf8())
2059                                .sum::<usize>();
2060
2061                            insert_extra_newline = language.brackets().iter().any(|pair| {
2062                                let pair_start = pair.start.trim_end();
2063                                let pair_end = pair.end.trim_start();
2064
2065                                pair.newline
2066                                    && buffer
2067                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
2068                                    && buffer.contains_str_at(
2069                                        (start - leading_whitespace_len)
2070                                            .saturating_sub(pair_start.len()),
2071                                        pair_start,
2072                                    )
2073                            });
2074                        }
2075
2076                        let mut new_text = String::with_capacity(1 + indent.len as usize);
2077                        new_text.push('\n');
2078                        new_text.extend(indent.chars());
2079                        if insert_extra_newline {
2080                            new_text = new_text.repeat(2);
2081                        }
2082
2083                        let anchor = buffer.anchor_after(end);
2084                        let new_selection = selection.map(|_| anchor.clone());
2085                        (
2086                            (start..end, new_text),
2087                            (insert_extra_newline, new_selection),
2088                        )
2089                    })
2090                    .unzip()
2091            };
2092
2093            this.edit_with_autoindent(edits, cx);
2094            let buffer = this.buffer.read(cx).snapshot(cx);
2095            let new_selections = selection_fixup_info
2096                .into_iter()
2097                .map(|(extra_newline_inserted, new_selection)| {
2098                    let mut cursor = new_selection.end.to_point(&buffer);
2099                    if extra_newline_inserted {
2100                        cursor.row -= 1;
2101                        cursor.column = buffer.line_len(cursor.row);
2102                    }
2103                    new_selection.map(|_| cursor)
2104                })
2105                .collect();
2106
2107            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
2108        });
2109    }
2110
2111    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2112        let buffer = self.buffer.read(cx);
2113        let snapshot = buffer.snapshot(cx);
2114
2115        let mut edits = Vec::new();
2116        let mut rows = Vec::new();
2117        let mut rows_inserted = 0;
2118
2119        for selection in self.selections.all_adjusted(cx) {
2120            let cursor = selection.head();
2121            let row = cursor.row;
2122
2123            let end_of_line = snapshot
2124                .clip_point(Point::new(row, snapshot.line_len(row)), Bias::Left)
2125                .to_point(&snapshot);
2126
2127            let newline = "\n".to_string();
2128            edits.push((end_of_line..end_of_line, newline));
2129
2130            rows_inserted += 1;
2131            rows.push(row + rows_inserted);
2132        }
2133
2134        self.transact(cx, |editor, cx| {
2135            editor.edit_with_autoindent(edits, cx);
2136
2137            editor.change_selections(Some(Autoscroll::Fit), cx, |s| {
2138                let mut index = 0;
2139                s.move_cursors_with(|map, _, _| {
2140                    let row = rows[index];
2141                    index += 1;
2142
2143                    let point = Point::new(row, 0);
2144                    let boundary = map.next_line_boundary(point).1;
2145                    let clipped = map.clip_point(boundary, Bias::Left);
2146
2147                    (clipped, SelectionGoal::None)
2148                });
2149            });
2150        });
2151    }
2152
2153    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2154        let text: Arc<str> = text.into();
2155        self.transact(cx, |this, cx| {
2156            let old_selections = this.selections.all_adjusted(cx);
2157            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2158                let anchors = {
2159                    let snapshot = buffer.read(cx);
2160                    old_selections
2161                        .iter()
2162                        .map(|s| {
2163                            let anchor = snapshot.anchor_after(s.end);
2164                            s.map(|_| anchor.clone())
2165                        })
2166                        .collect::<Vec<_>>()
2167                };
2168                buffer.edit(
2169                    old_selections
2170                        .iter()
2171                        .map(|s| (s.start..s.end, text.clone())),
2172                    Some(AutoindentMode::EachLine),
2173                    cx,
2174                );
2175                anchors
2176            });
2177
2178            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
2179                s.select_anchors(selection_anchors);
2180            })
2181        });
2182    }
2183
2184    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2185        if !cx.global::<Settings>().show_completions_on_input {
2186            return;
2187        }
2188
2189        let selection = self.selections.newest_anchor();
2190        if self
2191            .buffer
2192            .read(cx)
2193            .is_completion_trigger(selection.head(), text, cx)
2194        {
2195            self.show_completions(&ShowCompletions, cx);
2196        } else {
2197            self.hide_context_menu(cx);
2198        }
2199    }
2200
2201    /// If any empty selections is touching the start of its innermost containing autoclose
2202    /// region, expand it to select the brackets.
2203    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2204        let selections = self.selections.all::<usize>(cx);
2205        let buffer = self.buffer.read(cx).read(cx);
2206        let mut new_selections = Vec::new();
2207        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2208            if let (Some(region), true) = (region, selection.is_empty()) {
2209                let mut range = region.range.to_offset(&buffer);
2210                if selection.start == range.start {
2211                    if range.start >= region.pair.start.len() {
2212                        range.start -= region.pair.start.len();
2213                        if buffer.contains_str_at(range.start, &region.pair.start) {
2214                            if buffer.contains_str_at(range.end, &region.pair.end) {
2215                                range.end += region.pair.end.len();
2216                                selection.start = range.start;
2217                                selection.end = range.end;
2218                            }
2219                        }
2220                    }
2221                }
2222            }
2223            new_selections.push(selection);
2224        }
2225
2226        drop(buffer);
2227        self.change_selections(None, cx, |selections| selections.select(new_selections));
2228    }
2229
2230    /// Iterate the given selections, and for each one, find the smallest surrounding
2231    /// autoclose region. This uses the ordering of the selections and the autoclose
2232    /// regions to avoid repeated comparisons.
2233    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2234        &'a self,
2235        selections: impl IntoIterator<Item = Selection<D>>,
2236        buffer: &'a MultiBufferSnapshot,
2237    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2238        let mut i = 0;
2239        let mut regions = self.autoclose_regions.as_slice();
2240        selections.into_iter().map(move |selection| {
2241            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2242
2243            let mut enclosing = None;
2244            while let Some(pair_state) = regions.get(i) {
2245                if pair_state.range.end.to_offset(buffer) < range.start {
2246                    regions = &regions[i + 1..];
2247                    i = 0;
2248                } else if pair_state.range.start.to_offset(buffer) > range.end {
2249                    break;
2250                } else if pair_state.selection_id == selection.id {
2251                    enclosing = Some(pair_state);
2252                    i += 1;
2253                }
2254            }
2255
2256            (selection.clone(), enclosing)
2257        })
2258    }
2259
2260    /// Remove any autoclose regions that no longer contain their selection.
2261    fn invalidate_autoclose_regions(
2262        &mut self,
2263        mut selections: &[Selection<Anchor>],
2264        buffer: &MultiBufferSnapshot,
2265    ) {
2266        self.autoclose_regions.retain(|state| {
2267            let mut i = 0;
2268            while let Some(selection) = selections.get(i) {
2269                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2270                    selections = &selections[1..];
2271                    continue;
2272                }
2273                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2274                    break;
2275                }
2276                if selection.id == state.selection_id {
2277                    return true;
2278                } else {
2279                    i += 1;
2280                }
2281            }
2282            false
2283        });
2284    }
2285
2286    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2287        let offset = position.to_offset(buffer);
2288        let (word_range, kind) = buffer.surrounding_word(offset);
2289        if offset > word_range.start && kind == Some(CharKind::Word) {
2290            Some(
2291                buffer
2292                    .text_for_range(word_range.start..offset)
2293                    .collect::<String>(),
2294            )
2295        } else {
2296            None
2297        }
2298    }
2299
2300    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2301        if self.pending_rename.is_some() {
2302            return;
2303        }
2304
2305        let project = if let Some(project) = self.project.clone() {
2306            project
2307        } else {
2308            return;
2309        };
2310
2311        let position = self.selections.newest_anchor().head();
2312        let (buffer, buffer_position) = if let Some(output) = self
2313            .buffer
2314            .read(cx)
2315            .text_anchor_for_position(position.clone(), cx)
2316        {
2317            output
2318        } else {
2319            return;
2320        };
2321
2322        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2323        let completions = project.update(cx, |project, cx| {
2324            project.completions(&buffer, buffer_position, cx)
2325        });
2326
2327        let id = post_inc(&mut self.next_completion_id);
2328        let task = cx.spawn_weak(|this, mut cx| {
2329            async move {
2330                let completions = completions.await?;
2331                if completions.is_empty() {
2332                    return Ok(());
2333                }
2334
2335                let mut menu = CompletionsMenu {
2336                    id,
2337                    initial_position: position,
2338                    match_candidates: completions
2339                        .iter()
2340                        .enumerate()
2341                        .map(|(id, completion)| {
2342                            StringMatchCandidate::new(
2343                                id,
2344                                completion.label.text[completion.label.filter_range.clone()].into(),
2345                            )
2346                        })
2347                        .collect(),
2348                    buffer,
2349                    completions: completions.into(),
2350                    matches: Vec::new().into(),
2351                    selected_item: 0,
2352                    list: Default::default(),
2353                };
2354
2355                menu.filter(query.as_deref(), cx.background()).await;
2356
2357                if let Some(this) = this.upgrade(&cx) {
2358                    this.update(&mut cx, |this, cx| {
2359                        match this.context_menu.as_ref() {
2360                            None => {}
2361                            Some(ContextMenu::Completions(prev_menu)) => {
2362                                if prev_menu.id > menu.id {
2363                                    return;
2364                                }
2365                            }
2366                            _ => return,
2367                        }
2368
2369                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
2370                        if this.focused {
2371                            this.show_context_menu(ContextMenu::Completions(menu), cx);
2372                        }
2373
2374                        cx.notify();
2375                    });
2376                }
2377                Ok::<_, anyhow::Error>(())
2378            }
2379            .log_err()
2380        });
2381        self.completion_tasks.push((id, task));
2382    }
2383
2384    pub fn confirm_completion(
2385        &mut self,
2386        action: &ConfirmCompletion,
2387        cx: &mut ViewContext<Self>,
2388    ) -> Option<Task<Result<()>>> {
2389        use language::ToOffset as _;
2390
2391        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2392            menu
2393        } else {
2394            return None;
2395        };
2396
2397        let mat = completions_menu
2398            .matches
2399            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2400        let buffer_handle = completions_menu.buffer;
2401        let completion = completions_menu.completions.get(mat.candidate_id)?;
2402
2403        let snippet;
2404        let text;
2405        if completion.is_snippet() {
2406            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2407            text = snippet.as_ref().unwrap().text.clone();
2408        } else {
2409            snippet = None;
2410            text = completion.new_text.clone();
2411        };
2412        let selections = self.selections.all::<usize>(cx);
2413        let buffer = buffer_handle.read(cx);
2414        let old_range = completion.old_range.to_offset(buffer);
2415        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2416
2417        let newest_selection = self.selections.newest_anchor();
2418        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
2419            return None;
2420        }
2421
2422        let lookbehind = newest_selection
2423            .start
2424            .text_anchor
2425            .to_offset(buffer)
2426            .saturating_sub(old_range.start);
2427        let lookahead = old_range
2428            .end
2429            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2430        let mut common_prefix_len = old_text
2431            .bytes()
2432            .zip(text.bytes())
2433            .take_while(|(a, b)| a == b)
2434            .count();
2435
2436        let snapshot = self.buffer.read(cx).snapshot(cx);
2437        let mut ranges = Vec::new();
2438        for selection in &selections {
2439            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2440                let start = selection.start.saturating_sub(lookbehind);
2441                let end = selection.end + lookahead;
2442                ranges.push(start + common_prefix_len..end);
2443            } else {
2444                common_prefix_len = 0;
2445                ranges.clear();
2446                ranges.extend(selections.iter().map(|s| {
2447                    if s.id == newest_selection.id {
2448                        old_range.clone()
2449                    } else {
2450                        s.start..s.end
2451                    }
2452                }));
2453                break;
2454            }
2455        }
2456        let text = &text[common_prefix_len..];
2457
2458        self.transact(cx, |this, cx| {
2459            if let Some(mut snippet) = snippet {
2460                snippet.text = text.to_string();
2461                for tabstop in snippet.tabstops.iter_mut().flatten() {
2462                    tabstop.start -= common_prefix_len as isize;
2463                    tabstop.end -= common_prefix_len as isize;
2464                }
2465
2466                this.insert_snippet(&ranges, snippet, cx).log_err();
2467            } else {
2468                this.buffer.update(cx, |buffer, cx| {
2469                    buffer.edit(
2470                        ranges.iter().map(|range| (range.clone(), text)),
2471                        Some(AutoindentMode::EachLine),
2472                        cx,
2473                    );
2474                });
2475            }
2476        });
2477
2478        let project = self.project.clone()?;
2479        let apply_edits = project.update(cx, |project, cx| {
2480            project.apply_additional_edits_for_completion(
2481                buffer_handle,
2482                completion.clone(),
2483                true,
2484                cx,
2485            )
2486        });
2487        Some(cx.foreground().spawn(async move {
2488            apply_edits.await?;
2489            Ok(())
2490        }))
2491    }
2492
2493    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2494        if matches!(
2495            self.context_menu.as_ref(),
2496            Some(ContextMenu::CodeActions(_))
2497        ) {
2498            self.context_menu.take();
2499            cx.notify();
2500            return;
2501        }
2502
2503        let deployed_from_indicator = action.deployed_from_indicator;
2504        let mut task = self.code_actions_task.take();
2505        cx.spawn_weak(|this, mut cx| async move {
2506            while let Some(prev_task) = task {
2507                prev_task.await;
2508                task = this
2509                    .upgrade(&cx)
2510                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
2511            }
2512
2513            if let Some(this) = this.upgrade(&cx) {
2514                this.update(&mut cx, |this, cx| {
2515                    if this.focused {
2516                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
2517                            this.show_context_menu(
2518                                ContextMenu::CodeActions(CodeActionsMenu {
2519                                    buffer,
2520                                    actions,
2521                                    selected_item: Default::default(),
2522                                    list: Default::default(),
2523                                    deployed_from_indicator,
2524                                }),
2525                                cx,
2526                            );
2527                        }
2528                    }
2529                })
2530            }
2531            Ok::<_, anyhow::Error>(())
2532        })
2533        .detach_and_log_err(cx);
2534    }
2535
2536    pub fn confirm_code_action(
2537        workspace: &mut Workspace,
2538        action: &ConfirmCodeAction,
2539        cx: &mut ViewContext<Workspace>,
2540    ) -> Option<Task<Result<()>>> {
2541        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2542        let actions_menu = if let ContextMenu::CodeActions(menu) =
2543            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2544        {
2545            menu
2546        } else {
2547            return None;
2548        };
2549        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2550        let action = actions_menu.actions.get(action_ix)?.clone();
2551        let title = action.lsp_action.title.clone();
2552        let buffer = actions_menu.buffer;
2553
2554        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2555            project.apply_code_action(buffer, action, true, cx)
2556        });
2557        Some(cx.spawn(|workspace, cx| async move {
2558            let project_transaction = apply_code_actions.await?;
2559            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
2560        }))
2561    }
2562
2563    async fn open_project_transaction(
2564        this: ViewHandle<Editor>,
2565        workspace: ViewHandle<Workspace>,
2566        transaction: ProjectTransaction,
2567        title: String,
2568        mut cx: AsyncAppContext,
2569    ) -> Result<()> {
2570        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
2571
2572        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2573        entries.sort_unstable_by_key(|(buffer, _)| {
2574            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2575        });
2576
2577        // If the project transaction's edits are all contained within this editor, then
2578        // avoid opening a new editor to display them.
2579
2580        if let Some((buffer, transaction)) = entries.first() {
2581            if entries.len() == 1 {
2582                let excerpt = this.read_with(&cx, |editor, cx| {
2583                    editor
2584                        .buffer()
2585                        .read(cx)
2586                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2587                });
2588                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2589                    if excerpted_buffer == *buffer {
2590                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2591                            let excerpt_range = excerpt_range.to_offset(buffer);
2592                            buffer
2593                                .edited_ranges_for_transaction(transaction)
2594                                .all(|range| {
2595                                    excerpt_range.start <= range.start
2596                                        && excerpt_range.end >= range.end
2597                                })
2598                        });
2599
2600                        if all_edits_within_excerpt {
2601                            return Ok(());
2602                        }
2603                    }
2604                }
2605            }
2606        } else {
2607            return Ok(());
2608        }
2609
2610        let mut ranges_to_highlight = Vec::new();
2611        let excerpt_buffer = cx.add_model(|cx| {
2612            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2613            for (buffer_handle, transaction) in &entries {
2614                let buffer = buffer_handle.read(cx);
2615                ranges_to_highlight.extend(
2616                    multibuffer.push_excerpts_with_context_lines(
2617                        buffer_handle.clone(),
2618                        buffer
2619                            .edited_ranges_for_transaction::<usize>(transaction)
2620                            .collect(),
2621                        1,
2622                        cx,
2623                    ),
2624                );
2625            }
2626            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
2627            multibuffer
2628        });
2629
2630        workspace.update(&mut cx, |workspace, cx| {
2631            let project = workspace.project().clone();
2632            let editor =
2633                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2634            workspace.add_item(Box::new(editor.clone()), cx);
2635            editor.update(cx, |editor, cx| {
2636                editor.highlight_background::<Self>(
2637                    ranges_to_highlight,
2638                    |theme| theme.editor.highlighted_line_background,
2639                    cx,
2640                );
2641            });
2642        });
2643
2644        Ok(())
2645    }
2646
2647    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2648        let project = self.project.as_ref()?;
2649        let buffer = self.buffer.read(cx);
2650        let newest_selection = self.selections.newest_anchor().clone();
2651        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2652        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2653        if start_buffer != end_buffer {
2654            return None;
2655        }
2656
2657        let actions = project.update(cx, |project, cx| {
2658            project.code_actions(&start_buffer, start..end, cx)
2659        });
2660        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
2661            let actions = actions.await;
2662            if let Some(this) = this.upgrade(&cx) {
2663                this.update(&mut cx, |this, cx| {
2664                    this.available_code_actions = actions.log_err().and_then(|actions| {
2665                        if actions.is_empty() {
2666                            None
2667                        } else {
2668                            Some((start_buffer, actions.into()))
2669                        }
2670                    });
2671                    cx.notify();
2672                })
2673            }
2674        }));
2675        None
2676    }
2677
2678    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2679        if self.pending_rename.is_some() {
2680            return None;
2681        }
2682
2683        let project = self.project.as_ref()?;
2684        let buffer = self.buffer.read(cx);
2685        let newest_selection = self.selections.newest_anchor().clone();
2686        let cursor_position = newest_selection.head();
2687        let (cursor_buffer, cursor_buffer_position) =
2688            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2689        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2690        if cursor_buffer != tail_buffer {
2691            return None;
2692        }
2693
2694        let highlights = project.update(cx, |project, cx| {
2695            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2696        });
2697
2698        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
2699            let highlights = highlights.log_err().await;
2700            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
2701                this.update(&mut cx, |this, cx| {
2702                    if this.pending_rename.is_some() {
2703                        return;
2704                    }
2705
2706                    let buffer_id = cursor_position.buffer_id;
2707                    let buffer = this.buffer.read(cx);
2708                    if !buffer
2709                        .text_anchor_for_position(cursor_position, cx)
2710                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2711                    {
2712                        return;
2713                    }
2714
2715                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2716                    let mut write_ranges = Vec::new();
2717                    let mut read_ranges = Vec::new();
2718                    for highlight in highlights {
2719                        for (excerpt_id, excerpt_range) in
2720                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2721                        {
2722                            let start = highlight
2723                                .range
2724                                .start
2725                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
2726                            let end = highlight
2727                                .range
2728                                .end
2729                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
2730                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2731                                continue;
2732                            }
2733
2734                            let range = Anchor {
2735                                buffer_id,
2736                                excerpt_id: excerpt_id.clone(),
2737                                text_anchor: start,
2738                            }..Anchor {
2739                                buffer_id,
2740                                excerpt_id,
2741                                text_anchor: end,
2742                            };
2743                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2744                                write_ranges.push(range);
2745                            } else {
2746                                read_ranges.push(range);
2747                            }
2748                        }
2749                    }
2750
2751                    this.highlight_background::<DocumentHighlightRead>(
2752                        read_ranges,
2753                        |theme| theme.editor.document_highlight_read_background,
2754                        cx,
2755                    );
2756                    this.highlight_background::<DocumentHighlightWrite>(
2757                        write_ranges,
2758                        |theme| theme.editor.document_highlight_write_background,
2759                        cx,
2760                    );
2761                    cx.notify();
2762                });
2763            }
2764        }));
2765        None
2766    }
2767
2768    pub fn render_code_actions_indicator(
2769        &self,
2770        style: &EditorStyle,
2771        cx: &mut RenderContext<Self>,
2772    ) -> Option<ElementBox> {
2773        if self.available_code_actions.is_some() {
2774            enum Tag {}
2775            Some(
2776                MouseEventHandler::<Tag>::new(0, cx, |_, _| {
2777                    Svg::new("icons/bolt_8.svg")
2778                        .with_color(style.code_actions.indicator)
2779                        .boxed()
2780                })
2781                .with_cursor_style(CursorStyle::PointingHand)
2782                .with_padding(Padding::uniform(3.))
2783                .on_down(MouseButton::Left, |_, cx| {
2784                    cx.dispatch_action(ToggleCodeActions {
2785                        deployed_from_indicator: true,
2786                    });
2787                })
2788                .boxed(),
2789            )
2790        } else {
2791            None
2792        }
2793    }
2794
2795    pub fn context_menu_visible(&self) -> bool {
2796        self.context_menu
2797            .as_ref()
2798            .map_or(false, |menu| menu.visible())
2799    }
2800
2801    pub fn render_context_menu(
2802        &self,
2803        cursor_position: DisplayPoint,
2804        style: EditorStyle,
2805        cx: &mut RenderContext<Editor>,
2806    ) -> Option<(DisplayPoint, ElementBox)> {
2807        self.context_menu
2808            .as_ref()
2809            .map(|menu| menu.render(cursor_position, style, cx))
2810    }
2811
2812    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
2813        if !matches!(menu, ContextMenu::Completions(_)) {
2814            self.completion_tasks.clear();
2815        }
2816        self.context_menu = Some(menu);
2817        cx.notify();
2818    }
2819
2820    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
2821        cx.notify();
2822        self.completion_tasks.clear();
2823        self.context_menu.take()
2824    }
2825
2826    pub fn insert_snippet(
2827        &mut self,
2828        insertion_ranges: &[Range<usize>],
2829        snippet: Snippet,
2830        cx: &mut ViewContext<Self>,
2831    ) -> Result<()> {
2832        let tabstops = self.buffer.update(cx, |buffer, cx| {
2833            let snippet_text: Arc<str> = snippet.text.clone().into();
2834            buffer.edit(
2835                insertion_ranges
2836                    .iter()
2837                    .cloned()
2838                    .map(|range| (range, snippet_text.clone())),
2839                Some(AutoindentMode::EachLine),
2840                cx,
2841            );
2842
2843            let snapshot = &*buffer.read(cx);
2844            let snippet = &snippet;
2845            snippet
2846                .tabstops
2847                .iter()
2848                .map(|tabstop| {
2849                    let mut tabstop_ranges = tabstop
2850                        .iter()
2851                        .flat_map(|tabstop_range| {
2852                            let mut delta = 0_isize;
2853                            insertion_ranges.iter().map(move |insertion_range| {
2854                                let insertion_start = insertion_range.start as isize + delta;
2855                                delta +=
2856                                    snippet.text.len() as isize - insertion_range.len() as isize;
2857
2858                                let start = snapshot.anchor_before(
2859                                    (insertion_start + tabstop_range.start) as usize,
2860                                );
2861                                let end = snapshot
2862                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
2863                                start..end
2864                            })
2865                        })
2866                        .collect::<Vec<_>>();
2867                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
2868                    tabstop_ranges
2869                })
2870                .collect::<Vec<_>>()
2871        });
2872
2873        if let Some(tabstop) = tabstops.first() {
2874            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2875                s.select_ranges(tabstop.iter().cloned());
2876            });
2877            self.snippet_stack.push(SnippetState {
2878                active_index: 0,
2879                ranges: tabstops,
2880            });
2881        }
2882
2883        Ok(())
2884    }
2885
2886    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2887        self.move_to_snippet_tabstop(Bias::Right, cx)
2888    }
2889
2890    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
2891        self.move_to_snippet_tabstop(Bias::Left, cx)
2892    }
2893
2894    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
2895        if let Some(mut snippet) = self.snippet_stack.pop() {
2896            match bias {
2897                Bias::Left => {
2898                    if snippet.active_index > 0 {
2899                        snippet.active_index -= 1;
2900                    } else {
2901                        self.snippet_stack.push(snippet);
2902                        return false;
2903                    }
2904                }
2905                Bias::Right => {
2906                    if snippet.active_index + 1 < snippet.ranges.len() {
2907                        snippet.active_index += 1;
2908                    } else {
2909                        self.snippet_stack.push(snippet);
2910                        return false;
2911                    }
2912                }
2913            }
2914            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
2915                self.change_selections(Some(Autoscroll::Fit), cx, |s| {
2916                    s.select_anchor_ranges(current_ranges.iter().cloned())
2917                });
2918                // If snippet state is not at the last tabstop, push it back on the stack
2919                if snippet.active_index + 1 < snippet.ranges.len() {
2920                    self.snippet_stack.push(snippet);
2921                }
2922                return true;
2923            }
2924        }
2925
2926        false
2927    }
2928
2929    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
2930        self.transact(cx, |this, cx| {
2931            this.select_all(&SelectAll, cx);
2932            this.insert("", cx);
2933        });
2934    }
2935
2936    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
2937        self.transact(cx, |this, cx| {
2938            this.select_autoclose_pair(cx);
2939            let mut selections = this.selections.all::<Point>(cx);
2940            if !this.selections.line_mode {
2941                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
2942                for selection in &mut selections {
2943                    if selection.is_empty() {
2944                        let old_head = selection.head();
2945                        let mut new_head =
2946                            movement::left(&display_map, old_head.to_display_point(&display_map))
2947                                .to_point(&display_map);
2948                        if let Some((buffer, line_buffer_range)) = display_map
2949                            .buffer_snapshot
2950                            .buffer_line_for_row(old_head.row)
2951                        {
2952                            let indent_size =
2953                                buffer.indent_size_for_line(line_buffer_range.start.row);
2954                            let language_name = buffer
2955                                .language_at(line_buffer_range.start)
2956                                .map(|language| language.name());
2957                            let indent_len = match indent_size.kind {
2958                                IndentKind::Space => {
2959                                    cx.global::<Settings>().tab_size(language_name.as_deref())
2960                                }
2961                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
2962                            };
2963                            if old_head.column <= indent_size.len && old_head.column > 0 {
2964                                let indent_len = indent_len.get();
2965                                new_head = cmp::min(
2966                                    new_head,
2967                                    Point::new(
2968                                        old_head.row,
2969                                        ((old_head.column - 1) / indent_len) * indent_len,
2970                                    ),
2971                                );
2972                            }
2973                        }
2974
2975                        selection.set_head(new_head, SelectionGoal::None);
2976                    }
2977                }
2978            }
2979
2980            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
2981            this.insert("", cx);
2982        });
2983    }
2984
2985    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
2986        self.transact(cx, |this, cx| {
2987            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
2988                let line_mode = s.line_mode;
2989                s.move_with(|map, selection| {
2990                    if selection.is_empty() && !line_mode {
2991                        let cursor = movement::right(map, selection.head());
2992                        selection.set_head(cursor, SelectionGoal::None);
2993                    }
2994                })
2995            });
2996            this.insert("", cx);
2997        });
2998    }
2999
3000    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3001        if self.move_to_prev_snippet_tabstop(cx) {
3002            return;
3003        }
3004
3005        self.outdent(&Outdent, cx);
3006    }
3007
3008    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3009        if self.move_to_next_snippet_tabstop(cx) {
3010            return;
3011        }
3012
3013        let mut selections = self.selections.all_adjusted(cx);
3014        let buffer = self.buffer.read(cx);
3015        let snapshot = buffer.snapshot(cx);
3016        let rows_iter = selections.iter().map(|s| s.head().row);
3017        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3018
3019        let mut edits = Vec::new();
3020        let mut prev_edited_row = 0;
3021        let mut row_delta = 0;
3022        for selection in &mut selections {
3023            if selection.start.row != prev_edited_row {
3024                row_delta = 0;
3025            }
3026            prev_edited_row = selection.end.row;
3027
3028            // If the selection is non-empty, then increase the indentation of the selected lines.
3029            if !selection.is_empty() {
3030                row_delta =
3031                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3032                continue;
3033            }
3034
3035            // If the selection is empty and the cursor is in the leading whitespace before the
3036            // suggested indentation, then auto-indent the line.
3037            let cursor = selection.head();
3038            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3039                let current_indent = snapshot.indent_size_for_line(cursor.row);
3040                if cursor.column < suggested_indent.len
3041                    && cursor.column <= current_indent.len
3042                    && current_indent.len <= suggested_indent.len
3043                {
3044                    selection.start = Point::new(cursor.row, suggested_indent.len);
3045                    selection.end = selection.start;
3046                    if row_delta == 0 {
3047                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3048                            cursor.row,
3049                            current_indent,
3050                            suggested_indent,
3051                        ));
3052                        row_delta = suggested_indent.len - current_indent.len;
3053                    }
3054                    continue;
3055                }
3056            }
3057
3058            // Otherwise, insert a hard or soft tab.
3059            let settings = cx.global::<Settings>();
3060            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3061            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3062                IndentSize::tab()
3063            } else {
3064                let tab_size = settings.tab_size(language_name.as_deref()).get();
3065                let char_column = snapshot
3066                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3067                    .flat_map(str::chars)
3068                    .count()
3069                    + row_delta as usize;
3070                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3071                IndentSize::spaces(chars_to_next_tab_stop)
3072            };
3073            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3074            selection.end = selection.start;
3075            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3076            row_delta += tab_size.len;
3077        }
3078
3079        self.transact(cx, |this, cx| {
3080            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3081            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections))
3082        });
3083    }
3084
3085    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3086        let mut selections = self.selections.all::<Point>(cx);
3087        let mut prev_edited_row = 0;
3088        let mut row_delta = 0;
3089        let mut edits = Vec::new();
3090        let buffer = self.buffer.read(cx);
3091        let snapshot = buffer.snapshot(cx);
3092        for selection in &mut selections {
3093            if selection.start.row != prev_edited_row {
3094                row_delta = 0;
3095            }
3096            prev_edited_row = selection.end.row;
3097
3098            row_delta =
3099                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3100        }
3101
3102        self.transact(cx, |this, cx| {
3103            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3104            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3105        });
3106    }
3107
3108    fn indent_selection(
3109        buffer: &MultiBuffer,
3110        snapshot: &MultiBufferSnapshot,
3111        selection: &mut Selection<Point>,
3112        edits: &mut Vec<(Range<Point>, String)>,
3113        delta_for_start_row: u32,
3114        cx: &AppContext,
3115    ) -> u32 {
3116        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3117        let settings = cx.global::<Settings>();
3118        let tab_size = settings.tab_size(language_name.as_deref()).get();
3119        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3120            IndentKind::Tab
3121        } else {
3122            IndentKind::Space
3123        };
3124        let mut start_row = selection.start.row;
3125        let mut end_row = selection.end.row + 1;
3126
3127        // If a selection ends at the beginning of a line, don't indent
3128        // that last line.
3129        if selection.end.column == 0 {
3130            end_row -= 1;
3131        }
3132
3133        // Avoid re-indenting a row that has already been indented by a
3134        // previous selection, but still update this selection's column
3135        // to reflect that indentation.
3136        if delta_for_start_row > 0 {
3137            start_row += 1;
3138            selection.start.column += delta_for_start_row;
3139            if selection.end.row == selection.start.row {
3140                selection.end.column += delta_for_start_row;
3141            }
3142        }
3143
3144        let mut delta_for_end_row = 0;
3145        for row in start_row..end_row {
3146            let current_indent = snapshot.indent_size_for_line(row);
3147            let indent_delta = match (current_indent.kind, indent_kind) {
3148                (IndentKind::Space, IndentKind::Space) => {
3149                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3150                    IndentSize::spaces(columns_to_next_tab_stop)
3151                }
3152                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3153                (_, IndentKind::Tab) => IndentSize::tab(),
3154            };
3155
3156            let row_start = Point::new(row, 0);
3157            edits.push((
3158                row_start..row_start,
3159                indent_delta.chars().collect::<String>(),
3160            ));
3161
3162            // Update this selection's endpoints to reflect the indentation.
3163            if row == selection.start.row {
3164                selection.start.column += indent_delta.len;
3165            }
3166            if row == selection.end.row {
3167                selection.end.column += indent_delta.len;
3168                delta_for_end_row = indent_delta.len;
3169            }
3170        }
3171
3172        if selection.start.row == selection.end.row {
3173            delta_for_start_row + delta_for_end_row
3174        } else {
3175            delta_for_end_row
3176        }
3177    }
3178
3179    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3180        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3181        let selections = self.selections.all::<Point>(cx);
3182        let mut deletion_ranges = Vec::new();
3183        let mut last_outdent = None;
3184        {
3185            let buffer = self.buffer.read(cx);
3186            let snapshot = buffer.snapshot(cx);
3187            for selection in &selections {
3188                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3189                let tab_size = cx
3190                    .global::<Settings>()
3191                    .tab_size(language_name.as_deref())
3192                    .get();
3193                let mut rows = selection.spanned_rows(false, &display_map);
3194
3195                // Avoid re-outdenting a row that has already been outdented by a
3196                // previous selection.
3197                if let Some(last_row) = last_outdent {
3198                    if last_row == rows.start {
3199                        rows.start += 1;
3200                    }
3201                }
3202
3203                for row in rows {
3204                    let indent_size = snapshot.indent_size_for_line(row);
3205                    if indent_size.len > 0 {
3206                        let deletion_len = match indent_size.kind {
3207                            IndentKind::Space => {
3208                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3209                                if columns_to_prev_tab_stop == 0 {
3210                                    tab_size
3211                                } else {
3212                                    columns_to_prev_tab_stop
3213                                }
3214                            }
3215                            IndentKind::Tab => 1,
3216                        };
3217                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3218                        last_outdent = Some(row);
3219                    }
3220                }
3221            }
3222        }
3223
3224        self.transact(cx, |this, cx| {
3225            this.buffer.update(cx, |buffer, cx| {
3226                let empty_str: Arc<str> = "".into();
3227                buffer.edit(
3228                    deletion_ranges
3229                        .into_iter()
3230                        .map(|range| (range, empty_str.clone())),
3231                    None,
3232                    cx,
3233                );
3234            });
3235            let selections = this.selections.all::<usize>(cx);
3236            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3237        });
3238    }
3239
3240    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3241        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3242        let selections = self.selections.all::<Point>(cx);
3243
3244        let mut new_cursors = Vec::new();
3245        let mut edit_ranges = Vec::new();
3246        let mut selections = selections.iter().peekable();
3247        while let Some(selection) = selections.next() {
3248            let mut rows = selection.spanned_rows(false, &display_map);
3249            let goal_display_column = selection.head().to_display_point(&display_map).column();
3250
3251            // Accumulate contiguous regions of rows that we want to delete.
3252            while let Some(next_selection) = selections.peek() {
3253                let next_rows = next_selection.spanned_rows(false, &display_map);
3254                if next_rows.start <= rows.end {
3255                    rows.end = next_rows.end;
3256                    selections.next().unwrap();
3257                } else {
3258                    break;
3259                }
3260            }
3261
3262            let buffer = &display_map.buffer_snapshot;
3263            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3264            let edit_end;
3265            let cursor_buffer_row;
3266            if buffer.max_point().row >= rows.end {
3267                // If there's a line after the range, delete the \n from the end of the row range
3268                // and position the cursor on the next line.
3269                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3270                cursor_buffer_row = rows.end;
3271            } else {
3272                // If there isn't a line after the range, delete the \n from the line before the
3273                // start of the row range and position the cursor there.
3274                edit_start = edit_start.saturating_sub(1);
3275                edit_end = buffer.len();
3276                cursor_buffer_row = rows.start.saturating_sub(1);
3277            }
3278
3279            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3280            *cursor.column_mut() =
3281                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3282
3283            new_cursors.push((
3284                selection.id,
3285                buffer.anchor_after(cursor.to_point(&display_map)),
3286            ));
3287            edit_ranges.push(edit_start..edit_end);
3288        }
3289
3290        self.transact(cx, |this, cx| {
3291            let buffer = this.buffer.update(cx, |buffer, cx| {
3292                let empty_str: Arc<str> = "".into();
3293                buffer.edit(
3294                    edit_ranges
3295                        .into_iter()
3296                        .map(|range| (range, empty_str.clone())),
3297                    None,
3298                    cx,
3299                );
3300                buffer.snapshot(cx)
3301            });
3302            let new_selections = new_cursors
3303                .into_iter()
3304                .map(|(id, cursor)| {
3305                    let cursor = cursor.to_point(&buffer);
3306                    Selection {
3307                        id,
3308                        start: cursor,
3309                        end: cursor,
3310                        reversed: false,
3311                        goal: SelectionGoal::None,
3312                    }
3313                })
3314                .collect();
3315
3316            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3317                s.select(new_selections);
3318            });
3319        });
3320    }
3321
3322    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3323        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3324        let buffer = &display_map.buffer_snapshot;
3325        let selections = self.selections.all::<Point>(cx);
3326
3327        let mut edits = Vec::new();
3328        let mut selections_iter = selections.iter().peekable();
3329        while let Some(selection) = selections_iter.next() {
3330            // Avoid duplicating the same lines twice.
3331            let mut rows = selection.spanned_rows(false, &display_map);
3332
3333            while let Some(next_selection) = selections_iter.peek() {
3334                let next_rows = next_selection.spanned_rows(false, &display_map);
3335                if next_rows.start < rows.end {
3336                    rows.end = next_rows.end;
3337                    selections_iter.next().unwrap();
3338                } else {
3339                    break;
3340                }
3341            }
3342
3343            // Copy the text from the selected row region and splice it at the start of the region.
3344            let start = Point::new(rows.start, 0);
3345            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3346            let text = buffer
3347                .text_for_range(start..end)
3348                .chain(Some("\n"))
3349                .collect::<String>();
3350            edits.push((start..start, text));
3351        }
3352
3353        self.transact(cx, |this, cx| {
3354            this.buffer.update(cx, |buffer, cx| {
3355                buffer.edit(edits, None, cx);
3356            });
3357
3358            this.request_autoscroll(Autoscroll::Fit, cx);
3359        });
3360    }
3361
3362    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3363        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3364        let buffer = self.buffer.read(cx).snapshot(cx);
3365
3366        let mut edits = Vec::new();
3367        let mut unfold_ranges = Vec::new();
3368        let mut refold_ranges = Vec::new();
3369
3370        let selections = self.selections.all::<Point>(cx);
3371        let mut selections = selections.iter().peekable();
3372        let mut contiguous_row_selections = Vec::new();
3373        let mut new_selections = Vec::new();
3374
3375        while let Some(selection) = selections.next() {
3376            // Find all the selections that span a contiguous row range
3377            contiguous_row_selections.push(selection.clone());
3378            let start_row = selection.start.row;
3379            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3380                display_map.next_line_boundary(selection.end).0.row + 1
3381            } else {
3382                selection.end.row
3383            };
3384
3385            while let Some(next_selection) = selections.peek() {
3386                if next_selection.start.row <= end_row {
3387                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3388                        display_map.next_line_boundary(next_selection.end).0.row + 1
3389                    } else {
3390                        next_selection.end.row
3391                    };
3392                    contiguous_row_selections.push(selections.next().unwrap().clone());
3393                } else {
3394                    break;
3395                }
3396            }
3397
3398            // Move the text spanned by the row range to be before the line preceding the row range
3399            if start_row > 0 {
3400                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3401                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3402                let insertion_point = display_map
3403                    .prev_line_boundary(Point::new(start_row - 1, 0))
3404                    .0;
3405
3406                // Don't move lines across excerpts
3407                if buffer
3408                    .excerpt_boundaries_in_range((
3409                        Bound::Excluded(insertion_point),
3410                        Bound::Included(range_to_move.end),
3411                    ))
3412                    .next()
3413                    .is_none()
3414                {
3415                    let text = buffer
3416                        .text_for_range(range_to_move.clone())
3417                        .flat_map(|s| s.chars())
3418                        .skip(1)
3419                        .chain(['\n'])
3420                        .collect::<String>();
3421
3422                    edits.push((
3423                        buffer.anchor_after(range_to_move.start)
3424                            ..buffer.anchor_before(range_to_move.end),
3425                        String::new(),
3426                    ));
3427                    let insertion_anchor = buffer.anchor_after(insertion_point);
3428                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3429
3430                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3431
3432                    // Move selections up
3433                    new_selections.extend(contiguous_row_selections.drain(..).map(
3434                        |mut selection| {
3435                            selection.start.row -= row_delta;
3436                            selection.end.row -= row_delta;
3437                            selection
3438                        },
3439                    ));
3440
3441                    // Move folds up
3442                    unfold_ranges.push(range_to_move.clone());
3443                    for fold in display_map.folds_in_range(
3444                        buffer.anchor_before(range_to_move.start)
3445                            ..buffer.anchor_after(range_to_move.end),
3446                    ) {
3447                        let mut start = fold.start.to_point(&buffer);
3448                        let mut end = fold.end.to_point(&buffer);
3449                        start.row -= row_delta;
3450                        end.row -= row_delta;
3451                        refold_ranges.push(start..end);
3452                    }
3453                }
3454            }
3455
3456            // If we didn't move line(s), preserve the existing selections
3457            new_selections.append(&mut contiguous_row_selections);
3458        }
3459
3460        self.transact(cx, |this, cx| {
3461            this.unfold_ranges(unfold_ranges, true, cx);
3462            this.buffer.update(cx, |buffer, cx| {
3463                for (range, text) in edits {
3464                    buffer.edit([(range, text)], None, cx);
3465                }
3466            });
3467            this.fold_ranges(refold_ranges, cx);
3468            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3469                s.select(new_selections);
3470            })
3471        });
3472    }
3473
3474    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3475        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3476        let buffer = self.buffer.read(cx).snapshot(cx);
3477
3478        let mut edits = Vec::new();
3479        let mut unfold_ranges = Vec::new();
3480        let mut refold_ranges = Vec::new();
3481
3482        let selections = self.selections.all::<Point>(cx);
3483        let mut selections = selections.iter().peekable();
3484        let mut contiguous_row_selections = Vec::new();
3485        let mut new_selections = Vec::new();
3486
3487        while let Some(selection) = selections.next() {
3488            // Find all the selections that span a contiguous row range
3489            contiguous_row_selections.push(selection.clone());
3490            let start_row = selection.start.row;
3491            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
3492                display_map.next_line_boundary(selection.end).0.row + 1
3493            } else {
3494                selection.end.row
3495            };
3496
3497            while let Some(next_selection) = selections.peek() {
3498                if next_selection.start.row <= end_row {
3499                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
3500                        display_map.next_line_boundary(next_selection.end).0.row + 1
3501                    } else {
3502                        next_selection.end.row
3503                    };
3504                    contiguous_row_selections.push(selections.next().unwrap().clone());
3505                } else {
3506                    break;
3507                }
3508            }
3509
3510            // Move the text spanned by the row range to be after the last line of the row range
3511            if end_row <= buffer.max_point().row {
3512                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3513                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3514
3515                // Don't move lines across excerpt boundaries
3516                if buffer
3517                    .excerpt_boundaries_in_range((
3518                        Bound::Excluded(range_to_move.start),
3519                        Bound::Included(insertion_point),
3520                    ))
3521                    .next()
3522                    .is_none()
3523                {
3524                    let mut text = String::from("\n");
3525                    text.extend(buffer.text_for_range(range_to_move.clone()));
3526                    text.pop(); // Drop trailing newline
3527                    edits.push((
3528                        buffer.anchor_after(range_to_move.start)
3529                            ..buffer.anchor_before(range_to_move.end),
3530                        String::new(),
3531                    ));
3532                    let insertion_anchor = buffer.anchor_after(insertion_point);
3533                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
3534
3535                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3536
3537                    // Move selections down
3538                    new_selections.extend(contiguous_row_selections.drain(..).map(
3539                        |mut selection| {
3540                            selection.start.row += row_delta;
3541                            selection.end.row += row_delta;
3542                            selection
3543                        },
3544                    ));
3545
3546                    // Move folds down
3547                    unfold_ranges.push(range_to_move.clone());
3548                    for fold in display_map.folds_in_range(
3549                        buffer.anchor_before(range_to_move.start)
3550                            ..buffer.anchor_after(range_to_move.end),
3551                    ) {
3552                        let mut start = fold.start.to_point(&buffer);
3553                        let mut end = fold.end.to_point(&buffer);
3554                        start.row += row_delta;
3555                        end.row += row_delta;
3556                        refold_ranges.push(start..end);
3557                    }
3558                }
3559            }
3560
3561            // If we didn't move line(s), preserve the existing selections
3562            new_selections.append(&mut contiguous_row_selections);
3563        }
3564
3565        self.transact(cx, |this, cx| {
3566            this.unfold_ranges(unfold_ranges, true, cx);
3567            this.buffer.update(cx, |buffer, cx| {
3568                for (range, text) in edits {
3569                    buffer.edit([(range, text)], None, cx);
3570                }
3571            });
3572            this.fold_ranges(refold_ranges, cx);
3573            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(new_selections));
3574        });
3575    }
3576
3577    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3578        self.transact(cx, |this, cx| {
3579            let edits = this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3580                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3581                let line_mode = s.line_mode;
3582                s.move_with(|display_map, selection| {
3583                    if !selection.is_empty() || line_mode {
3584                        return;
3585                    }
3586
3587                    let mut head = selection.head();
3588                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3589                    if head.column() == display_map.line_len(head.row()) {
3590                        transpose_offset = display_map
3591                            .buffer_snapshot
3592                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3593                    }
3594
3595                    if transpose_offset == 0 {
3596                        return;
3597                    }
3598
3599                    *head.column_mut() += 1;
3600                    head = display_map.clip_point(head, Bias::Right);
3601                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3602
3603                    let transpose_start = display_map
3604                        .buffer_snapshot
3605                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3606                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3607                        let transpose_end = display_map
3608                            .buffer_snapshot
3609                            .clip_offset(transpose_offset + 1, Bias::Right);
3610                        if let Some(ch) =
3611                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3612                        {
3613                            edits.push((transpose_start..transpose_offset, String::new()));
3614                            edits.push((transpose_end..transpose_end, ch.to_string()));
3615                        }
3616                    }
3617                });
3618                edits
3619            });
3620            this.buffer
3621                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3622            let selections = this.selections.all::<usize>(cx);
3623            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3624                s.select(selections);
3625            });
3626        });
3627    }
3628
3629    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3630        let mut text = String::new();
3631        let buffer = self.buffer.read(cx).snapshot(cx);
3632        let mut selections = self.selections.all::<Point>(cx);
3633        let mut clipboard_selections = Vec::with_capacity(selections.len());
3634        {
3635            let max_point = buffer.max_point();
3636            for selection in &mut selections {
3637                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3638                if is_entire_line {
3639                    selection.start = Point::new(selection.start.row, 0);
3640                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3641                    selection.goal = SelectionGoal::None;
3642                }
3643                let mut len = 0;
3644                for chunk in buffer.text_for_range(selection.start..selection.end) {
3645                    text.push_str(chunk);
3646                    len += chunk.len();
3647                }
3648                clipboard_selections.push(ClipboardSelection {
3649                    len,
3650                    is_entire_line,
3651                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3652                });
3653            }
3654        }
3655
3656        self.transact(cx, |this, cx| {
3657            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3658                s.select(selections);
3659            });
3660            this.insert("", cx);
3661            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3662        });
3663    }
3664
3665    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3666        let selections = self.selections.all::<Point>(cx);
3667        let buffer = self.buffer.read(cx).read(cx);
3668        let mut text = String::new();
3669
3670        let mut clipboard_selections = Vec::with_capacity(selections.len());
3671        {
3672            let max_point = buffer.max_point();
3673            for selection in selections.iter() {
3674                let mut start = selection.start;
3675                let mut end = selection.end;
3676                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3677                if is_entire_line {
3678                    start = Point::new(start.row, 0);
3679                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3680                }
3681                let mut len = 0;
3682                for chunk in buffer.text_for_range(start..end) {
3683                    text.push_str(chunk);
3684                    len += chunk.len();
3685                }
3686                clipboard_selections.push(ClipboardSelection {
3687                    len,
3688                    is_entire_line,
3689                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3690                });
3691            }
3692        }
3693
3694        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3695    }
3696
3697    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3698        self.transact(cx, |this, cx| {
3699            if let Some(item) = cx.as_mut().read_from_clipboard() {
3700                let mut clipboard_text = Cow::Borrowed(item.text());
3701                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3702                    let old_selections = this.selections.all::<usize>(cx);
3703                    let all_selections_were_entire_line =
3704                        clipboard_selections.iter().all(|s| s.is_entire_line);
3705                    let first_selection_indent_column =
3706                        clipboard_selections.first().map(|s| s.first_line_indent);
3707                    if clipboard_selections.len() != old_selections.len() {
3708                        let mut newline_separated_text = String::new();
3709                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3710                        let mut ix = 0;
3711                        while let Some(clipboard_selection) = clipboard_selections.next() {
3712                            newline_separated_text
3713                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3714                            ix += clipboard_selection.len;
3715                            if clipboard_selections.peek().is_some() {
3716                                newline_separated_text.push('\n');
3717                            }
3718                        }
3719                        clipboard_text = Cow::Owned(newline_separated_text);
3720                    }
3721
3722                    this.buffer.update(cx, |buffer, cx| {
3723                        let snapshot = buffer.read(cx);
3724                        let mut start_offset = 0;
3725                        let mut edits = Vec::new();
3726                        let mut original_indent_columns = Vec::new();
3727                        let line_mode = this.selections.line_mode;
3728                        for (ix, selection) in old_selections.iter().enumerate() {
3729                            let to_insert;
3730                            let entire_line;
3731                            let original_indent_column;
3732                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3733                                let end_offset = start_offset + clipboard_selection.len;
3734                                to_insert = &clipboard_text[start_offset..end_offset];
3735                                entire_line = clipboard_selection.is_entire_line;
3736                                start_offset = end_offset;
3737                                original_indent_column =
3738                                    Some(clipboard_selection.first_line_indent);
3739                            } else {
3740                                to_insert = clipboard_text.as_str();
3741                                entire_line = all_selections_were_entire_line;
3742                                original_indent_column = first_selection_indent_column
3743                            }
3744
3745                            // If the corresponding selection was empty when this slice of the
3746                            // clipboard text was written, then the entire line containing the
3747                            // selection was copied. If this selection is also currently empty,
3748                            // then paste the line before the current line of the buffer.
3749                            let range = if selection.is_empty() && !line_mode && entire_line {
3750                                let column = selection.start.to_point(&snapshot).column as usize;
3751                                let line_start = selection.start - column;
3752                                line_start..line_start
3753                            } else {
3754                                selection.range()
3755                            };
3756
3757                            edits.push((range, to_insert));
3758                            original_indent_columns.extend(original_indent_column);
3759                        }
3760                        drop(snapshot);
3761
3762                        buffer.edit(
3763                            edits,
3764                            Some(AutoindentMode::Block {
3765                                original_indent_columns,
3766                            }),
3767                            cx,
3768                        );
3769                    });
3770
3771                    let selections = this.selections.all::<usize>(cx);
3772                    this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
3773                } else {
3774                    this.insert(&clipboard_text, cx);
3775                }
3776            }
3777        });
3778    }
3779
3780    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3781        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3782            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3783                self.change_selections(None, cx, |s| {
3784                    s.select_anchors(selections.to_vec());
3785                });
3786            }
3787            self.request_autoscroll(Autoscroll::Fit, cx);
3788            self.unmark_text(cx);
3789            cx.emit(Event::Edited);
3790        }
3791    }
3792
3793    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3794        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3795            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3796            {
3797                self.change_selections(None, cx, |s| {
3798                    s.select_anchors(selections.to_vec());
3799                });
3800            }
3801            self.request_autoscroll(Autoscroll::Fit, cx);
3802            self.unmark_text(cx);
3803            cx.emit(Event::Edited);
3804        }
3805    }
3806
3807    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
3808        self.buffer
3809            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
3810    }
3811
3812    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
3813        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3814            let line_mode = s.line_mode;
3815            s.move_with(|map, selection| {
3816                let cursor = if selection.is_empty() && !line_mode {
3817                    movement::left(map, selection.start)
3818                } else {
3819                    selection.start
3820                };
3821                selection.collapse_to(cursor, SelectionGoal::None);
3822            });
3823        })
3824    }
3825
3826    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
3827        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3828            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
3829        })
3830    }
3831
3832    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
3833        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3834            let line_mode = s.line_mode;
3835            s.move_with(|map, selection| {
3836                let cursor = if selection.is_empty() && !line_mode {
3837                    movement::right(map, selection.end)
3838                } else {
3839                    selection.end
3840                };
3841                selection.collapse_to(cursor, SelectionGoal::None)
3842            });
3843        })
3844    }
3845
3846    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
3847        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3848            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
3849        })
3850    }
3851
3852    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
3853        if self.take_rename(true, cx).is_some() {
3854            return;
3855        }
3856
3857        if let Some(context_menu) = self.context_menu.as_mut() {
3858            if context_menu.select_prev(cx) {
3859                return;
3860            }
3861        }
3862
3863        if matches!(self.mode, EditorMode::SingleLine) {
3864            cx.propagate_action();
3865            return;
3866        }
3867
3868        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3869            let line_mode = s.line_mode;
3870            s.move_with(|map, selection| {
3871                if !selection.is_empty() && !line_mode {
3872                    selection.goal = SelectionGoal::None;
3873                }
3874                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
3875                selection.collapse_to(cursor, goal);
3876            });
3877        })
3878    }
3879
3880    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
3881        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3882            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
3883        })
3884    }
3885
3886    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
3887        self.take_rename(true, cx);
3888
3889        if let Some(context_menu) = self.context_menu.as_mut() {
3890            if context_menu.select_next(cx) {
3891                return;
3892            }
3893        }
3894
3895        if matches!(self.mode, EditorMode::SingleLine) {
3896            cx.propagate_action();
3897            return;
3898        }
3899
3900        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3901            let line_mode = s.line_mode;
3902            s.move_with(|map, selection| {
3903                if !selection.is_empty() && !line_mode {
3904                    selection.goal = SelectionGoal::None;
3905                }
3906                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
3907                selection.collapse_to(cursor, goal);
3908            });
3909        });
3910    }
3911
3912    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
3913        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3914            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
3915        });
3916    }
3917
3918    pub fn move_to_previous_word_start(
3919        &mut self,
3920        _: &MoveToPreviousWordStart,
3921        cx: &mut ViewContext<Self>,
3922    ) {
3923        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3924            s.move_cursors_with(|map, head, _| {
3925                (
3926                    movement::previous_word_start(map, head),
3927                    SelectionGoal::None,
3928                )
3929            });
3930        })
3931    }
3932
3933    pub fn move_to_previous_subword_start(
3934        &mut self,
3935        _: &MoveToPreviousSubwordStart,
3936        cx: &mut ViewContext<Self>,
3937    ) {
3938        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3939            s.move_cursors_with(|map, head, _| {
3940                (
3941                    movement::previous_subword_start(map, head),
3942                    SelectionGoal::None,
3943                )
3944            });
3945        })
3946    }
3947
3948    pub fn select_to_previous_word_start(
3949        &mut self,
3950        _: &SelectToPreviousWordStart,
3951        cx: &mut ViewContext<Self>,
3952    ) {
3953        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3954            s.move_heads_with(|map, head, _| {
3955                (
3956                    movement::previous_word_start(map, head),
3957                    SelectionGoal::None,
3958                )
3959            });
3960        })
3961    }
3962
3963    pub fn select_to_previous_subword_start(
3964        &mut self,
3965        _: &SelectToPreviousSubwordStart,
3966        cx: &mut ViewContext<Self>,
3967    ) {
3968        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
3969            s.move_heads_with(|map, head, _| {
3970                (
3971                    movement::previous_subword_start(map, head),
3972                    SelectionGoal::None,
3973                )
3974            });
3975        })
3976    }
3977
3978    pub fn delete_to_previous_word_start(
3979        &mut self,
3980        _: &DeleteToPreviousWordStart,
3981        cx: &mut ViewContext<Self>,
3982    ) {
3983        self.transact(cx, |this, cx| {
3984            this.select_autoclose_pair(cx);
3985            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
3986                let line_mode = s.line_mode;
3987                s.move_with(|map, selection| {
3988                    if selection.is_empty() && !line_mode {
3989                        let cursor = movement::previous_word_start(map, selection.head());
3990                        selection.set_head(cursor, SelectionGoal::None);
3991                    }
3992                });
3993            });
3994            this.insert("", cx);
3995        });
3996    }
3997
3998    pub fn delete_to_previous_subword_start(
3999        &mut self,
4000        _: &DeleteToPreviousSubwordStart,
4001        cx: &mut ViewContext<Self>,
4002    ) {
4003        self.transact(cx, |this, cx| {
4004            this.select_autoclose_pair(cx);
4005            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4006                let line_mode = s.line_mode;
4007                s.move_with(|map, selection| {
4008                    if selection.is_empty() && !line_mode {
4009                        let cursor = movement::previous_subword_start(map, selection.head());
4010                        selection.set_head(cursor, SelectionGoal::None);
4011                    }
4012                });
4013            });
4014            this.insert("", cx);
4015        });
4016    }
4017
4018    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4019        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4020            s.move_cursors_with(|map, head, _| {
4021                (movement::next_word_end(map, head), SelectionGoal::None)
4022            });
4023        })
4024    }
4025
4026    pub fn move_to_next_subword_end(
4027        &mut self,
4028        _: &MoveToNextSubwordEnd,
4029        cx: &mut ViewContext<Self>,
4030    ) {
4031        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4032            s.move_cursors_with(|map, head, _| {
4033                (movement::next_subword_end(map, head), SelectionGoal::None)
4034            });
4035        })
4036    }
4037
4038    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4039        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4040            s.move_heads_with(|map, head, _| {
4041                (movement::next_word_end(map, head), SelectionGoal::None)
4042            });
4043        })
4044    }
4045
4046    pub fn select_to_next_subword_end(
4047        &mut self,
4048        _: &SelectToNextSubwordEnd,
4049        cx: &mut ViewContext<Self>,
4050    ) {
4051        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4052            s.move_heads_with(|map, head, _| {
4053                (movement::next_subword_end(map, head), SelectionGoal::None)
4054            });
4055        })
4056    }
4057
4058    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4059        self.transact(cx, |this, cx| {
4060            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4061                let line_mode = s.line_mode;
4062                s.move_with(|map, selection| {
4063                    if selection.is_empty() && !line_mode {
4064                        let cursor = movement::next_word_end(map, selection.head());
4065                        selection.set_head(cursor, SelectionGoal::None);
4066                    }
4067                });
4068            });
4069            this.insert("", cx);
4070        });
4071    }
4072
4073    pub fn delete_to_next_subword_end(
4074        &mut self,
4075        _: &DeleteToNextSubwordEnd,
4076        cx: &mut ViewContext<Self>,
4077    ) {
4078        self.transact(cx, |this, cx| {
4079            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4080                s.move_with(|map, selection| {
4081                    if selection.is_empty() {
4082                        let cursor = movement::next_subword_end(map, selection.head());
4083                        selection.set_head(cursor, SelectionGoal::None);
4084                    }
4085                });
4086            });
4087            this.insert("", cx);
4088        });
4089    }
4090
4091    pub fn move_to_beginning_of_line(
4092        &mut self,
4093        _: &MoveToBeginningOfLine,
4094        cx: &mut ViewContext<Self>,
4095    ) {
4096        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4097            s.move_cursors_with(|map, head, _| {
4098                (
4099                    movement::indented_line_beginning(map, head, true),
4100                    SelectionGoal::None,
4101                )
4102            });
4103        })
4104    }
4105
4106    pub fn select_to_beginning_of_line(
4107        &mut self,
4108        action: &SelectToBeginningOfLine,
4109        cx: &mut ViewContext<Self>,
4110    ) {
4111        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4112            s.move_heads_with(|map, head, _| {
4113                (
4114                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4115                    SelectionGoal::None,
4116                )
4117            });
4118        });
4119    }
4120
4121    pub fn delete_to_beginning_of_line(
4122        &mut self,
4123        _: &DeleteToBeginningOfLine,
4124        cx: &mut ViewContext<Self>,
4125    ) {
4126        self.transact(cx, |this, cx| {
4127            this.change_selections(Some(Autoscroll::Fit), cx, |s| {
4128                s.move_with(|_, selection| {
4129                    selection.reversed = true;
4130                });
4131            });
4132
4133            this.select_to_beginning_of_line(
4134                &SelectToBeginningOfLine {
4135                    stop_at_soft_wraps: false,
4136                },
4137                cx,
4138            );
4139            this.backspace(&Backspace, cx);
4140        });
4141    }
4142
4143    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4144        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4145            s.move_cursors_with(|map, head, _| {
4146                (movement::line_end(map, head, true), SelectionGoal::None)
4147            });
4148        })
4149    }
4150
4151    pub fn select_to_end_of_line(
4152        &mut self,
4153        action: &SelectToEndOfLine,
4154        cx: &mut ViewContext<Self>,
4155    ) {
4156        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4157            s.move_heads_with(|map, head, _| {
4158                (
4159                    movement::line_end(map, head, action.stop_at_soft_wraps),
4160                    SelectionGoal::None,
4161                )
4162            });
4163        })
4164    }
4165
4166    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4167        self.transact(cx, |this, cx| {
4168            this.select_to_end_of_line(
4169                &SelectToEndOfLine {
4170                    stop_at_soft_wraps: false,
4171                },
4172                cx,
4173            );
4174            this.delete(&Delete, cx);
4175        });
4176    }
4177
4178    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4179        self.transact(cx, |this, cx| {
4180            this.select_to_end_of_line(
4181                &SelectToEndOfLine {
4182                    stop_at_soft_wraps: false,
4183                },
4184                cx,
4185            );
4186            this.cut(&Cut, cx);
4187        });
4188    }
4189
4190    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4191        if matches!(self.mode, EditorMode::SingleLine) {
4192            cx.propagate_action();
4193            return;
4194        }
4195
4196        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4197            s.select_ranges(vec![0..0]);
4198        });
4199    }
4200
4201    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4202        let mut selection = self.selections.last::<Point>(cx);
4203        selection.set_head(Point::zero(), SelectionGoal::None);
4204
4205        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4206            s.select(vec![selection]);
4207        });
4208    }
4209
4210    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4211        if matches!(self.mode, EditorMode::SingleLine) {
4212            cx.propagate_action();
4213            return;
4214        }
4215
4216        let cursor = self.buffer.read(cx).read(cx).len();
4217        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4218            s.select_ranges(vec![cursor..cursor])
4219        });
4220    }
4221
4222    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4223        self.nav_history = nav_history;
4224    }
4225
4226    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4227        self.nav_history.as_ref()
4228    }
4229
4230    fn push_to_nav_history(
4231        &self,
4232        position: Anchor,
4233        new_position: Option<Point>,
4234        cx: &mut ViewContext<Self>,
4235    ) {
4236        if let Some(nav_history) = &self.nav_history {
4237            let buffer = self.buffer.read(cx).read(cx);
4238            let point = position.to_point(&buffer);
4239            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
4240            drop(buffer);
4241
4242            if let Some(new_position) = new_position {
4243                let row_delta = (new_position.row as i64 - point.row as i64).abs();
4244                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4245                    return;
4246                }
4247            }
4248
4249            nav_history.push(
4250                Some(NavigationData {
4251                    cursor_anchor: position,
4252                    cursor_position: point,
4253                    scroll_position: self.scroll_position,
4254                    scroll_top_anchor: self.scroll_top_anchor.clone(),
4255                    scroll_top_row,
4256                }),
4257                cx,
4258            );
4259        }
4260    }
4261
4262    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4263        let buffer = self.buffer.read(cx).snapshot(cx);
4264        let mut selection = self.selections.first::<usize>(cx);
4265        selection.set_head(buffer.len(), SelectionGoal::None);
4266        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4267            s.select(vec![selection]);
4268        });
4269    }
4270
4271    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4272        let end = self.buffer.read(cx).read(cx).len();
4273        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4274            s.select_ranges(vec![0..end]);
4275        });
4276    }
4277
4278    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4279        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4280        let mut selections = self.selections.all::<Point>(cx);
4281        let max_point = display_map.buffer_snapshot.max_point();
4282        for selection in &mut selections {
4283            let rows = selection.spanned_rows(true, &display_map);
4284            selection.start = Point::new(rows.start, 0);
4285            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4286            selection.reversed = false;
4287        }
4288        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4289            s.select(selections);
4290        });
4291    }
4292
4293    pub fn split_selection_into_lines(
4294        &mut self,
4295        _: &SplitSelectionIntoLines,
4296        cx: &mut ViewContext<Self>,
4297    ) {
4298        let mut to_unfold = Vec::new();
4299        let mut new_selection_ranges = Vec::new();
4300        {
4301            let selections = self.selections.all::<Point>(cx);
4302            let buffer = self.buffer.read(cx).read(cx);
4303            for selection in selections {
4304                for row in selection.start.row..selection.end.row {
4305                    let cursor = Point::new(row, buffer.line_len(row));
4306                    new_selection_ranges.push(cursor..cursor);
4307                }
4308                new_selection_ranges.push(selection.end..selection.end);
4309                to_unfold.push(selection.start..selection.end);
4310            }
4311        }
4312        self.unfold_ranges(to_unfold, true, cx);
4313        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4314            s.select_ranges(new_selection_ranges);
4315        });
4316    }
4317
4318    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4319        self.add_selection(true, cx);
4320    }
4321
4322    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4323        self.add_selection(false, cx);
4324    }
4325
4326    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4327        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4328        let mut selections = self.selections.all::<Point>(cx);
4329        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4330            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4331            let range = oldest_selection.display_range(&display_map).sorted();
4332            let columns = cmp::min(range.start.column(), range.end.column())
4333                ..cmp::max(range.start.column(), range.end.column());
4334
4335            selections.clear();
4336            let mut stack = Vec::new();
4337            for row in range.start.row()..=range.end.row() {
4338                if let Some(selection) = self.selections.build_columnar_selection(
4339                    &display_map,
4340                    row,
4341                    &columns,
4342                    oldest_selection.reversed,
4343                ) {
4344                    stack.push(selection.id);
4345                    selections.push(selection);
4346                }
4347            }
4348
4349            if above {
4350                stack.reverse();
4351            }
4352
4353            AddSelectionsState { above, stack }
4354        });
4355
4356        let last_added_selection = *state.stack.last().unwrap();
4357        let mut new_selections = Vec::new();
4358        if above == state.above {
4359            let end_row = if above {
4360                0
4361            } else {
4362                display_map.max_point().row()
4363            };
4364
4365            'outer: for selection in selections {
4366                if selection.id == last_added_selection {
4367                    let range = selection.display_range(&display_map).sorted();
4368                    debug_assert_eq!(range.start.row(), range.end.row());
4369                    let mut row = range.start.row();
4370                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4371                    {
4372                        start..end
4373                    } else {
4374                        cmp::min(range.start.column(), range.end.column())
4375                            ..cmp::max(range.start.column(), range.end.column())
4376                    };
4377
4378                    while row != end_row {
4379                        if above {
4380                            row -= 1;
4381                        } else {
4382                            row += 1;
4383                        }
4384
4385                        if let Some(new_selection) = self.selections.build_columnar_selection(
4386                            &display_map,
4387                            row,
4388                            &columns,
4389                            selection.reversed,
4390                        ) {
4391                            state.stack.push(new_selection.id);
4392                            if above {
4393                                new_selections.push(new_selection);
4394                                new_selections.push(selection);
4395                            } else {
4396                                new_selections.push(selection);
4397                                new_selections.push(new_selection);
4398                            }
4399
4400                            continue 'outer;
4401                        }
4402                    }
4403                }
4404
4405                new_selections.push(selection);
4406            }
4407        } else {
4408            new_selections = selections;
4409            new_selections.retain(|s| s.id != last_added_selection);
4410            state.stack.pop();
4411        }
4412
4413        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4414            s.select(new_selections);
4415        });
4416        if state.stack.len() > 1 {
4417            self.add_selections_state = Some(state);
4418        }
4419    }
4420
4421    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4422        self.push_to_selection_history();
4423        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4424        let buffer = &display_map.buffer_snapshot;
4425        let mut selections = self.selections.all::<usize>(cx);
4426        if let Some(mut select_next_state) = self.select_next_state.take() {
4427            let query = &select_next_state.query;
4428            if !select_next_state.done {
4429                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4430                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4431                let mut next_selected_range = None;
4432
4433                let bytes_after_last_selection =
4434                    buffer.bytes_in_range(last_selection.end..buffer.len());
4435                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4436                let query_matches = query
4437                    .stream_find_iter(bytes_after_last_selection)
4438                    .map(|result| (last_selection.end, result))
4439                    .chain(
4440                        query
4441                            .stream_find_iter(bytes_before_first_selection)
4442                            .map(|result| (0, result)),
4443                    );
4444                for (start_offset, query_match) in query_matches {
4445                    let query_match = query_match.unwrap(); // can only fail due to I/O
4446                    let offset_range =
4447                        start_offset + query_match.start()..start_offset + query_match.end();
4448                    let display_range = offset_range.start.to_display_point(&display_map)
4449                        ..offset_range.end.to_display_point(&display_map);
4450
4451                    if !select_next_state.wordwise
4452                        || (!movement::is_inside_word(&display_map, display_range.start)
4453                            && !movement::is_inside_word(&display_map, display_range.end))
4454                    {
4455                        next_selected_range = Some(offset_range);
4456                        break;
4457                    }
4458                }
4459
4460                if let Some(next_selected_range) = next_selected_range {
4461                    self.unfold_ranges([next_selected_range.clone()], false, cx);
4462                    self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4463                        if action.replace_newest {
4464                            s.delete(s.newest_anchor().id);
4465                        }
4466                        s.insert_range(next_selected_range);
4467                    });
4468                } else {
4469                    select_next_state.done = true;
4470                }
4471            }
4472
4473            self.select_next_state = Some(select_next_state);
4474        } else if selections.len() == 1 {
4475            let selection = selections.last_mut().unwrap();
4476            if selection.start == selection.end {
4477                let word_range = movement::surrounding_word(
4478                    &display_map,
4479                    selection.start.to_display_point(&display_map),
4480                );
4481                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4482                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4483                selection.goal = SelectionGoal::None;
4484                selection.reversed = false;
4485
4486                let query = buffer
4487                    .text_for_range(selection.start..selection.end)
4488                    .collect::<String>();
4489                let select_state = SelectNextState {
4490                    query: AhoCorasick::new_auto_configured(&[query]),
4491                    wordwise: true,
4492                    done: false,
4493                };
4494                self.unfold_ranges([selection.start..selection.end], false, cx);
4495                self.change_selections(Some(Autoscroll::Newest), cx, |s| {
4496                    s.select(selections);
4497                });
4498                self.select_next_state = Some(select_state);
4499            } else {
4500                let query = buffer
4501                    .text_for_range(selection.start..selection.end)
4502                    .collect::<String>();
4503                self.select_next_state = Some(SelectNextState {
4504                    query: AhoCorasick::new_auto_configured(&[query]),
4505                    wordwise: false,
4506                    done: false,
4507                });
4508                self.select_next(action, cx);
4509            }
4510        }
4511    }
4512
4513    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
4514        self.transact(cx, |this, cx| {
4515            let mut selections = this.selections.all::<Point>(cx);
4516            let mut edits = Vec::new();
4517            let mut selection_edit_ranges = Vec::new();
4518            let mut last_toggled_row = None;
4519            let snapshot = this.buffer.read(cx).read(cx);
4520            let empty_str: Arc<str> = "".into();
4521            let mut suffixes_inserted = Vec::new();
4522
4523            fn comment_prefix_range(
4524                snapshot: &MultiBufferSnapshot,
4525                row: u32,
4526                comment_prefix: &str,
4527                comment_prefix_whitespace: &str,
4528            ) -> Range<Point> {
4529                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4530
4531                let mut line_bytes = snapshot
4532                    .bytes_in_range(start..snapshot.max_point())
4533                    .flatten()
4534                    .copied();
4535
4536                // If this line currently begins with the line comment prefix, then record
4537                // the range containing the prefix.
4538                if line_bytes
4539                    .by_ref()
4540                    .take(comment_prefix.len())
4541                    .eq(comment_prefix.bytes())
4542                {
4543                    // Include any whitespace that matches the comment prefix.
4544                    let matching_whitespace_len = line_bytes
4545                        .zip(comment_prefix_whitespace.bytes())
4546                        .take_while(|(a, b)| a == b)
4547                        .count() as u32;
4548                    let end = Point::new(
4549                        start.row,
4550                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4551                    );
4552                    start..end
4553                } else {
4554                    start..start
4555                }
4556            }
4557
4558            fn comment_suffix_range(
4559                snapshot: &MultiBufferSnapshot,
4560                row: u32,
4561                comment_suffix: &str,
4562                comment_suffix_has_leading_space: bool,
4563            ) -> Range<Point> {
4564                let end = Point::new(row, snapshot.line_len(row));
4565                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4566
4567                let mut line_end_bytes = snapshot
4568                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4569                    .flatten()
4570                    .copied();
4571
4572                let leading_space_len = if suffix_start_column > 0
4573                    && line_end_bytes.next() == Some(b' ')
4574                    && comment_suffix_has_leading_space
4575                {
4576                    1
4577                } else {
4578                    0
4579                };
4580
4581                // If this line currently begins with the line comment prefix, then record
4582                // the range containing the prefix.
4583                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4584                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4585                    start..end
4586                } else {
4587                    end..end
4588                }
4589            }
4590
4591            // TODO: Handle selections that cross excerpts
4592            for selection in &mut selections {
4593                let language = if let Some(language) = snapshot.language_at(selection.start) {
4594                    language
4595                } else {
4596                    continue;
4597                };
4598
4599                selection_edit_ranges.clear();
4600
4601                // If multiple selections contain a given row, avoid processing that
4602                // row more than once.
4603                let mut start_row = selection.start.row;
4604                if last_toggled_row == Some(start_row) {
4605                    start_row += 1;
4606                }
4607                let end_row =
4608                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4609                        selection.end.row - 1
4610                    } else {
4611                        selection.end.row
4612                    };
4613                last_toggled_row = Some(end_row);
4614
4615                if start_row > end_row {
4616                    continue;
4617                }
4618
4619                // If the language has line comments, toggle those.
4620                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4621                    // Split the comment prefix's trailing whitespace into a separate string,
4622                    // as that portion won't be used for detecting if a line is a comment.
4623                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4624                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4625                    let mut all_selection_lines_are_comments = true;
4626
4627                    for row in start_row..=end_row {
4628                        if snapshot.is_line_blank(row) {
4629                            continue;
4630                        }
4631
4632                        let prefix_range = comment_prefix_range(
4633                            snapshot.deref(),
4634                            row,
4635                            comment_prefix,
4636                            comment_prefix_whitespace,
4637                        );
4638                        if prefix_range.is_empty() {
4639                            all_selection_lines_are_comments = false;
4640                        }
4641                        selection_edit_ranges.push(prefix_range);
4642                    }
4643
4644                    if all_selection_lines_are_comments {
4645                        edits.extend(
4646                            selection_edit_ranges
4647                                .iter()
4648                                .cloned()
4649                                .map(|range| (range, empty_str.clone())),
4650                        );
4651                    } else {
4652                        let min_column = selection_edit_ranges
4653                            .iter()
4654                            .map(|r| r.start.column)
4655                            .min()
4656                            .unwrap_or(0);
4657                        edits.extend(selection_edit_ranges.iter().map(|range| {
4658                            let position = Point::new(range.start.row, min_column);
4659                            (position..position, full_comment_prefix.clone())
4660                        }));
4661                    }
4662                } else if let Some((full_comment_prefix, comment_suffix)) =
4663                    language.block_comment_delimiters()
4664                {
4665                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4666                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4667                    let prefix_range = comment_prefix_range(
4668                        snapshot.deref(),
4669                        start_row,
4670                        comment_prefix,
4671                        comment_prefix_whitespace,
4672                    );
4673                    let suffix_range = comment_suffix_range(
4674                        snapshot.deref(),
4675                        end_row,
4676                        comment_suffix.trim_start_matches(' '),
4677                        comment_suffix.starts_with(' '),
4678                    );
4679
4680                    if prefix_range.is_empty() || suffix_range.is_empty() {
4681                        edits.push((
4682                            prefix_range.start..prefix_range.start,
4683                            full_comment_prefix.clone(),
4684                        ));
4685                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4686                        suffixes_inserted.push((end_row, comment_suffix.len()));
4687                    } else {
4688                        edits.push((prefix_range, empty_str.clone()));
4689                        edits.push((suffix_range, empty_str.clone()));
4690                    }
4691                } else {
4692                    continue;
4693                }
4694            }
4695
4696            drop(snapshot);
4697            this.buffer.update(cx, |buffer, cx| {
4698                buffer.edit(edits, None, cx);
4699            });
4700
4701            // Adjust selections so that they end before any comment suffixes that
4702            // were inserted.
4703            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4704            let mut selections = this.selections.all::<Point>(cx);
4705            let snapshot = this.buffer.read(cx).read(cx);
4706            for selection in &mut selections {
4707                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
4708                    match row.cmp(&selection.end.row) {
4709                        Ordering::Less => {
4710                            suffixes_inserted.next();
4711                            continue;
4712                        }
4713                        Ordering::Greater => break,
4714                        Ordering::Equal => {
4715                            if selection.end.column == snapshot.line_len(row) {
4716                                if selection.is_empty() {
4717                                    selection.start.column -= suffix_len as u32;
4718                                }
4719                                selection.end.column -= suffix_len as u32;
4720                            }
4721                            break;
4722                        }
4723                    }
4724                }
4725            }
4726
4727            drop(snapshot);
4728            this.change_selections(Some(Autoscroll::Fit), cx, |s| s.select(selections));
4729        });
4730    }
4731
4732    pub fn select_larger_syntax_node(
4733        &mut self,
4734        _: &SelectLargerSyntaxNode,
4735        cx: &mut ViewContext<Self>,
4736    ) {
4737        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4738        let buffer = self.buffer.read(cx).snapshot(cx);
4739        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
4740
4741        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4742        let mut selected_larger_node = false;
4743        let new_selections = old_selections
4744            .iter()
4745            .map(|selection| {
4746                let old_range = selection.start..selection.end;
4747                let mut new_range = old_range.clone();
4748                while let Some(containing_range) =
4749                    buffer.range_for_syntax_ancestor(new_range.clone())
4750                {
4751                    new_range = containing_range;
4752                    if !display_map.intersects_fold(new_range.start)
4753                        && !display_map.intersects_fold(new_range.end)
4754                    {
4755                        break;
4756                    }
4757                }
4758
4759                selected_larger_node |= new_range != old_range;
4760                Selection {
4761                    id: selection.id,
4762                    start: new_range.start,
4763                    end: new_range.end,
4764                    goal: SelectionGoal::None,
4765                    reversed: selection.reversed,
4766                }
4767            })
4768            .collect::<Vec<_>>();
4769
4770        if selected_larger_node {
4771            stack.push(old_selections);
4772            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4773                s.select(new_selections);
4774            });
4775        }
4776        self.select_larger_syntax_node_stack = stack;
4777    }
4778
4779    pub fn select_smaller_syntax_node(
4780        &mut self,
4781        _: &SelectSmallerSyntaxNode,
4782        cx: &mut ViewContext<Self>,
4783    ) {
4784        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
4785        if let Some(selections) = stack.pop() {
4786            self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4787                s.select(selections.to_vec());
4788            });
4789        }
4790        self.select_larger_syntax_node_stack = stack;
4791    }
4792
4793    pub fn move_to_enclosing_bracket(
4794        &mut self,
4795        _: &MoveToEnclosingBracket,
4796        cx: &mut ViewContext<Self>,
4797    ) {
4798        let buffer = self.buffer.read(cx).snapshot(cx);
4799        let mut selections = self.selections.all::<usize>(cx);
4800        for selection in &mut selections {
4801            if let Some((open_range, close_range)) =
4802                buffer.enclosing_bracket_ranges(selection.start..selection.end)
4803            {
4804                let close_range = close_range.to_inclusive();
4805                let destination = if close_range.contains(&selection.start)
4806                    && close_range.contains(&selection.end)
4807                {
4808                    open_range.end
4809                } else {
4810                    *close_range.start()
4811                };
4812                selection.start = destination;
4813                selection.end = destination;
4814            }
4815        }
4816
4817        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
4818            s.select(selections);
4819        });
4820    }
4821
4822    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
4823        self.end_selection(cx);
4824        self.selection_history.mode = SelectionHistoryMode::Undoing;
4825        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
4826            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4827            self.select_next_state = entry.select_next_state;
4828            self.add_selections_state = entry.add_selections_state;
4829            self.request_autoscroll(Autoscroll::Newest, cx);
4830        }
4831        self.selection_history.mode = SelectionHistoryMode::Normal;
4832    }
4833
4834    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
4835        self.end_selection(cx);
4836        self.selection_history.mode = SelectionHistoryMode::Redoing;
4837        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
4838            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
4839            self.select_next_state = entry.select_next_state;
4840            self.add_selections_state = entry.add_selections_state;
4841            self.request_autoscroll(Autoscroll::Newest, cx);
4842        }
4843        self.selection_history.mode = SelectionHistoryMode::Normal;
4844    }
4845
4846    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
4847        self.go_to_diagnostic_impl(Direction::Next, cx)
4848    }
4849
4850    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
4851        self.go_to_diagnostic_impl(Direction::Prev, cx)
4852    }
4853
4854    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
4855        let buffer = self.buffer.read(cx).snapshot(cx);
4856        let selection = self.selections.newest::<usize>(cx);
4857
4858        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
4859        if direction == Direction::Next {
4860            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
4861                let (group_id, jump_to) = popover.activation_info();
4862                if self.activate_diagnostics(group_id, cx) {
4863                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
4864                        let mut new_selection = s.newest_anchor().clone();
4865                        new_selection.collapse_to(jump_to, SelectionGoal::None);
4866                        s.select_anchors(vec![new_selection.clone()]);
4867                    });
4868                }
4869                return;
4870            }
4871        }
4872
4873        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
4874            active_diagnostics
4875                .primary_range
4876                .to_offset(&buffer)
4877                .to_inclusive()
4878        });
4879        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
4880            if active_primary_range.contains(&selection.head()) {
4881                *active_primary_range.end()
4882            } else {
4883                selection.head()
4884            }
4885        } else {
4886            selection.head()
4887        };
4888
4889        loop {
4890            let mut diagnostics = if direction == Direction::Prev {
4891                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
4892            } else {
4893                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
4894            };
4895            let group = diagnostics.find_map(|entry| {
4896                if entry.diagnostic.is_primary
4897                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
4898                    && !entry.range.is_empty()
4899                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
4900                {
4901                    Some((entry.range, entry.diagnostic.group_id))
4902                } else {
4903                    None
4904                }
4905            });
4906
4907            if let Some((primary_range, group_id)) = group {
4908                if self.activate_diagnostics(group_id, cx) {
4909                    self.change_selections(Some(Autoscroll::Center), cx, |s| {
4910                        s.select(vec![Selection {
4911                            id: selection.id,
4912                            start: primary_range.start,
4913                            end: primary_range.start,
4914                            reversed: false,
4915                            goal: SelectionGoal::None,
4916                        }]);
4917                    });
4918                }
4919                break;
4920            } else {
4921                // Cycle around to the start of the buffer, potentially moving back to the start of
4922                // the currently active diagnostic.
4923                active_primary_range.take();
4924                if direction == Direction::Prev {
4925                    if search_start == buffer.len() {
4926                        break;
4927                    } else {
4928                        search_start = buffer.len();
4929                    }
4930                } else if search_start == 0 {
4931                    break;
4932                } else {
4933                    search_start = 0;
4934                }
4935            }
4936        }
4937    }
4938
4939    pub fn go_to_definition(
4940        workspace: &mut Workspace,
4941        _: &GoToDefinition,
4942        cx: &mut ViewContext<Workspace>,
4943    ) {
4944        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
4945    }
4946
4947    pub fn go_to_type_definition(
4948        workspace: &mut Workspace,
4949        _: &GoToTypeDefinition,
4950        cx: &mut ViewContext<Workspace>,
4951    ) {
4952        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
4953    }
4954
4955    fn go_to_definition_of_kind(
4956        kind: GotoDefinitionKind,
4957        workspace: &mut Workspace,
4958        cx: &mut ViewContext<Workspace>,
4959    ) {
4960        let active_item = workspace.active_item(cx);
4961        let editor_handle = if let Some(editor) = active_item
4962            .as_ref()
4963            .and_then(|item| item.act_as::<Self>(cx))
4964        {
4965            editor
4966        } else {
4967            return;
4968        };
4969
4970        let editor = editor_handle.read(cx);
4971        let buffer = editor.buffer.read(cx);
4972        let head = editor.selections.newest::<usize>(cx).head();
4973        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
4974            text_anchor
4975        } else {
4976            return;
4977        };
4978
4979        let project = workspace.project().clone();
4980        let definitions = project.update(cx, |project, cx| match kind {
4981            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
4982            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
4983        });
4984
4985        cx.spawn(|workspace, mut cx| async move {
4986            let definitions = definitions.await?;
4987            workspace.update(&mut cx, |workspace, cx| {
4988                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
4989            });
4990
4991            Ok::<(), anyhow::Error>(())
4992        })
4993        .detach_and_log_err(cx);
4994    }
4995
4996    pub fn navigate_to_definitions(
4997        workspace: &mut Workspace,
4998        editor_handle: ViewHandle<Editor>,
4999        definitions: Vec<LocationLink>,
5000        cx: &mut ViewContext<Workspace>,
5001    ) {
5002        let pane = workspace.active_pane().clone();
5003        for definition in definitions {
5004            let range = definition
5005                .target
5006                .range
5007                .to_offset(definition.target.buffer.read(cx));
5008
5009            let target_editor_handle = workspace.open_project_item(definition.target.buffer, cx);
5010            target_editor_handle.update(cx, |target_editor, cx| {
5011                // When selecting a definition in a different buffer, disable the nav history
5012                // to avoid creating a history entry at the previous cursor location.
5013                if editor_handle != target_editor_handle {
5014                    pane.update(cx, |pane, _| pane.disable_history());
5015                }
5016                target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
5017                    s.select_ranges([range]);
5018                });
5019
5020                pane.update(cx, |pane, _| pane.enable_history());
5021            });
5022        }
5023    }
5024
5025    pub fn find_all_references(
5026        workspace: &mut Workspace,
5027        _: &FindAllReferences,
5028        cx: &mut ViewContext<Workspace>,
5029    ) -> Option<Task<Result<()>>> {
5030        let active_item = workspace.active_item(cx)?;
5031        let editor_handle = active_item.act_as::<Self>(cx)?;
5032
5033        let editor = editor_handle.read(cx);
5034        let buffer = editor.buffer.read(cx);
5035        let head = editor.selections.newest::<usize>(cx).head();
5036        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5037        let replica_id = editor.replica_id(cx);
5038
5039        let project = workspace.project().clone();
5040        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5041        Some(cx.spawn(|workspace, mut cx| async move {
5042            let mut locations = references.await?;
5043            if locations.is_empty() {
5044                return Ok(());
5045            }
5046
5047            locations.sort_by_key(|location| location.buffer.id());
5048            let mut locations = locations.into_iter().peekable();
5049            let mut ranges_to_highlight = Vec::new();
5050
5051            let excerpt_buffer = cx.add_model(|cx| {
5052                let mut symbol_name = None;
5053                let mut multibuffer = MultiBuffer::new(replica_id);
5054                while let Some(location) = locations.next() {
5055                    let buffer = location.buffer.read(cx);
5056                    let mut ranges_for_buffer = Vec::new();
5057                    let range = location.range.to_offset(buffer);
5058                    ranges_for_buffer.push(range.clone());
5059                    if symbol_name.is_none() {
5060                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
5061                    }
5062
5063                    while let Some(next_location) = locations.peek() {
5064                        if next_location.buffer == location.buffer {
5065                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
5066                            locations.next();
5067                        } else {
5068                            break;
5069                        }
5070                    }
5071
5072                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5073                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5074                        location.buffer.clone(),
5075                        ranges_for_buffer,
5076                        1,
5077                        cx,
5078                    ));
5079                }
5080                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
5081            });
5082
5083            workspace.update(&mut cx, |workspace, cx| {
5084                let editor =
5085                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
5086                editor.update(cx, |editor, cx| {
5087                    editor.highlight_background::<Self>(
5088                        ranges_to_highlight,
5089                        |theme| theme.editor.highlighted_line_background,
5090                        cx,
5091                    );
5092                });
5093                workspace.add_item(Box::new(editor), cx);
5094            });
5095
5096            Ok(())
5097        }))
5098    }
5099
5100    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5101        use language::ToOffset as _;
5102
5103        let project = self.project.clone()?;
5104        let selection = self.selections.newest_anchor().clone();
5105        let (cursor_buffer, cursor_buffer_position) = self
5106            .buffer
5107            .read(cx)
5108            .text_anchor_for_position(selection.head(), cx)?;
5109        let (tail_buffer, _) = self
5110            .buffer
5111            .read(cx)
5112            .text_anchor_for_position(selection.tail(), cx)?;
5113        if tail_buffer != cursor_buffer {
5114            return None;
5115        }
5116
5117        let snapshot = cursor_buffer.read(cx).snapshot();
5118        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5119        let prepare_rename = project.update(cx, |project, cx| {
5120            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5121        });
5122
5123        Some(cx.spawn(|this, mut cx| async move {
5124            let rename_range = if let Some(range) = prepare_rename.await? {
5125                Some(range)
5126            } else {
5127                this.read_with(&cx, |this, cx| {
5128                    let buffer = this.buffer.read(cx).snapshot(cx);
5129                    let mut buffer_highlights = this
5130                        .document_highlights_for_position(selection.head(), &buffer)
5131                        .filter(|highlight| {
5132                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5133                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5134                        });
5135                    buffer_highlights
5136                        .next()
5137                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5138                })
5139            };
5140            if let Some(rename_range) = rename_range {
5141                let rename_buffer_range = rename_range.to_offset(&snapshot);
5142                let cursor_offset_in_rename_range =
5143                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5144
5145                this.update(&mut cx, |this, cx| {
5146                    this.take_rename(false, cx);
5147                    let style = this.style(cx);
5148                    let buffer = this.buffer.read(cx).read(cx);
5149                    let cursor_offset = selection.head().to_offset(&buffer);
5150                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5151                    let rename_end = rename_start + rename_buffer_range.len();
5152                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5153                    let mut old_highlight_id = None;
5154                    let old_name: Arc<str> = buffer
5155                        .chunks(rename_start..rename_end, true)
5156                        .map(|chunk| {
5157                            if old_highlight_id.is_none() {
5158                                old_highlight_id = chunk.syntax_highlight_id;
5159                            }
5160                            chunk.text
5161                        })
5162                        .collect::<String>()
5163                        .into();
5164
5165                    drop(buffer);
5166
5167                    // Position the selection in the rename editor so that it matches the current selection.
5168                    this.show_local_selections = false;
5169                    let rename_editor = cx.add_view(|cx| {
5170                        let mut editor = Editor::single_line(None, cx);
5171                        if let Some(old_highlight_id) = old_highlight_id {
5172                            editor.override_text_style =
5173                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5174                        }
5175                        editor.buffer.update(cx, |buffer, cx| {
5176                            buffer.edit([(0..0, old_name.clone())], None, cx)
5177                        });
5178                        editor.select_all(&SelectAll, cx);
5179                        editor
5180                    });
5181
5182                    let ranges = this
5183                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5184                        .into_iter()
5185                        .flat_map(|(_, ranges)| ranges)
5186                        .chain(
5187                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5188                                .into_iter()
5189                                .flat_map(|(_, ranges)| ranges),
5190                        )
5191                        .collect();
5192
5193                    this.highlight_text::<Rename>(
5194                        ranges,
5195                        HighlightStyle {
5196                            fade_out: Some(style.rename_fade),
5197                            ..Default::default()
5198                        },
5199                        cx,
5200                    );
5201                    cx.focus(&rename_editor);
5202                    let block_id = this.insert_blocks(
5203                        [BlockProperties {
5204                            style: BlockStyle::Flex,
5205                            position: range.start.clone(),
5206                            height: 1,
5207                            render: Arc::new({
5208                                let editor = rename_editor.clone();
5209                                move |cx: &mut BlockContext| {
5210                                    ChildView::new(editor.clone(), cx)
5211                                        .contained()
5212                                        .with_padding_left(cx.anchor_x)
5213                                        .boxed()
5214                                }
5215                            }),
5216                            disposition: BlockDisposition::Below,
5217                        }],
5218                        cx,
5219                    )[0];
5220                    this.pending_rename = Some(RenameState {
5221                        range,
5222                        old_name,
5223                        editor: rename_editor,
5224                        block_id,
5225                    });
5226                });
5227            }
5228
5229            Ok(())
5230        }))
5231    }
5232
5233    pub fn confirm_rename(
5234        workspace: &mut Workspace,
5235        _: &ConfirmRename,
5236        cx: &mut ViewContext<Workspace>,
5237    ) -> Option<Task<Result<()>>> {
5238        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5239
5240        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5241            let rename = editor.take_rename(false, cx)?;
5242            let buffer = editor.buffer.read(cx);
5243            let (start_buffer, start) =
5244                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5245            let (end_buffer, end) =
5246                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5247            if start_buffer == end_buffer {
5248                let new_name = rename.editor.read(cx).text(cx);
5249                Some((start_buffer, start..end, rename.old_name, new_name))
5250            } else {
5251                None
5252            }
5253        })?;
5254
5255        let rename = workspace.project().clone().update(cx, |project, cx| {
5256            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5257        });
5258
5259        Some(cx.spawn(|workspace, mut cx| async move {
5260            let project_transaction = rename.await?;
5261            Self::open_project_transaction(
5262                editor.clone(),
5263                workspace,
5264                project_transaction,
5265                format!("Rename: {}{}", old_name, new_name),
5266                cx.clone(),
5267            )
5268            .await?;
5269
5270            editor.update(&mut cx, |editor, cx| {
5271                editor.refresh_document_highlights(cx);
5272            });
5273            Ok(())
5274        }))
5275    }
5276
5277    fn take_rename(
5278        &mut self,
5279        moving_cursor: bool,
5280        cx: &mut ViewContext<Self>,
5281    ) -> Option<RenameState> {
5282        let rename = self.pending_rename.take()?;
5283        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5284        self.clear_text_highlights::<Rename>(cx);
5285        self.show_local_selections = true;
5286
5287        if moving_cursor {
5288            let rename_editor = rename.editor.read(cx);
5289            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5290
5291            // Update the selection to match the position of the selection inside
5292            // the rename editor.
5293            let snapshot = self.buffer.read(cx).read(cx);
5294            let rename_range = rename.range.to_offset(&snapshot);
5295            let cursor_in_editor = snapshot
5296                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5297                .min(rename_range.end);
5298            drop(snapshot);
5299
5300            self.change_selections(None, cx, |s| {
5301                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5302            });
5303        } else {
5304            self.refresh_document_highlights(cx);
5305        }
5306
5307        Some(rename)
5308    }
5309
5310    #[cfg(any(test, feature = "test-support"))]
5311    pub fn pending_rename(&self) -> Option<&RenameState> {
5312        self.pending_rename.as_ref()
5313    }
5314
5315    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5316        let project = match &self.project {
5317            Some(project) => project.clone(),
5318            None => return None,
5319        };
5320
5321        Some(self.perform_format(project, cx))
5322    }
5323
5324    fn perform_format(
5325        &mut self,
5326        project: ModelHandle<Project>,
5327        cx: &mut ViewContext<'_, Self>,
5328    ) -> Task<Result<()>> {
5329        let buffer = self.buffer().clone();
5330        let buffers = buffer.read(cx).all_buffers();
5331
5332        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5333        let format = project.update(cx, |project, cx| {
5334            project.format(buffers, true, FormatTrigger::Manual, cx)
5335        });
5336
5337        cx.spawn(|_, mut cx| async move {
5338            let transaction = futures::select_biased! {
5339                _ = timeout => {
5340                    log::warn!("timed out waiting for formatting");
5341                    None
5342                }
5343                transaction = format.log_err().fuse() => transaction,
5344            };
5345
5346            buffer.update(&mut cx, |buffer, cx| {
5347                if let Some(transaction) = transaction {
5348                    if !buffer.is_singleton() {
5349                        buffer.push_transaction(&transaction.0);
5350                    }
5351                }
5352
5353                cx.notify();
5354            });
5355
5356            Ok(())
5357        })
5358    }
5359
5360    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5361        if let Some(project) = self.project.clone() {
5362            self.buffer.update(cx, |multi_buffer, cx| {
5363                project.update(cx, |project, cx| {
5364                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5365                });
5366            })
5367        }
5368    }
5369
5370    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5371        cx.show_character_palette();
5372    }
5373
5374    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5375        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5376            let buffer = self.buffer.read(cx).snapshot(cx);
5377            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5378            let is_valid = buffer
5379                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5380                .any(|entry| {
5381                    entry.diagnostic.is_primary
5382                        && !entry.range.is_empty()
5383                        && entry.range.start == primary_range_start
5384                        && entry.diagnostic.message == active_diagnostics.primary_message
5385                });
5386
5387            if is_valid != active_diagnostics.is_valid {
5388                active_diagnostics.is_valid = is_valid;
5389                let mut new_styles = HashMap::default();
5390                for (block_id, diagnostic) in &active_diagnostics.blocks {
5391                    new_styles.insert(
5392                        *block_id,
5393                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5394                    );
5395                }
5396                self.display_map
5397                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5398            }
5399        }
5400    }
5401
5402    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5403        self.dismiss_diagnostics(cx);
5404        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5405            let buffer = self.buffer.read(cx).snapshot(cx);
5406
5407            let mut primary_range = None;
5408            let mut primary_message = None;
5409            let mut group_end = Point::zero();
5410            let diagnostic_group = buffer
5411                .diagnostic_group::<Point>(group_id)
5412                .map(|entry| {
5413                    if entry.range.end > group_end {
5414                        group_end = entry.range.end;
5415                    }
5416                    if entry.diagnostic.is_primary {
5417                        primary_range = Some(entry.range.clone());
5418                        primary_message = Some(entry.diagnostic.message.clone());
5419                    }
5420                    entry
5421                })
5422                .collect::<Vec<_>>();
5423            let primary_range = primary_range?;
5424            let primary_message = primary_message?;
5425            let primary_range =
5426                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5427
5428            let blocks = display_map
5429                .insert_blocks(
5430                    diagnostic_group.iter().map(|entry| {
5431                        let diagnostic = entry.diagnostic.clone();
5432                        let message_height = diagnostic.message.lines().count() as u8;
5433                        BlockProperties {
5434                            style: BlockStyle::Fixed,
5435                            position: buffer.anchor_after(entry.range.start),
5436                            height: message_height,
5437                            render: diagnostic_block_renderer(diagnostic, true),
5438                            disposition: BlockDisposition::Below,
5439                        }
5440                    }),
5441                    cx,
5442                )
5443                .into_iter()
5444                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5445                .collect();
5446
5447            Some(ActiveDiagnosticGroup {
5448                primary_range,
5449                primary_message,
5450                blocks,
5451                is_valid: true,
5452            })
5453        });
5454        self.active_diagnostics.is_some()
5455    }
5456
5457    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5458        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5459            self.display_map.update(cx, |display_map, cx| {
5460                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5461            });
5462            cx.notify();
5463        }
5464    }
5465
5466    pub fn set_selections_from_remote(
5467        &mut self,
5468        selections: Vec<Selection<Anchor>>,
5469        cx: &mut ViewContext<Self>,
5470    ) {
5471        let old_cursor_position = self.selections.newest_anchor().head();
5472        self.selections.change_with(cx, |s| {
5473            s.select_anchors(selections);
5474        });
5475        self.selections_did_change(false, &old_cursor_position, cx);
5476    }
5477
5478    fn push_to_selection_history(&mut self) {
5479        self.selection_history.push(SelectionHistoryEntry {
5480            selections: self.selections.disjoint_anchors(),
5481            select_next_state: self.select_next_state.clone(),
5482            add_selections_state: self.add_selections_state.clone(),
5483        });
5484    }
5485
5486    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5487        self.autoscroll_request = Some((autoscroll, true));
5488        cx.notify();
5489    }
5490
5491    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
5492        self.autoscroll_request = Some((autoscroll, false));
5493        cx.notify();
5494    }
5495
5496    pub fn transact(
5497        &mut self,
5498        cx: &mut ViewContext<Self>,
5499        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5500    ) -> Option<TransactionId> {
5501        self.start_transaction_at(Instant::now(), cx);
5502        update(self, cx);
5503        self.end_transaction_at(Instant::now(), cx)
5504    }
5505
5506    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5507        self.end_selection(cx);
5508        if let Some(tx_id) = self
5509            .buffer
5510            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5511        {
5512            self.selection_history
5513                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5514        }
5515    }
5516
5517    fn end_transaction_at(
5518        &mut self,
5519        now: Instant,
5520        cx: &mut ViewContext<Self>,
5521    ) -> Option<TransactionId> {
5522        if let Some(tx_id) = self
5523            .buffer
5524            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5525        {
5526            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5527                *end_selections = Some(self.selections.disjoint_anchors());
5528            } else {
5529                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5530            }
5531
5532            cx.emit(Event::Edited);
5533            Some(tx_id)
5534        } else {
5535            None
5536        }
5537    }
5538
5539    pub fn page_up(&mut self, _: &PageUp, cx: &mut ViewContext<Self>) {
5540        let lines = match self.visible_line_count {
5541            Some(lines) => lines,
5542            None => return,
5543        };
5544
5545        let cur_position = self.scroll_position(cx);
5546        let new_pos = cur_position - vec2f(0., lines + 1.);
5547        self.set_scroll_position(new_pos, cx);
5548    }
5549
5550    pub fn page_down(&mut self, _: &PageDown, cx: &mut ViewContext<Self>) {
5551        let lines = match self.visible_line_count {
5552            Some(lines) => lines,
5553            None => return,
5554        };
5555
5556        let cur_position = self.scroll_position(cx);
5557        let new_pos = cur_position + vec2f(0., lines - 1.);
5558        self.set_scroll_position(new_pos, cx);
5559    }
5560
5561    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
5562        let mut fold_ranges = Vec::new();
5563
5564        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5565        let selections = self.selections.all::<Point>(cx);
5566        for selection in selections {
5567            let range = selection.display_range(&display_map).sorted();
5568            let buffer_start_row = range.start.to_point(&display_map).row;
5569
5570            for row in (0..=range.end.row()).rev() {
5571                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
5572                    let fold_range = self.foldable_range_for_line(&display_map, row);
5573                    if fold_range.end.row >= buffer_start_row {
5574                        fold_ranges.push(fold_range);
5575                        if row <= range.start.row() {
5576                            break;
5577                        }
5578                    }
5579                }
5580            }
5581        }
5582
5583        self.fold_ranges(fold_ranges, cx);
5584    }
5585
5586    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
5587        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5588        let buffer = &display_map.buffer_snapshot;
5589        let selections = self.selections.all::<Point>(cx);
5590        let ranges = selections
5591            .iter()
5592            .map(|s| {
5593                let range = s.display_range(&display_map).sorted();
5594                let mut start = range.start.to_point(&display_map);
5595                let mut end = range.end.to_point(&display_map);
5596                start.column = 0;
5597                end.column = buffer.line_len(end.row);
5598                start..end
5599            })
5600            .collect::<Vec<_>>();
5601        self.unfold_ranges(ranges, true, cx);
5602    }
5603
5604    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
5605        let max_point = display_map.max_point();
5606        if display_row >= max_point.row() {
5607            false
5608        } else {
5609            let (start_indent, is_blank) = display_map.line_indent(display_row);
5610            if is_blank {
5611                false
5612            } else {
5613                for display_row in display_row + 1..=max_point.row() {
5614                    let (indent, is_blank) = display_map.line_indent(display_row);
5615                    if !is_blank {
5616                        return indent > start_indent;
5617                    }
5618                }
5619                false
5620            }
5621        }
5622    }
5623
5624    fn foldable_range_for_line(
5625        &self,
5626        display_map: &DisplaySnapshot,
5627        start_row: u32,
5628    ) -> Range<Point> {
5629        let max_point = display_map.max_point();
5630
5631        let (start_indent, _) = display_map.line_indent(start_row);
5632        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
5633        let mut end = None;
5634        for row in start_row + 1..=max_point.row() {
5635            let (indent, is_blank) = display_map.line_indent(row);
5636            if !is_blank && indent <= start_indent {
5637                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
5638                break;
5639            }
5640        }
5641
5642        let end = end.unwrap_or(max_point);
5643        start.to_point(display_map)..end.to_point(display_map)
5644    }
5645
5646    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
5647        let selections = self.selections.all::<Point>(cx);
5648        let ranges = selections.into_iter().map(|s| s.start..s.end);
5649        self.fold_ranges(ranges, cx);
5650    }
5651
5652    pub fn fold_ranges<T: ToOffset>(
5653        &mut self,
5654        ranges: impl IntoIterator<Item = Range<T>>,
5655        cx: &mut ViewContext<Self>,
5656    ) {
5657        let mut ranges = ranges.into_iter().peekable();
5658        if ranges.peek().is_some() {
5659            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
5660            self.request_autoscroll(Autoscroll::Fit, cx);
5661            cx.notify();
5662        }
5663    }
5664
5665    pub fn unfold_ranges<T: ToOffset>(
5666        &mut self,
5667        ranges: impl IntoIterator<Item = Range<T>>,
5668        inclusive: bool,
5669        cx: &mut ViewContext<Self>,
5670    ) {
5671        let mut ranges = ranges.into_iter().peekable();
5672        if ranges.peek().is_some() {
5673            self.display_map
5674                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
5675            self.request_autoscroll(Autoscroll::Fit, cx);
5676            cx.notify();
5677        }
5678    }
5679
5680    pub fn insert_blocks(
5681        &mut self,
5682        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
5683        cx: &mut ViewContext<Self>,
5684    ) -> Vec<BlockId> {
5685        let blocks = self
5686            .display_map
5687            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
5688        self.request_autoscroll(Autoscroll::Fit, cx);
5689        blocks
5690    }
5691
5692    pub fn replace_blocks(
5693        &mut self,
5694        blocks: HashMap<BlockId, RenderBlock>,
5695        cx: &mut ViewContext<Self>,
5696    ) {
5697        self.display_map
5698            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
5699        self.request_autoscroll(Autoscroll::Fit, cx);
5700    }
5701
5702    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
5703        self.display_map.update(cx, |display_map, cx| {
5704            display_map.remove_blocks(block_ids, cx)
5705        });
5706    }
5707
5708    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
5709        self.display_map
5710            .update(cx, |map, cx| map.snapshot(cx))
5711            .longest_row()
5712    }
5713
5714    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
5715        self.display_map
5716            .update(cx, |map, cx| map.snapshot(cx))
5717            .max_point()
5718    }
5719
5720    pub fn text(&self, cx: &AppContext) -> String {
5721        self.buffer.read(cx).read(cx).text()
5722    }
5723
5724    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
5725        self.transact(cx, |this, cx| {
5726            this.buffer
5727                .read(cx)
5728                .as_singleton()
5729                .expect("you can only call set_text on editors for singleton buffers")
5730                .update(cx, |buffer, cx| buffer.set_text(text, cx));
5731        });
5732    }
5733
5734    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
5735        self.display_map
5736            .update(cx, |map, cx| map.snapshot(cx))
5737            .text()
5738    }
5739
5740    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
5741        let language_name = self
5742            .buffer
5743            .read(cx)
5744            .as_singleton()
5745            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
5746            .map(|l| l.name());
5747
5748        let settings = cx.global::<Settings>();
5749        let mode = self
5750            .soft_wrap_mode_override
5751            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
5752        match mode {
5753            settings::SoftWrap::None => SoftWrap::None,
5754            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
5755            settings::SoftWrap::PreferredLineLength => {
5756                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
5757            }
5758        }
5759    }
5760
5761    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
5762        self.soft_wrap_mode_override = Some(mode);
5763        cx.notify();
5764    }
5765
5766    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
5767        self.display_map
5768            .update(cx, |map, cx| map.set_wrap_width(width, cx))
5769    }
5770
5771    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
5772        self.highlighted_rows = rows;
5773    }
5774
5775    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
5776        self.highlighted_rows.clone()
5777    }
5778
5779    pub fn highlight_background<T: 'static>(
5780        &mut self,
5781        ranges: Vec<Range<Anchor>>,
5782        color_fetcher: fn(&Theme) -> Color,
5783        cx: &mut ViewContext<Self>,
5784    ) {
5785        self.background_highlights
5786            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
5787        cx.notify();
5788    }
5789
5790    #[allow(clippy::type_complexity)]
5791    pub fn clear_background_highlights<T: 'static>(
5792        &mut self,
5793        cx: &mut ViewContext<Self>,
5794    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
5795        cx.notify();
5796        self.background_highlights.remove(&TypeId::of::<T>())
5797    }
5798
5799    #[cfg(feature = "test-support")]
5800    pub fn all_background_highlights(
5801        &mut self,
5802        cx: &mut ViewContext<Self>,
5803    ) -> Vec<(Range<DisplayPoint>, Color)> {
5804        let snapshot = self.snapshot(cx);
5805        let buffer = &snapshot.buffer_snapshot;
5806        let start = buffer.anchor_before(0);
5807        let end = buffer.anchor_after(buffer.len());
5808        let theme = cx.global::<Settings>().theme.as_ref();
5809        self.background_highlights_in_range(start..end, &snapshot, theme)
5810    }
5811
5812    fn document_highlights_for_position<'a>(
5813        &'a self,
5814        position: Anchor,
5815        buffer: &'a MultiBufferSnapshot,
5816    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
5817        let read_highlights = self
5818            .background_highlights
5819            .get(&TypeId::of::<DocumentHighlightRead>())
5820            .map(|h| &h.1);
5821        let write_highlights = self
5822            .background_highlights
5823            .get(&TypeId::of::<DocumentHighlightWrite>())
5824            .map(|h| &h.1);
5825        let left_position = position.bias_left(buffer);
5826        let right_position = position.bias_right(buffer);
5827        read_highlights
5828            .into_iter()
5829            .chain(write_highlights)
5830            .flat_map(move |ranges| {
5831                let start_ix = match ranges.binary_search_by(|probe| {
5832                    let cmp = probe.end.cmp(&left_position, buffer);
5833                    if cmp.is_ge() {
5834                        Ordering::Greater
5835                    } else {
5836                        Ordering::Less
5837                    }
5838                }) {
5839                    Ok(i) | Err(i) => i,
5840                };
5841
5842                let right_position = right_position.clone();
5843                ranges[start_ix..]
5844                    .iter()
5845                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
5846            })
5847    }
5848
5849    pub fn background_highlights_in_range(
5850        &self,
5851        search_range: Range<Anchor>,
5852        display_snapshot: &DisplaySnapshot,
5853        theme: &Theme,
5854    ) -> Vec<(Range<DisplayPoint>, Color)> {
5855        let mut results = Vec::new();
5856        let buffer = &display_snapshot.buffer_snapshot;
5857        for (color_fetcher, ranges) in self.background_highlights.values() {
5858            let color = color_fetcher(theme);
5859            let start_ix = match ranges.binary_search_by(|probe| {
5860                let cmp = probe.end.cmp(&search_range.start, buffer);
5861                if cmp.is_gt() {
5862                    Ordering::Greater
5863                } else {
5864                    Ordering::Less
5865                }
5866            }) {
5867                Ok(i) | Err(i) => i,
5868            };
5869            for range in &ranges[start_ix..] {
5870                if range.start.cmp(&search_range.end, buffer).is_ge() {
5871                    break;
5872                }
5873                let start = range
5874                    .start
5875                    .to_point(buffer)
5876                    .to_display_point(display_snapshot);
5877                let end = range
5878                    .end
5879                    .to_point(buffer)
5880                    .to_display_point(display_snapshot);
5881                results.push((start..end, color))
5882            }
5883        }
5884        results
5885    }
5886
5887    pub fn highlight_text<T: 'static>(
5888        &mut self,
5889        ranges: Vec<Range<Anchor>>,
5890        style: HighlightStyle,
5891        cx: &mut ViewContext<Self>,
5892    ) {
5893        self.display_map.update(cx, |map, _| {
5894            map.highlight_text(TypeId::of::<T>(), ranges, style)
5895        });
5896        cx.notify();
5897    }
5898
5899    pub fn text_highlights<'a, T: 'static>(
5900        &'a self,
5901        cx: &'a AppContext,
5902    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
5903        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
5904    }
5905
5906    pub fn clear_text_highlights<T: 'static>(
5907        &mut self,
5908        cx: &mut ViewContext<Self>,
5909    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
5910        cx.notify();
5911        self.display_map
5912            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
5913    }
5914
5915    fn next_blink_epoch(&mut self) -> usize {
5916        self.blink_epoch += 1;
5917        self.blink_epoch
5918    }
5919
5920    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
5921        if !self.focused {
5922            return;
5923        }
5924
5925        self.show_local_cursors = true;
5926        cx.notify();
5927
5928        let epoch = self.next_blink_epoch();
5929        cx.spawn(|this, mut cx| {
5930            let this = this.downgrade();
5931            async move {
5932                Timer::after(CURSOR_BLINK_INTERVAL).await;
5933                if let Some(this) = this.upgrade(&cx) {
5934                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
5935                }
5936            }
5937        })
5938        .detach();
5939    }
5940
5941    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5942        if epoch == self.blink_epoch {
5943            self.blinking_paused = false;
5944            self.blink_cursors(epoch, cx);
5945        }
5946    }
5947
5948    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
5949        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
5950            self.show_local_cursors = !self.show_local_cursors;
5951            cx.notify();
5952
5953            let epoch = self.next_blink_epoch();
5954            cx.spawn(|this, mut cx| {
5955                let this = this.downgrade();
5956                async move {
5957                    Timer::after(CURSOR_BLINK_INTERVAL).await;
5958                    if let Some(this) = this.upgrade(&cx) {
5959                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
5960                    }
5961                }
5962            })
5963            .detach();
5964        }
5965    }
5966
5967    pub fn show_local_cursors(&self) -> bool {
5968        self.show_local_cursors && self.focused
5969    }
5970
5971    pub fn show_scrollbars(&self) -> bool {
5972        self.show_scrollbars
5973    }
5974
5975    fn make_scrollbar_visible(&mut self, cx: &mut ViewContext<Self>) {
5976        if !self.show_scrollbars {
5977            self.show_scrollbars = true;
5978            cx.notify();
5979        }
5980
5981        if cx.default_global::<ScrollbarAutoHide>().0 {
5982            self.hide_scrollbar_task = Some(cx.spawn_weak(|this, mut cx| async move {
5983                Timer::after(SCROLLBAR_SHOW_INTERVAL).await;
5984                if let Some(this) = this.upgrade(&cx) {
5985                    this.update(&mut cx, |this, cx| {
5986                        this.show_scrollbars = false;
5987                        cx.notify();
5988                    });
5989                }
5990            }));
5991        } else {
5992            self.hide_scrollbar_task = None;
5993        }
5994    }
5995
5996    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
5997        cx.notify();
5998    }
5999
6000    fn on_buffer_event(
6001        &mut self,
6002        _: ModelHandle<MultiBuffer>,
6003        event: &language::Event,
6004        cx: &mut ViewContext<Self>,
6005    ) {
6006        match event {
6007            language::Event::Edited => {
6008                self.refresh_active_diagnostics(cx);
6009                self.refresh_code_actions(cx);
6010                cx.emit(Event::BufferEdited);
6011            }
6012            language::Event::Reparsed => cx.emit(Event::Reparsed),
6013            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6014            language::Event::Saved => cx.emit(Event::Saved),
6015            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6016            language::Event::Reloaded => cx.emit(Event::TitleChanged),
6017            language::Event::Closed => cx.emit(Event::Closed),
6018            language::Event::DiagnosticsUpdated => {
6019                self.refresh_active_diagnostics(cx);
6020            }
6021            _ => {}
6022        }
6023    }
6024
6025    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6026        cx.notify();
6027    }
6028
6029    pub fn set_searchable(&mut self, searchable: bool) {
6030        self.searchable = searchable;
6031    }
6032
6033    pub fn searchable(&self) -> bool {
6034        self.searchable
6035    }
6036
6037    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6038        let active_item = workspace.active_item(cx);
6039        let editor_handle = if let Some(editor) = active_item
6040            .as_ref()
6041            .and_then(|item| item.act_as::<Self>(cx))
6042        {
6043            editor
6044        } else {
6045            cx.propagate_action();
6046            return;
6047        };
6048
6049        let editor = editor_handle.read(cx);
6050        let buffer = editor.buffer.read(cx);
6051        if buffer.is_singleton() {
6052            cx.propagate_action();
6053            return;
6054        }
6055
6056        let mut new_selections_by_buffer = HashMap::default();
6057        for selection in editor.selections.all::<usize>(cx) {
6058            for (buffer, mut range) in
6059                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6060            {
6061                if selection.reversed {
6062                    mem::swap(&mut range.start, &mut range.end);
6063                }
6064                new_selections_by_buffer
6065                    .entry(buffer)
6066                    .or_insert(Vec::new())
6067                    .push(range)
6068            }
6069        }
6070
6071        editor_handle.update(cx, |editor, cx| {
6072            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6073        });
6074        let pane = workspace.active_pane().clone();
6075        pane.update(cx, |pane, _| pane.disable_history());
6076
6077        // We defer the pane interaction because we ourselves are a workspace item
6078        // and activating a new item causes the pane to call a method on us reentrantly,
6079        // which panics if we're on the stack.
6080        cx.defer(move |workspace, cx| {
6081            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6082                let editor = workspace.open_project_item::<Self>(buffer, cx);
6083                editor.update(cx, |editor, cx| {
6084                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6085                        s.select_ranges(ranges);
6086                    });
6087                });
6088            }
6089
6090            pane.update(cx, |pane, _| pane.enable_history());
6091        });
6092    }
6093
6094    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6095        let editor = workspace.open_path(action.path.clone(), true, cx);
6096        let position = action.position;
6097        let anchor = action.anchor;
6098        cx.spawn_weak(|_, mut cx| async move {
6099            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6100            editor.update(&mut cx, |editor, cx| {
6101                let buffer = editor.buffer().read(cx).as_singleton()?;
6102                let buffer = buffer.read(cx);
6103                let cursor = if buffer.can_resolve(&anchor) {
6104                    language::ToPoint::to_point(&anchor, buffer)
6105                } else {
6106                    buffer.clip_point(position, Bias::Left)
6107                };
6108
6109                let nav_history = editor.nav_history.take();
6110                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
6111                    s.select_ranges([cursor..cursor]);
6112                });
6113                editor.nav_history = nav_history;
6114
6115                Some(())
6116            })?;
6117            Some(())
6118        })
6119        .detach()
6120    }
6121
6122    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6123        let snapshot = self.buffer.read(cx).read(cx);
6124        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6125        Some(
6126            ranges
6127                .iter()
6128                .map(move |range| {
6129                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6130                })
6131                .collect(),
6132        )
6133    }
6134
6135    fn selection_replacement_ranges(
6136        &self,
6137        range: Range<OffsetUtf16>,
6138        cx: &AppContext,
6139    ) -> Vec<Range<OffsetUtf16>> {
6140        let selections = self.selections.all::<OffsetUtf16>(cx);
6141        let newest_selection = selections
6142            .iter()
6143            .max_by_key(|selection| selection.id)
6144            .unwrap();
6145        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6146        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6147        let snapshot = self.buffer.read(cx).read(cx);
6148        selections
6149            .into_iter()
6150            .map(|mut selection| {
6151                selection.start.0 =
6152                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6153                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6154                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6155                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6156            })
6157            .collect()
6158    }
6159
6160    fn report_event(&self, name: &str, cx: &AppContext) {
6161        if let Some((project, file)) = self.project.as_ref().zip(
6162            self.buffer
6163                .read(cx)
6164                .as_singleton()
6165                .and_then(|b| b.read(cx).file()),
6166        ) {
6167            project.read(cx).client().report_event(
6168                name,
6169                json!({
6170                    "file_extension": file
6171                        .path()
6172                        .extension()
6173                        .and_then(|e| e.to_str())
6174                }),
6175            );
6176        }
6177    }
6178}
6179
6180impl EditorSnapshot {
6181    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6182        self.display_snapshot.buffer_snapshot.language_at(position)
6183    }
6184
6185    pub fn is_focused(&self) -> bool {
6186        self.is_focused
6187    }
6188
6189    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6190        self.placeholder_text.as_ref()
6191    }
6192
6193    pub fn scroll_position(&self) -> Vector2F {
6194        compute_scroll_position(
6195            &self.display_snapshot,
6196            self.scroll_position,
6197            &self.scroll_top_anchor,
6198        )
6199    }
6200}
6201
6202impl Deref for EditorSnapshot {
6203    type Target = DisplaySnapshot;
6204
6205    fn deref(&self) -> &Self::Target {
6206        &self.display_snapshot
6207    }
6208}
6209
6210fn compute_scroll_position(
6211    snapshot: &DisplaySnapshot,
6212    mut scroll_position: Vector2F,
6213    scroll_top_anchor: &Anchor,
6214) -> Vector2F {
6215    if *scroll_top_anchor != Anchor::min() {
6216        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
6217        scroll_position.set_y(scroll_top + scroll_position.y());
6218    } else {
6219        scroll_position.set_y(0.);
6220    }
6221    scroll_position
6222}
6223
6224#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6225pub enum Event {
6226    BufferEdited,
6227    Edited,
6228    Reparsed,
6229    Blurred,
6230    DirtyChanged,
6231    Saved,
6232    TitleChanged,
6233    SelectionsChanged { local: bool },
6234    ScrollPositionChanged { local: bool },
6235    Closed,
6236    IgnoredInput,
6237}
6238
6239pub struct EditorFocused(pub ViewHandle<Editor>);
6240pub struct EditorBlurred(pub ViewHandle<Editor>);
6241pub struct EditorReleased(pub WeakViewHandle<Editor>);
6242
6243impl Entity for Editor {
6244    type Event = Event;
6245
6246    fn release(&mut self, cx: &mut MutableAppContext) {
6247        cx.emit_global(EditorReleased(self.handle.clone()));
6248    }
6249}
6250
6251impl View for Editor {
6252    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6253        let style = self.style(cx);
6254        let font_changed = self.display_map.update(cx, |map, cx| {
6255            map.set_font(style.text.font_id, style.text.font_size, cx)
6256        });
6257
6258        if font_changed {
6259            let handle = self.handle.clone();
6260            cx.defer(move |cx| {
6261                if let Some(editor) = handle.upgrade(cx) {
6262                    editor.update(cx, |editor, cx| {
6263                        hide_hover(editor, cx);
6264                        hide_link_definition(editor, cx);
6265                    })
6266                }
6267            });
6268        }
6269
6270        Stack::new()
6271            .with_child(
6272                EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed(),
6273            )
6274            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6275            .boxed()
6276    }
6277
6278    fn ui_name() -> &'static str {
6279        "Editor"
6280    }
6281
6282    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6283        let focused_event = EditorFocused(cx.handle());
6284        cx.emit_global(focused_event);
6285        if let Some(rename) = self.pending_rename.as_ref() {
6286            cx.focus(&rename.editor);
6287        } else {
6288            self.focused = true;
6289            self.blink_cursors(self.blink_epoch, cx);
6290            self.buffer.update(cx, |buffer, cx| {
6291                buffer.finalize_last_transaction(cx);
6292                if self.leader_replica_id.is_none() {
6293                    buffer.set_active_selections(
6294                        &self.selections.disjoint_anchors(),
6295                        self.selections.line_mode,
6296                        cx,
6297                    );
6298                }
6299            });
6300        }
6301    }
6302
6303    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6304        let blurred_event = EditorBlurred(cx.handle());
6305        cx.emit_global(blurred_event);
6306        self.focused = false;
6307        self.buffer
6308            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6309        self.hide_context_menu(cx);
6310        hide_hover(self, cx);
6311        cx.emit(Event::Blurred);
6312        cx.notify();
6313    }
6314
6315    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
6316        let mut context = Self::default_keymap_context();
6317        let mode = match self.mode {
6318            EditorMode::SingleLine => "single_line",
6319            EditorMode::AutoHeight { .. } => "auto_height",
6320            EditorMode::Full => "full",
6321        };
6322        context.map.insert("mode".into(), mode.into());
6323        if self.pending_rename.is_some() {
6324            context.set.insert("renaming".into());
6325        }
6326        match self.context_menu.as_ref() {
6327            Some(ContextMenu::Completions(_)) => {
6328                context.set.insert("showing_completions".into());
6329            }
6330            Some(ContextMenu::CodeActions(_)) => {
6331                context.set.insert("showing_code_actions".into());
6332            }
6333            None => {}
6334        }
6335
6336        for layer in self.keymap_context_layers.values() {
6337            context.extend(layer);
6338        }
6339
6340        context
6341    }
6342
6343    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6344        Some(
6345            self.buffer
6346                .read(cx)
6347                .read(cx)
6348                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6349                .collect(),
6350        )
6351    }
6352
6353    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6354        // Prevent the IME menu from appearing when holding down an alphabetic key
6355        // while input is disabled.
6356        if !self.input_enabled {
6357            return None;
6358        }
6359
6360        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6361        Some(range.start.0..range.end.0)
6362    }
6363
6364    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6365        let snapshot = self.buffer.read(cx).read(cx);
6366        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6367        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6368    }
6369
6370    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6371        self.clear_text_highlights::<InputComposition>(cx);
6372        self.ime_transaction.take();
6373    }
6374
6375    fn replace_text_in_range(
6376        &mut self,
6377        range_utf16: Option<Range<usize>>,
6378        text: &str,
6379        cx: &mut ViewContext<Self>,
6380    ) {
6381        if !self.input_enabled {
6382            cx.emit(Event::IgnoredInput);
6383            return;
6384        }
6385
6386        self.transact(cx, |this, cx| {
6387            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6388                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6389                Some(this.selection_replacement_ranges(range_utf16, cx))
6390            } else {
6391                this.marked_text_ranges(cx)
6392            };
6393
6394            if let Some(new_selected_ranges) = new_selected_ranges {
6395                this.change_selections(None, cx, |selections| {
6396                    selections.select_ranges(new_selected_ranges)
6397                });
6398            }
6399            this.handle_input(text, cx);
6400        });
6401
6402        if let Some(transaction) = self.ime_transaction {
6403            self.buffer.update(cx, |buffer, cx| {
6404                buffer.group_until_transaction(transaction, cx);
6405            });
6406        }
6407
6408        self.unmark_text(cx);
6409    }
6410
6411    fn replace_and_mark_text_in_range(
6412        &mut self,
6413        range_utf16: Option<Range<usize>>,
6414        text: &str,
6415        new_selected_range_utf16: Option<Range<usize>>,
6416        cx: &mut ViewContext<Self>,
6417    ) {
6418        if !self.input_enabled {
6419            cx.emit(Event::IgnoredInput);
6420            return;
6421        }
6422
6423        let transaction = self.transact(cx, |this, cx| {
6424            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6425                let snapshot = this.buffer.read(cx).read(cx);
6426                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6427                    for marked_range in &mut marked_ranges {
6428                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6429                        marked_range.start.0 += relative_range_utf16.start;
6430                        marked_range.start =
6431                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6432                        marked_range.end =
6433                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6434                    }
6435                }
6436                Some(marked_ranges)
6437            } else if let Some(range_utf16) = range_utf16 {
6438                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6439                Some(this.selection_replacement_ranges(range_utf16, cx))
6440            } else {
6441                None
6442            };
6443
6444            if let Some(ranges) = ranges_to_replace {
6445                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6446            }
6447
6448            let marked_ranges = {
6449                let snapshot = this.buffer.read(cx).read(cx);
6450                this.selections
6451                    .disjoint_anchors()
6452                    .iter()
6453                    .map(|selection| {
6454                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
6455                    })
6456                    .collect::<Vec<_>>()
6457            };
6458
6459            if text.is_empty() {
6460                this.unmark_text(cx);
6461            } else {
6462                this.highlight_text::<InputComposition>(
6463                    marked_ranges.clone(),
6464                    this.style(cx).composition_mark,
6465                    cx,
6466                );
6467            }
6468
6469            this.handle_input(text, cx);
6470
6471            if let Some(new_selected_range) = new_selected_range_utf16 {
6472                let snapshot = this.buffer.read(cx).read(cx);
6473                let new_selected_ranges = marked_ranges
6474                    .into_iter()
6475                    .map(|marked_range| {
6476                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
6477                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
6478                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
6479                        snapshot.clip_offset_utf16(new_start, Bias::Left)
6480                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
6481                    })
6482                    .collect::<Vec<_>>();
6483
6484                drop(snapshot);
6485                this.change_selections(None, cx, |selections| {
6486                    selections.select_ranges(new_selected_ranges)
6487                });
6488            }
6489        });
6490
6491        self.ime_transaction = self.ime_transaction.or(transaction);
6492        if let Some(transaction) = self.ime_transaction {
6493            self.buffer.update(cx, |buffer, cx| {
6494                buffer.group_until_transaction(transaction, cx);
6495            });
6496        }
6497
6498        if self.text_highlights::<InputComposition>(cx).is_none() {
6499            self.ime_transaction.take();
6500        }
6501    }
6502}
6503
6504fn build_style(
6505    settings: &Settings,
6506    get_field_editor_theme: Option<GetFieldEditorTheme>,
6507    override_text_style: Option<&OverrideTextStyle>,
6508    cx: &AppContext,
6509) -> EditorStyle {
6510    let font_cache = cx.font_cache();
6511
6512    let mut theme = settings.theme.editor.clone();
6513    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
6514        let field_editor_theme = get_field_editor_theme(&settings.theme);
6515        theme.text_color = field_editor_theme.text.color;
6516        theme.selection = field_editor_theme.selection;
6517        theme.background = field_editor_theme
6518            .container
6519            .background_color
6520            .unwrap_or_default();
6521        EditorStyle {
6522            text: field_editor_theme.text,
6523            placeholder_text: field_editor_theme.placeholder_text,
6524            theme,
6525        }
6526    } else {
6527        let font_family_id = settings.buffer_font_family;
6528        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
6529        let font_properties = Default::default();
6530        let font_id = font_cache
6531            .select_font(font_family_id, &font_properties)
6532            .unwrap();
6533        let font_size = settings.buffer_font_size;
6534        EditorStyle {
6535            text: TextStyle {
6536                color: settings.theme.editor.text_color,
6537                font_family_name,
6538                font_family_id,
6539                font_id,
6540                font_size,
6541                font_properties,
6542                underline: Default::default(),
6543            },
6544            placeholder_text: None,
6545            theme,
6546        }
6547    };
6548
6549    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
6550        if let Some(highlighted) = style
6551            .text
6552            .clone()
6553            .highlight(highlight_style, font_cache)
6554            .log_err()
6555        {
6556            style.text = highlighted;
6557        }
6558    }
6559
6560    style
6561}
6562
6563trait SelectionExt {
6564    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
6565    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
6566    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
6567    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
6568        -> Range<u32>;
6569}
6570
6571impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
6572    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
6573        let start = self.start.to_point(buffer);
6574        let end = self.end.to_point(buffer);
6575        if self.reversed {
6576            end..start
6577        } else {
6578            start..end
6579        }
6580    }
6581
6582    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
6583        let start = self.start.to_offset(buffer);
6584        let end = self.end.to_offset(buffer);
6585        if self.reversed {
6586            end..start
6587        } else {
6588            start..end
6589        }
6590    }
6591
6592    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
6593        let start = self
6594            .start
6595            .to_point(&map.buffer_snapshot)
6596            .to_display_point(map);
6597        let end = self
6598            .end
6599            .to_point(&map.buffer_snapshot)
6600            .to_display_point(map);
6601        if self.reversed {
6602            end..start
6603        } else {
6604            start..end
6605        }
6606    }
6607
6608    fn spanned_rows(
6609        &self,
6610        include_end_if_at_line_start: bool,
6611        map: &DisplaySnapshot,
6612    ) -> Range<u32> {
6613        let start = self.start.to_point(&map.buffer_snapshot);
6614        let mut end = self.end.to_point(&map.buffer_snapshot);
6615        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
6616            end.row -= 1;
6617        }
6618
6619        let buffer_start = map.prev_line_boundary(start).0;
6620        let buffer_end = map.next_line_boundary(end).0;
6621        buffer_start.row..buffer_end.row + 1
6622    }
6623}
6624
6625impl<T: InvalidationRegion> InvalidationStack<T> {
6626    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
6627    where
6628        S: Clone + ToOffset,
6629    {
6630        while let Some(region) = self.last() {
6631            let all_selections_inside_invalidation_ranges =
6632                if selections.len() == region.ranges().len() {
6633                    selections
6634                        .iter()
6635                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
6636                        .all(|(selection, invalidation_range)| {
6637                            let head = selection.head().to_offset(buffer);
6638                            invalidation_range.start <= head && invalidation_range.end >= head
6639                        })
6640                } else {
6641                    false
6642                };
6643
6644            if all_selections_inside_invalidation_ranges {
6645                break;
6646            } else {
6647                self.pop();
6648            }
6649        }
6650    }
6651}
6652
6653impl<T> Default for InvalidationStack<T> {
6654    fn default() -> Self {
6655        Self(Default::default())
6656    }
6657}
6658
6659impl<T> Deref for InvalidationStack<T> {
6660    type Target = Vec<T>;
6661
6662    fn deref(&self) -> &Self::Target {
6663        &self.0
6664    }
6665}
6666
6667impl<T> DerefMut for InvalidationStack<T> {
6668    fn deref_mut(&mut self) -> &mut Self::Target {
6669        &mut self.0
6670    }
6671}
6672
6673impl InvalidationRegion for SnippetState {
6674    fn ranges(&self) -> &[Range<Anchor>] {
6675        &self.ranges[self.active_index]
6676    }
6677}
6678
6679impl Deref for EditorStyle {
6680    type Target = theme::Editor;
6681
6682    fn deref(&self) -> &Self::Target {
6683        &self.theme
6684    }
6685}
6686
6687pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
6688    let mut highlighted_lines = Vec::new();
6689    for line in diagnostic.message.lines() {
6690        highlighted_lines.push(highlight_diagnostic_message(line));
6691    }
6692
6693    Arc::new(move |cx: &mut BlockContext| {
6694        let settings = cx.global::<Settings>();
6695        let theme = &settings.theme.editor;
6696        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
6697        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
6698        Flex::column()
6699            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
6700                Label::new(
6701                    line.clone(),
6702                    style.message.clone().with_font_size(font_size),
6703                )
6704                .with_highlights(highlights.clone())
6705                .contained()
6706                .with_margin_left(cx.anchor_x)
6707                .boxed()
6708            }))
6709            .aligned()
6710            .left()
6711            .boxed()
6712    })
6713}
6714
6715pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
6716    let mut message_without_backticks = String::new();
6717    let mut prev_offset = 0;
6718    let mut inside_block = false;
6719    let mut highlights = Vec::new();
6720    for (match_ix, (offset, _)) in message
6721        .match_indices('`')
6722        .chain([(message.len(), "")])
6723        .enumerate()
6724    {
6725        message_without_backticks.push_str(&message[prev_offset..offset]);
6726        if inside_block {
6727            highlights.extend(prev_offset - match_ix..offset - match_ix);
6728        }
6729
6730        inside_block = !inside_block;
6731        prev_offset = offset + 1;
6732    }
6733
6734    (message_without_backticks, highlights)
6735}
6736
6737pub fn diagnostic_style(
6738    severity: DiagnosticSeverity,
6739    valid: bool,
6740    theme: &theme::Editor,
6741) -> DiagnosticStyle {
6742    match (severity, valid) {
6743        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
6744        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
6745        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
6746        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
6747        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
6748        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
6749        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
6750        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
6751        _ => theme.invalid_hint_diagnostic.clone(),
6752    }
6753}
6754
6755pub fn combine_syntax_and_fuzzy_match_highlights(
6756    text: &str,
6757    default_style: HighlightStyle,
6758    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
6759    match_indices: &[usize],
6760) -> Vec<(Range<usize>, HighlightStyle)> {
6761    let mut result = Vec::new();
6762    let mut match_indices = match_indices.iter().copied().peekable();
6763
6764    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
6765    {
6766        syntax_highlight.weight = None;
6767
6768        // Add highlights for any fuzzy match characters before the next
6769        // syntax highlight range.
6770        while let Some(&match_index) = match_indices.peek() {
6771            if match_index >= range.start {
6772                break;
6773            }
6774            match_indices.next();
6775            let end_index = char_ix_after(match_index, text);
6776            let mut match_style = default_style;
6777            match_style.weight = Some(fonts::Weight::BOLD);
6778            result.push((match_index..end_index, match_style));
6779        }
6780
6781        if range.start == usize::MAX {
6782            break;
6783        }
6784
6785        // Add highlights for any fuzzy match characters within the
6786        // syntax highlight range.
6787        let mut offset = range.start;
6788        while let Some(&match_index) = match_indices.peek() {
6789            if match_index >= range.end {
6790                break;
6791            }
6792
6793            match_indices.next();
6794            if match_index > offset {
6795                result.push((offset..match_index, syntax_highlight));
6796            }
6797
6798            let mut end_index = char_ix_after(match_index, text);
6799            while let Some(&next_match_index) = match_indices.peek() {
6800                if next_match_index == end_index && next_match_index < range.end {
6801                    end_index = char_ix_after(next_match_index, text);
6802                    match_indices.next();
6803                } else {
6804                    break;
6805                }
6806            }
6807
6808            let mut match_style = syntax_highlight;
6809            match_style.weight = Some(fonts::Weight::BOLD);
6810            result.push((match_index..end_index, match_style));
6811            offset = end_index;
6812        }
6813
6814        if offset < range.end {
6815            result.push((offset..range.end, syntax_highlight));
6816        }
6817    }
6818
6819    fn char_ix_after(ix: usize, text: &str) -> usize {
6820        ix + text[ix..].chars().next().unwrap().len_utf8()
6821    }
6822
6823    result
6824}
6825
6826pub fn styled_runs_for_code_label<'a>(
6827    label: &'a CodeLabel,
6828    syntax_theme: &'a theme::SyntaxTheme,
6829) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
6830    let fade_out = HighlightStyle {
6831        fade_out: Some(0.35),
6832        ..Default::default()
6833    };
6834
6835    let mut prev_end = label.filter_range.end;
6836    label
6837        .runs
6838        .iter()
6839        .enumerate()
6840        .flat_map(move |(ix, (range, highlight_id))| {
6841            let style = if let Some(style) = highlight_id.style(syntax_theme) {
6842                style
6843            } else {
6844                return Default::default();
6845            };
6846            let mut muted_style = style;
6847            muted_style.highlight(fade_out);
6848
6849            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
6850            if range.start >= label.filter_range.end {
6851                if range.start > prev_end {
6852                    runs.push((prev_end..range.start, fade_out));
6853                }
6854                runs.push((range.clone(), muted_style));
6855            } else if range.end <= label.filter_range.end {
6856                runs.push((range.clone(), style));
6857            } else {
6858                runs.push((range.start..label.filter_range.end, style));
6859                runs.push((label.filter_range.end..range.end, muted_style));
6860            }
6861            prev_end = cmp::max(prev_end, range.end);
6862
6863            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
6864                runs.push((prev_end..label.text.len(), fade_out));
6865            }
6866
6867            runs
6868        })
6869}
6870
6871trait RangeExt<T> {
6872    fn sorted(&self) -> Range<T>;
6873    fn to_inclusive(&self) -> RangeInclusive<T>;
6874}
6875
6876impl<T: Ord + Clone> RangeExt<T> for Range<T> {
6877    fn sorted(&self) -> Self {
6878        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
6879    }
6880
6881    fn to_inclusive(&self) -> RangeInclusive<T> {
6882        self.start.clone()..=self.end.clone()
6883    }
6884}
6885
6886trait RangeToAnchorExt {
6887    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
6888}
6889
6890impl<T: ToOffset> RangeToAnchorExt for Range<T> {
6891    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
6892        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
6893    }
6894}