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, Selection, SelectionGoal,
  47    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 rope::{offset_utf16::OffsetUtf16, point::Point};
  58use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  59use serde::{Deserialize, Serialize};
  60use settings::Settings;
  61use smallvec::SmallVec;
  62use smol::Timer;
  63use snippet::Snippet;
  64use std::{
  65    any::TypeId,
  66    borrow::Cow,
  67    cmp::{self, Ordering, Reverse},
  68    mem,
  69    num::NonZeroU32,
  70    ops::{Deref, DerefMut, Range, RangeInclusive},
  71    sync::Arc,
  72    time::{Duration, Instant},
  73};
  74pub use sum_tree::Bias;
  75use theme::{DiagnosticStyle, Theme};
  76use util::{post_inc, ResultExt, TryFutureExt};
  77use workspace::{ItemNavHistory, Workspace};
  78
  79const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  80const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
  81const MAX_LINE_LEN: usize = 1024;
  82const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  83const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  84
  85pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  86
  87#[derive(Clone, Deserialize, PartialEq, Default)]
  88pub struct SelectNext {
  89    #[serde(default)]
  90    pub replace_newest: bool,
  91}
  92
  93#[derive(Clone, PartialEq)]
  94pub struct Scroll(pub Vector2F);
  95
  96#[derive(Clone, PartialEq)]
  97pub struct Select(pub SelectPhase);
  98
  99#[derive(Clone, Debug, PartialEq)]
 100pub struct Jump {
 101    path: ProjectPath,
 102    position: Point,
 103    anchor: language::Anchor,
 104}
 105
 106#[derive(Clone, Deserialize, PartialEq)]
 107pub struct SelectToBeginningOfLine {
 108    #[serde(default)]
 109    stop_at_soft_wraps: bool,
 110}
 111
 112#[derive(Clone, Deserialize, PartialEq)]
 113pub struct SelectToEndOfLine {
 114    #[serde(default)]
 115    stop_at_soft_wraps: bool,
 116}
 117
 118#[derive(Clone, Deserialize, PartialEq)]
 119pub struct ToggleCodeActions {
 120    #[serde(default)]
 121    pub deployed_from_indicator: bool,
 122}
 123
 124#[derive(Clone, Default, Deserialize, PartialEq)]
 125pub struct ConfirmCompletion {
 126    #[serde(default)]
 127    pub item_ix: Option<usize>,
 128}
 129
 130#[derive(Clone, Default, Deserialize, PartialEq)]
 131pub struct ConfirmCodeAction {
 132    #[serde(default)]
 133    pub item_ix: Option<usize>,
 134}
 135
 136actions!(
 137    editor,
 138    [
 139        Cancel,
 140        Backspace,
 141        Delete,
 142        Newline,
 143        NewlineBelow,
 144        GoToDiagnostic,
 145        GoToPrevDiagnostic,
 146        Indent,
 147        Outdent,
 148        DeleteLine,
 149        DeleteToPreviousWordStart,
 150        DeleteToPreviousSubwordStart,
 151        DeleteToNextWordEnd,
 152        DeleteToNextSubwordEnd,
 153        DeleteToBeginningOfLine,
 154        DeleteToEndOfLine,
 155        CutToEndOfLine,
 156        DuplicateLine,
 157        MoveLineUp,
 158        MoveLineDown,
 159        Transpose,
 160        Cut,
 161        Copy,
 162        Paste,
 163        Undo,
 164        Redo,
 165        MoveUp,
 166        MoveDown,
 167        MoveLeft,
 168        MoveRight,
 169        MoveToPreviousWordStart,
 170        MoveToPreviousSubwordStart,
 171        MoveToNextWordEnd,
 172        MoveToNextSubwordEnd,
 173        MoveToBeginningOfLine,
 174        MoveToEndOfLine,
 175        MoveToBeginning,
 176        MoveToEnd,
 177        SelectUp,
 178        SelectDown,
 179        SelectLeft,
 180        SelectRight,
 181        SelectToPreviousWordStart,
 182        SelectToPreviousSubwordStart,
 183        SelectToNextWordEnd,
 184        SelectToNextSubwordEnd,
 185        SelectToBeginning,
 186        SelectToEnd,
 187        SelectAll,
 188        SelectLine,
 189        SplitSelectionIntoLines,
 190        AddSelectionAbove,
 191        AddSelectionBelow,
 192        Tab,
 193        TabPrev,
 194        ToggleComments,
 195        ShowCharacterPalette,
 196        SelectLargerSyntaxNode,
 197        SelectSmallerSyntaxNode,
 198        GoToDefinition,
 199        GoToTypeDefinition,
 200        MoveToEnclosingBracket,
 201        UndoSelection,
 202        RedoSelection,
 203        FindAllReferences,
 204        Rename,
 205        ConfirmRename,
 206        PageUp,
 207        PageDown,
 208        Fold,
 209        UnfoldLines,
 210        FoldSelectedRanges,
 211        ShowCompletions,
 212        OpenExcerpts,
 213        RestartLanguageServer,
 214        Hover,
 215        Format,
 216    ]
 217);
 218
 219impl_actions!(
 220    editor,
 221    [
 222        SelectNext,
 223        SelectToBeginningOfLine,
 224        SelectToEndOfLine,
 225        ToggleCodeActions,
 226        ConfirmCompletion,
 227        ConfirmCodeAction,
 228    ]
 229);
 230
 231impl_internal_actions!(editor, [Scroll, Select, Jump]);
 232
 233enum DocumentHighlightRead {}
 234enum DocumentHighlightWrite {}
 235enum InputComposition {}
 236
 237#[derive(Copy, Clone, PartialEq, Eq)]
 238pub enum Direction {
 239    Prev,
 240    Next,
 241}
 242
 243#[derive(Default)]
 244struct ScrollbarAutoHide(bool);
 245
 246pub fn init(cx: &mut MutableAppContext) {
 247    cx.add_action(Editor::new_file);
 248    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
 249    cx.add_action(Editor::select);
 250    cx.add_action(Editor::cancel);
 251    cx.add_action(Editor::newline);
 252    cx.add_action(Editor::newline_below);
 253    cx.add_action(Editor::backspace);
 254    cx.add_action(Editor::delete);
 255    cx.add_action(Editor::tab);
 256    cx.add_action(Editor::tab_prev);
 257    cx.add_action(Editor::indent);
 258    cx.add_action(Editor::outdent);
 259    cx.add_action(Editor::delete_line);
 260    cx.add_action(Editor::delete_to_previous_word_start);
 261    cx.add_action(Editor::delete_to_previous_subword_start);
 262    cx.add_action(Editor::delete_to_next_word_end);
 263    cx.add_action(Editor::delete_to_next_subword_end);
 264    cx.add_action(Editor::delete_to_beginning_of_line);
 265    cx.add_action(Editor::delete_to_end_of_line);
 266    cx.add_action(Editor::cut_to_end_of_line);
 267    cx.add_action(Editor::duplicate_line);
 268    cx.add_action(Editor::move_line_up);
 269    cx.add_action(Editor::move_line_down);
 270    cx.add_action(Editor::transpose);
 271    cx.add_action(Editor::cut);
 272    cx.add_action(Editor::copy);
 273    cx.add_action(Editor::paste);
 274    cx.add_action(Editor::undo);
 275    cx.add_action(Editor::redo);
 276    cx.add_action(Editor::move_up);
 277    cx.add_action(Editor::move_down);
 278    cx.add_action(Editor::move_left);
 279    cx.add_action(Editor::move_right);
 280    cx.add_action(Editor::move_to_previous_word_start);
 281    cx.add_action(Editor::move_to_previous_subword_start);
 282    cx.add_action(Editor::move_to_next_word_end);
 283    cx.add_action(Editor::move_to_next_subword_end);
 284    cx.add_action(Editor::move_to_beginning_of_line);
 285    cx.add_action(Editor::move_to_end_of_line);
 286    cx.add_action(Editor::move_to_beginning);
 287    cx.add_action(Editor::move_to_end);
 288    cx.add_action(Editor::select_up);
 289    cx.add_action(Editor::select_down);
 290    cx.add_action(Editor::select_left);
 291    cx.add_action(Editor::select_right);
 292    cx.add_action(Editor::select_to_previous_word_start);
 293    cx.add_action(Editor::select_to_previous_subword_start);
 294    cx.add_action(Editor::select_to_next_word_end);
 295    cx.add_action(Editor::select_to_next_subword_end);
 296    cx.add_action(Editor::select_to_beginning_of_line);
 297    cx.add_action(Editor::select_to_end_of_line);
 298    cx.add_action(Editor::select_to_beginning);
 299    cx.add_action(Editor::select_to_end);
 300    cx.add_action(Editor::select_all);
 301    cx.add_action(Editor::select_line);
 302    cx.add_action(Editor::split_selection_into_lines);
 303    cx.add_action(Editor::add_selection_above);
 304    cx.add_action(Editor::add_selection_below);
 305    cx.add_action(Editor::select_next);
 306    cx.add_action(Editor::toggle_comments);
 307    cx.add_action(Editor::select_larger_syntax_node);
 308    cx.add_action(Editor::select_smaller_syntax_node);
 309    cx.add_action(Editor::move_to_enclosing_bracket);
 310    cx.add_action(Editor::undo_selection);
 311    cx.add_action(Editor::redo_selection);
 312    cx.add_action(Editor::go_to_diagnostic);
 313    cx.add_action(Editor::go_to_prev_diagnostic);
 314    cx.add_action(Editor::go_to_definition);
 315    cx.add_action(Editor::go_to_type_definition);
 316    cx.add_action(Editor::page_up);
 317    cx.add_action(Editor::page_down);
 318    cx.add_action(Editor::fold);
 319    cx.add_action(Editor::unfold_lines);
 320    cx.add_action(Editor::fold_selected_ranges);
 321    cx.add_action(Editor::show_completions);
 322    cx.add_action(Editor::toggle_code_actions);
 323    cx.add_action(Editor::open_excerpts);
 324    cx.add_action(Editor::jump);
 325    cx.add_async_action(Editor::format);
 326    cx.add_action(Editor::restart_language_server);
 327    cx.add_action(Editor::show_character_palette);
 328    cx.add_async_action(Editor::confirm_completion);
 329    cx.add_async_action(Editor::confirm_code_action);
 330    cx.add_async_action(Editor::rename);
 331    cx.add_async_action(Editor::confirm_rename);
 332    cx.add_async_action(Editor::find_all_references);
 333
 334    hover_popover::init(cx);
 335    link_go_to_definition::init(cx);
 336    mouse_context_menu::init(cx);
 337
 338    workspace::register_project_item::<Editor>(cx);
 339    workspace::register_followable_item::<Editor>(cx);
 340}
 341
 342trait InvalidationRegion {
 343    fn ranges(&self) -> &[Range<Anchor>];
 344}
 345
 346#[derive(Clone, Debug, PartialEq)]
 347pub enum SelectPhase {
 348    Begin {
 349        position: DisplayPoint,
 350        add: bool,
 351        click_count: usize,
 352    },
 353    BeginColumnar {
 354        position: DisplayPoint,
 355        goal_column: u32,
 356    },
 357    Extend {
 358        position: DisplayPoint,
 359        click_count: usize,
 360    },
 361    Update {
 362        position: DisplayPoint,
 363        goal_column: u32,
 364        scroll_position: Vector2F,
 365    },
 366    End,
 367}
 368
 369#[derive(Clone, Debug)]
 370pub enum SelectMode {
 371    Character,
 372    Word(Range<Anchor>),
 373    Line(Range<Anchor>),
 374    All,
 375}
 376
 377#[derive(PartialEq, Eq)]
 378pub enum Autoscroll {
 379    Fit,
 380    Center,
 381    Newest,
 382}
 383
 384#[derive(Copy, Clone, PartialEq, Eq)]
 385pub enum EditorMode {
 386    SingleLine,
 387    AutoHeight { max_lines: usize },
 388    Full,
 389}
 390
 391#[derive(Clone)]
 392pub enum SoftWrap {
 393    None,
 394    EditorWidth,
 395    Column(u32),
 396}
 397
 398#[derive(Clone)]
 399pub struct EditorStyle {
 400    pub text: TextStyle,
 401    pub placeholder_text: Option<TextStyle>,
 402    pub theme: theme::Editor,
 403}
 404
 405type CompletionId = usize;
 406
 407pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor;
 408
 409type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 410
 411pub struct Editor {
 412    handle: WeakViewHandle<Self>,
 413    buffer: ModelHandle<MultiBuffer>,
 414    display_map: ModelHandle<DisplayMap>,
 415    pub selections: SelectionsCollection,
 416    columnar_selection_tail: Option<Anchor>,
 417    add_selections_state: Option<AddSelectionsState>,
 418    select_next_state: Option<SelectNextState>,
 419    selection_history: SelectionHistory,
 420    autoclose_regions: Vec<AutocloseRegion>,
 421    snippet_stack: InvalidationStack<SnippetState>,
 422    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 423    ime_transaction: Option<TransactionId>,
 424    active_diagnostics: Option<ActiveDiagnosticGroup>,
 425    scroll_position: Vector2F,
 426    scroll_top_anchor: Anchor,
 427    autoscroll_request: Option<(Autoscroll, bool)>,
 428    soft_wrap_mode_override: Option<settings::SoftWrap>,
 429    get_field_editor_theme: Option<GetFieldEditorTheme>,
 430    override_text_style: Option<Box<OverrideTextStyle>>,
 431    project: Option<ModelHandle<Project>>,
 432    focused: bool,
 433    show_local_cursors: bool,
 434    show_local_selections: bool,
 435    show_scrollbars: bool,
 436    hide_scrollbar_task: Option<Task<()>>,
 437    blink_epoch: usize,
 438    blinking_paused: bool,
 439    mode: EditorMode,
 440    vertical_scroll_margin: f32,
 441    placeholder_text: Option<Arc<str>>,
 442    highlighted_rows: Option<Range<u32>>,
 443    #[allow(clippy::type_complexity)]
 444    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 445    nav_history: Option<ItemNavHistory>,
 446    context_menu: Option<ContextMenu>,
 447    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 448    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 449    next_completion_id: CompletionId,
 450    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 451    code_actions_task: Option<Task<()>>,
 452    document_highlights_task: Option<Task<()>>,
 453    pending_rename: Option<RenameState>,
 454    searchable: bool,
 455    cursor_shape: CursorShape,
 456    keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
 457    input_enabled: bool,
 458    leader_replica_id: Option<u16>,
 459    hover_state: HoverState,
 460    link_go_to_definition_state: LinkGoToDefinitionState,
 461    visible_line_count: Option<f32>,
 462    _subscriptions: Vec<Subscription>,
 463}
 464
 465pub struct EditorSnapshot {
 466    pub mode: EditorMode,
 467    pub display_snapshot: DisplaySnapshot,
 468    pub placeholder_text: Option<Arc<str>>,
 469    is_focused: bool,
 470    scroll_position: Vector2F,
 471    scroll_top_anchor: Anchor,
 472}
 473
 474#[derive(Clone, Debug)]
 475struct SelectionHistoryEntry {
 476    selections: Arc<[Selection<Anchor>]>,
 477    select_next_state: Option<SelectNextState>,
 478    add_selections_state: Option<AddSelectionsState>,
 479}
 480
 481enum SelectionHistoryMode {
 482    Normal,
 483    Undoing,
 484    Redoing,
 485}
 486
 487impl Default for SelectionHistoryMode {
 488    fn default() -> Self {
 489        Self::Normal
 490    }
 491}
 492
 493#[derive(Default)]
 494struct SelectionHistory {
 495    #[allow(clippy::type_complexity)]
 496    selections_by_transaction:
 497        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 498    mode: SelectionHistoryMode,
 499    undo_stack: VecDeque<SelectionHistoryEntry>,
 500    redo_stack: VecDeque<SelectionHistoryEntry>,
 501}
 502
 503impl SelectionHistory {
 504    fn insert_transaction(
 505        &mut self,
 506        transaction_id: TransactionId,
 507        selections: Arc<[Selection<Anchor>]>,
 508    ) {
 509        self.selections_by_transaction
 510            .insert(transaction_id, (selections, None));
 511    }
 512
 513    #[allow(clippy::type_complexity)]
 514    fn transaction(
 515        &self,
 516        transaction_id: TransactionId,
 517    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 518        self.selections_by_transaction.get(&transaction_id)
 519    }
 520
 521    #[allow(clippy::type_complexity)]
 522    fn transaction_mut(
 523        &mut self,
 524        transaction_id: TransactionId,
 525    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 526        self.selections_by_transaction.get_mut(&transaction_id)
 527    }
 528
 529    fn push(&mut self, entry: SelectionHistoryEntry) {
 530        if !entry.selections.is_empty() {
 531            match self.mode {
 532                SelectionHistoryMode::Normal => {
 533                    self.push_undo(entry);
 534                    self.redo_stack.clear();
 535                }
 536                SelectionHistoryMode::Undoing => self.push_redo(entry),
 537                SelectionHistoryMode::Redoing => self.push_undo(entry),
 538            }
 539        }
 540    }
 541
 542    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 543        if self
 544            .undo_stack
 545            .back()
 546            .map_or(true, |e| e.selections != entry.selections)
 547        {
 548            self.undo_stack.push_back(entry);
 549            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 550                self.undo_stack.pop_front();
 551            }
 552        }
 553    }
 554
 555    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 556        if self
 557            .redo_stack
 558            .back()
 559            .map_or(true, |e| e.selections != entry.selections)
 560        {
 561            self.redo_stack.push_back(entry);
 562            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 563                self.redo_stack.pop_front();
 564            }
 565        }
 566    }
 567}
 568
 569#[derive(Clone, Debug)]
 570struct AddSelectionsState {
 571    above: bool,
 572    stack: Vec<usize>,
 573}
 574
 575#[derive(Clone, Debug)]
 576struct SelectNextState {
 577    query: AhoCorasick,
 578    wordwise: bool,
 579    done: bool,
 580}
 581
 582#[derive(Debug)]
 583struct AutocloseRegion {
 584    selection_id: usize,
 585    range: Range<Anchor>,
 586    pair: BracketPair,
 587}
 588
 589#[derive(Debug)]
 590struct SnippetState {
 591    ranges: Vec<Vec<Range<Anchor>>>,
 592    active_index: usize,
 593}
 594
 595pub struct RenameState {
 596    pub range: Range<Anchor>,
 597    pub old_name: Arc<str>,
 598    pub editor: ViewHandle<Editor>,
 599    block_id: BlockId,
 600}
 601
 602struct InvalidationStack<T>(Vec<T>);
 603
 604enum ContextMenu {
 605    Completions(CompletionsMenu),
 606    CodeActions(CodeActionsMenu),
 607}
 608
 609impl ContextMenu {
 610    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 611        if self.visible() {
 612            match self {
 613                ContextMenu::Completions(menu) => menu.select_prev(cx),
 614                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 615            }
 616            true
 617        } else {
 618            false
 619        }
 620    }
 621
 622    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 623        if self.visible() {
 624            match self {
 625                ContextMenu::Completions(menu) => menu.select_next(cx),
 626                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 627            }
 628            true
 629        } else {
 630            false
 631        }
 632    }
 633
 634    fn visible(&self) -> bool {
 635        match self {
 636            ContextMenu::Completions(menu) => menu.visible(),
 637            ContextMenu::CodeActions(menu) => menu.visible(),
 638        }
 639    }
 640
 641    fn render(
 642        &self,
 643        cursor_position: DisplayPoint,
 644        style: EditorStyle,
 645        cx: &mut RenderContext<Editor>,
 646    ) -> (DisplayPoint, ElementBox) {
 647        match self {
 648            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 649            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 650        }
 651    }
 652}
 653
 654struct CompletionsMenu {
 655    id: CompletionId,
 656    initial_position: Anchor,
 657    buffer: ModelHandle<Buffer>,
 658    completions: Arc<[Completion]>,
 659    match_candidates: Vec<StringMatchCandidate>,
 660    matches: Arc<[StringMatch]>,
 661    selected_item: usize,
 662    list: UniformListState,
 663}
 664
 665impl CompletionsMenu {
 666    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 667        if self.selected_item > 0 {
 668            self.selected_item -= 1;
 669            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 670        }
 671        cx.notify();
 672    }
 673
 674    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 675        if self.selected_item + 1 < self.matches.len() {
 676            self.selected_item += 1;
 677            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 678        }
 679        cx.notify();
 680    }
 681
 682    fn visible(&self) -> bool {
 683        !self.matches.is_empty()
 684    }
 685
 686    fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox {
 687        enum CompletionTag {}
 688
 689        let completions = self.completions.clone();
 690        let matches = self.matches.clone();
 691        let selected_item = self.selected_item;
 692        let container_style = style.autocomplete.container;
 693        UniformList::new(
 694            self.list.clone(),
 695            matches.len(),
 696            cx,
 697            move |_, range, items, cx| {
 698                let start_ix = range.start;
 699                for (ix, mat) in matches[range].iter().enumerate() {
 700                    let completion = &completions[mat.candidate_id];
 701                    let item_ix = start_ix + ix;
 702                    items.push(
 703                        MouseEventHandler::<CompletionTag>::new(
 704                            mat.candidate_id,
 705                            cx,
 706                            |state, _| {
 707                                let item_style = if item_ix == selected_item {
 708                                    style.autocomplete.selected_item
 709                                } else if state.hovered {
 710                                    style.autocomplete.hovered_item
 711                                } else {
 712                                    style.autocomplete.item
 713                                };
 714
 715                                Text::new(completion.label.text.clone(), style.text.clone())
 716                                    .with_soft_wrap(false)
 717                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 718                                        &completion.label.text,
 719                                        style.text.color.into(),
 720                                        styled_runs_for_code_label(
 721                                            &completion.label,
 722                                            &style.syntax,
 723                                        ),
 724                                        &mat.positions,
 725                                    ))
 726                                    .contained()
 727                                    .with_style(item_style)
 728                                    .boxed()
 729                            },
 730                        )
 731                        .with_cursor_style(CursorStyle::PointingHand)
 732                        .on_down(MouseButton::Left, move |_, cx| {
 733                            cx.dispatch_action(ConfirmCompletion {
 734                                item_ix: Some(item_ix),
 735                            });
 736                        })
 737                        .boxed(),
 738                    );
 739                }
 740            },
 741        )
 742        .with_width_from_item(
 743            self.matches
 744                .iter()
 745                .enumerate()
 746                .max_by_key(|(_, mat)| {
 747                    self.completions[mat.candidate_id]
 748                        .label
 749                        .text
 750                        .chars()
 751                        .count()
 752                })
 753                .map(|(ix, _)| ix),
 754        )
 755        .contained()
 756        .with_style(container_style)
 757        .boxed()
 758    }
 759
 760    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 761        let mut matches = if let Some(query) = query {
 762            fuzzy::match_strings(
 763                &self.match_candidates,
 764                query,
 765                false,
 766                100,
 767                &Default::default(),
 768                executor,
 769            )
 770            .await
 771        } else {
 772            self.match_candidates
 773                .iter()
 774                .enumerate()
 775                .map(|(candidate_id, candidate)| StringMatch {
 776                    candidate_id,
 777                    score: Default::default(),
 778                    positions: Default::default(),
 779                    string: candidate.string.clone(),
 780                })
 781                .collect()
 782        };
 783        matches.sort_unstable_by_key(|mat| {
 784            let completion = &self.completions[mat.candidate_id];
 785            (
 786                completion.lsp_completion.sort_text.as_ref(),
 787                Reverse(OrderedFloat(mat.score)),
 788                completion.sort_key(),
 789            )
 790        });
 791
 792        for mat in &mut matches {
 793            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 794            for position in &mut mat.positions {
 795                *position += filter_start;
 796            }
 797        }
 798
 799        self.matches = matches.into();
 800    }
 801}
 802
 803#[derive(Clone)]
 804struct CodeActionsMenu {
 805    actions: Arc<[CodeAction]>,
 806    buffer: ModelHandle<Buffer>,
 807    selected_item: usize,
 808    list: UniformListState,
 809    deployed_from_indicator: bool,
 810}
 811
 812impl CodeActionsMenu {
 813    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 814        if self.selected_item > 0 {
 815            self.selected_item -= 1;
 816            cx.notify()
 817        }
 818    }
 819
 820    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 821        if self.selected_item + 1 < self.actions.len() {
 822            self.selected_item += 1;
 823            cx.notify()
 824        }
 825    }
 826
 827    fn visible(&self) -> bool {
 828        !self.actions.is_empty()
 829    }
 830
 831    fn render(
 832        &self,
 833        mut cursor_position: DisplayPoint,
 834        style: EditorStyle,
 835        cx: &mut RenderContext<Editor>,
 836    ) -> (DisplayPoint, ElementBox) {
 837        enum ActionTag {}
 838
 839        let container_style = style.autocomplete.container;
 840        let actions = self.actions.clone();
 841        let selected_item = self.selected_item;
 842        let element = UniformList::new(
 843            self.list.clone(),
 844            actions.len(),
 845            cx,
 846            move |_, range, items, cx| {
 847                let start_ix = range.start;
 848                for (ix, action) in actions[range].iter().enumerate() {
 849                    let item_ix = start_ix + ix;
 850                    items.push(
 851                        MouseEventHandler::<ActionTag>::new(item_ix, cx, |state, _| {
 852                            let item_style = if item_ix == selected_item {
 853                                style.autocomplete.selected_item
 854                            } else if state.hovered {
 855                                style.autocomplete.hovered_item
 856                            } else {
 857                                style.autocomplete.item
 858                            };
 859
 860                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 861                                .with_soft_wrap(false)
 862                                .contained()
 863                                .with_style(item_style)
 864                                .boxed()
 865                        })
 866                        .with_cursor_style(CursorStyle::PointingHand)
 867                        .on_down(MouseButton::Left, move |_, cx| {
 868                            cx.dispatch_action(ConfirmCodeAction {
 869                                item_ix: Some(item_ix),
 870                            });
 871                        })
 872                        .boxed(),
 873                    );
 874                }
 875            },
 876        )
 877        .with_width_from_item(
 878            self.actions
 879                .iter()
 880                .enumerate()
 881                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 882                .map(|(ix, _)| ix),
 883        )
 884        .contained()
 885        .with_style(container_style)
 886        .boxed();
 887
 888        if self.deployed_from_indicator {
 889            *cursor_position.column_mut() = 0;
 890        }
 891
 892        (cursor_position, element)
 893    }
 894}
 895
 896#[derive(Debug)]
 897struct ActiveDiagnosticGroup {
 898    primary_range: Range<Anchor>,
 899    primary_message: String,
 900    blocks: HashMap<BlockId, Diagnostic>,
 901    is_valid: bool,
 902}
 903
 904#[derive(Serialize, Deserialize)]
 905pub struct ClipboardSelection {
 906    pub len: usize,
 907    pub is_entire_line: bool,
 908    pub first_line_indent: u32,
 909}
 910
 911#[derive(Debug)]
 912pub struct NavigationData {
 913    // Matching offsets for anchor and scroll_top_anchor allows us to recreate the anchor if the buffer
 914    // has since been closed
 915    cursor_anchor: Anchor,
 916    cursor_position: Point,
 917    scroll_position: Vector2F,
 918    scroll_top_anchor: Anchor,
 919    scroll_top_row: u32,
 920}
 921
 922pub struct EditorCreated(pub ViewHandle<Editor>);
 923
 924enum GotoDefinitionKind {
 925    Symbol,
 926    Type,
 927}
 928
 929impl Editor {
 930    pub fn single_line(
 931        field_editor_style: Option<GetFieldEditorTheme>,
 932        cx: &mut ViewContext<Self>,
 933    ) -> Self {
 934        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 935        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 936        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
 937    }
 938
 939    pub fn auto_height(
 940        max_lines: usize,
 941        field_editor_style: Option<GetFieldEditorTheme>,
 942        cx: &mut ViewContext<Self>,
 943    ) -> Self {
 944        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
 945        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 946        Self::new(
 947            EditorMode::AutoHeight { max_lines },
 948            buffer,
 949            None,
 950            field_editor_style,
 951            cx,
 952        )
 953    }
 954
 955    pub fn for_buffer(
 956        buffer: ModelHandle<Buffer>,
 957        project: Option<ModelHandle<Project>>,
 958        cx: &mut ViewContext<Self>,
 959    ) -> Self {
 960        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 961        Self::new(EditorMode::Full, buffer, project, None, cx)
 962    }
 963
 964    pub fn for_multibuffer(
 965        buffer: ModelHandle<MultiBuffer>,
 966        project: Option<ModelHandle<Project>>,
 967        cx: &mut ViewContext<Self>,
 968    ) -> Self {
 969        Self::new(EditorMode::Full, buffer, project, None, cx)
 970    }
 971
 972    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 973        let mut clone = Self::new(
 974            self.mode,
 975            self.buffer.clone(),
 976            self.project.clone(),
 977            self.get_field_editor_theme,
 978            cx,
 979        );
 980        self.display_map.update(cx, |display_map, cx| {
 981            let snapshot = display_map.snapshot(cx);
 982            clone.display_map.update(cx, |display_map, cx| {
 983                display_map.set_state(&snapshot, cx);
 984            });
 985        });
 986        clone.selections.set_state(&self.selections);
 987        clone.scroll_position = self.scroll_position;
 988        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
 989        clone.searchable = self.searchable;
 990        clone
 991    }
 992
 993    fn new(
 994        mode: EditorMode,
 995        buffer: ModelHandle<MultiBuffer>,
 996        project: Option<ModelHandle<Project>>,
 997        get_field_editor_theme: Option<GetFieldEditorTheme>,
 998        cx: &mut ViewContext<Self>,
 999    ) -> Self {
1000        let display_map = cx.add_model(|cx| {
1001            let settings = cx.global::<Settings>();
1002            let style = build_style(&*settings, get_field_editor_theme, None, cx);
1003            DisplayMap::new(
1004                buffer.clone(),
1005                style.text.font_id,
1006                style.text.font_size,
1007                None,
1008                2,
1009                1,
1010                cx,
1011            )
1012        });
1013
1014        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1015
1016        let mut this = Self {
1017            handle: cx.weak_handle(),
1018            buffer: buffer.clone(),
1019            display_map: display_map.clone(),
1020            selections,
1021            columnar_selection_tail: None,
1022            add_selections_state: None,
1023            select_next_state: None,
1024            selection_history: Default::default(),
1025            autoclose_regions: Default::default(),
1026            snippet_stack: Default::default(),
1027            select_larger_syntax_node_stack: Vec::new(),
1028            ime_transaction: Default::default(),
1029            active_diagnostics: None,
1030            soft_wrap_mode_override: None,
1031            get_field_editor_theme,
1032            project,
1033            scroll_position: Vector2F::zero(),
1034            scroll_top_anchor: Anchor::min(),
1035            autoscroll_request: None,
1036            focused: false,
1037            show_local_cursors: false,
1038            show_local_selections: true,
1039            show_scrollbars: true,
1040            hide_scrollbar_task: None,
1041            blink_epoch: 0,
1042            blinking_paused: false,
1043            mode,
1044            vertical_scroll_margin: 3.0,
1045            placeholder_text: None,
1046            highlighted_rows: None,
1047            background_highlights: Default::default(),
1048            nav_history: None,
1049            context_menu: None,
1050            mouse_context_menu: cx.add_view(context_menu::ContextMenu::new),
1051            completion_tasks: Default::default(),
1052            next_completion_id: 0,
1053            available_code_actions: Default::default(),
1054            code_actions_task: Default::default(),
1055            document_highlights_task: Default::default(),
1056            pending_rename: Default::default(),
1057            searchable: true,
1058            override_text_style: None,
1059            cursor_shape: Default::default(),
1060            keymap_context_layers: Default::default(),
1061            input_enabled: true,
1062            leader_replica_id: None,
1063            hover_state: Default::default(),
1064            link_go_to_definition_state: Default::default(),
1065            visible_line_count: None,
1066            _subscriptions: vec![
1067                cx.observe(&buffer, Self::on_buffer_changed),
1068                cx.subscribe(&buffer, Self::on_buffer_event),
1069                cx.observe(&display_map, Self::on_display_map_changed),
1070            ],
1071        };
1072        this.end_selection(cx);
1073        this.make_scrollbar_visible(cx);
1074
1075        let editor_created_event = EditorCreated(cx.handle());
1076        cx.emit_global(editor_created_event);
1077
1078        if mode == EditorMode::Full {
1079            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1080            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1081        }
1082
1083        this.report_event("open editor", cx);
1084        this
1085    }
1086
1087    pub fn new_file(
1088        workspace: &mut Workspace,
1089        _: &workspace::NewFile,
1090        cx: &mut ViewContext<Workspace>,
1091    ) {
1092        let project = workspace.project().clone();
1093        if project.read(cx).is_remote() {
1094            cx.propagate_action();
1095        } else if let Some(buffer) = project
1096            .update(cx, |project, cx| project.create_buffer("", None, cx))
1097            .log_err()
1098        {
1099            workspace.add_item(
1100                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1101                cx,
1102            );
1103        }
1104    }
1105
1106    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1107        self.buffer.read(cx).replica_id()
1108    }
1109
1110    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1111        self.leader_replica_id
1112    }
1113
1114    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1115        &self.buffer
1116    }
1117
1118    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1119        self.buffer().read(cx).title(cx)
1120    }
1121
1122    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
1123        EditorSnapshot {
1124            mode: self.mode,
1125            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1126            scroll_position: self.scroll_position,
1127            scroll_top_anchor: self.scroll_top_anchor.clone(),
1128            placeholder_text: self.placeholder_text.clone(),
1129            is_focused: self
1130                .handle
1131                .upgrade(cx)
1132                .map_or(false, |handle| handle.is_focused(cx)),
1133        }
1134    }
1135
1136    pub fn language_at<'a, T: ToOffset>(
1137        &self,
1138        point: T,
1139        cx: &'a AppContext,
1140    ) -> Option<Arc<Language>> {
1141        self.buffer.read(cx).language_at(point, cx)
1142    }
1143
1144    fn style(&self, cx: &AppContext) -> EditorStyle {
1145        build_style(
1146            cx.global::<Settings>(),
1147            self.get_field_editor_theme,
1148            self.override_text_style.as_deref(),
1149            cx,
1150        )
1151    }
1152
1153    pub fn mode(&self) -> EditorMode {
1154        self.mode
1155    }
1156
1157    pub fn set_placeholder_text(
1158        &mut self,
1159        placeholder_text: impl Into<Arc<str>>,
1160        cx: &mut ViewContext<Self>,
1161    ) {
1162        self.placeholder_text = Some(placeholder_text.into());
1163        cx.notify();
1164    }
1165
1166    pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
1167        self.vertical_scroll_margin = margin_rows as f32;
1168        cx.notify();
1169    }
1170
1171    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
1172        self.set_scroll_position_internal(scroll_position, true, cx);
1173    }
1174
1175    fn set_scroll_position_internal(
1176        &mut self,
1177        scroll_position: Vector2F,
1178        local: bool,
1179        cx: &mut ViewContext<Self>,
1180    ) {
1181        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1182
1183        if scroll_position.y() <= 0. {
1184            self.scroll_top_anchor = Anchor::min();
1185            self.scroll_position = scroll_position.max(vec2f(0., 0.));
1186        } else {
1187            let scroll_top_buffer_offset =
1188                DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
1189            let anchor = map
1190                .buffer_snapshot
1191                .anchor_at(scroll_top_buffer_offset, Bias::Right);
1192            self.scroll_position = vec2f(
1193                scroll_position.x(),
1194                scroll_position.y() - anchor.to_display_point(&map).row() as f32,
1195            );
1196            self.scroll_top_anchor = anchor;
1197        }
1198
1199        self.make_scrollbar_visible(cx);
1200        self.autoscroll_request.take();
1201        hide_hover(self, cx);
1202
1203        cx.emit(Event::ScrollPositionChanged { local });
1204        cx.notify();
1205    }
1206
1207    fn set_visible_line_count(&mut self, lines: f32) {
1208        self.visible_line_count = Some(lines)
1209    }
1210
1211    fn set_scroll_top_anchor(
1212        &mut self,
1213        anchor: Anchor,
1214        position: Vector2F,
1215        cx: &mut ViewContext<Self>,
1216    ) {
1217        self.scroll_top_anchor = anchor;
1218        self.scroll_position = position;
1219        cx.emit(Event::ScrollPositionChanged { local: false });
1220        cx.notify();
1221    }
1222
1223    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1224        self.cursor_shape = cursor_shape;
1225        cx.notify();
1226    }
1227
1228    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1229        if self.display_map.read(cx).clip_at_line_ends != clip {
1230            self.display_map
1231                .update(cx, |map, _| map.clip_at_line_ends = clip);
1232        }
1233    }
1234
1235    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: gpui::keymap::Context) {
1236        self.keymap_context_layers
1237            .insert(TypeId::of::<Tag>(), context);
1238    }
1239
1240    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
1241        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1242    }
1243
1244    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1245        self.input_enabled = input_enabled;
1246    }
1247
1248    pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
1249        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1250        compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
1251    }
1252
1253    pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
1254        if max < self.scroll_position.x() {
1255            self.scroll_position.set_x(max);
1256            true
1257        } else {
1258            false
1259        }
1260    }
1261
1262    pub fn autoscroll_vertically(
1263        &mut self,
1264        viewport_height: f32,
1265        line_height: f32,
1266        cx: &mut ViewContext<Self>,
1267    ) -> bool {
1268        let visible_lines = viewport_height / line_height;
1269        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1270        let mut scroll_position =
1271            compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
1272        let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
1273            (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
1274        } else {
1275            display_map.max_point().row() as f32
1276        };
1277        if scroll_position.y() > max_scroll_top {
1278            scroll_position.set_y(max_scroll_top);
1279            self.set_scroll_position(scroll_position, cx);
1280        }
1281
1282        let (autoscroll, local) = if let Some(autoscroll) = self.autoscroll_request.take() {
1283            autoscroll
1284        } else {
1285            return false;
1286        };
1287
1288        let first_cursor_top;
1289        let last_cursor_bottom;
1290        if let Some(highlighted_rows) = &self.highlighted_rows {
1291            first_cursor_top = highlighted_rows.start as f32;
1292            last_cursor_bottom = first_cursor_top + 1.;
1293        } else if autoscroll == Autoscroll::Newest {
1294            let newest_selection = self.selections.newest::<Point>(cx);
1295            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
1296            last_cursor_bottom = first_cursor_top + 1.;
1297        } else {
1298            let selections = self.selections.all::<Point>(cx);
1299            first_cursor_top = selections
1300                .first()
1301                .unwrap()
1302                .head()
1303                .to_display_point(&display_map)
1304                .row() as f32;
1305            last_cursor_bottom = selections
1306                .last()
1307                .unwrap()
1308                .head()
1309                .to_display_point(&display_map)
1310                .row() as f32
1311                + 1.0;
1312        }
1313
1314        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
1315            0.
1316        } else {
1317            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
1318        };
1319        if margin < 0.0 {
1320            return false;
1321        }
1322
1323        match autoscroll {
1324            Autoscroll::Fit | Autoscroll::Newest => {
1325                let margin = margin.min(self.vertical_scroll_margin);
1326                let target_top = (first_cursor_top - margin).max(0.0);
1327                let target_bottom = last_cursor_bottom + margin;
1328                let start_row = scroll_position.y();
1329                let end_row = start_row + visible_lines;
1330
1331                if target_top < start_row {
1332                    scroll_position.set_y(target_top);
1333                    self.set_scroll_position_internal(scroll_position, local, cx);
1334                } else if target_bottom >= end_row {
1335                    scroll_position.set_y(target_bottom - visible_lines);
1336                    self.set_scroll_position_internal(scroll_position, local, cx);
1337                }
1338            }
1339            Autoscroll::Center => {
1340                scroll_position.set_y((first_cursor_top - margin).max(0.0));
1341                self.set_scroll_position_internal(scroll_position, local, cx);
1342            }
1343        }
1344
1345        true
1346    }
1347
1348    pub fn autoscroll_horizontally(
1349        &mut self,
1350        start_row: u32,
1351        viewport_width: f32,
1352        scroll_width: f32,
1353        max_glyph_width: f32,
1354        layouts: &[text_layout::Line],
1355        cx: &mut ViewContext<Self>,
1356    ) -> bool {
1357        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1358        let selections = self.selections.all::<Point>(cx);
1359
1360        let mut target_left;
1361        let mut target_right;
1362
1363        if self.highlighted_rows.is_some() {
1364            target_left = 0.0_f32;
1365            target_right = 0.0_f32;
1366        } else {
1367            target_left = std::f32::INFINITY;
1368            target_right = 0.0_f32;
1369            for selection in selections {
1370                let head = selection.head().to_display_point(&display_map);
1371                if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
1372                    let start_column = head.column().saturating_sub(3);
1373                    let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
1374                    target_left = target_left.min(
1375                        layouts[(head.row() - start_row) as usize]
1376                            .x_for_index(start_column as usize),
1377                    );
1378                    target_right = target_right.max(
1379                        layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
1380                            + max_glyph_width,
1381                    );
1382                }
1383            }
1384        }
1385
1386        target_right = target_right.min(scroll_width);
1387
1388        if target_right - target_left > viewport_width {
1389            return false;
1390        }
1391
1392        let scroll_left = self.scroll_position.x() * max_glyph_width;
1393        let scroll_right = scroll_left + viewport_width;
1394
1395        if target_left < scroll_left {
1396            self.scroll_position.set_x(target_left / max_glyph_width);
1397            true
1398        } else if target_right > scroll_right {
1399            self.scroll_position
1400                .set_x((target_right - viewport_width) / max_glyph_width);
1401            true
1402        } else {
1403            false
1404        }
1405    }
1406
1407    fn selections_did_change(
1408        &mut self,
1409        local: bool,
1410        old_cursor_position: &Anchor,
1411        cx: &mut ViewContext<Self>,
1412    ) {
1413        if self.focused && self.leader_replica_id.is_none() {
1414            self.buffer.update(cx, |buffer, cx| {
1415                buffer.set_active_selections(
1416                    &self.selections.disjoint_anchors(),
1417                    self.selections.line_mode,
1418                    cx,
1419                )
1420            });
1421        }
1422
1423        let display_map = self
1424            .display_map
1425            .update(cx, |display_map, cx| display_map.snapshot(cx));
1426        let buffer = &display_map.buffer_snapshot;
1427        self.add_selections_state = None;
1428        self.select_next_state = None;
1429        self.select_larger_syntax_node_stack.clear();
1430        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1431        self.snippet_stack
1432            .invalidate(&self.selections.disjoint_anchors(), buffer);
1433        self.take_rename(false, cx);
1434
1435        let new_cursor_position = self.selections.newest_anchor().head();
1436
1437        self.push_to_nav_history(
1438            old_cursor_position.clone(),
1439            Some(new_cursor_position.to_point(buffer)),
1440            cx,
1441        );
1442
1443        if local {
1444            let new_cursor_position = self.selections.newest_anchor().head();
1445            let completion_menu = match self.context_menu.as_mut() {
1446                Some(ContextMenu::Completions(menu)) => Some(menu),
1447                _ => {
1448                    self.context_menu.take();
1449                    None
1450                }
1451            };
1452
1453            if let Some(completion_menu) = completion_menu {
1454                let cursor_position = new_cursor_position.to_offset(buffer);
1455                let (word_range, kind) =
1456                    buffer.surrounding_word(completion_menu.initial_position.clone());
1457                if kind == Some(CharKind::Word)
1458                    && word_range.to_inclusive().contains(&cursor_position)
1459                {
1460                    let query = Self::completion_query(buffer, cursor_position);
1461                    cx.background()
1462                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1463                    self.show_completions(&ShowCompletions, cx);
1464                } else {
1465                    self.hide_context_menu(cx);
1466                }
1467            }
1468
1469            hide_hover(self, cx);
1470
1471            if old_cursor_position.to_display_point(&display_map).row()
1472                != new_cursor_position.to_display_point(&display_map).row()
1473            {
1474                self.available_code_actions.take();
1475            }
1476            self.refresh_code_actions(cx);
1477            self.refresh_document_highlights(cx);
1478            refresh_matching_bracket_highlights(self, cx);
1479        }
1480
1481        self.pause_cursor_blinking(cx);
1482        cx.emit(Event::SelectionsChanged { local });
1483        cx.notify();
1484    }
1485
1486    pub fn change_selections<R>(
1487        &mut self,
1488        autoscroll: Option<Autoscroll>,
1489        cx: &mut ViewContext<Self>,
1490        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1491    ) -> R {
1492        let old_cursor_position = self.selections.newest_anchor().head();
1493        self.push_to_selection_history();
1494
1495        let (changed, result) = self.selections.change_with(cx, change);
1496
1497        if changed {
1498            if let Some(autoscroll) = autoscroll {
1499                self.request_autoscroll(autoscroll, cx);
1500            }
1501            self.selections_did_change(true, &old_cursor_position, cx);
1502        }
1503
1504        result
1505    }
1506
1507    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1508    where
1509        I: IntoIterator<Item = (Range<S>, T)>,
1510        S: ToOffset,
1511        T: Into<Arc<str>>,
1512    {
1513        self.buffer
1514            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1515    }
1516
1517    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1518    where
1519        I: IntoIterator<Item = (Range<S>, T)>,
1520        S: ToOffset,
1521        T: Into<Arc<str>>,
1522    {
1523        self.buffer.update(cx, |buffer, cx| {
1524            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
1525        });
1526    }
1527
1528    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
1529        self.hide_context_menu(cx);
1530
1531        match phase {
1532            SelectPhase::Begin {
1533                position,
1534                add,
1535                click_count,
1536            } => self.begin_selection(*position, *add, *click_count, cx),
1537            SelectPhase::BeginColumnar {
1538                position,
1539                goal_column,
1540            } => self.begin_columnar_selection(*position, *goal_column, cx),
1541            SelectPhase::Extend {
1542                position,
1543                click_count,
1544            } => self.extend_selection(*position, *click_count, cx),
1545            SelectPhase::Update {
1546                position,
1547                goal_column,
1548                scroll_position,
1549            } => self.update_selection(*position, *goal_column, *scroll_position, cx),
1550            SelectPhase::End => self.end_selection(cx),
1551        }
1552    }
1553
1554    fn extend_selection(
1555        &mut self,
1556        position: DisplayPoint,
1557        click_count: usize,
1558        cx: &mut ViewContext<Self>,
1559    ) {
1560        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1561        let tail = self.selections.newest::<usize>(cx).tail();
1562        self.begin_selection(position, false, click_count, cx);
1563
1564        let position = position.to_offset(&display_map, Bias::Left);
1565        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1566
1567        let mut pending_selection = self
1568            .selections
1569            .pending_anchor()
1570            .expect("extend_selection not called with pending selection");
1571        if position >= tail {
1572            pending_selection.start = tail_anchor.clone();
1573        } else {
1574            pending_selection.end = tail_anchor.clone();
1575            pending_selection.reversed = true;
1576        }
1577
1578        let mut pending_mode = self.selections.pending_mode().unwrap();
1579        match &mut pending_mode {
1580            SelectMode::Word(range) | SelectMode::Line(range) => {
1581                *range = tail_anchor.clone()..tail_anchor
1582            }
1583            _ => {}
1584        }
1585
1586        self.change_selections(Some(Autoscroll::Fit), cx, |s| {
1587            s.set_pending(pending_selection, pending_mode)
1588        });
1589    }
1590
1591    fn begin_selection(
1592        &mut self,
1593        position: DisplayPoint,
1594        add: bool,
1595        click_count: usize,
1596        cx: &mut ViewContext<Self>,
1597    ) {
1598        if !self.focused {
1599            cx.focus_self();
1600        }
1601
1602        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1603        let buffer = &display_map.buffer_snapshot;
1604        let newest_selection = self.selections.newest_anchor().clone();
1605        let position = display_map.clip_point(position, Bias::Left);
1606
1607        let start;
1608        let end;
1609        let mode;
1610        let auto_scroll;
1611        match click_count {
1612            1 => {
1613                start = buffer.anchor_before(position.to_point(&display_map));
1614                end = start.clone();
1615                mode = SelectMode::Character;
1616                auto_scroll = true;
1617            }
1618            2 => {
1619                let range = movement::surrounding_word(&display_map, position);
1620                start = buffer.anchor_before(range.start.to_point(&display_map));
1621                end = buffer.anchor_before(range.end.to_point(&display_map));
1622                mode = SelectMode::Word(start.clone()..end.clone());
1623                auto_scroll = true;
1624            }
1625            3 => {
1626                let position = display_map
1627                    .clip_point(position, Bias::Left)
1628                    .to_point(&display_map);
1629                let line_start = display_map.prev_line_boundary(position).0;
1630                let next_line_start = buffer.clip_point(
1631                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1632                    Bias::Left,
1633                );
1634                start = buffer.anchor_before(line_start);
1635                end = buffer.anchor_before(next_line_start);
1636                mode = SelectMode::Line(start.clone()..end.clone());
1637                auto_scroll = true;
1638            }
1639            _ => {
1640                start = buffer.anchor_before(0);
1641                end = buffer.anchor_before(buffer.len());
1642                mode = SelectMode::All;
1643                auto_scroll = false;
1644            }
1645        }
1646
1647        self.change_selections(auto_scroll.then(|| Autoscroll::Newest), cx, |s| {
1648            if !add {
1649                s.clear_disjoint();
1650            } else if click_count > 1 {
1651                s.delete(newest_selection.id)
1652            }
1653
1654            s.set_pending_anchor_range(start..end, mode);
1655        });
1656    }
1657
1658    fn begin_columnar_selection(
1659        &mut self,
1660        position: DisplayPoint,
1661        goal_column: u32,
1662        cx: &mut ViewContext<Self>,
1663    ) {
1664        if !self.focused {
1665            cx.focus_self();
1666        }
1667
1668        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1669        let tail = self.selections.newest::<Point>(cx).tail();
1670        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1671
1672        self.select_columns(
1673            tail.to_display_point(&display_map),
1674            position,
1675            goal_column,
1676            &display_map,
1677            cx,
1678        );
1679    }
1680
1681    fn update_selection(
1682        &mut self,
1683        position: DisplayPoint,
1684        goal_column: u32,
1685        scroll_position: Vector2F,
1686        cx: &mut ViewContext<Self>,
1687    ) {
1688        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1689
1690        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1691            let tail = tail.to_display_point(&display_map);
1692            self.select_columns(tail, position, goal_column, &display_map, cx);
1693        } else if let Some(mut pending) = self.selections.pending_anchor() {
1694            let buffer = self.buffer.read(cx).snapshot(cx);
1695            let head;
1696            let tail;
1697            let mode = self.selections.pending_mode().unwrap();
1698            match &mode {
1699                SelectMode::Character => {
1700                    head = position.to_point(&display_map);
1701                    tail = pending.tail().to_point(&buffer);
1702                }
1703                SelectMode::Word(original_range) => {
1704                    let original_display_range = original_range.start.to_display_point(&display_map)
1705                        ..original_range.end.to_display_point(&display_map);
1706                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1707                        ..original_display_range.end.to_point(&display_map);
1708                    if movement::is_inside_word(&display_map, position)
1709                        || original_display_range.contains(&position)
1710                    {
1711                        let word_range = movement::surrounding_word(&display_map, position);
1712                        if word_range.start < original_display_range.start {
1713                            head = word_range.start.to_point(&display_map);
1714                        } else {
1715                            head = word_range.end.to_point(&display_map);
1716                        }
1717                    } else {
1718                        head = position.to_point(&display_map);
1719                    }
1720
1721                    if head <= original_buffer_range.start {
1722                        tail = original_buffer_range.end;
1723                    } else {
1724                        tail = original_buffer_range.start;
1725                    }
1726                }
1727                SelectMode::Line(original_range) => {
1728                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1729
1730                    let position = display_map
1731                        .clip_point(position, Bias::Left)
1732                        .to_point(&display_map);
1733                    let line_start = display_map.prev_line_boundary(position).0;
1734                    let next_line_start = buffer.clip_point(
1735                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1736                        Bias::Left,
1737                    );
1738
1739                    if line_start < original_range.start {
1740                        head = line_start
1741                    } else {
1742                        head = next_line_start
1743                    }
1744
1745                    if head <= original_range.start {
1746                        tail = original_range.end;
1747                    } else {
1748                        tail = original_range.start;
1749                    }
1750                }
1751                SelectMode::All => {
1752                    return;
1753                }
1754            };
1755
1756            if head < tail {
1757                pending.start = buffer.anchor_before(head);
1758                pending.end = buffer.anchor_before(tail);
1759                pending.reversed = true;
1760            } else {
1761                pending.start = buffer.anchor_before(tail);
1762                pending.end = buffer.anchor_before(head);
1763                pending.reversed = false;
1764            }
1765
1766            self.change_selections(None, cx, |s| {
1767                s.set_pending(pending, mode);
1768            });
1769        } else {
1770            log::error!("update_selection dispatched with no pending selection");
1771            return;
1772        }
1773
1774        self.set_scroll_position(scroll_position, cx);
1775        cx.notify();
1776    }
1777
1778    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1779        self.columnar_selection_tail.take();
1780        if self.selections.pending_anchor().is_some() {
1781            let selections = self.selections.all::<usize>(cx);
1782            self.change_selections(None, cx, |s| {
1783                s.select(selections);
1784                s.clear_pending();
1785            });
1786        }
1787    }
1788
1789    fn select_columns(
1790        &mut self,
1791        tail: DisplayPoint,
1792        head: DisplayPoint,
1793        goal_column: u32,
1794        display_map: &DisplaySnapshot,
1795        cx: &mut ViewContext<Self>,
1796    ) {
1797        let start_row = cmp::min(tail.row(), head.row());
1798        let end_row = cmp::max(tail.row(), head.row());
1799        let start_column = cmp::min(tail.column(), goal_column);
1800        let end_column = cmp::max(tail.column(), goal_column);
1801        let reversed = start_column < tail.column();
1802
1803        let selection_ranges = (start_row..=end_row)
1804            .filter_map(|row| {
1805                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1806                    let start = display_map
1807                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1808                        .to_point(display_map);
1809                    let end = display_map
1810                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1811                        .to_point(display_map);
1812                    if reversed {
1813                        Some(end..start)
1814                    } else {
1815                        Some(start..end)
1816                    }
1817                } else {
1818                    None
1819                }
1820            })
1821            .collect::<Vec<_>>();
1822
1823        self.change_selections(None, cx, |s| {
1824            s.select_ranges(selection_ranges);
1825        });
1826        cx.notify();
1827    }
1828
1829    pub fn has_pending_nonempty_selection(&self) -> bool {
1830        let pending_nonempty_selection = match self.selections.pending_anchor() {
1831            Some(Selection { start, end, .. }) => start != end,
1832            None => false,
1833        };
1834        pending_nonempty_selection || self.columnar_selection_tail.is_some()
1835    }
1836
1837    pub fn has_pending_selection(&self) -> bool {
1838        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1839    }
1840
1841    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1842        if self.take_rename(false, cx).is_some() {
1843            return;
1844        }
1845
1846        if hide_hover(self, cx) {
1847            return;
1848        }
1849
1850        if self.hide_context_menu(cx).is_some() {
1851            return;
1852        }
1853
1854        if self.snippet_stack.pop().is_some() {
1855            return;
1856        }
1857
1858        if self.mode == EditorMode::Full {
1859            if self.active_diagnostics.is_some() {
1860                self.dismiss_diagnostics(cx);
1861                return;
1862            }
1863
1864            if self.change_selections(Some(Autoscroll::Fit), cx, |s| s.try_cancel()) {
1865                return;
1866            }
1867        }
1868
1869        cx.propagate_action();
1870    }
1871
1872    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1873        if !self.input_enabled {
1874            return;
1875        }
1876
1877        let text: Arc<str> = text.into();
1878        let selections = self.selections.all_adjusted(cx);
1879        let mut edits = Vec::new();
1880        let mut new_selections = Vec::with_capacity(selections.len());
1881        let mut new_autoclose_regions = Vec::new();
1882        let snapshot = self.buffer.read(cx).read(cx);
1883
1884        for (selection, autoclose_region) in
1885            self.selections_with_autoclose_regions(selections, &snapshot)
1886        {
1887            if let Some(language) = snapshot.language_at(selection.head()) {
1888                // Determine if the inserted text matches the opening or closing
1889                // bracket of any of this language's bracket pairs.
1890                let mut bracket_pair = None;
1891                let mut is_bracket_pair_start = false;
1892                for pair in language.brackets() {
1893                    if pair.close && pair.start.ends_with(text.as_ref()) {
1894                        bracket_pair = Some(pair.clone());
1895                        is_bracket_pair_start = true;
1896                        break;
1897                    } else if pair.end.as_str() == text.as_ref() {
1898                        bracket_pair = Some(pair.clone());
1899                        break;
1900                    }
1901                }
1902
1903                if let Some(bracket_pair) = bracket_pair {
1904                    if selection.is_empty() {
1905                        if is_bracket_pair_start {
1906                            let prefix_len = bracket_pair.start.len() - text.len();
1907
1908                            // If the inserted text is a suffix of an opening bracket and the
1909                            // selection is preceded by the rest of the opening bracket, then
1910                            // insert the closing bracket.
1911                            let following_text_allows_autoclose = snapshot
1912                                .chars_at(selection.start)
1913                                .next()
1914                                .map_or(true, |c| language.should_autoclose_before(c));
1915                            let preceding_text_matches_prefix = prefix_len == 0
1916                                || (selection.start.column >= (prefix_len as u32)
1917                                    && snapshot.contains_str_at(
1918                                        Point::new(
1919                                            selection.start.row,
1920                                            selection.start.column - (prefix_len as u32),
1921                                        ),
1922                                        &bracket_pair.start[..prefix_len],
1923                                    ));
1924                            if following_text_allows_autoclose && preceding_text_matches_prefix {
1925                                let anchor = snapshot.anchor_before(selection.end);
1926                                new_selections
1927                                    .push((selection.map(|_| anchor.clone()), text.len()));
1928                                new_autoclose_regions.push((
1929                                    anchor.clone(),
1930                                    text.len(),
1931                                    selection.id,
1932                                    bracket_pair.clone(),
1933                                ));
1934                                edits.push((
1935                                    selection.range(),
1936                                    format!("{}{}", text, bracket_pair.end).into(),
1937                                ));
1938                                continue;
1939                            }
1940                        } else if let Some(region) = autoclose_region {
1941                            // If the selection is followed by an auto-inserted closing bracket,
1942                            // then don't insert anything else; just move the selection past the
1943                            // closing bracket.
1944                            let should_skip = selection.end == region.range.end.to_point(&snapshot);
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(None, 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())
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).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}