editor.rs

    1pub mod display_map;
    2mod element;
    3pub mod items;
    4pub mod movement;
    5mod multi_buffer;
    6
    7#[cfg(test)]
    8mod test;
    9
   10use aho_corasick::AhoCorasick;
   11use anyhow::Result;
   12use clock::ReplicaId;
   13use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   14pub use display_map::DisplayPoint;
   15use display_map::*;
   16pub use element::*;
   17use fuzzy::{StringMatch, StringMatchCandidate};
   18use gpui::{
   19    actions,
   20    color::Color,
   21    elements::*,
   22    executor,
   23    fonts::{self, HighlightStyle, TextStyle},
   24    geometry::vector::{vec2f, Vector2F},
   25    impl_actions, impl_internal_actions,
   26    platform::CursorStyle,
   27    text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
   28    ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
   29    WeakViewHandle,
   30};
   31use itertools::Itertools as _;
   32pub use language::{char_kind, CharKind};
   33use language::{
   34    BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticSeverity,
   35    Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
   36};
   37use multi_buffer::MultiBufferChunks;
   38pub use multi_buffer::{
   39    Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
   40};
   41use ordered_float::OrderedFloat;
   42use project::{Project, ProjectTransaction};
   43use serde::{Deserialize, Serialize};
   44use settings::Settings;
   45use smallvec::SmallVec;
   46use smol::Timer;
   47use snippet::Snippet;
   48use std::{
   49    any::TypeId,
   50    borrow::Cow,
   51    cmp::{self, Ordering, Reverse},
   52    iter::{self, FromIterator},
   53    mem,
   54    ops::{Deref, DerefMut, Range, RangeInclusive, Sub},
   55    sync::Arc,
   56    time::{Duration, Instant},
   57};
   58pub use sum_tree::Bias;
   59use text::rope::TextDimension;
   60use theme::{DiagnosticStyle, Theme};
   61use util::{post_inc, ResultExt, TryFutureExt};
   62use workspace::{ItemNavHistory, Workspace};
   63
   64const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
   65const MAX_LINE_LEN: usize = 1024;
   66const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
   67const MAX_SELECTION_HISTORY_LEN: usize = 1024;
   68
   69#[derive(Clone, Deserialize)]
   70pub struct SelectNext {
   71    #[serde(default)]
   72    pub replace_newest: bool,
   73}
   74
   75#[derive(Clone)]
   76pub struct GoToDiagnostic(pub Direction);
   77
   78#[derive(Clone)]
   79pub struct Scroll(pub Vector2F);
   80
   81#[derive(Clone)]
   82pub struct Select(pub SelectPhase);
   83
   84#[derive(Clone, Deserialize)]
   85pub struct Input(pub String);
   86
   87#[derive(Clone, Deserialize)]
   88pub struct SelectToBeginningOfLine {
   89    #[serde(default)]
   90    stop_at_soft_wraps: bool,
   91}
   92
   93#[derive(Clone, Deserialize)]
   94pub struct SelectToEndOfLine {
   95    #[serde(default)]
   96    stop_at_soft_wraps: bool,
   97}
   98
   99#[derive(Clone, Deserialize)]
  100pub struct ToggleCodeActions {
  101    #[serde(default)]
  102    pub deployed_from_indicator: bool,
  103}
  104
  105#[derive(Clone, Default, Deserialize)]
  106pub struct ConfirmCompletion {
  107    #[serde(default)]
  108    pub item_ix: Option<usize>,
  109}
  110
  111#[derive(Clone, Default, Deserialize)]
  112pub struct ConfirmCodeAction {
  113    #[serde(default)]
  114    pub item_ix: Option<usize>,
  115}
  116
  117actions!(
  118    editor,
  119    [
  120        Cancel,
  121        Backspace,
  122        Delete,
  123        Newline,
  124        GoToNextDiagnostic,
  125        GoToPrevDiagnostic,
  126        Indent,
  127        Outdent,
  128        DeleteLine,
  129        DeleteToPreviousWordStart,
  130        DeleteToPreviousSubwordStart,
  131        DeleteToNextWordEnd,
  132        DeleteToNextSubwordEnd,
  133        DeleteToBeginningOfLine,
  134        DeleteToEndOfLine,
  135        CutToEndOfLine,
  136        DuplicateLine,
  137        MoveLineUp,
  138        MoveLineDown,
  139        Transpose,
  140        Cut,
  141        Copy,
  142        Paste,
  143        Undo,
  144        Redo,
  145        MoveUp,
  146        MoveDown,
  147        MoveLeft,
  148        MoveRight,
  149        MoveToPreviousWordStart,
  150        MoveToPreviousSubwordStart,
  151        MoveToNextWordEnd,
  152        MoveToNextSubwordEnd,
  153        MoveToBeginningOfLine,
  154        MoveToEndOfLine,
  155        MoveToBeginning,
  156        MoveToEnd,
  157        SelectUp,
  158        SelectDown,
  159        SelectLeft,
  160        SelectRight,
  161        SelectToPreviousWordStart,
  162        SelectToPreviousSubwordStart,
  163        SelectToNextWordEnd,
  164        SelectToNextSubwordEnd,
  165        SelectToBeginning,
  166        SelectToEnd,
  167        SelectAll,
  168        SelectLine,
  169        SplitSelectionIntoLines,
  170        AddSelectionAbove,
  171        AddSelectionBelow,
  172        Tab,
  173        TabPrev,
  174        ToggleComments,
  175        SelectLargerSyntaxNode,
  176        SelectSmallerSyntaxNode,
  177        MoveToEnclosingBracket,
  178        UndoSelection,
  179        RedoSelection,
  180        GoToDefinition,
  181        FindAllReferences,
  182        Rename,
  183        ConfirmRename,
  184        PageUp,
  185        PageDown,
  186        Fold,
  187        UnfoldLines,
  188        FoldSelectedRanges,
  189        ShowCompletions,
  190        OpenExcerpts,
  191        RestartLanguageServer,
  192    ]
  193);
  194
  195impl_actions!(
  196    editor,
  197    [
  198        Input,
  199        SelectNext,
  200        SelectToBeginningOfLine,
  201        SelectToEndOfLine,
  202        ToggleCodeActions,
  203        ConfirmCompletion,
  204        ConfirmCodeAction,
  205    ]
  206);
  207
  208impl_internal_actions!(editor, [Scroll, Select]);
  209
  210enum DocumentHighlightRead {}
  211enum DocumentHighlightWrite {}
  212
  213#[derive(Copy, Clone, PartialEq, Eq)]
  214pub enum Direction {
  215    Prev,
  216    Next,
  217}
  218
  219pub fn init(cx: &mut MutableAppContext) {
  220    cx.add_action(Editor::open_new);
  221    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
  222    cx.add_action(Editor::select);
  223    cx.add_action(Editor::cancel);
  224    cx.add_action(Editor::handle_input);
  225    cx.add_action(Editor::newline);
  226    cx.add_action(Editor::backspace);
  227    cx.add_action(Editor::delete);
  228    cx.add_action(Editor::tab);
  229    cx.add_action(Editor::tab_prev);
  230    cx.add_action(Editor::indent);
  231    cx.add_action(Editor::outdent);
  232    cx.add_action(Editor::delete_line);
  233    cx.add_action(Editor::delete_to_previous_word_start);
  234    cx.add_action(Editor::delete_to_previous_subword_start);
  235    cx.add_action(Editor::delete_to_next_word_end);
  236    cx.add_action(Editor::delete_to_next_subword_end);
  237    cx.add_action(Editor::delete_to_beginning_of_line);
  238    cx.add_action(Editor::delete_to_end_of_line);
  239    cx.add_action(Editor::cut_to_end_of_line);
  240    cx.add_action(Editor::duplicate_line);
  241    cx.add_action(Editor::move_line_up);
  242    cx.add_action(Editor::move_line_down);
  243    cx.add_action(Editor::transpose);
  244    cx.add_action(Editor::cut);
  245    cx.add_action(Editor::copy);
  246    cx.add_action(Editor::paste);
  247    cx.add_action(Editor::undo);
  248    cx.add_action(Editor::redo);
  249    cx.add_action(Editor::move_up);
  250    cx.add_action(Editor::move_down);
  251    cx.add_action(Editor::move_left);
  252    cx.add_action(Editor::move_right);
  253    cx.add_action(Editor::move_to_previous_word_start);
  254    cx.add_action(Editor::move_to_previous_subword_start);
  255    cx.add_action(Editor::move_to_next_word_end);
  256    cx.add_action(Editor::move_to_next_subword_end);
  257    cx.add_action(Editor::move_to_beginning_of_line);
  258    cx.add_action(Editor::move_to_end_of_line);
  259    cx.add_action(Editor::move_to_beginning);
  260    cx.add_action(Editor::move_to_end);
  261    cx.add_action(Editor::select_up);
  262    cx.add_action(Editor::select_down);
  263    cx.add_action(Editor::select_left);
  264    cx.add_action(Editor::select_right);
  265    cx.add_action(Editor::select_to_previous_word_start);
  266    cx.add_action(Editor::select_to_previous_subword_start);
  267    cx.add_action(Editor::select_to_next_word_end);
  268    cx.add_action(Editor::select_to_next_subword_end);
  269    cx.add_action(Editor::select_to_beginning_of_line);
  270    cx.add_action(Editor::select_to_end_of_line);
  271    cx.add_action(Editor::select_to_beginning);
  272    cx.add_action(Editor::select_to_end);
  273    cx.add_action(Editor::select_all);
  274    cx.add_action(Editor::select_line);
  275    cx.add_action(Editor::split_selection_into_lines);
  276    cx.add_action(Editor::add_selection_above);
  277    cx.add_action(Editor::add_selection_below);
  278    cx.add_action(Editor::select_next);
  279    cx.add_action(Editor::toggle_comments);
  280    cx.add_action(Editor::select_larger_syntax_node);
  281    cx.add_action(Editor::select_smaller_syntax_node);
  282    cx.add_action(Editor::move_to_enclosing_bracket);
  283    cx.add_action(Editor::undo_selection);
  284    cx.add_action(Editor::redo_selection);
  285    cx.add_action(Editor::go_to_next_diagnostic);
  286    cx.add_action(Editor::go_to_prev_diagnostic);
  287    cx.add_action(Editor::go_to_definition);
  288    cx.add_action(Editor::page_up);
  289    cx.add_action(Editor::page_down);
  290    cx.add_action(Editor::fold);
  291    cx.add_action(Editor::unfold_lines);
  292    cx.add_action(Editor::fold_selected_ranges);
  293    cx.add_action(Editor::show_completions);
  294    cx.add_action(Editor::toggle_code_actions);
  295    cx.add_action(Editor::open_excerpts);
  296    cx.add_action(Editor::restart_language_server);
  297    cx.add_async_action(Editor::confirm_completion);
  298    cx.add_async_action(Editor::confirm_code_action);
  299    cx.add_async_action(Editor::rename);
  300    cx.add_async_action(Editor::confirm_rename);
  301    cx.add_async_action(Editor::find_all_references);
  302
  303    workspace::register_project_item::<Editor>(cx);
  304    workspace::register_followable_item::<Editor>(cx);
  305}
  306
  307trait InvalidationRegion {
  308    fn ranges(&self) -> &[Range<Anchor>];
  309}
  310
  311#[derive(Clone, Debug)]
  312pub enum SelectPhase {
  313    Begin {
  314        position: DisplayPoint,
  315        add: bool,
  316        click_count: usize,
  317    },
  318    BeginColumnar {
  319        position: DisplayPoint,
  320        overshoot: u32,
  321    },
  322    Extend {
  323        position: DisplayPoint,
  324        click_count: usize,
  325    },
  326    Update {
  327        position: DisplayPoint,
  328        overshoot: u32,
  329        scroll_position: Vector2F,
  330    },
  331    End,
  332}
  333
  334#[derive(Clone, Debug)]
  335pub enum SelectMode {
  336    Character,
  337    Word(Range<Anchor>),
  338    Line(Range<Anchor>),
  339    All,
  340}
  341
  342#[derive(PartialEq, Eq)]
  343pub enum Autoscroll {
  344    Fit,
  345    Center,
  346    Newest,
  347}
  348
  349#[derive(Copy, Clone, PartialEq, Eq)]
  350pub enum EditorMode {
  351    SingleLine,
  352    AutoHeight { max_lines: usize },
  353    Full,
  354}
  355
  356#[derive(Clone)]
  357pub enum SoftWrap {
  358    None,
  359    EditorWidth,
  360    Column(u32),
  361}
  362
  363#[derive(Clone)]
  364pub struct EditorStyle {
  365    pub text: TextStyle,
  366    pub placeholder_text: Option<TextStyle>,
  367    pub theme: theme::Editor,
  368}
  369
  370type CompletionId = usize;
  371
  372pub type GetFieldEditorTheme = fn(&theme::Theme) -> theme::FieldEditor;
  373
  374type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  375
  376pub struct Editor {
  377    handle: WeakViewHandle<Self>,
  378    buffer: ModelHandle<MultiBuffer>,
  379    display_map: ModelHandle<DisplayMap>,
  380    next_selection_id: usize,
  381    selections: Arc<[Selection<Anchor>]>,
  382    pending_selection: Option<PendingSelection>,
  383    columnar_selection_tail: Option<Anchor>,
  384    add_selections_state: Option<AddSelectionsState>,
  385    select_next_state: Option<SelectNextState>,
  386    selection_history: SelectionHistory,
  387    autoclose_stack: InvalidationStack<BracketPairState>,
  388    snippet_stack: InvalidationStack<SnippetState>,
  389    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  390    active_diagnostics: Option<ActiveDiagnosticGroup>,
  391    scroll_position: Vector2F,
  392    scroll_top_anchor: Anchor,
  393    autoscroll_request: Option<(Autoscroll, bool)>,
  394    soft_wrap_mode_override: Option<settings::SoftWrap>,
  395    get_field_editor_theme: Option<GetFieldEditorTheme>,
  396    override_text_style: Option<Box<OverrideTextStyle>>,
  397    project: Option<ModelHandle<Project>>,
  398    focused: bool,
  399    show_local_cursors: bool,
  400    show_local_selections: bool,
  401    blink_epoch: usize,
  402    blinking_paused: bool,
  403    mode: EditorMode,
  404    vertical_scroll_margin: f32,
  405    placeholder_text: Option<Arc<str>>,
  406    highlighted_rows: Option<Range<u32>>,
  407    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
  408    nav_history: Option<ItemNavHistory>,
  409    context_menu: Option<ContextMenu>,
  410    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  411    next_completion_id: CompletionId,
  412    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
  413    code_actions_task: Option<Task<()>>,
  414    document_highlights_task: Option<Task<()>>,
  415    pending_rename: Option<RenameState>,
  416    searchable: bool,
  417    cursor_shape: CursorShape,
  418    keymap_context_layers: BTreeMap<TypeId, gpui::keymap::Context>,
  419    input_enabled: bool,
  420    leader_replica_id: Option<u16>,
  421}
  422
  423pub struct EditorSnapshot {
  424    pub mode: EditorMode,
  425    pub display_snapshot: DisplaySnapshot,
  426    pub placeholder_text: Option<Arc<str>>,
  427    is_focused: bool,
  428    scroll_position: Vector2F,
  429    scroll_top_anchor: Anchor,
  430}
  431
  432#[derive(Clone)]
  433pub struct PendingSelection {
  434    selection: Selection<Anchor>,
  435    mode: SelectMode,
  436}
  437
  438#[derive(Clone)]
  439struct SelectionHistoryEntry {
  440    selections: Arc<[Selection<Anchor>]>,
  441    select_next_state: Option<SelectNextState>,
  442    add_selections_state: Option<AddSelectionsState>,
  443}
  444
  445enum SelectionHistoryMode {
  446    Normal,
  447    Undoing,
  448    Redoing,
  449}
  450
  451impl Default for SelectionHistoryMode {
  452    fn default() -> Self {
  453        Self::Normal
  454    }
  455}
  456
  457#[derive(Default)]
  458struct SelectionHistory {
  459    selections_by_transaction:
  460        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  461    mode: SelectionHistoryMode,
  462    undo_stack: VecDeque<SelectionHistoryEntry>,
  463    redo_stack: VecDeque<SelectionHistoryEntry>,
  464}
  465
  466impl SelectionHistory {
  467    fn insert_transaction(
  468        &mut self,
  469        transaction_id: TransactionId,
  470        selections: Arc<[Selection<Anchor>]>,
  471    ) {
  472        self.selections_by_transaction
  473            .insert(transaction_id, (selections, None));
  474    }
  475
  476    fn transaction(
  477        &self,
  478        transaction_id: TransactionId,
  479    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  480        self.selections_by_transaction.get(&transaction_id)
  481    }
  482
  483    fn transaction_mut(
  484        &mut self,
  485        transaction_id: TransactionId,
  486    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  487        self.selections_by_transaction.get_mut(&transaction_id)
  488    }
  489
  490    fn push(&mut self, entry: SelectionHistoryEntry) {
  491        if !entry.selections.is_empty() {
  492            match self.mode {
  493                SelectionHistoryMode::Normal => {
  494                    self.push_undo(entry);
  495                    self.redo_stack.clear();
  496                }
  497                SelectionHistoryMode::Undoing => self.push_redo(entry),
  498                SelectionHistoryMode::Redoing => self.push_undo(entry),
  499            }
  500        }
  501    }
  502
  503    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  504        if self
  505            .undo_stack
  506            .back()
  507            .map_or(true, |e| e.selections != entry.selections)
  508        {
  509            self.undo_stack.push_back(entry);
  510            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  511                self.undo_stack.pop_front();
  512            }
  513        }
  514    }
  515
  516    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  517        if self
  518            .redo_stack
  519            .back()
  520            .map_or(true, |e| e.selections != entry.selections)
  521        {
  522            self.redo_stack.push_back(entry);
  523            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  524                self.redo_stack.pop_front();
  525            }
  526        }
  527    }
  528}
  529
  530#[derive(Clone)]
  531struct AddSelectionsState {
  532    above: bool,
  533    stack: Vec<usize>,
  534}
  535
  536#[derive(Clone)]
  537struct SelectNextState {
  538    query: AhoCorasick,
  539    wordwise: bool,
  540    done: bool,
  541}
  542
  543struct BracketPairState {
  544    ranges: Vec<Range<Anchor>>,
  545    pair: BracketPair,
  546}
  547
  548struct SnippetState {
  549    ranges: Vec<Vec<Range<Anchor>>>,
  550    active_index: usize,
  551}
  552
  553pub struct RenameState {
  554    pub range: Range<Anchor>,
  555    pub old_name: Arc<str>,
  556    pub editor: ViewHandle<Editor>,
  557    block_id: BlockId,
  558}
  559
  560struct InvalidationStack<T>(Vec<T>);
  561
  562enum ContextMenu {
  563    Completions(CompletionsMenu),
  564    CodeActions(CodeActionsMenu),
  565}
  566
  567impl ContextMenu {
  568    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
  569        if self.visible() {
  570            match self {
  571                ContextMenu::Completions(menu) => menu.select_prev(cx),
  572                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  573            }
  574            true
  575        } else {
  576            false
  577        }
  578    }
  579
  580    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
  581        if self.visible() {
  582            match self {
  583                ContextMenu::Completions(menu) => menu.select_next(cx),
  584                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  585            }
  586            true
  587        } else {
  588            false
  589        }
  590    }
  591
  592    fn visible(&self) -> bool {
  593        match self {
  594            ContextMenu::Completions(menu) => menu.visible(),
  595            ContextMenu::CodeActions(menu) => menu.visible(),
  596        }
  597    }
  598
  599    fn render(
  600        &self,
  601        cursor_position: DisplayPoint,
  602        style: EditorStyle,
  603        cx: &AppContext,
  604    ) -> (DisplayPoint, ElementBox) {
  605        match self {
  606            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
  607            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style),
  608        }
  609    }
  610}
  611
  612struct CompletionsMenu {
  613    id: CompletionId,
  614    initial_position: Anchor,
  615    buffer: ModelHandle<Buffer>,
  616    completions: Arc<[Completion]>,
  617    match_candidates: Vec<StringMatchCandidate>,
  618    matches: Arc<[StringMatch]>,
  619    selected_item: usize,
  620    list: UniformListState,
  621}
  622
  623impl CompletionsMenu {
  624    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
  625        if self.selected_item > 0 {
  626            self.selected_item -= 1;
  627            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  628        }
  629        cx.notify();
  630    }
  631
  632    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
  633        if self.selected_item + 1 < self.matches.len() {
  634            self.selected_item += 1;
  635            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  636        }
  637        cx.notify();
  638    }
  639
  640    fn visible(&self) -> bool {
  641        !self.matches.is_empty()
  642    }
  643
  644    fn render(&self, style: EditorStyle, _: &AppContext) -> ElementBox {
  645        enum CompletionTag {}
  646
  647        let completions = self.completions.clone();
  648        let matches = self.matches.clone();
  649        let selected_item = self.selected_item;
  650        let container_style = style.autocomplete.container;
  651        UniformList::new(self.list.clone(), matches.len(), move |range, items, cx| {
  652            let start_ix = range.start;
  653            for (ix, mat) in matches[range].iter().enumerate() {
  654                let completion = &completions[mat.candidate_id];
  655                let item_ix = start_ix + ix;
  656                items.push(
  657                    MouseEventHandler::new::<CompletionTag, _, _>(
  658                        mat.candidate_id,
  659                        cx,
  660                        |state, _| {
  661                            let item_style = if item_ix == selected_item {
  662                                style.autocomplete.selected_item
  663                            } else if state.hovered {
  664                                style.autocomplete.hovered_item
  665                            } else {
  666                                style.autocomplete.item
  667                            };
  668
  669                            Text::new(completion.label.text.clone(), style.text.clone())
  670                                .with_soft_wrap(false)
  671                                .with_highlights(combine_syntax_and_fuzzy_match_highlights(
  672                                    &completion.label.text,
  673                                    style.text.color.into(),
  674                                    styled_runs_for_code_label(&completion.label, &style.syntax),
  675                                    &mat.positions,
  676                                ))
  677                                .contained()
  678                                .with_style(item_style)
  679                                .boxed()
  680                        },
  681                    )
  682                    .with_cursor_style(CursorStyle::PointingHand)
  683                    .on_mouse_down(move |cx| {
  684                        cx.dispatch_action(ConfirmCompletion {
  685                            item_ix: Some(item_ix),
  686                        });
  687                    })
  688                    .boxed(),
  689                );
  690            }
  691        })
  692        .with_width_from_item(
  693            self.matches
  694                .iter()
  695                .enumerate()
  696                .max_by_key(|(_, mat)| {
  697                    self.completions[mat.candidate_id]
  698                        .label
  699                        .text
  700                        .chars()
  701                        .count()
  702                })
  703                .map(|(ix, _)| ix),
  704        )
  705        .contained()
  706        .with_style(container_style)
  707        .boxed()
  708    }
  709
  710    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
  711        let mut matches = if let Some(query) = query {
  712            fuzzy::match_strings(
  713                &self.match_candidates,
  714                query,
  715                false,
  716                100,
  717                &Default::default(),
  718                executor,
  719            )
  720            .await
  721        } else {
  722            self.match_candidates
  723                .iter()
  724                .enumerate()
  725                .map(|(candidate_id, candidate)| StringMatch {
  726                    candidate_id,
  727                    score: Default::default(),
  728                    positions: Default::default(),
  729                    string: candidate.string.clone(),
  730                })
  731                .collect()
  732        };
  733        matches.sort_unstable_by_key(|mat| {
  734            (
  735                Reverse(OrderedFloat(mat.score)),
  736                self.completions[mat.candidate_id].sort_key(),
  737            )
  738        });
  739
  740        for mat in &mut matches {
  741            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
  742            for position in &mut mat.positions {
  743                *position += filter_start;
  744            }
  745        }
  746
  747        self.matches = matches.into();
  748    }
  749}
  750
  751#[derive(Clone)]
  752struct CodeActionsMenu {
  753    actions: Arc<[CodeAction]>,
  754    buffer: ModelHandle<Buffer>,
  755    selected_item: usize,
  756    list: UniformListState,
  757    deployed_from_indicator: bool,
  758}
  759
  760impl CodeActionsMenu {
  761    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
  762        if self.selected_item > 0 {
  763            self.selected_item -= 1;
  764            cx.notify()
  765        }
  766    }
  767
  768    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
  769        if self.selected_item + 1 < self.actions.len() {
  770            self.selected_item += 1;
  771            cx.notify()
  772        }
  773    }
  774
  775    fn visible(&self) -> bool {
  776        !self.actions.is_empty()
  777    }
  778
  779    fn render(
  780        &self,
  781        mut cursor_position: DisplayPoint,
  782        style: EditorStyle,
  783    ) -> (DisplayPoint, ElementBox) {
  784        enum ActionTag {}
  785
  786        let container_style = style.autocomplete.container;
  787        let actions = self.actions.clone();
  788        let selected_item = self.selected_item;
  789        let element =
  790            UniformList::new(self.list.clone(), actions.len(), move |range, items, cx| {
  791                let start_ix = range.start;
  792                for (ix, action) in actions[range].iter().enumerate() {
  793                    let item_ix = start_ix + ix;
  794                    items.push(
  795                        MouseEventHandler::new::<ActionTag, _, _>(item_ix, cx, |state, _| {
  796                            let item_style = if item_ix == selected_item {
  797                                style.autocomplete.selected_item
  798                            } else if state.hovered {
  799                                style.autocomplete.hovered_item
  800                            } else {
  801                                style.autocomplete.item
  802                            };
  803
  804                            Text::new(action.lsp_action.title.clone(), style.text.clone())
  805                                .with_soft_wrap(false)
  806                                .contained()
  807                                .with_style(item_style)
  808                                .boxed()
  809                        })
  810                        .with_cursor_style(CursorStyle::PointingHand)
  811                        .on_mouse_down(move |cx| {
  812                            cx.dispatch_action(ConfirmCodeAction {
  813                                item_ix: Some(item_ix),
  814                            });
  815                        })
  816                        .boxed(),
  817                    );
  818                }
  819            })
  820            .with_width_from_item(
  821                self.actions
  822                    .iter()
  823                    .enumerate()
  824                    .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
  825                    .map(|(ix, _)| ix),
  826            )
  827            .contained()
  828            .with_style(container_style)
  829            .boxed();
  830
  831        if self.deployed_from_indicator {
  832            *cursor_position.column_mut() = 0;
  833        }
  834
  835        (cursor_position, element)
  836    }
  837}
  838
  839#[derive(Debug)]
  840struct ActiveDiagnosticGroup {
  841    primary_range: Range<Anchor>,
  842    primary_message: String,
  843    blocks: HashMap<BlockId, Diagnostic>,
  844    is_valid: bool,
  845}
  846
  847#[derive(Serialize, Deserialize)]
  848struct ClipboardSelection {
  849    len: usize,
  850    is_entire_line: bool,
  851}
  852
  853#[derive(Debug)]
  854pub struct NavigationData {
  855    // Matching offsets for anchor and scroll_top_anchor allows us to recreate the anchor if the buffer
  856    // has since been closed
  857    cursor_anchor: Anchor,
  858    cursor_position: Point,
  859    scroll_position: Vector2F,
  860    scroll_top_anchor: Anchor,
  861    scroll_top_row: u32,
  862}
  863
  864pub struct EditorCreated(pub ViewHandle<Editor>);
  865
  866impl Editor {
  867    pub fn single_line(
  868        field_editor_style: Option<GetFieldEditorTheme>,
  869        cx: &mut ViewContext<Self>,
  870    ) -> Self {
  871        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
  872        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  873        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
  874    }
  875
  876    pub fn auto_height(
  877        max_lines: usize,
  878        field_editor_style: Option<GetFieldEditorTheme>,
  879        cx: &mut ViewContext<Self>,
  880    ) -> Self {
  881        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
  882        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  883        Self::new(
  884            EditorMode::AutoHeight { max_lines },
  885            buffer,
  886            None,
  887            field_editor_style,
  888            cx,
  889        )
  890    }
  891
  892    pub fn for_buffer(
  893        buffer: ModelHandle<Buffer>,
  894        project: Option<ModelHandle<Project>>,
  895        cx: &mut ViewContext<Self>,
  896    ) -> Self {
  897        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
  898        Self::new(EditorMode::Full, buffer, project, None, cx)
  899    }
  900
  901    pub fn for_multibuffer(
  902        buffer: ModelHandle<MultiBuffer>,
  903        project: Option<ModelHandle<Project>>,
  904        cx: &mut ViewContext<Self>,
  905    ) -> Self {
  906        Self::new(EditorMode::Full, buffer, project, None, cx)
  907    }
  908
  909    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
  910        let mut clone = Self::new(
  911            self.mode,
  912            self.buffer.clone(),
  913            self.project.clone(),
  914            self.get_field_editor_theme,
  915            cx,
  916        );
  917        clone.scroll_position = self.scroll_position;
  918        clone.scroll_top_anchor = self.scroll_top_anchor.clone();
  919        clone.searchable = self.searchable;
  920        clone
  921    }
  922
  923    fn new(
  924        mode: EditorMode,
  925        buffer: ModelHandle<MultiBuffer>,
  926        project: Option<ModelHandle<Project>>,
  927        get_field_editor_theme: Option<GetFieldEditorTheme>,
  928        cx: &mut ViewContext<Self>,
  929    ) -> Self {
  930        let display_map = cx.add_model(|cx| {
  931            let settings = cx.global::<Settings>();
  932            let style = build_style(&*settings, get_field_editor_theme, None, cx);
  933            DisplayMap::new(
  934                buffer.clone(),
  935                style.text.font_id,
  936                style.text.font_size,
  937                None,
  938                2,
  939                1,
  940                cx,
  941            )
  942        });
  943        cx.observe(&buffer, Self::on_buffer_changed).detach();
  944        cx.subscribe(&buffer, Self::on_buffer_event).detach();
  945        cx.observe(&display_map, Self::on_display_map_changed)
  946            .detach();
  947
  948        let mut this = Self {
  949            handle: cx.weak_handle(),
  950            buffer,
  951            display_map,
  952            selections: Arc::from([]),
  953            pending_selection: Some(PendingSelection {
  954                selection: Selection {
  955                    id: 0,
  956                    start: Anchor::min(),
  957                    end: Anchor::min(),
  958                    reversed: false,
  959                    goal: SelectionGoal::None,
  960                },
  961                mode: SelectMode::Character,
  962            }),
  963            columnar_selection_tail: None,
  964            next_selection_id: 1,
  965            add_selections_state: None,
  966            select_next_state: None,
  967            selection_history: Default::default(),
  968            autoclose_stack: Default::default(),
  969            snippet_stack: Default::default(),
  970            select_larger_syntax_node_stack: Vec::new(),
  971            active_diagnostics: None,
  972            soft_wrap_mode_override: None,
  973            get_field_editor_theme,
  974            project,
  975            scroll_position: Vector2F::zero(),
  976            scroll_top_anchor: Anchor::min(),
  977            autoscroll_request: None,
  978            focused: false,
  979            show_local_cursors: false,
  980            show_local_selections: true,
  981            blink_epoch: 0,
  982            blinking_paused: false,
  983            mode,
  984            vertical_scroll_margin: 3.0,
  985            placeholder_text: None,
  986            highlighted_rows: None,
  987            background_highlights: Default::default(),
  988            nav_history: None,
  989            context_menu: None,
  990            completion_tasks: Default::default(),
  991            next_completion_id: 0,
  992            available_code_actions: Default::default(),
  993            code_actions_task: Default::default(),
  994            document_highlights_task: Default::default(),
  995            pending_rename: Default::default(),
  996            searchable: true,
  997            override_text_style: None,
  998            cursor_shape: Default::default(),
  999            keymap_context_layers: Default::default(),
 1000            input_enabled: true,
 1001            leader_replica_id: None,
 1002        };
 1003        this.end_selection(cx);
 1004
 1005        let editor_created_event = EditorCreated(cx.handle());
 1006        cx.emit_global(editor_created_event);
 1007
 1008        this
 1009    }
 1010
 1011    pub fn open_new(
 1012        workspace: &mut Workspace,
 1013        _: &workspace::OpenNew,
 1014        cx: &mut ViewContext<Workspace>,
 1015    ) {
 1016        let project = workspace.project().clone();
 1017        if project.read(cx).is_remote() {
 1018            cx.propagate_action();
 1019        } else if let Some(buffer) = project
 1020            .update(cx, |project, cx| project.create_buffer("", None, cx))
 1021            .log_err()
 1022        {
 1023            workspace.add_item(
 1024                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 1025                cx,
 1026            );
 1027        }
 1028    }
 1029
 1030    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 1031        self.buffer.read(cx).replica_id()
 1032    }
 1033
 1034    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
 1035        &self.buffer
 1036    }
 1037
 1038    pub fn title(&self, cx: &AppContext) -> String {
 1039        self.buffer().read(cx).title(cx)
 1040    }
 1041
 1042    pub fn snapshot(&mut self, cx: &mut MutableAppContext) -> EditorSnapshot {
 1043        EditorSnapshot {
 1044            mode: self.mode,
 1045            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1046            scroll_position: self.scroll_position,
 1047            scroll_top_anchor: self.scroll_top_anchor.clone(),
 1048            placeholder_text: self.placeholder_text.clone(),
 1049            is_focused: self
 1050                .handle
 1051                .upgrade(cx)
 1052                .map_or(false, |handle| handle.is_focused(cx)),
 1053        }
 1054    }
 1055
 1056    pub fn language_at<'a, T: ToOffset>(
 1057        &self,
 1058        point: T,
 1059        cx: &'a AppContext,
 1060    ) -> Option<&'a Arc<Language>> {
 1061        self.buffer.read(cx).language_at(point, cx)
 1062    }
 1063
 1064    fn style(&self, cx: &AppContext) -> EditorStyle {
 1065        build_style(
 1066            cx.global::<Settings>(),
 1067            self.get_field_editor_theme,
 1068            self.override_text_style.as_deref(),
 1069            cx,
 1070        )
 1071    }
 1072
 1073    pub fn mode(&self) -> EditorMode {
 1074        self.mode
 1075    }
 1076
 1077    pub fn set_placeholder_text(
 1078        &mut self,
 1079        placeholder_text: impl Into<Arc<str>>,
 1080        cx: &mut ViewContext<Self>,
 1081    ) {
 1082        self.placeholder_text = Some(placeholder_text.into());
 1083        cx.notify();
 1084    }
 1085
 1086    pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
 1087        self.vertical_scroll_margin = margin_rows as f32;
 1088        cx.notify();
 1089    }
 1090
 1091    pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
 1092        self.set_scroll_position_internal(scroll_position, true, cx);
 1093    }
 1094
 1095    fn set_scroll_position_internal(
 1096        &mut self,
 1097        scroll_position: Vector2F,
 1098        local: bool,
 1099        cx: &mut ViewContext<Self>,
 1100    ) {
 1101        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1102
 1103        if scroll_position.y() == 0. {
 1104            self.scroll_top_anchor = Anchor::min();
 1105            self.scroll_position = scroll_position;
 1106        } else {
 1107            let scroll_top_buffer_offset =
 1108                DisplayPoint::new(scroll_position.y() as u32, 0).to_offset(&map, Bias::Right);
 1109            let anchor = map
 1110                .buffer_snapshot
 1111                .anchor_at(scroll_top_buffer_offset, Bias::Right);
 1112            self.scroll_position = vec2f(
 1113                scroll_position.x(),
 1114                scroll_position.y() - anchor.to_display_point(&map).row() as f32,
 1115            );
 1116            self.scroll_top_anchor = anchor;
 1117        }
 1118
 1119        self.autoscroll_request.take();
 1120        cx.emit(Event::ScrollPositionChanged { local });
 1121        cx.notify();
 1122    }
 1123
 1124    fn set_scroll_top_anchor(
 1125        &mut self,
 1126        anchor: Anchor,
 1127        position: Vector2F,
 1128        cx: &mut ViewContext<Self>,
 1129    ) {
 1130        self.scroll_top_anchor = anchor;
 1131        self.scroll_position = position;
 1132        cx.emit(Event::ScrollPositionChanged { local: false });
 1133        cx.notify();
 1134    }
 1135
 1136    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 1137        self.cursor_shape = cursor_shape;
 1138        cx.notify();
 1139    }
 1140
 1141    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 1142        if self.display_map.read(cx).clip_at_line_ends != clip {
 1143            self.display_map
 1144                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1145        }
 1146    }
 1147
 1148    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: gpui::keymap::Context) {
 1149        self.keymap_context_layers
 1150            .insert(TypeId::of::<Tag>(), context);
 1151    }
 1152
 1153    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
 1154        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
 1155    }
 1156
 1157    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1158        self.input_enabled = input_enabled;
 1159    }
 1160
 1161    pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
 1162        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1163        compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
 1164    }
 1165
 1166    pub fn clamp_scroll_left(&mut self, max: f32) -> bool {
 1167        if max < self.scroll_position.x() {
 1168            self.scroll_position.set_x(max);
 1169            true
 1170        } else {
 1171            false
 1172        }
 1173    }
 1174
 1175    pub fn autoscroll_vertically(
 1176        &mut self,
 1177        viewport_height: f32,
 1178        line_height: f32,
 1179        cx: &mut ViewContext<Self>,
 1180    ) -> bool {
 1181        let visible_lines = viewport_height / line_height;
 1182        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1183        let mut scroll_position =
 1184            compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor);
 1185        let max_scroll_top = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 1186            (display_map.max_point().row() as f32 - visible_lines + 1.).max(0.)
 1187        } else {
 1188            display_map.max_point().row().saturating_sub(1) as f32
 1189        };
 1190        if scroll_position.y() > max_scroll_top {
 1191            scroll_position.set_y(max_scroll_top);
 1192            self.set_scroll_position(scroll_position, cx);
 1193        }
 1194
 1195        let (autoscroll, local) = if let Some(autoscroll) = self.autoscroll_request.take() {
 1196            autoscroll
 1197        } else {
 1198            return false;
 1199        };
 1200
 1201        let first_cursor_top;
 1202        let last_cursor_bottom;
 1203        if let Some(highlighted_rows) = &self.highlighted_rows {
 1204            first_cursor_top = highlighted_rows.start as f32;
 1205            last_cursor_bottom = first_cursor_top + 1.;
 1206        } else if autoscroll == Autoscroll::Newest {
 1207            let newest_selection =
 1208                self.newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot);
 1209            first_cursor_top = newest_selection.head().to_display_point(&display_map).row() as f32;
 1210            last_cursor_bottom = first_cursor_top + 1.;
 1211        } else {
 1212            let selections = self.local_selections::<Point>(cx);
 1213            first_cursor_top = selections
 1214                .first()
 1215                .unwrap()
 1216                .head()
 1217                .to_display_point(&display_map)
 1218                .row() as f32;
 1219            last_cursor_bottom = selections
 1220                .last()
 1221                .unwrap()
 1222                .head()
 1223                .to_display_point(&display_map)
 1224                .row() as f32
 1225                + 1.0;
 1226        }
 1227
 1228        let margin = if matches!(self.mode, EditorMode::AutoHeight { .. }) {
 1229            0.
 1230        } else {
 1231            ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0).floor()
 1232        };
 1233        if margin < 0.0 {
 1234            return false;
 1235        }
 1236
 1237        match autoscroll {
 1238            Autoscroll::Fit | Autoscroll::Newest => {
 1239                let margin = margin.min(self.vertical_scroll_margin);
 1240                let target_top = (first_cursor_top - margin).max(0.0);
 1241                let target_bottom = last_cursor_bottom + margin;
 1242                let start_row = scroll_position.y();
 1243                let end_row = start_row + visible_lines;
 1244
 1245                if target_top < start_row {
 1246                    scroll_position.set_y(target_top);
 1247                    self.set_scroll_position_internal(scroll_position, local, cx);
 1248                } else if target_bottom >= end_row {
 1249                    scroll_position.set_y(target_bottom - visible_lines);
 1250                    self.set_scroll_position_internal(scroll_position, local, cx);
 1251                }
 1252            }
 1253            Autoscroll::Center => {
 1254                scroll_position.set_y((first_cursor_top - margin).max(0.0));
 1255                self.set_scroll_position_internal(scroll_position, local, cx);
 1256            }
 1257        }
 1258
 1259        true
 1260    }
 1261
 1262    pub fn autoscroll_horizontally(
 1263        &mut self,
 1264        start_row: u32,
 1265        viewport_width: f32,
 1266        scroll_width: f32,
 1267        max_glyph_width: f32,
 1268        layouts: &[text_layout::Line],
 1269        cx: &mut ViewContext<Self>,
 1270    ) -> bool {
 1271        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1272        let selections = self.local_selections::<Point>(cx);
 1273
 1274        let mut target_left;
 1275        let mut target_right;
 1276
 1277        if self.highlighted_rows.is_some() {
 1278            target_left = 0.0_f32;
 1279            target_right = 0.0_f32;
 1280        } else {
 1281            target_left = std::f32::INFINITY;
 1282            target_right = 0.0_f32;
 1283            for selection in selections {
 1284                let head = selection.head().to_display_point(&display_map);
 1285                if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
 1286                    let start_column = head.column().saturating_sub(3);
 1287                    let end_column = cmp::min(display_map.line_len(head.row()), head.column() + 3);
 1288                    target_left = target_left.min(
 1289                        layouts[(head.row() - start_row) as usize]
 1290                            .x_for_index(start_column as usize),
 1291                    );
 1292                    target_right = target_right.max(
 1293                        layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 1294                            + max_glyph_width,
 1295                    );
 1296                }
 1297            }
 1298        }
 1299
 1300        target_right = target_right.min(scroll_width);
 1301
 1302        if target_right - target_left > viewport_width {
 1303            return false;
 1304        }
 1305
 1306        let scroll_left = self.scroll_position.x() * max_glyph_width;
 1307        let scroll_right = scroll_left + viewport_width;
 1308
 1309        if target_left < scroll_left {
 1310            self.scroll_position.set_x(target_left / max_glyph_width);
 1311            true
 1312        } else if target_right > scroll_right {
 1313            self.scroll_position
 1314                .set_x((target_right - viewport_width) / max_glyph_width);
 1315            true
 1316        } else {
 1317            false
 1318        }
 1319    }
 1320
 1321    pub fn replace_selections_with(
 1322        &mut self,
 1323        cx: &mut ViewContext<Self>,
 1324        mut find_replacement: impl FnMut(&DisplaySnapshot) -> DisplayPoint,
 1325    ) {
 1326        let display_map = self.snapshot(cx);
 1327        let cursor = find_replacement(&display_map);
 1328        let selection = Selection {
 1329            id: post_inc(&mut self.next_selection_id),
 1330            start: cursor,
 1331            end: cursor,
 1332            reversed: false,
 1333            goal: SelectionGoal::None,
 1334        }
 1335        .map(|display_point| display_point.to_point(&display_map));
 1336        self.update_selections(vec![selection], None, cx);
 1337    }
 1338
 1339    pub fn display_selections(
 1340        &mut self,
 1341        cx: &mut ViewContext<Self>,
 1342    ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
 1343        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1344        let selections = self
 1345            .local_selections::<Point>(cx)
 1346            .into_iter()
 1347            .map(|selection| selection.map(|point| point.to_display_point(&display_map)))
 1348            .collect();
 1349        (display_map, selections)
 1350    }
 1351
 1352    pub fn move_selections(
 1353        &mut self,
 1354        cx: &mut ViewContext<Self>,
 1355        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
 1356    ) {
 1357        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1358        let selections = self
 1359            .local_selections::<Point>(cx)
 1360            .into_iter()
 1361            .map(|selection| {
 1362                let mut selection = selection.map(|point| point.to_display_point(&display_map));
 1363                move_selection(&display_map, &mut selection);
 1364                selection.map(|display_point| display_point.to_point(&display_map))
 1365            })
 1366            .collect();
 1367        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 1368    }
 1369
 1370    pub fn move_selection_heads(
 1371        &mut self,
 1372        cx: &mut ViewContext<Self>,
 1373        mut update_head: impl FnMut(
 1374            &DisplaySnapshot,
 1375            DisplayPoint,
 1376            SelectionGoal,
 1377        ) -> (DisplayPoint, SelectionGoal),
 1378    ) {
 1379        self.move_selections(cx, |map, selection| {
 1380            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
 1381            selection.set_head(new_head, new_goal);
 1382        });
 1383    }
 1384
 1385    pub fn move_cursors(
 1386        &mut self,
 1387        cx: &mut ViewContext<Self>,
 1388        mut update_cursor_position: impl FnMut(
 1389            &DisplaySnapshot,
 1390            DisplayPoint,
 1391            SelectionGoal,
 1392        ) -> (DisplayPoint, SelectionGoal),
 1393    ) {
 1394        self.move_selections(cx, |map, selection| {
 1395            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
 1396            selection.collapse_to(cursor, new_goal)
 1397        });
 1398    }
 1399
 1400    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1401    where
 1402        I: IntoIterator<Item = (Range<S>, T)>,
 1403        S: ToOffset,
 1404        T: Into<Arc<str>>,
 1405    {
 1406        self.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
 1407    }
 1408
 1409    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1410    where
 1411        I: IntoIterator<Item = (Range<S>, T)>,
 1412        S: ToOffset,
 1413        T: Into<Arc<str>>,
 1414    {
 1415        self.buffer
 1416            .update(cx, |buffer, cx| buffer.edit_with_autoindent(edits, cx));
 1417    }
 1418
 1419    fn select(&mut self, Select(phase): &Select, cx: &mut ViewContext<Self>) {
 1420        self.hide_context_menu(cx);
 1421
 1422        match phase {
 1423            SelectPhase::Begin {
 1424                position,
 1425                add,
 1426                click_count,
 1427            } => self.begin_selection(*position, *add, *click_count, cx),
 1428            SelectPhase::BeginColumnar {
 1429                position,
 1430                overshoot,
 1431            } => self.begin_columnar_selection(*position, *overshoot, cx),
 1432            SelectPhase::Extend {
 1433                position,
 1434                click_count,
 1435            } => self.extend_selection(*position, *click_count, cx),
 1436            SelectPhase::Update {
 1437                position,
 1438                overshoot,
 1439                scroll_position,
 1440            } => self.update_selection(*position, *overshoot, *scroll_position, cx),
 1441            SelectPhase::End => self.end_selection(cx),
 1442        }
 1443    }
 1444
 1445    fn extend_selection(
 1446        &mut self,
 1447        position: DisplayPoint,
 1448        click_count: usize,
 1449        cx: &mut ViewContext<Self>,
 1450    ) {
 1451        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1452        let tail = self
 1453            .newest_selection_with_snapshot::<usize>(&display_map.buffer_snapshot)
 1454            .tail();
 1455        self.begin_selection(position, false, click_count, cx);
 1456
 1457        let position = position.to_offset(&display_map, Bias::Left);
 1458        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 1459        let mut pending = self.pending_selection.clone().unwrap();
 1460
 1461        if position >= tail {
 1462            pending.selection.start = tail_anchor.clone();
 1463        } else {
 1464            pending.selection.end = tail_anchor.clone();
 1465            pending.selection.reversed = true;
 1466        }
 1467
 1468        match &mut pending.mode {
 1469            SelectMode::Word(range) | SelectMode::Line(range) => {
 1470                *range = tail_anchor.clone()..tail_anchor
 1471            }
 1472            _ => {}
 1473        }
 1474
 1475        self.set_selections(self.selections.clone(), Some(pending), true, cx);
 1476    }
 1477
 1478    fn begin_selection(
 1479        &mut self,
 1480        position: DisplayPoint,
 1481        add: bool,
 1482        click_count: usize,
 1483        cx: &mut ViewContext<Self>,
 1484    ) {
 1485        if !self.focused {
 1486            cx.focus_self();
 1487            cx.emit(Event::Activate);
 1488        }
 1489
 1490        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1491        let buffer = &display_map.buffer_snapshot;
 1492        let newest_selection = self.newest_anchor_selection().clone();
 1493        let position = display_map.clip_point(position, Bias::Left);
 1494
 1495        let start;
 1496        let end;
 1497        let mode;
 1498        match click_count {
 1499            1 => {
 1500                start = buffer.anchor_before(position.to_point(&display_map));
 1501                end = start.clone();
 1502                mode = SelectMode::Character;
 1503            }
 1504            2 => {
 1505                let range = movement::surrounding_word(&display_map, position);
 1506                start = buffer.anchor_before(range.start.to_point(&display_map));
 1507                end = buffer.anchor_before(range.end.to_point(&display_map));
 1508                mode = SelectMode::Word(start.clone()..end.clone());
 1509            }
 1510            3 => {
 1511                let position = display_map
 1512                    .clip_point(position, Bias::Left)
 1513                    .to_point(&display_map);
 1514                let line_start = display_map.prev_line_boundary(position).0;
 1515                let next_line_start = buffer.clip_point(
 1516                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 1517                    Bias::Left,
 1518                );
 1519                start = buffer.anchor_before(line_start);
 1520                end = buffer.anchor_before(next_line_start);
 1521                mode = SelectMode::Line(start.clone()..end.clone());
 1522            }
 1523            _ => {
 1524                start = buffer.anchor_before(0);
 1525                end = buffer.anchor_before(buffer.len());
 1526                mode = SelectMode::All;
 1527            }
 1528        }
 1529
 1530        let selection = Selection {
 1531            id: post_inc(&mut self.next_selection_id),
 1532            start,
 1533            end,
 1534            reversed: false,
 1535            goal: SelectionGoal::None,
 1536        };
 1537
 1538        let mut selections;
 1539        if add {
 1540            selections = self.selections.clone();
 1541            // Remove the newest selection if it was added due to a previous mouse up
 1542            // within this multi-click.
 1543            if click_count > 1 {
 1544                selections = self
 1545                    .selections
 1546                    .iter()
 1547                    .filter(|selection| selection.id != newest_selection.id)
 1548                    .cloned()
 1549                    .collect();
 1550            }
 1551        } else {
 1552            selections = Arc::from([]);
 1553        }
 1554        self.set_selections(
 1555            selections,
 1556            Some(PendingSelection { selection, mode }),
 1557            true,
 1558            cx,
 1559        );
 1560
 1561        cx.notify();
 1562    }
 1563
 1564    fn begin_columnar_selection(
 1565        &mut self,
 1566        position: DisplayPoint,
 1567        overshoot: u32,
 1568        cx: &mut ViewContext<Self>,
 1569    ) {
 1570        if !self.focused {
 1571            cx.focus_self();
 1572            cx.emit(Event::Activate);
 1573        }
 1574
 1575        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1576        let tail = self
 1577            .newest_selection_with_snapshot::<Point>(&display_map.buffer_snapshot)
 1578            .tail();
 1579        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 1580
 1581        self.select_columns(
 1582            tail.to_display_point(&display_map),
 1583            position,
 1584            overshoot,
 1585            &display_map,
 1586            cx,
 1587        );
 1588    }
 1589
 1590    fn update_selection(
 1591        &mut self,
 1592        position: DisplayPoint,
 1593        overshoot: u32,
 1594        scroll_position: Vector2F,
 1595        cx: &mut ViewContext<Self>,
 1596    ) {
 1597        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1598
 1599        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 1600            let tail = tail.to_display_point(&display_map);
 1601            self.select_columns(tail, position, overshoot, &display_map, cx);
 1602        } else if let Some(mut pending) = self.pending_selection.clone() {
 1603            let buffer = self.buffer.read(cx).snapshot(cx);
 1604            let head;
 1605            let tail;
 1606            match &pending.mode {
 1607                SelectMode::Character => {
 1608                    head = position.to_point(&display_map);
 1609                    tail = pending.selection.tail().to_point(&buffer);
 1610                }
 1611                SelectMode::Word(original_range) => {
 1612                    let original_display_range = original_range.start.to_display_point(&display_map)
 1613                        ..original_range.end.to_display_point(&display_map);
 1614                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 1615                        ..original_display_range.end.to_point(&display_map);
 1616                    if movement::is_inside_word(&display_map, position)
 1617                        || original_display_range.contains(&position)
 1618                    {
 1619                        let word_range = movement::surrounding_word(&display_map, position);
 1620                        if word_range.start < original_display_range.start {
 1621                            head = word_range.start.to_point(&display_map);
 1622                        } else {
 1623                            head = word_range.end.to_point(&display_map);
 1624                        }
 1625                    } else {
 1626                        head = position.to_point(&display_map);
 1627                    }
 1628
 1629                    if head <= original_buffer_range.start {
 1630                        tail = original_buffer_range.end;
 1631                    } else {
 1632                        tail = original_buffer_range.start;
 1633                    }
 1634                }
 1635                SelectMode::Line(original_range) => {
 1636                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 1637
 1638                    let position = display_map
 1639                        .clip_point(position, Bias::Left)
 1640                        .to_point(&display_map);
 1641                    let line_start = display_map.prev_line_boundary(position).0;
 1642                    let next_line_start = buffer.clip_point(
 1643                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 1644                        Bias::Left,
 1645                    );
 1646
 1647                    if line_start < original_range.start {
 1648                        head = line_start
 1649                    } else {
 1650                        head = next_line_start
 1651                    }
 1652
 1653                    if head <= original_range.start {
 1654                        tail = original_range.end;
 1655                    } else {
 1656                        tail = original_range.start;
 1657                    }
 1658                }
 1659                SelectMode::All => {
 1660                    return;
 1661                }
 1662            };
 1663
 1664            if head < tail {
 1665                pending.selection.start = buffer.anchor_before(head);
 1666                pending.selection.end = buffer.anchor_before(tail);
 1667                pending.selection.reversed = true;
 1668            } else {
 1669                pending.selection.start = buffer.anchor_before(tail);
 1670                pending.selection.end = buffer.anchor_before(head);
 1671                pending.selection.reversed = false;
 1672            }
 1673            self.set_selections(self.selections.clone(), Some(pending), true, cx);
 1674        } else {
 1675            log::error!("update_selection dispatched with no pending selection");
 1676            return;
 1677        }
 1678
 1679        self.set_scroll_position(scroll_position, cx);
 1680        cx.notify();
 1681    }
 1682
 1683    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 1684        self.columnar_selection_tail.take();
 1685        if self.pending_selection.is_some() {
 1686            let selections = self.local_selections::<usize>(cx);
 1687            self.update_selections(selections, None, cx);
 1688        }
 1689    }
 1690
 1691    fn select_columns(
 1692        &mut self,
 1693        tail: DisplayPoint,
 1694        head: DisplayPoint,
 1695        overshoot: u32,
 1696        display_map: &DisplaySnapshot,
 1697        cx: &mut ViewContext<Self>,
 1698    ) {
 1699        let start_row = cmp::min(tail.row(), head.row());
 1700        let end_row = cmp::max(tail.row(), head.row());
 1701        let start_column = cmp::min(tail.column(), head.column() + overshoot);
 1702        let end_column = cmp::max(tail.column(), head.column() + overshoot);
 1703        let reversed = start_column < tail.column();
 1704
 1705        let selections = (start_row..=end_row)
 1706            .filter_map(|row| {
 1707                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 1708                    let start = display_map
 1709                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 1710                        .to_point(&display_map);
 1711                    let end = display_map
 1712                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 1713                        .to_point(&display_map);
 1714                    Some(Selection {
 1715                        id: post_inc(&mut self.next_selection_id),
 1716                        start,
 1717                        end,
 1718                        reversed,
 1719                        goal: SelectionGoal::None,
 1720                    })
 1721                } else {
 1722                    None
 1723                }
 1724            })
 1725            .collect::<Vec<_>>();
 1726
 1727        self.update_selections(selections, None, cx);
 1728        cx.notify();
 1729    }
 1730
 1731    pub fn is_selecting(&self) -> bool {
 1732        self.pending_selection.is_some() || self.columnar_selection_tail.is_some()
 1733    }
 1734
 1735    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 1736        if self.take_rename(false, cx).is_some() {
 1737            return;
 1738        }
 1739
 1740        if self.hide_context_menu(cx).is_some() {
 1741            return;
 1742        }
 1743
 1744        if self.snippet_stack.pop().is_some() {
 1745            return;
 1746        }
 1747
 1748        if self.mode == EditorMode::Full {
 1749            if self.active_diagnostics.is_some() {
 1750                self.dismiss_diagnostics(cx);
 1751                return;
 1752            }
 1753
 1754            if let Some(pending) = self.pending_selection.clone() {
 1755                let mut selections = self.selections.clone();
 1756                if selections.is_empty() {
 1757                    selections = Arc::from([pending.selection]);
 1758                }
 1759                self.set_selections(selections, None, true, cx);
 1760                self.request_autoscroll(Autoscroll::Fit, cx);
 1761                return;
 1762            }
 1763
 1764            let mut oldest_selection = self.oldest_selection::<usize>(&cx);
 1765            if self.selection_count() > 1 {
 1766                self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx);
 1767                return;
 1768            }
 1769
 1770            if !oldest_selection.is_empty() {
 1771                oldest_selection.start = oldest_selection.head().clone();
 1772                oldest_selection.end = oldest_selection.head().clone();
 1773                self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx);
 1774                return;
 1775            }
 1776        }
 1777
 1778        cx.propagate_action();
 1779    }
 1780
 1781    #[cfg(any(test, feature = "test-support"))]
 1782    pub fn selected_ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
 1783        &self,
 1784        cx: &AppContext,
 1785    ) -> Vec<Range<D>> {
 1786        self.local_selections::<D>(cx)
 1787            .iter()
 1788            .map(|s| {
 1789                if s.reversed {
 1790                    s.end.clone()..s.start.clone()
 1791                } else {
 1792                    s.start.clone()..s.end.clone()
 1793                }
 1794            })
 1795            .collect()
 1796    }
 1797
 1798    #[cfg(any(test, feature = "test-support"))]
 1799    pub fn selected_display_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
 1800        let display_map = self
 1801            .display_map
 1802            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1803        self.selections
 1804            .iter()
 1805            .chain(
 1806                self.pending_selection
 1807                    .as_ref()
 1808                    .map(|pending| &pending.selection),
 1809            )
 1810            .map(|s| {
 1811                if s.reversed {
 1812                    s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
 1813                } else {
 1814                    s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
 1815                }
 1816            })
 1817            .collect()
 1818    }
 1819
 1820    pub fn select_ranges<I, T>(
 1821        &mut self,
 1822        ranges: I,
 1823        autoscroll: Option<Autoscroll>,
 1824        cx: &mut ViewContext<Self>,
 1825    ) where
 1826        I: IntoIterator<Item = Range<T>>,
 1827        T: ToOffset,
 1828    {
 1829        let buffer = self.buffer.read(cx).snapshot(cx);
 1830        let selections = ranges
 1831            .into_iter()
 1832            .map(|range| {
 1833                let mut start = range.start.to_offset(&buffer);
 1834                let mut end = range.end.to_offset(&buffer);
 1835                let reversed = if start > end {
 1836                    mem::swap(&mut start, &mut end);
 1837                    true
 1838                } else {
 1839                    false
 1840                };
 1841                Selection {
 1842                    id: post_inc(&mut self.next_selection_id),
 1843                    start,
 1844                    end,
 1845                    reversed,
 1846                    goal: SelectionGoal::None,
 1847                }
 1848            })
 1849            .collect::<Vec<_>>();
 1850        self.update_selections(selections, autoscroll, cx);
 1851    }
 1852
 1853    #[cfg(any(test, feature = "test-support"))]
 1854    pub fn select_display_ranges<'a, T>(&mut self, ranges: T, cx: &mut ViewContext<Self>)
 1855    where
 1856        T: IntoIterator<Item = &'a Range<DisplayPoint>>,
 1857    {
 1858        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 1859        let selections = ranges
 1860            .into_iter()
 1861            .map(|range| {
 1862                let mut start = range.start;
 1863                let mut end = range.end;
 1864                let reversed = if start > end {
 1865                    mem::swap(&mut start, &mut end);
 1866                    true
 1867                } else {
 1868                    false
 1869                };
 1870                Selection {
 1871                    id: post_inc(&mut self.next_selection_id),
 1872                    start: start.to_point(&display_map),
 1873                    end: end.to_point(&display_map),
 1874                    reversed,
 1875                    goal: SelectionGoal::None,
 1876                }
 1877            })
 1878            .collect();
 1879        self.update_selections(selections, None, cx);
 1880    }
 1881
 1882    pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
 1883        if !self.input_enabled {
 1884            cx.propagate_action();
 1885            return;
 1886        }
 1887
 1888        let text = action.0.as_ref();
 1889        if !self.skip_autoclose_end(text, cx) {
 1890            self.transact(cx, |this, cx| {
 1891                if !this.surround_with_bracket_pair(text, cx) {
 1892                    this.insert(text, cx);
 1893                    this.autoclose_bracket_pairs(cx);
 1894                }
 1895            });
 1896            self.trigger_completion_on_input(text, cx);
 1897        }
 1898    }
 1899
 1900    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 1901        self.transact(cx, |this, cx| {
 1902            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 1903                let selections = this.local_selections::<usize>(cx);
 1904                let buffer = this.buffer.read(cx).snapshot(cx);
 1905                selections
 1906                    .iter()
 1907                    .map(|selection| {
 1908                        let start_point = selection.start.to_point(&buffer);
 1909                        let indent = buffer
 1910                            .indent_column_for_line(start_point.row)
 1911                            .min(start_point.column);
 1912                        let start = selection.start;
 1913                        let end = selection.end;
 1914
 1915                        let mut insert_extra_newline = false;
 1916                        if let Some(language) = buffer.language() {
 1917                            let leading_whitespace_len = buffer
 1918                                .reversed_chars_at(start)
 1919                                .take_while(|c| c.is_whitespace() && *c != '\n')
 1920                                .map(|c| c.len_utf8())
 1921                                .sum::<usize>();
 1922
 1923                            let trailing_whitespace_len = buffer
 1924                                .chars_at(end)
 1925                                .take_while(|c| c.is_whitespace() && *c != '\n')
 1926                                .map(|c| c.len_utf8())
 1927                                .sum::<usize>();
 1928
 1929                            insert_extra_newline = language.brackets().iter().any(|pair| {
 1930                                let pair_start = pair.start.trim_end();
 1931                                let pair_end = pair.end.trim_start();
 1932
 1933                                pair.newline
 1934                                    && buffer
 1935                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
 1936                                    && buffer.contains_str_at(
 1937                                        (start - leading_whitespace_len)
 1938                                            .saturating_sub(pair_start.len()),
 1939                                        pair_start,
 1940                                    )
 1941                            });
 1942                        }
 1943
 1944                        let mut new_text = String::with_capacity(1 + indent as usize);
 1945                        new_text.push('\n');
 1946                        new_text.extend(iter::repeat(' ').take(indent as usize));
 1947                        if insert_extra_newline {
 1948                            new_text = new_text.repeat(2);
 1949                        }
 1950                        (
 1951                            (start..end, new_text),
 1952                            (insert_extra_newline, buffer.anchor_after(end)),
 1953                        )
 1954                    })
 1955                    .unzip()
 1956            };
 1957
 1958            this.buffer.update(cx, |buffer, cx| {
 1959                buffer.edit_with_autoindent(edits, cx);
 1960
 1961                let buffer = buffer.read(cx);
 1962                this.selections = this
 1963                    .selections
 1964                    .iter()
 1965                    .cloned()
 1966                    .zip(selection_fixup_info)
 1967                    .map(|(mut new_selection, (extra_newline_inserted, end))| {
 1968                        let mut cursor = end.to_point(&buffer);
 1969                        if extra_newline_inserted {
 1970                            cursor.row -= 1;
 1971                            cursor.column = buffer.line_len(cursor.row);
 1972                        }
 1973                        let anchor = buffer.anchor_after(cursor);
 1974                        new_selection.start = anchor.clone();
 1975                        new_selection.end = anchor;
 1976                        new_selection
 1977                    })
 1978                    .collect();
 1979            });
 1980
 1981            this.request_autoscroll(Autoscroll::Fit, cx);
 1982        });
 1983    }
 1984
 1985    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 1986        let text: Arc<str> = text.into();
 1987        self.transact(cx, |this, cx| {
 1988            let old_selections = this.local_selections::<usize>(cx);
 1989            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 1990                let anchors = {
 1991                    let snapshot = buffer.read(cx);
 1992                    old_selections
 1993                        .iter()
 1994                        .map(|s| (s.id, s.goal, snapshot.anchor_after(s.end)))
 1995                        .collect::<Vec<_>>()
 1996                };
 1997                buffer.edit_with_autoindent(
 1998                    old_selections
 1999                        .iter()
 2000                        .map(|s| (s.start..s.end, text.clone())),
 2001                    cx,
 2002                );
 2003                anchors
 2004            });
 2005
 2006            let selections = {
 2007                let snapshot = this.buffer.read(cx).read(cx);
 2008                selection_anchors
 2009                    .into_iter()
 2010                    .map(|(id, goal, position)| {
 2011                        let position = position.to_offset(&snapshot);
 2012                        Selection {
 2013                            id,
 2014                            start: position,
 2015                            end: position,
 2016                            goal,
 2017                            reversed: false,
 2018                        }
 2019                    })
 2020                    .collect()
 2021            };
 2022            this.update_selections(selections, Some(Autoscroll::Fit), cx);
 2023        });
 2024    }
 2025
 2026    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2027        let selection = self.newest_anchor_selection();
 2028        if self
 2029            .buffer
 2030            .read(cx)
 2031            .is_completion_trigger(selection.head(), text, cx)
 2032        {
 2033            self.show_completions(&ShowCompletions, cx);
 2034        } else {
 2035            self.hide_context_menu(cx);
 2036        }
 2037    }
 2038
 2039    fn surround_with_bracket_pair(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
 2040        let snapshot = self.buffer.read(cx).snapshot(cx);
 2041        if let Some(pair) = snapshot
 2042            .language()
 2043            .and_then(|language| language.brackets().iter().find(|b| b.start == text))
 2044            .cloned()
 2045        {
 2046            if self
 2047                .local_selections::<usize>(cx)
 2048                .iter()
 2049                .any(|selection| selection.is_empty())
 2050            {
 2051                false
 2052            } else {
 2053                let mut selections = self.selections.to_vec();
 2054                for selection in &mut selections {
 2055                    selection.end = selection.end.bias_left(&snapshot);
 2056                }
 2057                drop(snapshot);
 2058
 2059                self.buffer.update(cx, |buffer, cx| {
 2060                    let pair_start: Arc<str> = pair.start.clone().into();
 2061                    buffer.edit(
 2062                        selections
 2063                            .iter()
 2064                            .map(|s| (s.start.clone()..s.start.clone(), pair_start.clone())),
 2065                        cx,
 2066                    );
 2067                    let pair_end: Arc<str> = pair.end.clone().into();
 2068                    buffer.edit(
 2069                        selections
 2070                            .iter()
 2071                            .map(|s| (s.end.clone()..s.end.clone(), pair_end.clone())),
 2072                        cx,
 2073                    );
 2074                });
 2075
 2076                let snapshot = self.buffer.read(cx).read(cx);
 2077                for selection in &mut selections {
 2078                    selection.end = selection.end.bias_right(&snapshot);
 2079                }
 2080                drop(snapshot);
 2081
 2082                self.set_selections(selections.into(), None, true, cx);
 2083                true
 2084            }
 2085        } else {
 2086            false
 2087        }
 2088    }
 2089
 2090    fn autoclose_bracket_pairs(&mut self, cx: &mut ViewContext<Self>) {
 2091        let selections = self.local_selections::<usize>(cx);
 2092        let mut bracket_pair_state = None;
 2093        let mut new_selections = None;
 2094        self.buffer.update(cx, |buffer, cx| {
 2095            let mut snapshot = buffer.snapshot(cx);
 2096            let left_biased_selections = selections
 2097                .iter()
 2098                .map(|selection| Selection {
 2099                    id: selection.id,
 2100                    start: snapshot.anchor_before(selection.start),
 2101                    end: snapshot.anchor_before(selection.end),
 2102                    reversed: selection.reversed,
 2103                    goal: selection.goal,
 2104                })
 2105                .collect::<Vec<_>>();
 2106
 2107            let autoclose_pair = snapshot.language().and_then(|language| {
 2108                let first_selection_start = selections.first().unwrap().start;
 2109                let pair = language.brackets().iter().find(|pair| {
 2110                    snapshot.contains_str_at(
 2111                        first_selection_start.saturating_sub(pair.start.len()),
 2112                        &pair.start,
 2113                    )
 2114                });
 2115                pair.and_then(|pair| {
 2116                    let should_autoclose = selections.iter().all(|selection| {
 2117                        // Ensure all selections are parked at the end of a pair start.
 2118                        if snapshot.contains_str_at(
 2119                            selection.start.saturating_sub(pair.start.len()),
 2120                            &pair.start,
 2121                        ) {
 2122                            snapshot
 2123                                .chars_at(selection.start)
 2124                                .next()
 2125                                .map_or(true, |c| language.should_autoclose_before(c))
 2126                        } else {
 2127                            false
 2128                        }
 2129                    });
 2130
 2131                    if should_autoclose {
 2132                        Some(pair.clone())
 2133                    } else {
 2134                        None
 2135                    }
 2136                })
 2137            });
 2138
 2139            if let Some(pair) = autoclose_pair {
 2140                let selection_ranges = selections
 2141                    .iter()
 2142                    .map(|selection| {
 2143                        let start = selection.start.to_offset(&snapshot);
 2144                        start..start
 2145                    })
 2146                    .collect::<SmallVec<[_; 32]>>();
 2147
 2148                let pair_end: Arc<str> = pair.end.clone().into();
 2149                buffer.edit(
 2150                    selection_ranges
 2151                        .iter()
 2152                        .map(|range| (range.clone(), pair_end.clone())),
 2153                    cx,
 2154                );
 2155                snapshot = buffer.snapshot(cx);
 2156
 2157                new_selections = Some(
 2158                    self.resolve_selections::<usize, _>(left_biased_selections.iter(), &snapshot)
 2159                        .collect::<Vec<_>>(),
 2160                );
 2161
 2162                if pair.end.len() == 1 {
 2163                    let mut delta = 0;
 2164                    bracket_pair_state = Some(BracketPairState {
 2165                        ranges: selections
 2166                            .iter()
 2167                            .map(move |selection| {
 2168                                let offset = selection.start + delta;
 2169                                delta += 1;
 2170                                snapshot.anchor_before(offset)..snapshot.anchor_after(offset)
 2171                            })
 2172                            .collect(),
 2173                        pair,
 2174                    });
 2175                }
 2176            }
 2177        });
 2178
 2179        if let Some(new_selections) = new_selections {
 2180            self.update_selections(new_selections, None, cx);
 2181        }
 2182        if let Some(bracket_pair_state) = bracket_pair_state {
 2183            self.autoclose_stack.push(bracket_pair_state);
 2184        }
 2185    }
 2186
 2187    fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
 2188        let old_selections = self.local_selections::<usize>(cx);
 2189        let autoclose_pair = if let Some(autoclose_pair) = self.autoclose_stack.last() {
 2190            autoclose_pair
 2191        } else {
 2192            return false;
 2193        };
 2194        if text != autoclose_pair.pair.end {
 2195            return false;
 2196        }
 2197
 2198        debug_assert_eq!(old_selections.len(), autoclose_pair.ranges.len());
 2199
 2200        let buffer = self.buffer.read(cx).snapshot(cx);
 2201        if old_selections
 2202            .iter()
 2203            .zip(autoclose_pair.ranges.iter().map(|r| r.to_offset(&buffer)))
 2204            .all(|(selection, autoclose_range)| {
 2205                let autoclose_range_end = autoclose_range.end.to_offset(&buffer);
 2206                selection.is_empty() && selection.start == autoclose_range_end
 2207            })
 2208        {
 2209            let new_selections = old_selections
 2210                .into_iter()
 2211                .map(|selection| {
 2212                    let cursor = selection.start + 1;
 2213                    Selection {
 2214                        id: selection.id,
 2215                        start: cursor,
 2216                        end: cursor,
 2217                        reversed: false,
 2218                        goal: SelectionGoal::None,
 2219                    }
 2220                })
 2221                .collect();
 2222            self.autoclose_stack.pop();
 2223            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 2224            true
 2225        } else {
 2226            false
 2227        }
 2228    }
 2229
 2230    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 2231        let offset = position.to_offset(buffer);
 2232        let (word_range, kind) = buffer.surrounding_word(offset);
 2233        if offset > word_range.start && kind == Some(CharKind::Word) {
 2234            Some(
 2235                buffer
 2236                    .text_for_range(word_range.start..offset)
 2237                    .collect::<String>(),
 2238            )
 2239        } else {
 2240            None
 2241        }
 2242    }
 2243
 2244    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 2245        if self.pending_rename.is_some() {
 2246            return;
 2247        }
 2248
 2249        let project = if let Some(project) = self.project.clone() {
 2250            project
 2251        } else {
 2252            return;
 2253        };
 2254
 2255        let position = self.newest_anchor_selection().head();
 2256        let (buffer, buffer_position) = if let Some(output) = self
 2257            .buffer
 2258            .read(cx)
 2259            .text_anchor_for_position(position.clone(), cx)
 2260        {
 2261            output
 2262        } else {
 2263            return;
 2264        };
 2265
 2266        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 2267        let completions = project.update(cx, |project, cx| {
 2268            project.completions(&buffer, buffer_position.clone(), cx)
 2269        });
 2270
 2271        let id = post_inc(&mut self.next_completion_id);
 2272        let task = cx.spawn_weak(|this, mut cx| {
 2273            async move {
 2274                let completions = completions.await?;
 2275                if completions.is_empty() {
 2276                    return Ok(());
 2277                }
 2278
 2279                let mut menu = CompletionsMenu {
 2280                    id,
 2281                    initial_position: position,
 2282                    match_candidates: completions
 2283                        .iter()
 2284                        .enumerate()
 2285                        .map(|(id, completion)| {
 2286                            StringMatchCandidate::new(
 2287                                id,
 2288                                completion.label.text[completion.label.filter_range.clone()].into(),
 2289                            )
 2290                        })
 2291                        .collect(),
 2292                    buffer,
 2293                    completions: completions.into(),
 2294                    matches: Vec::new().into(),
 2295                    selected_item: 0,
 2296                    list: Default::default(),
 2297                };
 2298
 2299                menu.filter(query.as_deref(), cx.background()).await;
 2300
 2301                if let Some(this) = this.upgrade(&cx) {
 2302                    this.update(&mut cx, |this, cx| {
 2303                        match this.context_menu.as_ref() {
 2304                            None => {}
 2305                            Some(ContextMenu::Completions(prev_menu)) => {
 2306                                if prev_menu.id > menu.id {
 2307                                    return;
 2308                                }
 2309                            }
 2310                            _ => return,
 2311                        }
 2312
 2313                        this.completion_tasks.retain(|(id, _)| *id > menu.id);
 2314                        if this.focused {
 2315                            this.show_context_menu(ContextMenu::Completions(menu), cx);
 2316                        }
 2317
 2318                        cx.notify();
 2319                    });
 2320                }
 2321                Ok::<_, anyhow::Error>(())
 2322            }
 2323            .log_err()
 2324        });
 2325        self.completion_tasks.push((id, task));
 2326    }
 2327
 2328    pub fn confirm_completion(
 2329        &mut self,
 2330        action: &ConfirmCompletion,
 2331        cx: &mut ViewContext<Self>,
 2332    ) -> Option<Task<Result<()>>> {
 2333        use language::ToOffset as _;
 2334
 2335        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 2336            menu
 2337        } else {
 2338            return None;
 2339        };
 2340
 2341        let mat = completions_menu
 2342            .matches
 2343            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 2344        let buffer_handle = completions_menu.buffer;
 2345        let completion = completions_menu.completions.get(mat.candidate_id)?;
 2346
 2347        let snippet;
 2348        let text;
 2349        if completion.is_snippet() {
 2350            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 2351            text = snippet.as_ref().unwrap().text.clone();
 2352        } else {
 2353            snippet = None;
 2354            text = completion.new_text.clone();
 2355        };
 2356        let buffer = buffer_handle.read(cx);
 2357        let old_range = completion.old_range.to_offset(&buffer);
 2358        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 2359
 2360        let selections = self.local_selections::<usize>(cx);
 2361        let newest_selection = self.newest_anchor_selection();
 2362        if newest_selection.start.buffer_id != Some(buffer_handle.id()) {
 2363            return None;
 2364        }
 2365
 2366        let lookbehind = newest_selection
 2367            .start
 2368            .text_anchor
 2369            .to_offset(buffer)
 2370            .saturating_sub(old_range.start);
 2371        let lookahead = old_range
 2372            .end
 2373            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 2374        let mut common_prefix_len = old_text
 2375            .bytes()
 2376            .zip(text.bytes())
 2377            .take_while(|(a, b)| a == b)
 2378            .count();
 2379
 2380        let snapshot = self.buffer.read(cx).snapshot(cx);
 2381        let mut ranges = Vec::new();
 2382        for selection in &selections {
 2383            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 2384                let start = selection.start.saturating_sub(lookbehind);
 2385                let end = selection.end + lookahead;
 2386                ranges.push(start + common_prefix_len..end);
 2387            } else {
 2388                common_prefix_len = 0;
 2389                ranges.clear();
 2390                ranges.extend(selections.iter().map(|s| {
 2391                    if s.id == newest_selection.id {
 2392                        old_range.clone()
 2393                    } else {
 2394                        s.start..s.end
 2395                    }
 2396                }));
 2397                break;
 2398            }
 2399        }
 2400        let text = &text[common_prefix_len..];
 2401
 2402        self.transact(cx, |this, cx| {
 2403            if let Some(mut snippet) = snippet {
 2404                snippet.text = text.to_string();
 2405                for tabstop in snippet.tabstops.iter_mut().flatten() {
 2406                    tabstop.start -= common_prefix_len as isize;
 2407                    tabstop.end -= common_prefix_len as isize;
 2408                }
 2409
 2410                this.insert_snippet(&ranges, snippet, cx).log_err();
 2411            } else {
 2412                this.buffer.update(cx, |buffer, cx| {
 2413                    buffer
 2414                        .edit_with_autoindent(ranges.iter().map(|range| (range.clone(), text)), cx);
 2415                });
 2416            }
 2417        });
 2418
 2419        let project = self.project.clone()?;
 2420        let apply_edits = project.update(cx, |project, cx| {
 2421            project.apply_additional_edits_for_completion(
 2422                buffer_handle,
 2423                completion.clone(),
 2424                true,
 2425                cx,
 2426            )
 2427        });
 2428        Some(cx.foreground().spawn(async move {
 2429            apply_edits.await?;
 2430            Ok(())
 2431        }))
 2432    }
 2433
 2434    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 2435        if matches!(
 2436            self.context_menu.as_ref(),
 2437            Some(ContextMenu::CodeActions(_))
 2438        ) {
 2439            self.context_menu.take();
 2440            cx.notify();
 2441            return;
 2442        }
 2443
 2444        let deployed_from_indicator = action.deployed_from_indicator;
 2445        let mut task = self.code_actions_task.take();
 2446        cx.spawn_weak(|this, mut cx| async move {
 2447            while let Some(prev_task) = task {
 2448                prev_task.await;
 2449                task = this
 2450                    .upgrade(&cx)
 2451                    .and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take()));
 2452            }
 2453
 2454            if let Some(this) = this.upgrade(&cx) {
 2455                this.update(&mut cx, |this, cx| {
 2456                    if this.focused {
 2457                        if let Some((buffer, actions)) = this.available_code_actions.clone() {
 2458                            this.show_context_menu(
 2459                                ContextMenu::CodeActions(CodeActionsMenu {
 2460                                    buffer,
 2461                                    actions,
 2462                                    selected_item: Default::default(),
 2463                                    list: Default::default(),
 2464                                    deployed_from_indicator,
 2465                                }),
 2466                                cx,
 2467                            );
 2468                        }
 2469                    }
 2470                })
 2471            }
 2472            Ok::<_, anyhow::Error>(())
 2473        })
 2474        .detach_and_log_err(cx);
 2475    }
 2476
 2477    pub fn confirm_code_action(
 2478        workspace: &mut Workspace,
 2479        action: &ConfirmCodeAction,
 2480        cx: &mut ViewContext<Workspace>,
 2481    ) -> Option<Task<Result<()>>> {
 2482        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 2483        let actions_menu = if let ContextMenu::CodeActions(menu) =
 2484            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
 2485        {
 2486            menu
 2487        } else {
 2488            return None;
 2489        };
 2490        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 2491        let action = actions_menu.actions.get(action_ix)?.clone();
 2492        let title = action.lsp_action.title.clone();
 2493        let buffer = actions_menu.buffer;
 2494
 2495        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
 2496            project.apply_code_action(buffer, action, true, cx)
 2497        });
 2498        Some(cx.spawn(|workspace, cx| async move {
 2499            let project_transaction = apply_code_actions.await?;
 2500            Self::open_project_transaction(editor, workspace, project_transaction, title, cx).await
 2501        }))
 2502    }
 2503
 2504    async fn open_project_transaction(
 2505        this: ViewHandle<Editor>,
 2506        workspace: ViewHandle<Workspace>,
 2507        transaction: ProjectTransaction,
 2508        title: String,
 2509        mut cx: AsyncAppContext,
 2510    ) -> Result<()> {
 2511        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx));
 2512
 2513        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 2514        entries.sort_unstable_by_key(|(buffer, _)| {
 2515            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
 2516        });
 2517
 2518        // If the project transaction's edits are all contained within this editor, then
 2519        // avoid opening a new editor to display them.
 2520
 2521        if let Some((buffer, transaction)) = entries.first() {
 2522            if entries.len() == 1 {
 2523                let excerpt = this.read_with(&cx, |editor, cx| {
 2524                    editor
 2525                        .buffer()
 2526                        .read(cx)
 2527                        .excerpt_containing(editor.newest_anchor_selection().head(), cx)
 2528                });
 2529                if let Some((excerpted_buffer, excerpt_range)) = excerpt {
 2530                    if excerpted_buffer == *buffer {
 2531                        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
 2532                        let excerpt_range = excerpt_range.to_offset(&snapshot);
 2533                        if snapshot
 2534                            .edited_ranges_for_transaction(transaction)
 2535                            .all(|range| {
 2536                                excerpt_range.start <= range.start && excerpt_range.end >= range.end
 2537                            })
 2538                        {
 2539                            return Ok(());
 2540                        }
 2541                    }
 2542                }
 2543            }
 2544        } else {
 2545            return Ok(());
 2546        }
 2547
 2548        let mut ranges_to_highlight = Vec::new();
 2549        let excerpt_buffer = cx.add_model(|cx| {
 2550            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
 2551            for (buffer, transaction) in &entries {
 2552                let snapshot = buffer.read(cx).snapshot();
 2553                ranges_to_highlight.extend(
 2554                    multibuffer.push_excerpts_with_context_lines(
 2555                        buffer.clone(),
 2556                        snapshot
 2557                            .edited_ranges_for_transaction::<usize>(transaction)
 2558                            .collect(),
 2559                        1,
 2560                        cx,
 2561                    ),
 2562                );
 2563            }
 2564            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)));
 2565            multibuffer
 2566        });
 2567
 2568        workspace.update(&mut cx, |workspace, cx| {
 2569            let project = workspace.project().clone();
 2570            let editor =
 2571                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 2572            workspace.add_item(Box::new(editor.clone()), cx);
 2573            editor.update(cx, |editor, cx| {
 2574                editor.highlight_background::<Self>(
 2575                    ranges_to_highlight,
 2576                    |theme| theme.editor.highlighted_line_background,
 2577                    cx,
 2578                );
 2579            });
 2580        });
 2581
 2582        Ok(())
 2583    }
 2584
 2585    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2586        let project = self.project.as_ref()?;
 2587        let buffer = self.buffer.read(cx);
 2588        let newest_selection = self.newest_anchor_selection().clone();
 2589        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 2590        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 2591        if start_buffer != end_buffer {
 2592            return None;
 2593        }
 2594
 2595        let actions = project.update(cx, |project, cx| {
 2596            project.code_actions(&start_buffer, start..end, cx)
 2597        });
 2598        self.code_actions_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2599            let actions = actions.await;
 2600            if let Some(this) = this.upgrade(&cx) {
 2601                this.update(&mut cx, |this, cx| {
 2602                    this.available_code_actions = actions.log_err().and_then(|actions| {
 2603                        if actions.is_empty() {
 2604                            None
 2605                        } else {
 2606                            Some((start_buffer, actions.into()))
 2607                        }
 2608                    });
 2609                    cx.notify();
 2610                })
 2611            }
 2612        }));
 2613        None
 2614    }
 2615
 2616    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 2617        if self.pending_rename.is_some() {
 2618            return None;
 2619        }
 2620
 2621        let project = self.project.as_ref()?;
 2622        let buffer = self.buffer.read(cx);
 2623        let newest_selection = self.newest_anchor_selection().clone();
 2624        let cursor_position = newest_selection.head();
 2625        let (cursor_buffer, cursor_buffer_position) =
 2626            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 2627        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 2628        if cursor_buffer != tail_buffer {
 2629            return None;
 2630        }
 2631
 2632        let highlights = project.update(cx, |project, cx| {
 2633            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 2634        });
 2635
 2636        self.document_highlights_task = Some(cx.spawn_weak(|this, mut cx| async move {
 2637            let highlights = highlights.log_err().await;
 2638            if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
 2639                this.update(&mut cx, |this, cx| {
 2640                    if this.pending_rename.is_some() {
 2641                        return;
 2642                    }
 2643
 2644                    let buffer_id = cursor_position.buffer_id;
 2645                    let buffer = this.buffer.read(cx);
 2646                    if !buffer
 2647                        .text_anchor_for_position(cursor_position, cx)
 2648                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 2649                    {
 2650                        return;
 2651                    }
 2652
 2653                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 2654                    let mut write_ranges = Vec::new();
 2655                    let mut read_ranges = Vec::new();
 2656                    for highlight in highlights {
 2657                        for (excerpt_id, excerpt_range) in
 2658                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 2659                        {
 2660                            let start = highlight
 2661                                .range
 2662                                .start
 2663                                .max(&excerpt_range.start, cursor_buffer_snapshot);
 2664                            let end = highlight
 2665                                .range
 2666                                .end
 2667                                .min(&excerpt_range.end, cursor_buffer_snapshot);
 2668                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 2669                                continue;
 2670                            }
 2671
 2672                            let range = Anchor {
 2673                                buffer_id,
 2674                                excerpt_id: excerpt_id.clone(),
 2675                                text_anchor: start,
 2676                            }..Anchor {
 2677                                buffer_id,
 2678                                excerpt_id,
 2679                                text_anchor: end,
 2680                            };
 2681                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 2682                                write_ranges.push(range);
 2683                            } else {
 2684                                read_ranges.push(range);
 2685                            }
 2686                        }
 2687                    }
 2688
 2689                    this.highlight_background::<DocumentHighlightRead>(
 2690                        read_ranges,
 2691                        |theme| theme.editor.document_highlight_read_background,
 2692                        cx,
 2693                    );
 2694                    this.highlight_background::<DocumentHighlightWrite>(
 2695                        write_ranges,
 2696                        |theme| theme.editor.document_highlight_write_background,
 2697                        cx,
 2698                    );
 2699                    cx.notify();
 2700                });
 2701            }
 2702        }));
 2703        None
 2704    }
 2705
 2706    pub fn render_code_actions_indicator(
 2707        &self,
 2708        style: &EditorStyle,
 2709        cx: &mut ViewContext<Self>,
 2710    ) -> Option<ElementBox> {
 2711        if self.available_code_actions.is_some() {
 2712            enum Tag {}
 2713            Some(
 2714                MouseEventHandler::new::<Tag, _, _>(0, cx, |_, _| {
 2715                    Svg::new("icons/zap.svg")
 2716                        .with_color(style.code_actions_indicator)
 2717                        .boxed()
 2718                })
 2719                .with_cursor_style(CursorStyle::PointingHand)
 2720                .with_padding(Padding::uniform(3.))
 2721                .on_mouse_down(|cx| {
 2722                    cx.dispatch_action(ToggleCodeActions {
 2723                        deployed_from_indicator: true,
 2724                    });
 2725                })
 2726                .boxed(),
 2727            )
 2728        } else {
 2729            None
 2730        }
 2731    }
 2732
 2733    pub fn context_menu_visible(&self) -> bool {
 2734        self.context_menu
 2735            .as_ref()
 2736            .map_or(false, |menu| menu.visible())
 2737    }
 2738
 2739    pub fn render_context_menu(
 2740        &self,
 2741        cursor_position: DisplayPoint,
 2742        style: EditorStyle,
 2743        cx: &AppContext,
 2744    ) -> Option<(DisplayPoint, ElementBox)> {
 2745        self.context_menu
 2746            .as_ref()
 2747            .map(|menu| menu.render(cursor_position, style, cx))
 2748    }
 2749
 2750    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
 2751        if !matches!(menu, ContextMenu::Completions(_)) {
 2752            self.completion_tasks.clear();
 2753        }
 2754        self.context_menu = Some(menu);
 2755        cx.notify();
 2756    }
 2757
 2758    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 2759        cx.notify();
 2760        self.completion_tasks.clear();
 2761        self.context_menu.take()
 2762    }
 2763
 2764    pub fn insert_snippet(
 2765        &mut self,
 2766        insertion_ranges: &[Range<usize>],
 2767        snippet: Snippet,
 2768        cx: &mut ViewContext<Self>,
 2769    ) -> Result<()> {
 2770        let tabstops = self.buffer.update(cx, |buffer, cx| {
 2771            let snippet_text: Arc<str> = snippet.text.clone().into();
 2772            buffer.edit_with_autoindent(
 2773                insertion_ranges
 2774                    .iter()
 2775                    .cloned()
 2776                    .map(|range| (range, snippet_text.clone())),
 2777                cx,
 2778            );
 2779
 2780            let snapshot = &*buffer.read(cx);
 2781            let snippet = &snippet;
 2782            snippet
 2783                .tabstops
 2784                .iter()
 2785                .map(|tabstop| {
 2786                    let mut tabstop_ranges = tabstop
 2787                        .iter()
 2788                        .flat_map(|tabstop_range| {
 2789                            let mut delta = 0 as isize;
 2790                            insertion_ranges.iter().map(move |insertion_range| {
 2791                                let insertion_start = insertion_range.start as isize + delta;
 2792                                delta +=
 2793                                    snippet.text.len() as isize - insertion_range.len() as isize;
 2794
 2795                                let start = snapshot.anchor_before(
 2796                                    (insertion_start + tabstop_range.start) as usize,
 2797                                );
 2798                                let end = snapshot
 2799                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 2800                                start..end
 2801                            })
 2802                        })
 2803                        .collect::<Vec<_>>();
 2804                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 2805                    tabstop_ranges
 2806                })
 2807                .collect::<Vec<_>>()
 2808        });
 2809
 2810        if let Some(tabstop) = tabstops.first() {
 2811            self.select_ranges(tabstop.iter().cloned(), Some(Autoscroll::Fit), cx);
 2812            self.snippet_stack.push(SnippetState {
 2813                active_index: 0,
 2814                ranges: tabstops,
 2815            });
 2816        }
 2817
 2818        Ok(())
 2819    }
 2820
 2821    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 2822        self.move_to_snippet_tabstop(Bias::Right, cx)
 2823    }
 2824
 2825    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 2826        self.move_to_snippet_tabstop(Bias::Left, cx)
 2827    }
 2828
 2829    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 2830        let buffer = self.buffer.read(cx).snapshot(cx);
 2831
 2832        if let Some(snippet) = self.snippet_stack.last_mut() {
 2833            match bias {
 2834                Bias::Left => {
 2835                    if snippet.active_index > 0 {
 2836                        snippet.active_index -= 1;
 2837                    } else {
 2838                        return false;
 2839                    }
 2840                }
 2841                Bias::Right => {
 2842                    if snippet.active_index + 1 < snippet.ranges.len() {
 2843                        snippet.active_index += 1;
 2844                    } else {
 2845                        return false;
 2846                    }
 2847                }
 2848            }
 2849            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 2850                let new_selections = current_ranges
 2851                    .iter()
 2852                    .map(|new_range| {
 2853                        let new_range = new_range.to_offset(&buffer);
 2854                        Selection {
 2855                            id: post_inc(&mut self.next_selection_id),
 2856                            start: new_range.start,
 2857                            end: new_range.end,
 2858                            reversed: false,
 2859                            goal: SelectionGoal::None,
 2860                        }
 2861                    })
 2862                    .collect();
 2863
 2864                // Remove the snippet state when moving to the last tabstop.
 2865                if snippet.active_index + 1 == snippet.ranges.len() {
 2866                    self.snippet_stack.pop();
 2867                }
 2868
 2869                self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 2870                return true;
 2871            }
 2872            self.snippet_stack.pop();
 2873        }
 2874
 2875        false
 2876    }
 2877
 2878    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 2879        self.transact(cx, |this, cx| {
 2880            this.select_all(&SelectAll, cx);
 2881            this.insert("", cx);
 2882        });
 2883    }
 2884
 2885    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 2886        let mut selections = self.local_selections::<Point>(cx);
 2887        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2888        for selection in &mut selections {
 2889            if selection.is_empty() {
 2890                let old_head = selection.head();
 2891                let mut new_head =
 2892                    movement::left(&display_map, old_head.to_display_point(&display_map))
 2893                        .to_point(&display_map);
 2894                if let Some((buffer, line_buffer_range)) = display_map
 2895                    .buffer_snapshot
 2896                    .buffer_line_for_row(old_head.row)
 2897                {
 2898                    let indent_column = buffer.indent_column_for_line(line_buffer_range.start.row);
 2899                    let language_name = buffer.language().map(|language| language.name());
 2900                    let indent = cx.global::<Settings>().tab_size(language_name.as_deref());
 2901                    if old_head.column <= indent_column && old_head.column > 0 {
 2902                        new_head = cmp::min(
 2903                            new_head,
 2904                            Point::new(old_head.row, ((old_head.column - 1) / indent) * indent),
 2905                        );
 2906                    }
 2907                }
 2908
 2909                selection.set_head(new_head, SelectionGoal::None);
 2910            }
 2911        }
 2912
 2913        self.transact(cx, |this, cx| {
 2914            this.update_selections(selections, Some(Autoscroll::Fit), cx);
 2915            this.insert("", cx);
 2916        });
 2917    }
 2918
 2919    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 2920        self.transact(cx, |this, cx| {
 2921            this.move_selections(cx, |map, selection| {
 2922                if selection.is_empty() {
 2923                    let cursor = movement::right(map, selection.head());
 2924                    selection.set_head(cursor, SelectionGoal::None);
 2925                }
 2926            });
 2927            this.insert(&"", cx);
 2928        });
 2929    }
 2930
 2931    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 2932        if self.move_to_prev_snippet_tabstop(cx) {
 2933            return;
 2934        }
 2935
 2936        self.outdent(&Outdent, cx);
 2937    }
 2938
 2939    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 2940        if self.move_to_next_snippet_tabstop(cx) {
 2941            return;
 2942        }
 2943
 2944        let mut selections = self.local_selections::<Point>(cx);
 2945        if selections.iter().all(|s| s.is_empty()) {
 2946            self.transact(cx, |this, cx| {
 2947                this.buffer.update(cx, |buffer, cx| {
 2948                    for selection in &mut selections {
 2949                        let language_name =
 2950                            buffer.language_at(selection.start, cx).map(|l| l.name());
 2951                        let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
 2952                        let char_column = buffer
 2953                            .read(cx)
 2954                            .text_for_range(Point::new(selection.start.row, 0)..selection.start)
 2955                            .flat_map(str::chars)
 2956                            .count();
 2957                        let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 2958                        buffer.edit(
 2959                            [(
 2960                                selection.start..selection.start,
 2961                                " ".repeat(chars_to_next_tab_stop as usize),
 2962                            )],
 2963                            cx,
 2964                        );
 2965                        selection.start.column += chars_to_next_tab_stop;
 2966                        selection.end = selection.start;
 2967                    }
 2968                });
 2969                this.update_selections(selections, Some(Autoscroll::Fit), cx);
 2970            });
 2971        } else {
 2972            self.indent(&Indent, cx);
 2973        }
 2974    }
 2975
 2976    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 2977        let mut selections = self.local_selections::<Point>(cx);
 2978        self.transact(cx, |this, cx| {
 2979            let mut last_indent = None;
 2980            this.buffer.update(cx, |buffer, cx| {
 2981                let snapshot = buffer.snapshot(cx);
 2982                for selection in &mut selections {
 2983                    let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 2984                    let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
 2985                    let mut start_row = selection.start.row;
 2986                    let mut end_row = selection.end.row + 1;
 2987
 2988                    // If a selection ends at the beginning of a line, don't indent
 2989                    // that last line.
 2990                    if selection.end.column == 0 {
 2991                        end_row -= 1;
 2992                    }
 2993
 2994                    // Avoid re-indenting a row that has already been indented by a
 2995                    // previous selection, but still update this selection's column
 2996                    // to reflect that indentation.
 2997                    if let Some((last_indent_row, last_indent_len)) = last_indent {
 2998                        if last_indent_row == selection.start.row {
 2999                            selection.start.column += last_indent_len;
 3000                            start_row += 1;
 3001                        }
 3002                        if last_indent_row == selection.end.row {
 3003                            selection.end.column += last_indent_len;
 3004                        }
 3005                    }
 3006
 3007                    for row in start_row..end_row {
 3008                        let indent_column = snapshot.indent_column_for_line(row);
 3009                        let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
 3010                        let row_start = Point::new(row, 0);
 3011                        buffer.edit(
 3012                            [(
 3013                                row_start..row_start,
 3014                                " ".repeat(columns_to_next_tab_stop as usize),
 3015                            )],
 3016                            cx,
 3017                        );
 3018
 3019                        // Update this selection's endpoints to reflect the indentation.
 3020                        if row == selection.start.row {
 3021                            selection.start.column += columns_to_next_tab_stop as u32;
 3022                        }
 3023                        if row == selection.end.row {
 3024                            selection.end.column += columns_to_next_tab_stop as u32;
 3025                        }
 3026
 3027                        last_indent = Some((row, columns_to_next_tab_stop as u32));
 3028                    }
 3029                }
 3030            });
 3031
 3032            this.update_selections(selections, Some(Autoscroll::Fit), cx);
 3033        });
 3034    }
 3035
 3036    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 3037        let selections = self.local_selections::<Point>(cx);
 3038        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3039        let mut deletion_ranges = Vec::new();
 3040        let mut last_outdent = None;
 3041        {
 3042            let buffer = self.buffer.read(cx);
 3043            let snapshot = buffer.snapshot(cx);
 3044            for selection in &selections {
 3045                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
 3046                let tab_size = cx.global::<Settings>().tab_size(language_name.as_deref());
 3047                let mut rows = selection.spanned_rows(false, &display_map);
 3048
 3049                // Avoid re-outdenting a row that has already been outdented by a
 3050                // previous selection.
 3051                if let Some(last_row) = last_outdent {
 3052                    if last_row == rows.start {
 3053                        rows.start += 1;
 3054                    }
 3055                }
 3056
 3057                for row in rows {
 3058                    let column = snapshot.indent_column_for_line(row);
 3059                    if column > 0 {
 3060                        let mut deletion_len = column % tab_size;
 3061                        if deletion_len == 0 {
 3062                            deletion_len = tab_size;
 3063                        }
 3064                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 3065                        last_outdent = Some(row);
 3066                    }
 3067                }
 3068            }
 3069        }
 3070
 3071        self.transact(cx, |this, cx| {
 3072            this.buffer.update(cx, |buffer, cx| {
 3073                let empty_str: Arc<str> = "".into();
 3074                buffer.edit(
 3075                    deletion_ranges
 3076                        .into_iter()
 3077                        .map(|range| (range, empty_str.clone())),
 3078                    cx,
 3079                );
 3080            });
 3081            this.update_selections(
 3082                this.local_selections::<usize>(cx),
 3083                Some(Autoscroll::Fit),
 3084                cx,
 3085            );
 3086        });
 3087    }
 3088
 3089    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 3090        let selections = self.local_selections::<Point>(cx);
 3091        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3092        let buffer = self.buffer.read(cx).snapshot(cx);
 3093
 3094        let mut new_cursors = Vec::new();
 3095        let mut edit_ranges = Vec::new();
 3096        let mut selections = selections.iter().peekable();
 3097        while let Some(selection) = selections.next() {
 3098            let mut rows = selection.spanned_rows(false, &display_map);
 3099            let goal_display_column = selection.head().to_display_point(&display_map).column();
 3100
 3101            // Accumulate contiguous regions of rows that we want to delete.
 3102            while let Some(next_selection) = selections.peek() {
 3103                let next_rows = next_selection.spanned_rows(false, &display_map);
 3104                if next_rows.start <= rows.end {
 3105                    rows.end = next_rows.end;
 3106                    selections.next().unwrap();
 3107                } else {
 3108                    break;
 3109                }
 3110            }
 3111
 3112            let mut edit_start = Point::new(rows.start, 0).to_offset(&buffer);
 3113            let edit_end;
 3114            let cursor_buffer_row;
 3115            if buffer.max_point().row >= rows.end {
 3116                // If there's a line after the range, delete the \n from the end of the row range
 3117                // and position the cursor on the next line.
 3118                edit_end = Point::new(rows.end, 0).to_offset(&buffer);
 3119                cursor_buffer_row = rows.end;
 3120            } else {
 3121                // If there isn't a line after the range, delete the \n from the line before the
 3122                // start of the row range and position the cursor there.
 3123                edit_start = edit_start.saturating_sub(1);
 3124                edit_end = buffer.len();
 3125                cursor_buffer_row = rows.start.saturating_sub(1);
 3126            }
 3127
 3128            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 3129            *cursor.column_mut() =
 3130                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 3131
 3132            new_cursors.push((
 3133                selection.id,
 3134                buffer.anchor_after(cursor.to_point(&display_map)),
 3135            ));
 3136            edit_ranges.push(edit_start..edit_end);
 3137        }
 3138
 3139        self.transact(cx, |this, cx| {
 3140            let buffer = this.buffer.update(cx, |buffer, cx| {
 3141                let empty_str: Arc<str> = "".into();
 3142                buffer.edit(
 3143                    edit_ranges
 3144                        .into_iter()
 3145                        .map(|range| (range, empty_str.clone())),
 3146                    cx,
 3147                );
 3148                buffer.snapshot(cx)
 3149            });
 3150            let new_selections = new_cursors
 3151                .into_iter()
 3152                .map(|(id, cursor)| {
 3153                    let cursor = cursor.to_point(&buffer);
 3154                    Selection {
 3155                        id,
 3156                        start: cursor,
 3157                        end: cursor,
 3158                        reversed: false,
 3159                        goal: SelectionGoal::None,
 3160                    }
 3161                })
 3162                .collect();
 3163            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 3164        });
 3165    }
 3166
 3167    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 3168        let selections = self.local_selections::<Point>(cx);
 3169        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3170        let buffer = &display_map.buffer_snapshot;
 3171
 3172        let mut edits = Vec::new();
 3173        let mut selections_iter = selections.iter().peekable();
 3174        while let Some(selection) = selections_iter.next() {
 3175            // Avoid duplicating the same lines twice.
 3176            let mut rows = selection.spanned_rows(false, &display_map);
 3177
 3178            while let Some(next_selection) = selections_iter.peek() {
 3179                let next_rows = next_selection.spanned_rows(false, &display_map);
 3180                if next_rows.start <= rows.end - 1 {
 3181                    rows.end = next_rows.end;
 3182                    selections_iter.next().unwrap();
 3183                } else {
 3184                    break;
 3185                }
 3186            }
 3187
 3188            // Copy the text from the selected row region and splice it at the start of the region.
 3189            let start = Point::new(rows.start, 0);
 3190            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 3191            let text = buffer
 3192                .text_for_range(start..end)
 3193                .chain(Some("\n"))
 3194                .collect::<String>();
 3195            edits.push((start..start, text));
 3196        }
 3197
 3198        self.transact(cx, |this, cx| {
 3199            this.buffer.update(cx, |buffer, cx| {
 3200                buffer.edit(edits, cx);
 3201            });
 3202
 3203            this.request_autoscroll(Autoscroll::Fit, cx);
 3204        });
 3205    }
 3206
 3207    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 3208        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3209        let buffer = self.buffer.read(cx).snapshot(cx);
 3210
 3211        let mut edits = Vec::new();
 3212        let mut unfold_ranges = Vec::new();
 3213        let mut refold_ranges = Vec::new();
 3214
 3215        let selections = self.local_selections::<Point>(cx);
 3216        let mut selections = selections.iter().peekable();
 3217        let mut contiguous_row_selections = Vec::new();
 3218        let mut new_selections = Vec::new();
 3219
 3220        while let Some(selection) = selections.next() {
 3221            // Find all the selections that span a contiguous row range
 3222            contiguous_row_selections.push(selection.clone());
 3223            let start_row = selection.start.row;
 3224            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3225                display_map.next_line_boundary(selection.end).0.row + 1
 3226            } else {
 3227                selection.end.row
 3228            };
 3229
 3230            while let Some(next_selection) = selections.peek() {
 3231                if next_selection.start.row <= end_row {
 3232                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3233                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3234                    } else {
 3235                        next_selection.end.row
 3236                    };
 3237                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3238                } else {
 3239                    break;
 3240                }
 3241            }
 3242
 3243            // Move the text spanned by the row range to be before the line preceding the row range
 3244            if start_row > 0 {
 3245                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 3246                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 3247                let insertion_point = display_map
 3248                    .prev_line_boundary(Point::new(start_row - 1, 0))
 3249                    .0;
 3250
 3251                // Don't move lines across excerpts
 3252                if buffer
 3253                    .excerpt_boundaries_in_range((
 3254                        Bound::Excluded(insertion_point),
 3255                        Bound::Included(range_to_move.end),
 3256                    ))
 3257                    .next()
 3258                    .is_none()
 3259                {
 3260                    let text = buffer
 3261                        .text_for_range(range_to_move.clone())
 3262                        .flat_map(|s| s.chars())
 3263                        .skip(1)
 3264                        .chain(['\n'])
 3265                        .collect::<String>();
 3266
 3267                    edits.push((
 3268                        buffer.anchor_after(range_to_move.start)
 3269                            ..buffer.anchor_before(range_to_move.end),
 3270                        String::new(),
 3271                    ));
 3272                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3273                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3274
 3275                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 3276
 3277                    // Move selections up
 3278                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3279                        |mut selection| {
 3280                            selection.start.row -= row_delta;
 3281                            selection.end.row -= row_delta;
 3282                            selection
 3283                        },
 3284                    ));
 3285
 3286                    // Move folds up
 3287                    unfold_ranges.push(range_to_move.clone());
 3288                    for fold in display_map.folds_in_range(
 3289                        buffer.anchor_before(range_to_move.start)
 3290                            ..buffer.anchor_after(range_to_move.end),
 3291                    ) {
 3292                        let mut start = fold.start.to_point(&buffer);
 3293                        let mut end = fold.end.to_point(&buffer);
 3294                        start.row -= row_delta;
 3295                        end.row -= row_delta;
 3296                        refold_ranges.push(start..end);
 3297                    }
 3298                }
 3299            }
 3300
 3301            // If we didn't move line(s), preserve the existing selections
 3302            new_selections.extend(contiguous_row_selections.drain(..));
 3303        }
 3304
 3305        self.transact(cx, |this, cx| {
 3306            this.unfold_ranges(unfold_ranges, true, cx);
 3307            this.buffer.update(cx, |buffer, cx| {
 3308                for (range, text) in edits {
 3309                    buffer.edit([(range, text)], cx);
 3310                }
 3311            });
 3312            this.fold_ranges(refold_ranges, cx);
 3313            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 3314        });
 3315    }
 3316
 3317    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 3318        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 3319        let buffer = self.buffer.read(cx).snapshot(cx);
 3320
 3321        let mut edits = Vec::new();
 3322        let mut unfold_ranges = Vec::new();
 3323        let mut refold_ranges = Vec::new();
 3324
 3325        let selections = self.local_selections::<Point>(cx);
 3326        let mut selections = selections.iter().peekable();
 3327        let mut contiguous_row_selections = Vec::new();
 3328        let mut new_selections = Vec::new();
 3329
 3330        while let Some(selection) = selections.next() {
 3331            // Find all the selections that span a contiguous row range
 3332            contiguous_row_selections.push(selection.clone());
 3333            let start_row = selection.start.row;
 3334            let mut end_row = if selection.end.column > 0 || selection.is_empty() {
 3335                display_map.next_line_boundary(selection.end).0.row + 1
 3336            } else {
 3337                selection.end.row
 3338            };
 3339
 3340            while let Some(next_selection) = selections.peek() {
 3341                if next_selection.start.row <= end_row {
 3342                    end_row = if next_selection.end.column > 0 || next_selection.is_empty() {
 3343                        display_map.next_line_boundary(next_selection.end).0.row + 1
 3344                    } else {
 3345                        next_selection.end.row
 3346                    };
 3347                    contiguous_row_selections.push(selections.next().unwrap().clone());
 3348                } else {
 3349                    break;
 3350                }
 3351            }
 3352
 3353            // Move the text spanned by the row range to be after the last line of the row range
 3354            if end_row <= buffer.max_point().row {
 3355                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 3356                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 3357
 3358                // Don't move lines across excerpt boundaries
 3359                if buffer
 3360                    .excerpt_boundaries_in_range((
 3361                        Bound::Excluded(range_to_move.start),
 3362                        Bound::Included(insertion_point),
 3363                    ))
 3364                    .next()
 3365                    .is_none()
 3366                {
 3367                    let mut text = String::from("\n");
 3368                    text.extend(buffer.text_for_range(range_to_move.clone()));
 3369                    text.pop(); // Drop trailing newline
 3370                    edits.push((
 3371                        buffer.anchor_after(range_to_move.start)
 3372                            ..buffer.anchor_before(range_to_move.end),
 3373                        String::new(),
 3374                    ));
 3375                    let insertion_anchor = buffer.anchor_after(insertion_point);
 3376                    edits.push((insertion_anchor.clone()..insertion_anchor, text));
 3377
 3378                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 3379
 3380                    // Move selections down
 3381                    new_selections.extend(contiguous_row_selections.drain(..).map(
 3382                        |mut selection| {
 3383                            selection.start.row += row_delta;
 3384                            selection.end.row += row_delta;
 3385                            selection
 3386                        },
 3387                    ));
 3388
 3389                    // Move folds down
 3390                    unfold_ranges.push(range_to_move.clone());
 3391                    for fold in display_map.folds_in_range(
 3392                        buffer.anchor_before(range_to_move.start)
 3393                            ..buffer.anchor_after(range_to_move.end),
 3394                    ) {
 3395                        let mut start = fold.start.to_point(&buffer);
 3396                        let mut end = fold.end.to_point(&buffer);
 3397                        start.row += row_delta;
 3398                        end.row += row_delta;
 3399                        refold_ranges.push(start..end);
 3400                    }
 3401                }
 3402            }
 3403
 3404            // If we didn't move line(s), preserve the existing selections
 3405            new_selections.extend(contiguous_row_selections.drain(..));
 3406        }
 3407
 3408        self.transact(cx, |this, cx| {
 3409            this.unfold_ranges(unfold_ranges, true, cx);
 3410            this.buffer.update(cx, |buffer, cx| {
 3411                for (range, text) in edits {
 3412                    buffer.edit([(range, text)], cx);
 3413                }
 3414            });
 3415            this.fold_ranges(refold_ranges, cx);
 3416            this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 3417        });
 3418    }
 3419
 3420    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 3421        self.transact(cx, |this, cx| {
 3422            let mut edits: Vec<(Range<usize>, String)> = Default::default();
 3423            this.move_selections(cx, |display_map, selection| {
 3424                if !selection.is_empty() {
 3425                    return;
 3426                }
 3427
 3428                let mut head = selection.head();
 3429                let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 3430                if head.column() == display_map.line_len(head.row()) {
 3431                    transpose_offset = display_map
 3432                        .buffer_snapshot
 3433                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3434                }
 3435
 3436                if transpose_offset == 0 {
 3437                    return;
 3438                }
 3439
 3440                *head.column_mut() += 1;
 3441                head = display_map.clip_point(head, Bias::Right);
 3442                selection.collapse_to(head, SelectionGoal::Column(head.column()));
 3443
 3444                let transpose_start = display_map
 3445                    .buffer_snapshot
 3446                    .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 3447                if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 3448                    let transpose_end = display_map
 3449                        .buffer_snapshot
 3450                        .clip_offset(transpose_offset + 1, Bias::Right);
 3451                    if let Some(ch) = display_map.buffer_snapshot.chars_at(transpose_start).next() {
 3452                        edits.push((transpose_start..transpose_offset, String::new()));
 3453                        edits.push((transpose_end..transpose_end, ch.to_string()));
 3454                    }
 3455                }
 3456            });
 3457            this.buffer.update(cx, |buffer, cx| buffer.edit(edits, cx));
 3458            this.update_selections(
 3459                this.local_selections::<usize>(cx),
 3460                Some(Autoscroll::Fit),
 3461                cx,
 3462            );
 3463        });
 3464    }
 3465
 3466    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 3467        let mut text = String::new();
 3468        let mut selections = self.local_selections::<Point>(cx);
 3469        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3470        {
 3471            let buffer = self.buffer.read(cx).read(cx);
 3472            let max_point = buffer.max_point();
 3473            for selection in &mut selections {
 3474                let is_entire_line = selection.is_empty();
 3475                if is_entire_line {
 3476                    selection.start = Point::new(selection.start.row, 0);
 3477                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 3478                    selection.goal = SelectionGoal::None;
 3479                }
 3480                let mut len = 0;
 3481                for chunk in buffer.text_for_range(selection.start..selection.end) {
 3482                    text.push_str(chunk);
 3483                    len += chunk.len();
 3484                }
 3485                clipboard_selections.push(ClipboardSelection {
 3486                    len,
 3487                    is_entire_line,
 3488                });
 3489            }
 3490        }
 3491
 3492        self.transact(cx, |this, cx| {
 3493            this.update_selections(selections, Some(Autoscroll::Fit), cx);
 3494            this.insert("", cx);
 3495            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3496        });
 3497    }
 3498
 3499    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 3500        let selections = self.local_selections::<Point>(cx);
 3501        let mut text = String::new();
 3502        let mut clipboard_selections = Vec::with_capacity(selections.len());
 3503        {
 3504            let buffer = self.buffer.read(cx).read(cx);
 3505            let max_point = buffer.max_point();
 3506            for selection in selections.iter() {
 3507                let mut start = selection.start;
 3508                let mut end = selection.end;
 3509                let is_entire_line = selection.is_empty();
 3510                if is_entire_line {
 3511                    start = Point::new(start.row, 0);
 3512                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
 3513                }
 3514                let mut len = 0;
 3515                for chunk in buffer.text_for_range(start..end) {
 3516                    text.push_str(chunk);
 3517                    len += chunk.len();
 3518                }
 3519                clipboard_selections.push(ClipboardSelection {
 3520                    len,
 3521                    is_entire_line,
 3522                });
 3523            }
 3524        }
 3525
 3526        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 3527    }
 3528
 3529    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 3530        self.transact(cx, |this, cx| {
 3531            if let Some(item) = cx.as_mut().read_from_clipboard() {
 3532                let mut clipboard_text = Cow::Borrowed(item.text());
 3533                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 3534                    let old_selections = this.local_selections::<usize>(cx);
 3535                    let all_selections_were_entire_line =
 3536                        clipboard_selections.iter().all(|s| s.is_entire_line);
 3537                    if clipboard_selections.len() != old_selections.len() {
 3538                        let mut newline_separated_text = String::new();
 3539                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
 3540                        let mut ix = 0;
 3541                        while let Some(clipboard_selection) = clipboard_selections.next() {
 3542                            newline_separated_text
 3543                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
 3544                            ix += clipboard_selection.len;
 3545                            if clipboard_selections.peek().is_some() {
 3546                                newline_separated_text.push('\n');
 3547                            }
 3548                        }
 3549                        clipboard_text = Cow::Owned(newline_separated_text);
 3550                    }
 3551
 3552                    this.buffer.update(cx, |buffer, cx| {
 3553                        let snapshot = buffer.read(cx);
 3554                        let mut start_offset = 0;
 3555                        let mut edits = Vec::new();
 3556                        for (ix, selection) in old_selections.iter().enumerate() {
 3557                            let to_insert;
 3558                            let entire_line;
 3559                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 3560                                let end_offset = start_offset + clipboard_selection.len;
 3561                                to_insert = &clipboard_text[start_offset..end_offset];
 3562                                entire_line = clipboard_selection.is_entire_line;
 3563                                start_offset = end_offset;
 3564                            } else {
 3565                                to_insert = clipboard_text.as_str();
 3566                                entire_line = all_selections_were_entire_line;
 3567                            }
 3568
 3569                            // If the corresponding selection was empty when this slice of the
 3570                            // clipboard text was written, then the entire line containing the
 3571                            // selection was copied. If this selection is also currently empty,
 3572                            // then paste the line before the current line of the buffer.
 3573                            let range = if selection.is_empty() && entire_line {
 3574                                let column = selection.start.to_point(&snapshot).column as usize;
 3575                                let line_start = selection.start - column;
 3576                                line_start..line_start
 3577                            } else {
 3578                                selection.start..selection.end
 3579                            };
 3580
 3581                            edits.push((range, to_insert));
 3582                        }
 3583                        drop(snapshot);
 3584                        buffer.edit_with_autoindent(edits, cx);
 3585                    });
 3586
 3587                    let selections = this.local_selections::<usize>(cx);
 3588                    this.update_selections(selections, Some(Autoscroll::Fit), cx);
 3589                } else {
 3590                    this.insert(&clipboard_text, cx);
 3591                }
 3592            }
 3593        });
 3594    }
 3595
 3596    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 3597        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 3598            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 3599                self.set_selections(selections, None, true, cx);
 3600            }
 3601            self.request_autoscroll(Autoscroll::Fit, cx);
 3602            cx.emit(Event::Edited);
 3603        }
 3604    }
 3605
 3606    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 3607        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 3608            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 3609            {
 3610                self.set_selections(selections, None, true, cx);
 3611            }
 3612            self.request_autoscroll(Autoscroll::Fit, cx);
 3613            cx.emit(Event::Edited);
 3614        }
 3615    }
 3616
 3617    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 3618        self.buffer
 3619            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 3620    }
 3621
 3622    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 3623        self.move_selections(cx, |map, selection| {
 3624            let cursor = if selection.is_empty() {
 3625                movement::left(map, selection.start)
 3626            } else {
 3627                selection.start
 3628            };
 3629            selection.collapse_to(cursor, SelectionGoal::None);
 3630        });
 3631    }
 3632
 3633    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 3634        self.move_selection_heads(cx, |map, head, _| {
 3635            (movement::left(map, head), SelectionGoal::None)
 3636        });
 3637    }
 3638
 3639    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 3640        self.move_selections(cx, |map, selection| {
 3641            let cursor = if selection.is_empty() {
 3642                movement::right(map, selection.end)
 3643            } else {
 3644                selection.end
 3645            };
 3646            selection.collapse_to(cursor, SelectionGoal::None)
 3647        });
 3648    }
 3649
 3650    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 3651        self.move_selection_heads(cx, |map, head, _| {
 3652            (movement::right(map, head), SelectionGoal::None)
 3653        });
 3654    }
 3655
 3656    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 3657        if self.take_rename(true, cx).is_some() {
 3658            return;
 3659        }
 3660
 3661        if let Some(context_menu) = self.context_menu.as_mut() {
 3662            if context_menu.select_prev(cx) {
 3663                return;
 3664            }
 3665        }
 3666
 3667        if matches!(self.mode, EditorMode::SingleLine) {
 3668            cx.propagate_action();
 3669            return;
 3670        }
 3671
 3672        self.move_selections(cx, |map, selection| {
 3673            if !selection.is_empty() {
 3674                selection.goal = SelectionGoal::None;
 3675            }
 3676            let (cursor, goal) = movement::up(&map, selection.start, selection.goal, false);
 3677            selection.collapse_to(cursor, goal);
 3678        });
 3679    }
 3680
 3681    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 3682        self.move_selection_heads(cx, |map, head, goal| movement::up(map, head, goal, false))
 3683    }
 3684
 3685    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 3686        self.take_rename(true, cx);
 3687
 3688        if let Some(context_menu) = self.context_menu.as_mut() {
 3689            if context_menu.select_next(cx) {
 3690                return;
 3691            }
 3692        }
 3693
 3694        if matches!(self.mode, EditorMode::SingleLine) {
 3695            cx.propagate_action();
 3696            return;
 3697        }
 3698
 3699        self.move_selections(cx, |map, selection| {
 3700            if !selection.is_empty() {
 3701                selection.goal = SelectionGoal::None;
 3702            }
 3703            let (cursor, goal) = movement::down(&map, selection.end, selection.goal, false);
 3704            selection.collapse_to(cursor, goal);
 3705        });
 3706    }
 3707
 3708    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 3709        self.move_selection_heads(cx, |map, head, goal| movement::down(map, head, goal, false))
 3710    }
 3711
 3712    pub fn move_to_previous_word_start(
 3713        &mut self,
 3714        _: &MoveToPreviousWordStart,
 3715        cx: &mut ViewContext<Self>,
 3716    ) {
 3717        self.move_cursors(cx, |map, head, _| {
 3718            (
 3719                movement::previous_word_start(map, head),
 3720                SelectionGoal::None,
 3721            )
 3722        });
 3723    }
 3724
 3725    pub fn move_to_previous_subword_start(
 3726        &mut self,
 3727        _: &MoveToPreviousSubwordStart,
 3728        cx: &mut ViewContext<Self>,
 3729    ) {
 3730        self.move_cursors(cx, |map, head, _| {
 3731            (
 3732                movement::previous_subword_start(map, head),
 3733                SelectionGoal::None,
 3734            )
 3735        });
 3736    }
 3737
 3738    pub fn select_to_previous_word_start(
 3739        &mut self,
 3740        _: &SelectToPreviousWordStart,
 3741        cx: &mut ViewContext<Self>,
 3742    ) {
 3743        self.move_selection_heads(cx, |map, head, _| {
 3744            (
 3745                movement::previous_word_start(map, head),
 3746                SelectionGoal::None,
 3747            )
 3748        });
 3749    }
 3750
 3751    pub fn select_to_previous_subword_start(
 3752        &mut self,
 3753        _: &SelectToPreviousSubwordStart,
 3754        cx: &mut ViewContext<Self>,
 3755    ) {
 3756        self.move_selection_heads(cx, |map, head, _| {
 3757            (
 3758                movement::previous_subword_start(map, head),
 3759                SelectionGoal::None,
 3760            )
 3761        });
 3762    }
 3763
 3764    pub fn delete_to_previous_word_start(
 3765        &mut self,
 3766        _: &DeleteToPreviousWordStart,
 3767        cx: &mut ViewContext<Self>,
 3768    ) {
 3769        self.transact(cx, |this, cx| {
 3770            this.move_selections(cx, |map, selection| {
 3771                if selection.is_empty() {
 3772                    let cursor = movement::previous_word_start(map, selection.head());
 3773                    selection.set_head(cursor, SelectionGoal::None);
 3774                }
 3775            });
 3776            this.insert("", cx);
 3777        });
 3778    }
 3779
 3780    pub fn delete_to_previous_subword_start(
 3781        &mut self,
 3782        _: &DeleteToPreviousSubwordStart,
 3783        cx: &mut ViewContext<Self>,
 3784    ) {
 3785        self.transact(cx, |this, cx| {
 3786            this.move_selections(cx, |map, selection| {
 3787                if selection.is_empty() {
 3788                    let cursor = movement::previous_subword_start(map, selection.head());
 3789                    selection.set_head(cursor, SelectionGoal::None);
 3790                }
 3791            });
 3792            this.insert("", cx);
 3793        });
 3794    }
 3795
 3796    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 3797        self.move_cursors(cx, |map, head, _| {
 3798            (movement::next_word_end(map, head), SelectionGoal::None)
 3799        });
 3800    }
 3801
 3802    pub fn move_to_next_subword_end(
 3803        &mut self,
 3804        _: &MoveToNextSubwordEnd,
 3805        cx: &mut ViewContext<Self>,
 3806    ) {
 3807        self.move_cursors(cx, |map, head, _| {
 3808            (movement::next_subword_end(map, head), SelectionGoal::None)
 3809        });
 3810    }
 3811
 3812    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 3813        self.move_selection_heads(cx, |map, head, _| {
 3814            (movement::next_word_end(map, head), SelectionGoal::None)
 3815        });
 3816    }
 3817
 3818    pub fn select_to_next_subword_end(
 3819        &mut self,
 3820        _: &SelectToNextSubwordEnd,
 3821        cx: &mut ViewContext<Self>,
 3822    ) {
 3823        self.move_selection_heads(cx, |map, head, _| {
 3824            (movement::next_subword_end(map, head), SelectionGoal::None)
 3825        });
 3826    }
 3827
 3828    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 3829        self.transact(cx, |this, cx| {
 3830            this.move_selections(cx, |map, selection| {
 3831                if selection.is_empty() {
 3832                    let cursor = movement::next_word_end(map, selection.head());
 3833                    selection.set_head(cursor, SelectionGoal::None);
 3834                }
 3835            });
 3836            this.insert("", cx);
 3837        });
 3838    }
 3839
 3840    pub fn delete_to_next_subword_end(
 3841        &mut self,
 3842        _: &DeleteToNextSubwordEnd,
 3843        cx: &mut ViewContext<Self>,
 3844    ) {
 3845        self.transact(cx, |this, cx| {
 3846            this.move_selections(cx, |map, selection| {
 3847                if selection.is_empty() {
 3848                    let cursor = movement::next_subword_end(map, selection.head());
 3849                    selection.set_head(cursor, SelectionGoal::None);
 3850                }
 3851            });
 3852            this.insert("", cx);
 3853        });
 3854    }
 3855
 3856    pub fn move_to_beginning_of_line(
 3857        &mut self,
 3858        _: &MoveToBeginningOfLine,
 3859        cx: &mut ViewContext<Self>,
 3860    ) {
 3861        self.move_cursors(cx, |map, head, _| {
 3862            (
 3863                movement::line_beginning(map, head, true),
 3864                SelectionGoal::None,
 3865            )
 3866        });
 3867    }
 3868
 3869    pub fn select_to_beginning_of_line(
 3870        &mut self,
 3871        action: &SelectToBeginningOfLine,
 3872        cx: &mut ViewContext<Self>,
 3873    ) {
 3874        self.move_selection_heads(cx, |map, head, _| {
 3875            (
 3876                movement::line_beginning(map, head, action.stop_at_soft_wraps),
 3877                SelectionGoal::None,
 3878            )
 3879        });
 3880    }
 3881
 3882    pub fn delete_to_beginning_of_line(
 3883        &mut self,
 3884        _: &DeleteToBeginningOfLine,
 3885        cx: &mut ViewContext<Self>,
 3886    ) {
 3887        self.transact(cx, |this, cx| {
 3888            this.move_selections(cx, |_, selection| {
 3889                selection.reversed = true;
 3890            });
 3891
 3892            this.select_to_beginning_of_line(
 3893                &SelectToBeginningOfLine {
 3894                    stop_at_soft_wraps: false,
 3895                },
 3896                cx,
 3897            );
 3898            this.backspace(&Backspace, cx);
 3899        });
 3900    }
 3901
 3902    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 3903        self.move_cursors(cx, |map, head, _| {
 3904            (movement::line_end(map, head, true), SelectionGoal::None)
 3905        });
 3906    }
 3907
 3908    pub fn select_to_end_of_line(
 3909        &mut self,
 3910        action: &SelectToEndOfLine,
 3911        cx: &mut ViewContext<Self>,
 3912    ) {
 3913        self.move_selection_heads(cx, |map, head, _| {
 3914            (
 3915                movement::line_end(map, head, action.stop_at_soft_wraps),
 3916                SelectionGoal::None,
 3917            )
 3918        });
 3919    }
 3920
 3921    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 3922        self.transact(cx, |this, cx| {
 3923            this.select_to_end_of_line(
 3924                &SelectToEndOfLine {
 3925                    stop_at_soft_wraps: false,
 3926                },
 3927                cx,
 3928            );
 3929            this.delete(&Delete, cx);
 3930        });
 3931    }
 3932
 3933    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 3934        self.transact(cx, |this, cx| {
 3935            this.select_to_end_of_line(
 3936                &SelectToEndOfLine {
 3937                    stop_at_soft_wraps: false,
 3938                },
 3939                cx,
 3940            );
 3941            this.cut(&Cut, cx);
 3942        });
 3943    }
 3944
 3945    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 3946        if matches!(self.mode, EditorMode::SingleLine) {
 3947            cx.propagate_action();
 3948            return;
 3949        }
 3950
 3951        let selection = Selection {
 3952            id: post_inc(&mut self.next_selection_id),
 3953            start: 0,
 3954            end: 0,
 3955            reversed: false,
 3956            goal: SelectionGoal::None,
 3957        };
 3958        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3959    }
 3960
 3961    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 3962        let mut selection = self.local_selections::<Point>(cx).last().unwrap().clone();
 3963        selection.set_head(Point::zero(), SelectionGoal::None);
 3964        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3965    }
 3966
 3967    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 3968        if matches!(self.mode, EditorMode::SingleLine) {
 3969            cx.propagate_action();
 3970            return;
 3971        }
 3972
 3973        let cursor = self.buffer.read(cx).read(cx).len();
 3974        let selection = Selection {
 3975            id: post_inc(&mut self.next_selection_id),
 3976            start: cursor,
 3977            end: cursor,
 3978            reversed: false,
 3979            goal: SelectionGoal::None,
 3980        };
 3981        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 3982    }
 3983
 3984    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 3985        self.nav_history = nav_history;
 3986    }
 3987
 3988    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 3989        self.nav_history.as_ref()
 3990    }
 3991
 3992    fn push_to_nav_history(
 3993        &self,
 3994        position: Anchor,
 3995        new_position: Option<Point>,
 3996        cx: &mut ViewContext<Self>,
 3997    ) {
 3998        if let Some(nav_history) = &self.nav_history {
 3999            let buffer = self.buffer.read(cx).read(cx);
 4000            let point = position.to_point(&buffer);
 4001            let scroll_top_row = self.scroll_top_anchor.to_point(&buffer).row;
 4002            drop(buffer);
 4003
 4004            if let Some(new_position) = new_position {
 4005                let row_delta = (new_position.row as i64 - point.row as i64).abs();
 4006                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 4007                    return;
 4008                }
 4009            }
 4010
 4011            nav_history.push(Some(NavigationData {
 4012                cursor_anchor: position,
 4013                cursor_position: point,
 4014                scroll_position: self.scroll_position,
 4015                scroll_top_anchor: self.scroll_top_anchor.clone(),
 4016                scroll_top_row,
 4017            }));
 4018        }
 4019    }
 4020
 4021    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 4022        let mut selection = self.local_selections::<usize>(cx).first().unwrap().clone();
 4023        selection.set_head(self.buffer.read(cx).read(cx).len(), SelectionGoal::None);
 4024        self.update_selections(vec![selection], Some(Autoscroll::Fit), cx);
 4025    }
 4026
 4027    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 4028        let selection = Selection {
 4029            id: post_inc(&mut self.next_selection_id),
 4030            start: 0,
 4031            end: self.buffer.read(cx).read(cx).len(),
 4032            reversed: false,
 4033            goal: SelectionGoal::None,
 4034        };
 4035        self.update_selections(vec![selection], None, cx);
 4036    }
 4037
 4038    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 4039        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4040        let mut selections = self.local_selections::<Point>(cx);
 4041        let max_point = display_map.buffer_snapshot.max_point();
 4042        for selection in &mut selections {
 4043            let rows = selection.spanned_rows(true, &display_map);
 4044            selection.start = Point::new(rows.start, 0);
 4045            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 4046            selection.reversed = false;
 4047        }
 4048        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4049    }
 4050
 4051    pub fn split_selection_into_lines(
 4052        &mut self,
 4053        _: &SplitSelectionIntoLines,
 4054        cx: &mut ViewContext<Self>,
 4055    ) {
 4056        let mut to_unfold = Vec::new();
 4057        let mut new_selections = Vec::new();
 4058        {
 4059            let selections = self.local_selections::<Point>(cx);
 4060            let buffer = self.buffer.read(cx).read(cx);
 4061            for selection in selections {
 4062                for row in selection.start.row..selection.end.row {
 4063                    let cursor = Point::new(row, buffer.line_len(row));
 4064                    new_selections.push(Selection {
 4065                        id: post_inc(&mut self.next_selection_id),
 4066                        start: cursor,
 4067                        end: cursor,
 4068                        reversed: false,
 4069                        goal: SelectionGoal::None,
 4070                    });
 4071                }
 4072                new_selections.push(Selection {
 4073                    id: selection.id,
 4074                    start: selection.end,
 4075                    end: selection.end,
 4076                    reversed: false,
 4077                    goal: SelectionGoal::None,
 4078                });
 4079                to_unfold.push(selection.start..selection.end);
 4080            }
 4081        }
 4082        self.unfold_ranges(to_unfold, true, cx);
 4083        self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4084    }
 4085
 4086    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 4087        self.add_selection(true, cx);
 4088    }
 4089
 4090    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 4091        self.add_selection(false, cx);
 4092    }
 4093
 4094    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 4095        self.push_to_selection_history();
 4096        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4097        let mut selections = self.local_selections::<Point>(cx);
 4098        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 4099            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 4100            let range = oldest_selection.display_range(&display_map).sorted();
 4101            let columns = cmp::min(range.start.column(), range.end.column())
 4102                ..cmp::max(range.start.column(), range.end.column());
 4103
 4104            selections.clear();
 4105            let mut stack = Vec::new();
 4106            for row in range.start.row()..=range.end.row() {
 4107                if let Some(selection) = self.build_columnar_selection(
 4108                    &display_map,
 4109                    row,
 4110                    &columns,
 4111                    oldest_selection.reversed,
 4112                ) {
 4113                    stack.push(selection.id);
 4114                    selections.push(selection);
 4115                }
 4116            }
 4117
 4118            if above {
 4119                stack.reverse();
 4120            }
 4121
 4122            AddSelectionsState { above, stack }
 4123        });
 4124
 4125        let last_added_selection = *state.stack.last().unwrap();
 4126        let mut new_selections = Vec::new();
 4127        if above == state.above {
 4128            let end_row = if above {
 4129                0
 4130            } else {
 4131                display_map.max_point().row()
 4132            };
 4133
 4134            'outer: for selection in selections {
 4135                if selection.id == last_added_selection {
 4136                    let range = selection.display_range(&display_map).sorted();
 4137                    debug_assert_eq!(range.start.row(), range.end.row());
 4138                    let mut row = range.start.row();
 4139                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
 4140                    {
 4141                        start..end
 4142                    } else {
 4143                        cmp::min(range.start.column(), range.end.column())
 4144                            ..cmp::max(range.start.column(), range.end.column())
 4145                    };
 4146
 4147                    while row != end_row {
 4148                        if above {
 4149                            row -= 1;
 4150                        } else {
 4151                            row += 1;
 4152                        }
 4153
 4154                        if let Some(new_selection) = self.build_columnar_selection(
 4155                            &display_map,
 4156                            row,
 4157                            &columns,
 4158                            selection.reversed,
 4159                        ) {
 4160                            state.stack.push(new_selection.id);
 4161                            if above {
 4162                                new_selections.push(new_selection);
 4163                                new_selections.push(selection);
 4164                            } else {
 4165                                new_selections.push(selection);
 4166                                new_selections.push(new_selection);
 4167                            }
 4168
 4169                            continue 'outer;
 4170                        }
 4171                    }
 4172                }
 4173
 4174                new_selections.push(selection);
 4175            }
 4176        } else {
 4177            new_selections = selections;
 4178            new_selections.retain(|s| s.id != last_added_selection);
 4179            state.stack.pop();
 4180        }
 4181
 4182        self.update_selections(new_selections, Some(Autoscroll::Newest), cx);
 4183        if state.stack.len() > 1 {
 4184            self.add_selections_state = Some(state);
 4185        }
 4186    }
 4187
 4188    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
 4189        self.push_to_selection_history();
 4190        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4191        let buffer = &display_map.buffer_snapshot;
 4192        let mut selections = self.local_selections::<usize>(cx);
 4193        if let Some(mut select_next_state) = self.select_next_state.take() {
 4194            let query = &select_next_state.query;
 4195            if !select_next_state.done {
 4196                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 4197                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 4198                let mut next_selected_range = None;
 4199
 4200                let bytes_after_last_selection =
 4201                    buffer.bytes_in_range(last_selection.end..buffer.len());
 4202                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 4203                let query_matches = query
 4204                    .stream_find_iter(bytes_after_last_selection)
 4205                    .map(|result| (last_selection.end, result))
 4206                    .chain(
 4207                        query
 4208                            .stream_find_iter(bytes_before_first_selection)
 4209                            .map(|result| (0, result)),
 4210                    );
 4211                for (start_offset, query_match) in query_matches {
 4212                    let query_match = query_match.unwrap(); // can only fail due to I/O
 4213                    let offset_range =
 4214                        start_offset + query_match.start()..start_offset + query_match.end();
 4215                    let display_range = offset_range.start.to_display_point(&display_map)
 4216                        ..offset_range.end.to_display_point(&display_map);
 4217
 4218                    if !select_next_state.wordwise
 4219                        || (!movement::is_inside_word(&display_map, display_range.start)
 4220                            && !movement::is_inside_word(&display_map, display_range.end))
 4221                    {
 4222                        next_selected_range = Some(offset_range);
 4223                        break;
 4224                    }
 4225                }
 4226
 4227                if let Some(next_selected_range) = next_selected_range {
 4228                    if action.replace_newest {
 4229                        if let Some(newest_id) =
 4230                            selections.iter().max_by_key(|s| s.id).map(|s| s.id)
 4231                        {
 4232                            selections.retain(|s| s.id != newest_id);
 4233                        }
 4234                    }
 4235                    selections.push(Selection {
 4236                        id: post_inc(&mut self.next_selection_id),
 4237                        start: next_selected_range.start,
 4238                        end: next_selected_range.end,
 4239                        reversed: false,
 4240                        goal: SelectionGoal::None,
 4241                    });
 4242                    self.unfold_ranges([next_selected_range], false, cx);
 4243                    self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4244                } else {
 4245                    select_next_state.done = true;
 4246                }
 4247            }
 4248
 4249            self.select_next_state = Some(select_next_state);
 4250        } else if selections.len() == 1 {
 4251            let selection = selections.last_mut().unwrap();
 4252            if selection.start == selection.end {
 4253                let word_range = movement::surrounding_word(
 4254                    &display_map,
 4255                    selection.start.to_display_point(&display_map),
 4256                );
 4257                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 4258                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 4259                selection.goal = SelectionGoal::None;
 4260                selection.reversed = false;
 4261
 4262                let query = buffer
 4263                    .text_for_range(selection.start..selection.end)
 4264                    .collect::<String>();
 4265                let select_state = SelectNextState {
 4266                    query: AhoCorasick::new_auto_configured(&[query]),
 4267                    wordwise: true,
 4268                    done: false,
 4269                };
 4270                self.unfold_ranges([selection.start..selection.end], false, cx);
 4271                self.update_selections(selections, Some(Autoscroll::Newest), cx);
 4272                self.select_next_state = Some(select_state);
 4273            } else {
 4274                let query = buffer
 4275                    .text_for_range(selection.start..selection.end)
 4276                    .collect::<String>();
 4277                self.select_next_state = Some(SelectNextState {
 4278                    query: AhoCorasick::new_auto_configured(&[query]),
 4279                    wordwise: false,
 4280                    done: false,
 4281                });
 4282                self.select_next(action, cx);
 4283            }
 4284        }
 4285    }
 4286
 4287    pub fn toggle_comments(&mut self, _: &ToggleComments, cx: &mut ViewContext<Self>) {
 4288        self.transact(cx, |this, cx| {
 4289            let mut selections = this.local_selections::<Point>(cx);
 4290            let mut all_selection_lines_are_comments = true;
 4291            let mut edit_ranges = Vec::new();
 4292            let mut last_toggled_row = None;
 4293            this.buffer.update(cx, |buffer, cx| {
 4294                // TODO: Handle selections that cross excerpts
 4295                for selection in &mut selections {
 4296                    // Get the line comment prefix. Split its trailing whitespace into a separate string,
 4297                    // as that portion won't be used for detecting if a line is a comment.
 4298                    let full_comment_prefix: Arc<str> = if let Some(prefix) = buffer
 4299                        .language_at(selection.start, cx)
 4300                        .and_then(|l| l.line_comment_prefix())
 4301                    {
 4302                        prefix.into()
 4303                    } else {
 4304                        return;
 4305                    };
 4306                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 4307                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 4308                    edit_ranges.clear();
 4309                    let snapshot = buffer.snapshot(cx);
 4310
 4311                    let end_row =
 4312                        if selection.end.row > selection.start.row && selection.end.column == 0 {
 4313                            selection.end.row
 4314                        } else {
 4315                            selection.end.row + 1
 4316                        };
 4317
 4318                    for row in selection.start.row..end_row {
 4319                        // If multiple selections contain a given row, avoid processing that
 4320                        // row more than once.
 4321                        if last_toggled_row == Some(row) {
 4322                            continue;
 4323                        } else {
 4324                            last_toggled_row = Some(row);
 4325                        }
 4326
 4327                        if snapshot.is_line_blank(row) {
 4328                            continue;
 4329                        }
 4330
 4331                        let start = Point::new(row, snapshot.indent_column_for_line(row));
 4332                        let mut line_bytes = snapshot
 4333                            .bytes_in_range(start..snapshot.max_point())
 4334                            .flatten()
 4335                            .copied();
 4336
 4337                        // If this line currently begins with the line comment prefix, then record
 4338                        // the range containing the prefix.
 4339                        if all_selection_lines_are_comments
 4340                            && line_bytes
 4341                                .by_ref()
 4342                                .take(comment_prefix.len())
 4343                                .eq(comment_prefix.bytes())
 4344                        {
 4345                            // Include any whitespace that matches the comment prefix.
 4346                            let matching_whitespace_len = line_bytes
 4347                                .zip(comment_prefix_whitespace.bytes())
 4348                                .take_while(|(a, b)| a == b)
 4349                                .count()
 4350                                as u32;
 4351                            let end = Point::new(
 4352                                row,
 4353                                start.column
 4354                                    + comment_prefix.len() as u32
 4355                                    + matching_whitespace_len,
 4356                            );
 4357                            edit_ranges.push(start..end);
 4358                        }
 4359                        // If this line does not begin with the line comment prefix, then record
 4360                        // the position where the prefix should be inserted.
 4361                        else {
 4362                            all_selection_lines_are_comments = false;
 4363                            edit_ranges.push(start..start);
 4364                        }
 4365                    }
 4366
 4367                    if !edit_ranges.is_empty() {
 4368                        if all_selection_lines_are_comments {
 4369                            let empty_str: Arc<str> = "".into();
 4370                            buffer.edit(
 4371                                edit_ranges
 4372                                    .iter()
 4373                                    .cloned()
 4374                                    .map(|range| (range, empty_str.clone())),
 4375                                cx,
 4376                            );
 4377                        } else {
 4378                            let min_column =
 4379                                edit_ranges.iter().map(|r| r.start.column).min().unwrap();
 4380                            let edits = edit_ranges.iter().map(|range| {
 4381                                let position = Point::new(range.start.row, min_column);
 4382                                (position..position, full_comment_prefix.clone())
 4383                            });
 4384                            buffer.edit(edits, cx);
 4385                        }
 4386                    }
 4387                }
 4388            });
 4389
 4390            this.update_selections(
 4391                this.local_selections::<usize>(cx),
 4392                Some(Autoscroll::Fit),
 4393                cx,
 4394            );
 4395        });
 4396    }
 4397
 4398    pub fn select_larger_syntax_node(
 4399        &mut self,
 4400        _: &SelectLargerSyntaxNode,
 4401        cx: &mut ViewContext<Self>,
 4402    ) {
 4403        let old_selections = self.local_selections::<usize>(cx).into_boxed_slice();
 4404        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4405        let buffer = self.buffer.read(cx).snapshot(cx);
 4406
 4407        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4408        let mut selected_larger_node = false;
 4409        let new_selections = old_selections
 4410            .iter()
 4411            .map(|selection| {
 4412                let old_range = selection.start..selection.end;
 4413                let mut new_range = old_range.clone();
 4414                while let Some(containing_range) =
 4415                    buffer.range_for_syntax_ancestor(new_range.clone())
 4416                {
 4417                    new_range = containing_range;
 4418                    if !display_map.intersects_fold(new_range.start)
 4419                        && !display_map.intersects_fold(new_range.end)
 4420                    {
 4421                        break;
 4422                    }
 4423                }
 4424
 4425                selected_larger_node |= new_range != old_range;
 4426                Selection {
 4427                    id: selection.id,
 4428                    start: new_range.start,
 4429                    end: new_range.end,
 4430                    goal: SelectionGoal::None,
 4431                    reversed: selection.reversed,
 4432                }
 4433            })
 4434            .collect::<Vec<_>>();
 4435
 4436        if selected_larger_node {
 4437            stack.push(old_selections);
 4438            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 4439        }
 4440        self.select_larger_syntax_node_stack = stack;
 4441    }
 4442
 4443    pub fn select_smaller_syntax_node(
 4444        &mut self,
 4445        _: &SelectSmallerSyntaxNode,
 4446        cx: &mut ViewContext<Self>,
 4447    ) {
 4448        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 4449        if let Some(selections) = stack.pop() {
 4450            self.update_selections(selections.to_vec(), Some(Autoscroll::Fit), cx);
 4451        }
 4452        self.select_larger_syntax_node_stack = stack;
 4453    }
 4454
 4455    pub fn move_to_enclosing_bracket(
 4456        &mut self,
 4457        _: &MoveToEnclosingBracket,
 4458        cx: &mut ViewContext<Self>,
 4459    ) {
 4460        let mut selections = self.local_selections::<usize>(cx);
 4461        let buffer = self.buffer.read(cx).snapshot(cx);
 4462        for selection in &mut selections {
 4463            if let Some((open_range, close_range)) =
 4464                buffer.enclosing_bracket_ranges(selection.start..selection.end)
 4465            {
 4466                let close_range = close_range.to_inclusive();
 4467                let destination = if close_range.contains(&selection.start)
 4468                    && close_range.contains(&selection.end)
 4469                {
 4470                    open_range.end
 4471                } else {
 4472                    *close_range.start()
 4473                };
 4474                selection.start = destination;
 4475                selection.end = destination;
 4476            }
 4477        }
 4478
 4479        self.update_selections(selections, Some(Autoscroll::Fit), cx);
 4480    }
 4481
 4482    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 4483        self.end_selection(cx);
 4484        self.selection_history.mode = SelectionHistoryMode::Undoing;
 4485        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 4486            self.set_selections(entry.selections, None, true, cx);
 4487            self.select_next_state = entry.select_next_state;
 4488            self.add_selections_state = entry.add_selections_state;
 4489            self.request_autoscroll(Autoscroll::Newest, cx);
 4490        }
 4491        self.selection_history.mode = SelectionHistoryMode::Normal;
 4492    }
 4493
 4494    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 4495        self.end_selection(cx);
 4496        self.selection_history.mode = SelectionHistoryMode::Redoing;
 4497        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 4498            self.set_selections(entry.selections, None, true, cx);
 4499            self.select_next_state = entry.select_next_state;
 4500            self.add_selections_state = entry.add_selections_state;
 4501            self.request_autoscroll(Autoscroll::Newest, cx);
 4502        }
 4503        self.selection_history.mode = SelectionHistoryMode::Normal;
 4504    }
 4505
 4506    fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext<Self>) {
 4507        self.go_to_diagnostic(Direction::Next, cx)
 4508    }
 4509
 4510    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 4511        self.go_to_diagnostic(Direction::Prev, cx)
 4512    }
 4513
 4514    pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 4515        let buffer = self.buffer.read(cx).snapshot(cx);
 4516        let selection = self.newest_selection_with_snapshot::<usize>(&buffer);
 4517        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 4518            active_diagnostics
 4519                .primary_range
 4520                .to_offset(&buffer)
 4521                .to_inclusive()
 4522        });
 4523        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 4524            if active_primary_range.contains(&selection.head()) {
 4525                *active_primary_range.end()
 4526            } else {
 4527                selection.head()
 4528            }
 4529        } else {
 4530            selection.head()
 4531        };
 4532
 4533        loop {
 4534            let mut diagnostics = if direction == Direction::Prev {
 4535                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 4536            } else {
 4537                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 4538            };
 4539            let group = diagnostics.find_map(|entry| {
 4540                if entry.diagnostic.is_primary
 4541                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 4542                    && !entry.range.is_empty()
 4543                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 4544                {
 4545                    Some((entry.range, entry.diagnostic.group_id))
 4546                } else {
 4547                    None
 4548                }
 4549            });
 4550
 4551            if let Some((primary_range, group_id)) = group {
 4552                self.activate_diagnostics(group_id, cx);
 4553                self.update_selections(
 4554                    vec![Selection {
 4555                        id: selection.id,
 4556                        start: primary_range.start,
 4557                        end: primary_range.start,
 4558                        reversed: false,
 4559                        goal: SelectionGoal::None,
 4560                    }],
 4561                    Some(Autoscroll::Center),
 4562                    cx,
 4563                );
 4564                break;
 4565            } else {
 4566                // Cycle around to the start of the buffer, potentially moving back to the start of
 4567                // the currently active diagnostic.
 4568                active_primary_range.take();
 4569                if direction == Direction::Prev {
 4570                    if search_start == buffer.len() {
 4571                        break;
 4572                    } else {
 4573                        search_start = buffer.len();
 4574                    }
 4575                } else {
 4576                    if search_start == 0 {
 4577                        break;
 4578                    } else {
 4579                        search_start = 0;
 4580                    }
 4581                }
 4582            }
 4583        }
 4584    }
 4585
 4586    pub fn go_to_definition(
 4587        workspace: &mut Workspace,
 4588        _: &GoToDefinition,
 4589        cx: &mut ViewContext<Workspace>,
 4590    ) {
 4591        let active_item = workspace.active_item(cx);
 4592        let editor_handle = if let Some(editor) = active_item
 4593            .as_ref()
 4594            .and_then(|item| item.act_as::<Self>(cx))
 4595        {
 4596            editor
 4597        } else {
 4598            return;
 4599        };
 4600
 4601        let editor = editor_handle.read(cx);
 4602        let head = editor.newest_selection::<usize>(cx).head();
 4603        let (buffer, head) =
 4604            if let Some(text_anchor) = editor.buffer.read(cx).text_anchor_for_position(head, cx) {
 4605                text_anchor
 4606            } else {
 4607                return;
 4608            };
 4609
 4610        let project = workspace.project().clone();
 4611        let definitions = project.update(cx, |project, cx| project.definition(&buffer, head, cx));
 4612        cx.spawn(|workspace, mut cx| async move {
 4613            let definitions = definitions.await?;
 4614            workspace.update(&mut cx, |workspace, cx| {
 4615                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 4616                for definition in definitions {
 4617                    let range = definition.range.to_offset(definition.buffer.read(cx));
 4618
 4619                    let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
 4620                    target_editor_handle.update(cx, |target_editor, cx| {
 4621                        // When selecting a definition in a different buffer, disable the nav history
 4622                        // to avoid creating a history entry at the previous cursor location.
 4623                        if editor_handle != target_editor_handle {
 4624                            nav_history.borrow_mut().disable();
 4625                        }
 4626                        target_editor.select_ranges([range], Some(Autoscroll::Center), cx);
 4627                        nav_history.borrow_mut().enable();
 4628                    });
 4629                }
 4630            });
 4631
 4632            Ok::<(), anyhow::Error>(())
 4633        })
 4634        .detach_and_log_err(cx);
 4635    }
 4636
 4637    pub fn find_all_references(
 4638        workspace: &mut Workspace,
 4639        _: &FindAllReferences,
 4640        cx: &mut ViewContext<Workspace>,
 4641    ) -> Option<Task<Result<()>>> {
 4642        let active_item = workspace.active_item(cx)?;
 4643        let editor_handle = active_item.act_as::<Self>(cx)?;
 4644
 4645        let editor = editor_handle.read(cx);
 4646        let head = editor.newest_selection::<usize>(cx).head();
 4647        let (buffer, head) = editor.buffer.read(cx).text_anchor_for_position(head, cx)?;
 4648        let replica_id = editor.replica_id(cx);
 4649
 4650        let project = workspace.project().clone();
 4651        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4652        Some(cx.spawn(|workspace, mut cx| async move {
 4653            let mut locations = references.await?;
 4654            if locations.is_empty() {
 4655                return Ok(());
 4656            }
 4657
 4658            locations.sort_by_key(|location| location.buffer.id());
 4659            let mut locations = locations.into_iter().peekable();
 4660            let mut ranges_to_highlight = Vec::new();
 4661
 4662            let excerpt_buffer = cx.add_model(|cx| {
 4663                let mut symbol_name = None;
 4664                let mut multibuffer = MultiBuffer::new(replica_id);
 4665                while let Some(location) = locations.next() {
 4666                    let buffer = location.buffer.read(cx);
 4667                    let mut ranges_for_buffer = Vec::new();
 4668                    let range = location.range.to_offset(buffer);
 4669                    ranges_for_buffer.push(range.clone());
 4670                    if symbol_name.is_none() {
 4671                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4672                    }
 4673
 4674                    while let Some(next_location) = locations.peek() {
 4675                        if next_location.buffer == location.buffer {
 4676                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4677                            locations.next();
 4678                        } else {
 4679                            break;
 4680                        }
 4681                    }
 4682
 4683                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4684                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4685                        location.buffer.clone(),
 4686                        ranges_for_buffer,
 4687                        1,
 4688                        cx,
 4689                    ));
 4690                }
 4691                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4692            });
 4693
 4694            workspace.update(&mut cx, |workspace, cx| {
 4695                let editor =
 4696                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4697                editor.update(cx, |editor, cx| {
 4698                    editor.highlight_background::<Self>(
 4699                        ranges_to_highlight,
 4700                        |theme| theme.editor.highlighted_line_background,
 4701                        cx,
 4702                    );
 4703                });
 4704                workspace.add_item(Box::new(editor), cx);
 4705            });
 4706
 4707            Ok(())
 4708        }))
 4709    }
 4710
 4711    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4712        use language::ToOffset as _;
 4713
 4714        let project = self.project.clone()?;
 4715        let selection = self.newest_anchor_selection().clone();
 4716        let (cursor_buffer, cursor_buffer_position) = self
 4717            .buffer
 4718            .read(cx)
 4719            .text_anchor_for_position(selection.head(), cx)?;
 4720        let (tail_buffer, _) = self
 4721            .buffer
 4722            .read(cx)
 4723            .text_anchor_for_position(selection.tail(), cx)?;
 4724        if tail_buffer != cursor_buffer {
 4725            return None;
 4726        }
 4727
 4728        let snapshot = cursor_buffer.read(cx).snapshot();
 4729        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4730        let prepare_rename = project.update(cx, |project, cx| {
 4731            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4732        });
 4733
 4734        Some(cx.spawn(|this, mut cx| async move {
 4735            let rename_range = if let Some(range) = prepare_rename.await? {
 4736                Some(range)
 4737            } else {
 4738                this.read_with(&cx, |this, cx| {
 4739                    let buffer = this.buffer.read(cx).snapshot(cx);
 4740                    let mut buffer_highlights = this
 4741                        .document_highlights_for_position(selection.head(), &buffer)
 4742                        .filter(|highlight| {
 4743                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4744                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4745                        });
 4746                    buffer_highlights
 4747                        .next()
 4748                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4749                })
 4750            };
 4751            if let Some(rename_range) = rename_range {
 4752                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4753                let cursor_offset_in_rename_range =
 4754                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4755
 4756                this.update(&mut cx, |this, cx| {
 4757                    this.take_rename(false, cx);
 4758                    let style = this.style(cx);
 4759                    let buffer = this.buffer.read(cx).read(cx);
 4760                    let cursor_offset = selection.head().to_offset(&buffer);
 4761                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4762                    let rename_end = rename_start + rename_buffer_range.len();
 4763                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4764                    let mut old_highlight_id = None;
 4765                    let old_name: Arc<str> = buffer
 4766                        .chunks(rename_start..rename_end, true)
 4767                        .map(|chunk| {
 4768                            if old_highlight_id.is_none() {
 4769                                old_highlight_id = chunk.syntax_highlight_id;
 4770                            }
 4771                            chunk.text
 4772                        })
 4773                        .collect::<String>()
 4774                        .into();
 4775
 4776                    drop(buffer);
 4777
 4778                    // Position the selection in the rename editor so that it matches the current selection.
 4779                    this.show_local_selections = false;
 4780                    let rename_editor = cx.add_view(|cx| {
 4781                        let mut editor = Editor::single_line(None, cx);
 4782                        if let Some(old_highlight_id) = old_highlight_id {
 4783                            editor.override_text_style =
 4784                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4785                        }
 4786                        editor
 4787                            .buffer
 4788                            .update(cx, |buffer, cx| buffer.edit([(0..0, old_name.clone())], cx));
 4789                        editor.select_all(&SelectAll, cx);
 4790                        editor
 4791                    });
 4792
 4793                    let ranges = this
 4794                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4795                        .into_iter()
 4796                        .flat_map(|(_, ranges)| ranges)
 4797                        .chain(
 4798                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4799                                .into_iter()
 4800                                .flat_map(|(_, ranges)| ranges),
 4801                        )
 4802                        .collect();
 4803
 4804                    this.highlight_text::<Rename>(
 4805                        ranges,
 4806                        HighlightStyle {
 4807                            fade_out: Some(style.rename_fade),
 4808                            ..Default::default()
 4809                        },
 4810                        cx,
 4811                    );
 4812                    cx.focus(&rename_editor);
 4813                    let block_id = this.insert_blocks(
 4814                        [BlockProperties {
 4815                            position: range.start.clone(),
 4816                            height: 1,
 4817                            render: Arc::new({
 4818                                let editor = rename_editor.clone();
 4819                                move |cx: &BlockContext| {
 4820                                    ChildView::new(editor.clone())
 4821                                        .contained()
 4822                                        .with_padding_left(cx.anchor_x)
 4823                                        .boxed()
 4824                                }
 4825                            }),
 4826                            disposition: BlockDisposition::Below,
 4827                        }],
 4828                        cx,
 4829                    )[0];
 4830                    this.pending_rename = Some(RenameState {
 4831                        range,
 4832                        old_name,
 4833                        editor: rename_editor,
 4834                        block_id,
 4835                    });
 4836                });
 4837            }
 4838
 4839            Ok(())
 4840        }))
 4841    }
 4842
 4843    pub fn confirm_rename(
 4844        workspace: &mut Workspace,
 4845        _: &ConfirmRename,
 4846        cx: &mut ViewContext<Workspace>,
 4847    ) -> Option<Task<Result<()>>> {
 4848        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4849
 4850        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4851            let rename = editor.take_rename(false, cx)?;
 4852            let buffer = editor.buffer.read(cx);
 4853            let (start_buffer, start) =
 4854                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4855            let (end_buffer, end) =
 4856                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4857            if start_buffer == end_buffer {
 4858                let new_name = rename.editor.read(cx).text(cx);
 4859                Some((start_buffer, start..end, rename.old_name, new_name))
 4860            } else {
 4861                None
 4862            }
 4863        })?;
 4864
 4865        let rename = workspace.project().clone().update(cx, |project, cx| {
 4866            project.perform_rename(
 4867                buffer.clone(),
 4868                range.start.clone(),
 4869                new_name.clone(),
 4870                true,
 4871                cx,
 4872            )
 4873        });
 4874
 4875        Some(cx.spawn(|workspace, mut cx| async move {
 4876            let project_transaction = rename.await?;
 4877            Self::open_project_transaction(
 4878                editor.clone(),
 4879                workspace,
 4880                project_transaction,
 4881                format!("Rename: {}{}", old_name, new_name),
 4882                cx.clone(),
 4883            )
 4884            .await?;
 4885
 4886            editor.update(&mut cx, |editor, cx| {
 4887                editor.refresh_document_highlights(cx);
 4888            });
 4889            Ok(())
 4890        }))
 4891    }
 4892
 4893    fn take_rename(
 4894        &mut self,
 4895        moving_cursor: bool,
 4896        cx: &mut ViewContext<Self>,
 4897    ) -> Option<RenameState> {
 4898        let rename = self.pending_rename.take()?;
 4899        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4900        self.clear_text_highlights::<Rename>(cx);
 4901        self.show_local_selections = true;
 4902
 4903        if moving_cursor {
 4904            let cursor_in_rename_editor =
 4905                rename.editor.read(cx).newest_selection::<usize>(cx).head();
 4906
 4907            // Update the selection to match the position of the selection inside
 4908            // the rename editor.
 4909            let snapshot = self.buffer.read(cx).read(cx);
 4910            let rename_range = rename.range.to_offset(&snapshot);
 4911            let cursor_in_editor = snapshot
 4912                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4913                .min(rename_range.end);
 4914            drop(snapshot);
 4915
 4916            self.update_selections(
 4917                vec![Selection {
 4918                    id: self.newest_anchor_selection().id,
 4919                    start: cursor_in_editor,
 4920                    end: cursor_in_editor,
 4921                    reversed: false,
 4922                    goal: SelectionGoal::None,
 4923                }],
 4924                None,
 4925                cx,
 4926            );
 4927        }
 4928
 4929        Some(rename)
 4930    }
 4931
 4932    #[cfg(any(test, feature = "test-support"))]
 4933    pub fn pending_rename(&self) -> Option<&RenameState> {
 4934        self.pending_rename.as_ref()
 4935    }
 4936
 4937    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4938        if let Some(project) = self.project.clone() {
 4939            self.buffer.update(cx, |multi_buffer, cx| {
 4940                project.update(cx, |project, cx| {
 4941                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4942                });
 4943            })
 4944        }
 4945    }
 4946
 4947    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4948        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4949            let buffer = self.buffer.read(cx).snapshot(cx);
 4950            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4951            let is_valid = buffer
 4952                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4953                .any(|entry| {
 4954                    entry.diagnostic.is_primary
 4955                        && !entry.range.is_empty()
 4956                        && entry.range.start == primary_range_start
 4957                        && entry.diagnostic.message == active_diagnostics.primary_message
 4958                });
 4959
 4960            if is_valid != active_diagnostics.is_valid {
 4961                active_diagnostics.is_valid = is_valid;
 4962                let mut new_styles = HashMap::default();
 4963                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4964                    new_styles.insert(
 4965                        *block_id,
 4966                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4967                    );
 4968                }
 4969                self.display_map
 4970                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4971            }
 4972        }
 4973    }
 4974
 4975    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4976        self.dismiss_diagnostics(cx);
 4977        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4978            let buffer = self.buffer.read(cx).snapshot(cx);
 4979
 4980            let mut primary_range = None;
 4981            let mut primary_message = None;
 4982            let mut group_end = Point::zero();
 4983            let diagnostic_group = buffer
 4984                .diagnostic_group::<Point>(group_id)
 4985                .map(|entry| {
 4986                    if entry.range.end > group_end {
 4987                        group_end = entry.range.end;
 4988                    }
 4989                    if entry.diagnostic.is_primary {
 4990                        primary_range = Some(entry.range.clone());
 4991                        primary_message = Some(entry.diagnostic.message.clone());
 4992                    }
 4993                    entry
 4994                })
 4995                .collect::<Vec<_>>();
 4996            let primary_range = primary_range.unwrap();
 4997            let primary_message = primary_message.unwrap();
 4998            let primary_range =
 4999                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 5000
 5001            let blocks = display_map
 5002                .insert_blocks(
 5003                    diagnostic_group.iter().map(|entry| {
 5004                        let diagnostic = entry.diagnostic.clone();
 5005                        let message_height = diagnostic.message.lines().count() as u8;
 5006                        BlockProperties {
 5007                            position: buffer.anchor_after(entry.range.start),
 5008                            height: message_height,
 5009                            render: diagnostic_block_renderer(diagnostic, true),
 5010                            disposition: BlockDisposition::Below,
 5011                        }
 5012                    }),
 5013                    cx,
 5014                )
 5015                .into_iter()
 5016                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5017                .collect();
 5018
 5019            Some(ActiveDiagnosticGroup {
 5020                primary_range,
 5021                primary_message,
 5022                blocks,
 5023                is_valid: true,
 5024            })
 5025        });
 5026    }
 5027
 5028    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5029        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5030            self.display_map.update(cx, |display_map, cx| {
 5031                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5032            });
 5033            cx.notify();
 5034        }
 5035    }
 5036
 5037    fn build_columnar_selection(
 5038        &mut self,
 5039        display_map: &DisplaySnapshot,
 5040        row: u32,
 5041        columns: &Range<u32>,
 5042        reversed: bool,
 5043    ) -> Option<Selection<Point>> {
 5044        let is_empty = columns.start == columns.end;
 5045        let line_len = display_map.line_len(row);
 5046        if columns.start < line_len || (is_empty && columns.start == line_len) {
 5047            let start = DisplayPoint::new(row, columns.start);
 5048            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
 5049            Some(Selection {
 5050                id: post_inc(&mut self.next_selection_id),
 5051                start: start.to_point(display_map),
 5052                end: end.to_point(display_map),
 5053                reversed,
 5054                goal: SelectionGoal::ColumnRange {
 5055                    start: columns.start,
 5056                    end: columns.end,
 5057                },
 5058            })
 5059        } else {
 5060            None
 5061        }
 5062    }
 5063
 5064    pub fn local_selections_in_range(
 5065        &self,
 5066        range: Range<Anchor>,
 5067        display_map: &DisplaySnapshot,
 5068    ) -> Vec<Selection<Point>> {
 5069        let buffer = &display_map.buffer_snapshot;
 5070
 5071        let start_ix = match self
 5072            .selections
 5073            .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
 5074        {
 5075            Ok(ix) | Err(ix) => ix,
 5076        };
 5077        let end_ix = match self
 5078            .selections
 5079            .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
 5080        {
 5081            Ok(ix) => ix + 1,
 5082            Err(ix) => ix,
 5083        };
 5084
 5085        fn point_selection(
 5086            selection: &Selection<Anchor>,
 5087            buffer: &MultiBufferSnapshot,
 5088        ) -> Selection<Point> {
 5089            let start = selection.start.to_point(&buffer);
 5090            let end = selection.end.to_point(&buffer);
 5091            Selection {
 5092                id: selection.id,
 5093                start,
 5094                end,
 5095                reversed: selection.reversed,
 5096                goal: selection.goal,
 5097            }
 5098        }
 5099
 5100        self.selections[start_ix..end_ix]
 5101            .iter()
 5102            .chain(
 5103                self.pending_selection
 5104                    .as_ref()
 5105                    .map(|pending| &pending.selection),
 5106            )
 5107            .map(|s| point_selection(s, &buffer))
 5108            .collect()
 5109    }
 5110
 5111    pub fn local_selections<'a, D>(&self, cx: &'a AppContext) -> Vec<Selection<D>>
 5112    where
 5113        D: 'a + TextDimension + Ord + Sub<D, Output = D>,
 5114    {
 5115        let buffer = self.buffer.read(cx).snapshot(cx);
 5116        let mut selections = self
 5117            .resolve_selections::<D, _>(self.selections.iter(), &buffer)
 5118            .peekable();
 5119
 5120        let mut pending_selection = self.pending_selection::<D>(&buffer);
 5121
 5122        iter::from_fn(move || {
 5123            if let Some(pending) = pending_selection.as_mut() {
 5124                while let Some(next_selection) = selections.peek() {
 5125                    if pending.start <= next_selection.end && pending.end >= next_selection.start {
 5126                        let next_selection = selections.next().unwrap();
 5127                        if next_selection.start < pending.start {
 5128                            pending.start = next_selection.start;
 5129                        }
 5130                        if next_selection.end > pending.end {
 5131                            pending.end = next_selection.end;
 5132                        }
 5133                    } else if next_selection.end < pending.start {
 5134                        return selections.next();
 5135                    } else {
 5136                        break;
 5137                    }
 5138                }
 5139
 5140                pending_selection.take()
 5141            } else {
 5142                selections.next()
 5143            }
 5144        })
 5145        .collect()
 5146    }
 5147
 5148    fn resolve_selections<'a, D, I>(
 5149        &self,
 5150        selections: I,
 5151        snapshot: &MultiBufferSnapshot,
 5152    ) -> impl 'a + Iterator<Item = Selection<D>>
 5153    where
 5154        D: TextDimension + Ord + Sub<D, Output = D>,
 5155        I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
 5156    {
 5157        let (to_summarize, selections) = selections.into_iter().tee();
 5158        let mut summaries = snapshot
 5159            .summaries_for_anchors::<D, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
 5160            .into_iter();
 5161        selections.map(move |s| Selection {
 5162            id: s.id,
 5163            start: summaries.next().unwrap(),
 5164            end: summaries.next().unwrap(),
 5165            reversed: s.reversed,
 5166            goal: s.goal,
 5167        })
 5168    }
 5169
 5170    fn pending_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5171        &self,
 5172        snapshot: &MultiBufferSnapshot,
 5173    ) -> Option<Selection<D>> {
 5174        self.pending_selection
 5175            .as_ref()
 5176            .map(|pending| self.resolve_selection(&pending.selection, &snapshot))
 5177    }
 5178
 5179    fn resolve_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5180        &self,
 5181        selection: &Selection<Anchor>,
 5182        buffer: &MultiBufferSnapshot,
 5183    ) -> Selection<D> {
 5184        Selection {
 5185            id: selection.id,
 5186            start: selection.start.summary::<D>(&buffer),
 5187            end: selection.end.summary::<D>(&buffer),
 5188            reversed: selection.reversed,
 5189            goal: selection.goal,
 5190        }
 5191    }
 5192
 5193    fn selection_count<'a>(&self) -> usize {
 5194        let mut count = self.selections.len();
 5195        if self.pending_selection.is_some() {
 5196            count += 1;
 5197        }
 5198        count
 5199    }
 5200
 5201    pub fn oldest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5202        &self,
 5203        cx: &AppContext,
 5204    ) -> Selection<D> {
 5205        let snapshot = self.buffer.read(cx).read(cx);
 5206        self.selections
 5207            .iter()
 5208            .min_by_key(|s| s.id)
 5209            .map(|selection| self.resolve_selection(selection, &snapshot))
 5210            .or_else(|| self.pending_selection(&snapshot))
 5211            .unwrap()
 5212    }
 5213
 5214    pub fn newest_selection<D: TextDimension + Ord + Sub<D, Output = D>>(
 5215        &self,
 5216        cx: &AppContext,
 5217    ) -> Selection<D> {
 5218        self.resolve_selection(
 5219            self.newest_anchor_selection(),
 5220            &self.buffer.read(cx).read(cx),
 5221        )
 5222    }
 5223
 5224    pub fn newest_selection_with_snapshot<D: TextDimension + Ord + Sub<D, Output = D>>(
 5225        &self,
 5226        snapshot: &MultiBufferSnapshot,
 5227    ) -> Selection<D> {
 5228        self.resolve_selection(self.newest_anchor_selection(), snapshot)
 5229    }
 5230
 5231    pub fn newest_anchor_selection(&self) -> &Selection<Anchor> {
 5232        self.pending_selection
 5233            .as_ref()
 5234            .map(|s| &s.selection)
 5235            .or_else(|| self.selections.iter().max_by_key(|s| s.id))
 5236            .unwrap()
 5237    }
 5238
 5239    pub fn update_selections<T>(
 5240        &mut self,
 5241        mut selections: Vec<Selection<T>>,
 5242        autoscroll: Option<Autoscroll>,
 5243        cx: &mut ViewContext<Self>,
 5244    ) where
 5245        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
 5246    {
 5247        let buffer = self.buffer.read(cx).snapshot(cx);
 5248        selections.sort_unstable_by_key(|s| s.start);
 5249
 5250        // Merge overlapping selections.
 5251        let mut i = 1;
 5252        while i < selections.len() {
 5253            if selections[i - 1].end >= selections[i].start {
 5254                let removed = selections.remove(i);
 5255                if removed.start < selections[i - 1].start {
 5256                    selections[i - 1].start = removed.start;
 5257                }
 5258                if removed.end > selections[i - 1].end {
 5259                    selections[i - 1].end = removed.end;
 5260                }
 5261            } else {
 5262                i += 1;
 5263            }
 5264        }
 5265
 5266        if let Some(autoscroll) = autoscroll {
 5267            self.request_autoscroll(autoscroll, cx);
 5268        }
 5269
 5270        self.set_selections(
 5271            Arc::from_iter(selections.into_iter().map(|selection| {
 5272                let end_bias = if selection.end > selection.start {
 5273                    Bias::Left
 5274                } else {
 5275                    Bias::Right
 5276                };
 5277                Selection {
 5278                    id: selection.id,
 5279                    start: buffer.anchor_after(selection.start),
 5280                    end: buffer.anchor_at(selection.end, end_bias),
 5281                    reversed: selection.reversed,
 5282                    goal: selection.goal,
 5283                }
 5284            })),
 5285            None,
 5286            true,
 5287            cx,
 5288        );
 5289    }
 5290
 5291    pub fn set_selections_from_remote(
 5292        &mut self,
 5293        mut selections: Vec<Selection<Anchor>>,
 5294        cx: &mut ViewContext<Self>,
 5295    ) {
 5296        let buffer = self.buffer.read(cx);
 5297        let buffer = buffer.read(cx);
 5298        selections.sort_by(|a, b| {
 5299            a.start
 5300                .cmp(&b.start, &*buffer)
 5301                .then_with(|| b.end.cmp(&a.end, &*buffer))
 5302        });
 5303
 5304        // Merge overlapping selections
 5305        let mut i = 1;
 5306        while i < selections.len() {
 5307            if selections[i - 1]
 5308                .end
 5309                .cmp(&selections[i].start, &*buffer)
 5310                .is_ge()
 5311            {
 5312                let removed = selections.remove(i);
 5313                if removed
 5314                    .start
 5315                    .cmp(&selections[i - 1].start, &*buffer)
 5316                    .is_lt()
 5317                {
 5318                    selections[i - 1].start = removed.start;
 5319                }
 5320                if removed.end.cmp(&selections[i - 1].end, &*buffer).is_gt() {
 5321                    selections[i - 1].end = removed.end;
 5322                }
 5323            } else {
 5324                i += 1;
 5325            }
 5326        }
 5327
 5328        drop(buffer);
 5329        self.set_selections(selections.into(), None, false, cx);
 5330    }
 5331
 5332    /// Compute new ranges for any selections that were located in excerpts that have
 5333    /// since been removed.
 5334    ///
 5335    /// Returns a `HashMap` indicating which selections whose former head position
 5336    /// was no longer present. The keys of the map are selection ids. The values are
 5337    /// the id of the new excerpt where the head of the selection has been moved.
 5338    pub fn refresh_selections(&mut self, cx: &mut ViewContext<Self>) -> HashMap<usize, ExcerptId> {
 5339        let snapshot = self.buffer.read(cx).read(cx);
 5340        let mut selections_with_lost_position = HashMap::default();
 5341
 5342        let mut pending_selection = self.pending_selection.take();
 5343        if let Some(pending) = pending_selection.as_mut() {
 5344            let anchors =
 5345                snapshot.refresh_anchors([&pending.selection.start, &pending.selection.end]);
 5346            let (_, start, kept_start) = anchors[0].clone();
 5347            let (_, end, kept_end) = anchors[1].clone();
 5348            let kept_head = if pending.selection.reversed {
 5349                kept_start
 5350            } else {
 5351                kept_end
 5352            };
 5353            if !kept_head {
 5354                selections_with_lost_position.insert(
 5355                    pending.selection.id,
 5356                    pending.selection.head().excerpt_id.clone(),
 5357                );
 5358            }
 5359
 5360            pending.selection.start = start;
 5361            pending.selection.end = end;
 5362        }
 5363
 5364        let anchors_with_status = snapshot.refresh_anchors(
 5365            self.selections
 5366                .iter()
 5367                .flat_map(|selection| [&selection.start, &selection.end]),
 5368        );
 5369        self.selections = anchors_with_status
 5370            .chunks(2)
 5371            .map(|selection_anchors| {
 5372                let (anchor_ix, start, kept_start) = selection_anchors[0].clone();
 5373                let (_, end, kept_end) = selection_anchors[1].clone();
 5374                let selection = &self.selections[anchor_ix / 2];
 5375                let kept_head = if selection.reversed {
 5376                    kept_start
 5377                } else {
 5378                    kept_end
 5379                };
 5380                if !kept_head {
 5381                    selections_with_lost_position
 5382                        .insert(selection.id, selection.head().excerpt_id.clone());
 5383                }
 5384
 5385                Selection {
 5386                    id: selection.id,
 5387                    start,
 5388                    end,
 5389                    reversed: selection.reversed,
 5390                    goal: selection.goal,
 5391                }
 5392            })
 5393            .collect();
 5394        drop(snapshot);
 5395
 5396        let new_selections = self.local_selections::<usize>(cx);
 5397        if !new_selections.is_empty() {
 5398            self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
 5399        }
 5400        self.pending_selection = pending_selection;
 5401
 5402        selections_with_lost_position
 5403    }
 5404
 5405    fn set_selections(
 5406        &mut self,
 5407        selections: Arc<[Selection<Anchor>]>,
 5408        pending_selection: Option<PendingSelection>,
 5409        local: bool,
 5410        cx: &mut ViewContext<Self>,
 5411    ) {
 5412        assert!(
 5413            !selections.is_empty() || pending_selection.is_some(),
 5414            "must have at least one selection"
 5415        );
 5416
 5417        let old_cursor_position = self.newest_anchor_selection().head();
 5418
 5419        self.push_to_selection_history();
 5420        self.selections = selections;
 5421        self.pending_selection = pending_selection;
 5422        if self.focused && self.leader_replica_id.is_none() {
 5423            self.buffer.update(cx, |buffer, cx| {
 5424                buffer.set_active_selections(&self.selections, cx)
 5425            });
 5426        }
 5427
 5428        let display_map = self
 5429            .display_map
 5430            .update(cx, |display_map, cx| display_map.snapshot(cx));
 5431        let buffer = &display_map.buffer_snapshot;
 5432        self.add_selections_state = None;
 5433        self.select_next_state = None;
 5434        self.select_larger_syntax_node_stack.clear();
 5435        self.autoclose_stack.invalidate(&self.selections, &buffer);
 5436        self.snippet_stack.invalidate(&self.selections, &buffer);
 5437        self.take_rename(false, cx);
 5438
 5439        let new_cursor_position = self.newest_anchor_selection().head();
 5440
 5441        self.push_to_nav_history(
 5442            old_cursor_position.clone(),
 5443            Some(new_cursor_position.to_point(&buffer)),
 5444            cx,
 5445        );
 5446
 5447        if local {
 5448            let completion_menu = match self.context_menu.as_mut() {
 5449                Some(ContextMenu::Completions(menu)) => Some(menu),
 5450                _ => {
 5451                    self.context_menu.take();
 5452                    None
 5453                }
 5454            };
 5455
 5456            if let Some(completion_menu) = completion_menu {
 5457                let cursor_position = new_cursor_position.to_offset(&buffer);
 5458                let (word_range, kind) =
 5459                    buffer.surrounding_word(completion_menu.initial_position.clone());
 5460                if kind == Some(CharKind::Word)
 5461                    && word_range.to_inclusive().contains(&cursor_position)
 5462                {
 5463                    let query = Self::completion_query(&buffer, cursor_position);
 5464                    cx.background()
 5465                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
 5466                    self.show_completions(&ShowCompletions, cx);
 5467                } else {
 5468                    self.hide_context_menu(cx);
 5469                }
 5470            }
 5471
 5472            if old_cursor_position.to_display_point(&display_map).row()
 5473                != new_cursor_position.to_display_point(&display_map).row()
 5474            {
 5475                self.available_code_actions.take();
 5476            }
 5477            self.refresh_code_actions(cx);
 5478            self.refresh_document_highlights(cx);
 5479        }
 5480
 5481        self.pause_cursor_blinking(cx);
 5482        cx.emit(Event::SelectionsChanged { local });
 5483    }
 5484
 5485    fn push_to_selection_history(&mut self) {
 5486        self.selection_history.push(SelectionHistoryEntry {
 5487            selections: self.selections.clone(),
 5488            select_next_state: self.select_next_state.clone(),
 5489            add_selections_state: self.add_selections_state.clone(),
 5490        });
 5491    }
 5492
 5493    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5494        self.autoscroll_request = Some((autoscroll, true));
 5495        cx.notify();
 5496    }
 5497
 5498    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5499        self.autoscroll_request = Some((autoscroll, false));
 5500        cx.notify();
 5501    }
 5502
 5503    pub fn transact(
 5504        &mut self,
 5505        cx: &mut ViewContext<Self>,
 5506        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5507    ) {
 5508        self.start_transaction_at(Instant::now(), cx);
 5509        update(self, cx);
 5510        self.end_transaction_at(Instant::now(), cx);
 5511    }
 5512
 5513    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5514        self.end_selection(cx);
 5515        if let Some(tx_id) = self
 5516            .buffer
 5517            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5518        {
 5519            self.selection_history
 5520                .insert_transaction(tx_id, self.selections.clone());
 5521        }
 5522    }
 5523
 5524    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5525        if let Some(tx_id) = self
 5526            .buffer
 5527            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5528        {
 5529            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5530                *end_selections = Some(self.selections.clone());
 5531            } else {
 5532                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5533            }
 5534
 5535            cx.emit(Event::Edited);
 5536        }
 5537    }
 5538
 5539    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5540        log::info!("Editor::page_up");
 5541    }
 5542
 5543    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5544        log::info!("Editor::page_down");
 5545    }
 5546
 5547    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5548        let mut fold_ranges = Vec::new();
 5549
 5550        let selections = self.local_selections::<Point>(cx);
 5551        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5552        for selection in selections {
 5553            let range = selection.display_range(&display_map).sorted();
 5554            let buffer_start_row = range.start.to_point(&display_map).row;
 5555
 5556            for row in (0..=range.end.row()).rev() {
 5557                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5558                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5559                    if fold_range.end.row >= buffer_start_row {
 5560                        fold_ranges.push(fold_range);
 5561                        if row <= range.start.row() {
 5562                            break;
 5563                        }
 5564                    }
 5565                }
 5566            }
 5567        }
 5568
 5569        self.fold_ranges(fold_ranges, cx);
 5570    }
 5571
 5572    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5573        let selections = self.local_selections::<Point>(cx);
 5574        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5575        let buffer = &display_map.buffer_snapshot;
 5576        let ranges = selections
 5577            .iter()
 5578            .map(|s| {
 5579                let range = s.display_range(&display_map).sorted();
 5580                let mut start = range.start.to_point(&display_map);
 5581                let mut end = range.end.to_point(&display_map);
 5582                start.column = 0;
 5583                end.column = buffer.line_len(end.row);
 5584                start..end
 5585            })
 5586            .collect::<Vec<_>>();
 5587        self.unfold_ranges(ranges, true, cx);
 5588    }
 5589
 5590    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5591        let max_point = display_map.max_point();
 5592        if display_row >= max_point.row() {
 5593            false
 5594        } else {
 5595            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5596            if is_blank {
 5597                false
 5598            } else {
 5599                for display_row in display_row + 1..=max_point.row() {
 5600                    let (indent, is_blank) = display_map.line_indent(display_row);
 5601                    if !is_blank {
 5602                        return indent > start_indent;
 5603                    }
 5604                }
 5605                false
 5606            }
 5607        }
 5608    }
 5609
 5610    fn foldable_range_for_line(
 5611        &self,
 5612        display_map: &DisplaySnapshot,
 5613        start_row: u32,
 5614    ) -> Range<Point> {
 5615        let max_point = display_map.max_point();
 5616
 5617        let (start_indent, _) = display_map.line_indent(start_row);
 5618        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5619        let mut end = None;
 5620        for row in start_row + 1..=max_point.row() {
 5621            let (indent, is_blank) = display_map.line_indent(row);
 5622            if !is_blank && indent <= start_indent {
 5623                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5624                break;
 5625            }
 5626        }
 5627
 5628        let end = end.unwrap_or(max_point);
 5629        return start.to_point(display_map)..end.to_point(display_map);
 5630    }
 5631
 5632    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5633        let selections = self.local_selections::<Point>(cx);
 5634        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5635        self.fold_ranges(ranges, cx);
 5636    }
 5637
 5638    pub fn fold_ranges<T: ToOffset>(
 5639        &mut self,
 5640        ranges: impl IntoIterator<Item = Range<T>>,
 5641        cx: &mut ViewContext<Self>,
 5642    ) {
 5643        let mut ranges = ranges.into_iter().peekable();
 5644        if ranges.peek().is_some() {
 5645            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5646            self.request_autoscroll(Autoscroll::Fit, cx);
 5647            cx.notify();
 5648        }
 5649    }
 5650
 5651    pub fn unfold_ranges<T: ToOffset>(
 5652        &mut self,
 5653        ranges: impl IntoIterator<Item = Range<T>>,
 5654        inclusive: bool,
 5655        cx: &mut ViewContext<Self>,
 5656    ) {
 5657        let mut ranges = ranges.into_iter().peekable();
 5658        if ranges.peek().is_some() {
 5659            self.display_map
 5660                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5661            self.request_autoscroll(Autoscroll::Fit, cx);
 5662            cx.notify();
 5663        }
 5664    }
 5665
 5666    pub fn insert_blocks(
 5667        &mut self,
 5668        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5669        cx: &mut ViewContext<Self>,
 5670    ) -> Vec<BlockId> {
 5671        let blocks = self
 5672            .display_map
 5673            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5674        self.request_autoscroll(Autoscroll::Fit, cx);
 5675        blocks
 5676    }
 5677
 5678    pub fn replace_blocks(
 5679        &mut self,
 5680        blocks: HashMap<BlockId, RenderBlock>,
 5681        cx: &mut ViewContext<Self>,
 5682    ) {
 5683        self.display_map
 5684            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5685        self.request_autoscroll(Autoscroll::Fit, cx);
 5686    }
 5687
 5688    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5689        self.display_map.update(cx, |display_map, cx| {
 5690            display_map.remove_blocks(block_ids, cx)
 5691        });
 5692    }
 5693
 5694    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5695        self.display_map
 5696            .update(cx, |map, cx| map.snapshot(cx))
 5697            .longest_row()
 5698    }
 5699
 5700    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5701        self.display_map
 5702            .update(cx, |map, cx| map.snapshot(cx))
 5703            .max_point()
 5704    }
 5705
 5706    pub fn text(&self, cx: &AppContext) -> String {
 5707        self.buffer.read(cx).read(cx).text()
 5708    }
 5709
 5710    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5711        self.transact(cx, |this, cx| {
 5712            this.buffer
 5713                .read(cx)
 5714                .as_singleton()
 5715                .expect("you can only call set_text on editors for singleton buffers")
 5716                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5717        });
 5718    }
 5719
 5720    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5721        self.display_map
 5722            .update(cx, |map, cx| map.snapshot(cx))
 5723            .text()
 5724    }
 5725
 5726    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5727        let language_name = self
 5728            .buffer
 5729            .read(cx)
 5730            .as_singleton()
 5731            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5732            .map(|l| l.name());
 5733
 5734        let settings = cx.global::<Settings>();
 5735        let mode = self
 5736            .soft_wrap_mode_override
 5737            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5738        match mode {
 5739            settings::SoftWrap::None => SoftWrap::None,
 5740            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5741            settings::SoftWrap::PreferredLineLength => {
 5742                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5743            }
 5744        }
 5745    }
 5746
 5747    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5748        self.soft_wrap_mode_override = Some(mode);
 5749        cx.notify();
 5750    }
 5751
 5752    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5753        self.display_map
 5754            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5755    }
 5756
 5757    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5758        self.highlighted_rows = rows;
 5759    }
 5760
 5761    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5762        self.highlighted_rows.clone()
 5763    }
 5764
 5765    pub fn highlight_background<T: 'static>(
 5766        &mut self,
 5767        ranges: Vec<Range<Anchor>>,
 5768        color_fetcher: fn(&Theme) -> Color,
 5769        cx: &mut ViewContext<Self>,
 5770    ) {
 5771        self.background_highlights
 5772            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5773        cx.notify();
 5774    }
 5775
 5776    pub fn clear_background_highlights<T: 'static>(
 5777        &mut self,
 5778        cx: &mut ViewContext<Self>,
 5779    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5780        cx.notify();
 5781        self.background_highlights.remove(&TypeId::of::<T>())
 5782    }
 5783
 5784    #[cfg(feature = "test-support")]
 5785    pub fn all_background_highlights(
 5786        &mut self,
 5787        cx: &mut ViewContext<Self>,
 5788    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5789        let snapshot = self.snapshot(cx);
 5790        let buffer = &snapshot.buffer_snapshot;
 5791        let start = buffer.anchor_before(0);
 5792        let end = buffer.anchor_after(buffer.len());
 5793        let theme = cx.global::<Settings>().theme.as_ref();
 5794        self.background_highlights_in_range(start..end, &snapshot, theme)
 5795    }
 5796
 5797    fn document_highlights_for_position<'a>(
 5798        &'a self,
 5799        position: Anchor,
 5800        buffer: &'a MultiBufferSnapshot,
 5801    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5802        let read_highlights = self
 5803            .background_highlights
 5804            .get(&TypeId::of::<DocumentHighlightRead>())
 5805            .map(|h| &h.1);
 5806        let write_highlights = self
 5807            .background_highlights
 5808            .get(&TypeId::of::<DocumentHighlightRead>())
 5809            .map(|h| &h.1);
 5810        let left_position = position.bias_left(buffer);
 5811        let right_position = position.bias_right(buffer);
 5812        read_highlights
 5813            .into_iter()
 5814            .chain(write_highlights)
 5815            .flat_map(move |ranges| {
 5816                let start_ix = match ranges.binary_search_by(|probe| {
 5817                    let cmp = probe.end.cmp(&left_position, &buffer);
 5818                    if cmp.is_ge() {
 5819                        Ordering::Greater
 5820                    } else {
 5821                        Ordering::Less
 5822                    }
 5823                }) {
 5824                    Ok(i) | Err(i) => i,
 5825                };
 5826
 5827                let right_position = right_position.clone();
 5828                ranges[start_ix..]
 5829                    .iter()
 5830                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5831            })
 5832    }
 5833
 5834    pub fn background_highlights_in_range(
 5835        &self,
 5836        search_range: Range<Anchor>,
 5837        display_snapshot: &DisplaySnapshot,
 5838        theme: &Theme,
 5839    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5840        let mut results = Vec::new();
 5841        let buffer = &display_snapshot.buffer_snapshot;
 5842        for (color_fetcher, ranges) in self.background_highlights.values() {
 5843            let color = color_fetcher(theme);
 5844            let start_ix = match ranges.binary_search_by(|probe| {
 5845                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5846                if cmp.is_gt() {
 5847                    Ordering::Greater
 5848                } else {
 5849                    Ordering::Less
 5850                }
 5851            }) {
 5852                Ok(i) | Err(i) => i,
 5853            };
 5854            for range in &ranges[start_ix..] {
 5855                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5856                    break;
 5857                }
 5858                let start = range
 5859                    .start
 5860                    .to_point(buffer)
 5861                    .to_display_point(display_snapshot);
 5862                let end = range
 5863                    .end
 5864                    .to_point(buffer)
 5865                    .to_display_point(display_snapshot);
 5866                results.push((start..end, color))
 5867            }
 5868        }
 5869        results
 5870    }
 5871
 5872    pub fn highlight_text<T: 'static>(
 5873        &mut self,
 5874        ranges: Vec<Range<Anchor>>,
 5875        style: HighlightStyle,
 5876        cx: &mut ViewContext<Self>,
 5877    ) {
 5878        self.display_map.update(cx, |map, _| {
 5879            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5880        });
 5881        cx.notify();
 5882    }
 5883
 5884    pub fn clear_text_highlights<T: 'static>(
 5885        &mut self,
 5886        cx: &mut ViewContext<Self>,
 5887    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5888        cx.notify();
 5889        self.display_map
 5890            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5891    }
 5892
 5893    fn next_blink_epoch(&mut self) -> usize {
 5894        self.blink_epoch += 1;
 5895        self.blink_epoch
 5896    }
 5897
 5898    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5899        if !self.focused {
 5900            return;
 5901        }
 5902
 5903        self.show_local_cursors = true;
 5904        cx.notify();
 5905
 5906        let epoch = self.next_blink_epoch();
 5907        cx.spawn(|this, mut cx| {
 5908            let this = this.downgrade();
 5909            async move {
 5910                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5911                if let Some(this) = this.upgrade(&cx) {
 5912                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5913                }
 5914            }
 5915        })
 5916        .detach();
 5917    }
 5918
 5919    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5920        if epoch == self.blink_epoch {
 5921            self.blinking_paused = false;
 5922            self.blink_cursors(epoch, cx);
 5923        }
 5924    }
 5925
 5926    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5927        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5928            self.show_local_cursors = !self.show_local_cursors;
 5929            cx.notify();
 5930
 5931            let epoch = self.next_blink_epoch();
 5932            cx.spawn(|this, mut cx| {
 5933                let this = this.downgrade();
 5934                async move {
 5935                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5936                    if let Some(this) = this.upgrade(&cx) {
 5937                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5938                    }
 5939                }
 5940            })
 5941            .detach();
 5942        }
 5943    }
 5944
 5945    pub fn show_local_cursors(&self) -> bool {
 5946        self.show_local_cursors && self.focused
 5947    }
 5948
 5949    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5950        cx.notify();
 5951    }
 5952
 5953    fn on_buffer_event(
 5954        &mut self,
 5955        _: ModelHandle<MultiBuffer>,
 5956        event: &language::Event,
 5957        cx: &mut ViewContext<Self>,
 5958    ) {
 5959        match event {
 5960            language::Event::Edited => {
 5961                self.refresh_active_diagnostics(cx);
 5962                self.refresh_code_actions(cx);
 5963                cx.emit(Event::BufferEdited);
 5964            }
 5965            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5966            language::Event::Dirtied => cx.emit(Event::Dirtied),
 5967            language::Event::Saved => cx.emit(Event::Saved),
 5968            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5969            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5970            language::Event::Closed => cx.emit(Event::Closed),
 5971            language::Event::DiagnosticsUpdated => {
 5972                self.refresh_active_diagnostics(cx);
 5973            }
 5974            _ => {}
 5975        }
 5976    }
 5977
 5978    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5979        cx.notify();
 5980    }
 5981
 5982    pub fn set_searchable(&mut self, searchable: bool) {
 5983        self.searchable = searchable;
 5984    }
 5985
 5986    pub fn searchable(&self) -> bool {
 5987        self.searchable
 5988    }
 5989
 5990    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5991        let active_item = workspace.active_item(cx);
 5992        let editor_handle = if let Some(editor) = active_item
 5993            .as_ref()
 5994            .and_then(|item| item.act_as::<Self>(cx))
 5995        {
 5996            editor
 5997        } else {
 5998            cx.propagate_action();
 5999            return;
 6000        };
 6001
 6002        let editor = editor_handle.read(cx);
 6003        let buffer = editor.buffer.read(cx);
 6004        if buffer.is_singleton() {
 6005            cx.propagate_action();
 6006            return;
 6007        }
 6008
 6009        let mut new_selections_by_buffer = HashMap::default();
 6010        for selection in editor.local_selections::<usize>(cx) {
 6011            for (buffer, mut range) in
 6012                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 6013            {
 6014                if selection.reversed {
 6015                    mem::swap(&mut range.start, &mut range.end);
 6016                }
 6017                new_selections_by_buffer
 6018                    .entry(buffer)
 6019                    .or_insert(Vec::new())
 6020                    .push(range)
 6021            }
 6022        }
 6023
 6024        editor_handle.update(cx, |editor, cx| {
 6025            editor.push_to_nav_history(editor.newest_anchor_selection().head(), None, cx);
 6026        });
 6027        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 6028        nav_history.borrow_mut().disable();
 6029
 6030        // We defer the pane interaction because we ourselves are a workspace item
 6031        // and activating a new item causes the pane to call a method on us reentrantly,
 6032        // which panics if we're on the stack.
 6033        cx.defer(move |workspace, cx| {
 6034            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 6035                let editor = workspace.open_project_item::<Self>(buffer, cx);
 6036                editor.update(cx, |editor, cx| {
 6037                    editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
 6038                });
 6039            }
 6040
 6041            nav_history.borrow_mut().enable();
 6042        });
 6043    }
 6044}
 6045
 6046impl EditorSnapshot {
 6047    pub fn is_focused(&self) -> bool {
 6048        self.is_focused
 6049    }
 6050
 6051    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 6052        self.placeholder_text.as_ref()
 6053    }
 6054
 6055    pub fn scroll_position(&self) -> Vector2F {
 6056        compute_scroll_position(
 6057            &self.display_snapshot,
 6058            self.scroll_position,
 6059            &self.scroll_top_anchor,
 6060        )
 6061    }
 6062}
 6063
 6064impl Deref for EditorSnapshot {
 6065    type Target = DisplaySnapshot;
 6066
 6067    fn deref(&self) -> &Self::Target {
 6068        &self.display_snapshot
 6069    }
 6070}
 6071
 6072fn compute_scroll_position(
 6073    snapshot: &DisplaySnapshot,
 6074    mut scroll_position: Vector2F,
 6075    scroll_top_anchor: &Anchor,
 6076) -> Vector2F {
 6077    if *scroll_top_anchor != Anchor::min() {
 6078        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 6079        scroll_position.set_y(scroll_top + scroll_position.y());
 6080    } else {
 6081        scroll_position.set_y(0.);
 6082    }
 6083    scroll_position
 6084}
 6085
 6086#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 6087pub enum Event {
 6088    Activate,
 6089    BufferEdited,
 6090    Edited,
 6091    Reparsed,
 6092    Blurred,
 6093    Dirtied,
 6094    Saved,
 6095    TitleChanged,
 6096    SelectionsChanged { local: bool },
 6097    ScrollPositionChanged { local: bool },
 6098    Closed,
 6099}
 6100
 6101pub struct EditorFocused(pub ViewHandle<Editor>);
 6102pub struct EditorBlurred(pub ViewHandle<Editor>);
 6103pub struct EditorReleased(pub WeakViewHandle<Editor>);
 6104
 6105impl Entity for Editor {
 6106    type Event = Event;
 6107
 6108    fn release(&mut self, cx: &mut MutableAppContext) {
 6109        cx.emit_global(EditorReleased(self.handle.clone()));
 6110    }
 6111}
 6112
 6113impl View for Editor {
 6114    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 6115        let style = self.style(cx);
 6116        self.display_map.update(cx, |map, cx| {
 6117            map.set_font(style.text.font_id, style.text.font_size, cx)
 6118        });
 6119        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 6120    }
 6121
 6122    fn ui_name() -> &'static str {
 6123        "Editor"
 6124    }
 6125
 6126    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 6127        let focused_event = EditorFocused(cx.handle());
 6128        cx.emit_global(focused_event);
 6129        if let Some(rename) = self.pending_rename.as_ref() {
 6130            cx.focus(&rename.editor);
 6131        } else {
 6132            self.focused = true;
 6133            self.blink_cursors(self.blink_epoch, cx);
 6134            self.buffer.update(cx, |buffer, cx| {
 6135                buffer.finalize_last_transaction(cx);
 6136                if self.leader_replica_id.is_none() {
 6137                    buffer.set_active_selections(&self.selections, cx);
 6138                }
 6139            });
 6140        }
 6141    }
 6142
 6143    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 6144        let blurred_event = EditorBlurred(cx.handle());
 6145        cx.emit_global(blurred_event);
 6146        self.focused = false;
 6147        self.buffer
 6148            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 6149        self.hide_context_menu(cx);
 6150        cx.emit(Event::Blurred);
 6151        cx.notify();
 6152    }
 6153
 6154    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 6155        let mut context = Self::default_keymap_context();
 6156        let mode = match self.mode {
 6157            EditorMode::SingleLine => "single_line",
 6158            EditorMode::AutoHeight { .. } => "auto_height",
 6159            EditorMode::Full => "full",
 6160        };
 6161        context.map.insert("mode".into(), mode.into());
 6162        if self.pending_rename.is_some() {
 6163            context.set.insert("renaming".into());
 6164        }
 6165        match self.context_menu.as_ref() {
 6166            Some(ContextMenu::Completions(_)) => {
 6167                context.set.insert("showing_completions".into());
 6168            }
 6169            Some(ContextMenu::CodeActions(_)) => {
 6170                context.set.insert("showing_code_actions".into());
 6171            }
 6172            None => {}
 6173        }
 6174
 6175        for layer in self.keymap_context_layers.values() {
 6176            context.extend(layer);
 6177        }
 6178
 6179        context
 6180    }
 6181}
 6182
 6183fn build_style(
 6184    settings: &Settings,
 6185    get_field_editor_theme: Option<GetFieldEditorTheme>,
 6186    override_text_style: Option<&OverrideTextStyle>,
 6187    cx: &AppContext,
 6188) -> EditorStyle {
 6189    let font_cache = cx.font_cache();
 6190
 6191    let mut theme = settings.theme.editor.clone();
 6192    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 6193        let field_editor_theme = get_field_editor_theme(&settings.theme);
 6194        theme.text_color = field_editor_theme.text.color;
 6195        theme.selection = field_editor_theme.selection;
 6196        theme.background = field_editor_theme
 6197            .container
 6198            .background_color
 6199            .unwrap_or_default();
 6200        EditorStyle {
 6201            text: field_editor_theme.text,
 6202            placeholder_text: field_editor_theme.placeholder_text,
 6203            theme,
 6204        }
 6205    } else {
 6206        let font_family_id = settings.buffer_font_family;
 6207        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 6208        let font_properties = Default::default();
 6209        let font_id = font_cache
 6210            .select_font(font_family_id, &font_properties)
 6211            .unwrap();
 6212        let font_size = settings.buffer_font_size;
 6213        EditorStyle {
 6214            text: TextStyle {
 6215                color: settings.theme.editor.text_color,
 6216                font_family_name,
 6217                font_family_id,
 6218                font_id,
 6219                font_size,
 6220                font_properties,
 6221                underline: Default::default(),
 6222            },
 6223            placeholder_text: None,
 6224            theme,
 6225        }
 6226    };
 6227
 6228    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 6229        if let Some(highlighted) = style
 6230            .text
 6231            .clone()
 6232            .highlight(highlight_style, font_cache)
 6233            .log_err()
 6234        {
 6235            style.text = highlighted;
 6236        }
 6237    }
 6238
 6239    style
 6240}
 6241
 6242trait SelectionExt {
 6243    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 6244    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 6245    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 6246    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 6247        -> Range<u32>;
 6248}
 6249
 6250impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 6251    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 6252        let start = self.start.to_point(buffer);
 6253        let end = self.end.to_point(buffer);
 6254        if self.reversed {
 6255            end..start
 6256        } else {
 6257            start..end
 6258        }
 6259    }
 6260
 6261    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 6262        let start = self.start.to_offset(buffer);
 6263        let end = self.end.to_offset(buffer);
 6264        if self.reversed {
 6265            end..start
 6266        } else {
 6267            start..end
 6268        }
 6269    }
 6270
 6271    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 6272        let start = self
 6273            .start
 6274            .to_point(&map.buffer_snapshot)
 6275            .to_display_point(map);
 6276        let end = self
 6277            .end
 6278            .to_point(&map.buffer_snapshot)
 6279            .to_display_point(map);
 6280        if self.reversed {
 6281            end..start
 6282        } else {
 6283            start..end
 6284        }
 6285    }
 6286
 6287    fn spanned_rows(
 6288        &self,
 6289        include_end_if_at_line_start: bool,
 6290        map: &DisplaySnapshot,
 6291    ) -> Range<u32> {
 6292        let start = self.start.to_point(&map.buffer_snapshot);
 6293        let mut end = self.end.to_point(&map.buffer_snapshot);
 6294        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 6295            end.row -= 1;
 6296        }
 6297
 6298        let buffer_start = map.prev_line_boundary(start).0;
 6299        let buffer_end = map.next_line_boundary(end).0;
 6300        buffer_start.row..buffer_end.row + 1
 6301    }
 6302}
 6303
 6304impl<T: InvalidationRegion> InvalidationStack<T> {
 6305    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 6306    where
 6307        S: Clone + ToOffset,
 6308    {
 6309        while let Some(region) = self.last() {
 6310            let all_selections_inside_invalidation_ranges =
 6311                if selections.len() == region.ranges().len() {
 6312                    selections
 6313                        .iter()
 6314                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 6315                        .all(|(selection, invalidation_range)| {
 6316                            let head = selection.head().to_offset(&buffer);
 6317                            invalidation_range.start <= head && invalidation_range.end >= head
 6318                        })
 6319                } else {
 6320                    false
 6321                };
 6322
 6323            if all_selections_inside_invalidation_ranges {
 6324                break;
 6325            } else {
 6326                self.pop();
 6327            }
 6328        }
 6329    }
 6330}
 6331
 6332impl<T> Default for InvalidationStack<T> {
 6333    fn default() -> Self {
 6334        Self(Default::default())
 6335    }
 6336}
 6337
 6338impl<T> Deref for InvalidationStack<T> {
 6339    type Target = Vec<T>;
 6340
 6341    fn deref(&self) -> &Self::Target {
 6342        &self.0
 6343    }
 6344}
 6345
 6346impl<T> DerefMut for InvalidationStack<T> {
 6347    fn deref_mut(&mut self) -> &mut Self::Target {
 6348        &mut self.0
 6349    }
 6350}
 6351
 6352impl InvalidationRegion for BracketPairState {
 6353    fn ranges(&self) -> &[Range<Anchor>] {
 6354        &self.ranges
 6355    }
 6356}
 6357
 6358impl InvalidationRegion for SnippetState {
 6359    fn ranges(&self) -> &[Range<Anchor>] {
 6360        &self.ranges[self.active_index]
 6361    }
 6362}
 6363
 6364impl Deref for EditorStyle {
 6365    type Target = theme::Editor;
 6366
 6367    fn deref(&self) -> &Self::Target {
 6368        &self.theme
 6369    }
 6370}
 6371
 6372pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 6373    let mut highlighted_lines = Vec::new();
 6374    for line in diagnostic.message.lines() {
 6375        highlighted_lines.push(highlight_diagnostic_message(line));
 6376    }
 6377
 6378    Arc::new(move |cx: &BlockContext| {
 6379        let settings = cx.global::<Settings>();
 6380        let theme = &settings.theme.editor;
 6381        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 6382        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 6383        Flex::column()
 6384            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 6385                Label::new(
 6386                    line.clone(),
 6387                    style.message.clone().with_font_size(font_size),
 6388                )
 6389                .with_highlights(highlights.clone())
 6390                .contained()
 6391                .with_margin_left(cx.anchor_x)
 6392                .boxed()
 6393            }))
 6394            .aligned()
 6395            .left()
 6396            .boxed()
 6397    })
 6398}
 6399
 6400pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6401    let mut message_without_backticks = String::new();
 6402    let mut prev_offset = 0;
 6403    let mut inside_block = false;
 6404    let mut highlights = Vec::new();
 6405    for (match_ix, (offset, _)) in message
 6406        .match_indices('`')
 6407        .chain([(message.len(), "")])
 6408        .enumerate()
 6409    {
 6410        message_without_backticks.push_str(&message[prev_offset..offset]);
 6411        if inside_block {
 6412            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6413        }
 6414
 6415        inside_block = !inside_block;
 6416        prev_offset = offset + 1;
 6417    }
 6418
 6419    (message_without_backticks, highlights)
 6420}
 6421
 6422pub fn diagnostic_style(
 6423    severity: DiagnosticSeverity,
 6424    valid: bool,
 6425    theme: &theme::Editor,
 6426) -> DiagnosticStyle {
 6427    match (severity, valid) {
 6428        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6429        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6430        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6431        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6432        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6433        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6434        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6435        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6436        _ => theme.invalid_hint_diagnostic.clone(),
 6437    }
 6438}
 6439
 6440pub fn combine_syntax_and_fuzzy_match_highlights(
 6441    text: &str,
 6442    default_style: HighlightStyle,
 6443    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6444    match_indices: &[usize],
 6445) -> Vec<(Range<usize>, HighlightStyle)> {
 6446    let mut result = Vec::new();
 6447    let mut match_indices = match_indices.iter().copied().peekable();
 6448
 6449    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6450    {
 6451        syntax_highlight.weight = None;
 6452
 6453        // Add highlights for any fuzzy match characters before the next
 6454        // syntax highlight range.
 6455        while let Some(&match_index) = match_indices.peek() {
 6456            if match_index >= range.start {
 6457                break;
 6458            }
 6459            match_indices.next();
 6460            let end_index = char_ix_after(match_index, text);
 6461            let mut match_style = default_style;
 6462            match_style.weight = Some(fonts::Weight::BOLD);
 6463            result.push((match_index..end_index, match_style));
 6464        }
 6465
 6466        if range.start == usize::MAX {
 6467            break;
 6468        }
 6469
 6470        // Add highlights for any fuzzy match characters within the
 6471        // syntax highlight range.
 6472        let mut offset = range.start;
 6473        while let Some(&match_index) = match_indices.peek() {
 6474            if match_index >= range.end {
 6475                break;
 6476            }
 6477
 6478            match_indices.next();
 6479            if match_index > offset {
 6480                result.push((offset..match_index, syntax_highlight));
 6481            }
 6482
 6483            let mut end_index = char_ix_after(match_index, text);
 6484            while let Some(&next_match_index) = match_indices.peek() {
 6485                if next_match_index == end_index && next_match_index < range.end {
 6486                    end_index = char_ix_after(next_match_index, text);
 6487                    match_indices.next();
 6488                } else {
 6489                    break;
 6490                }
 6491            }
 6492
 6493            let mut match_style = syntax_highlight;
 6494            match_style.weight = Some(fonts::Weight::BOLD);
 6495            result.push((match_index..end_index, match_style));
 6496            offset = end_index;
 6497        }
 6498
 6499        if offset < range.end {
 6500            result.push((offset..range.end, syntax_highlight));
 6501        }
 6502    }
 6503
 6504    fn char_ix_after(ix: usize, text: &str) -> usize {
 6505        ix + text[ix..].chars().next().unwrap().len_utf8()
 6506    }
 6507
 6508    result
 6509}
 6510
 6511pub fn styled_runs_for_code_label<'a>(
 6512    label: &'a CodeLabel,
 6513    syntax_theme: &'a theme::SyntaxTheme,
 6514) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6515    let fade_out = HighlightStyle {
 6516        fade_out: Some(0.35),
 6517        ..Default::default()
 6518    };
 6519
 6520    let mut prev_end = label.filter_range.end;
 6521    label
 6522        .runs
 6523        .iter()
 6524        .enumerate()
 6525        .flat_map(move |(ix, (range, highlight_id))| {
 6526            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6527                style
 6528            } else {
 6529                return Default::default();
 6530            };
 6531            let mut muted_style = style.clone();
 6532            muted_style.highlight(fade_out);
 6533
 6534            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6535            if range.start >= label.filter_range.end {
 6536                if range.start > prev_end {
 6537                    runs.push((prev_end..range.start, fade_out));
 6538                }
 6539                runs.push((range.clone(), muted_style));
 6540            } else if range.end <= label.filter_range.end {
 6541                runs.push((range.clone(), style));
 6542            } else {
 6543                runs.push((range.start..label.filter_range.end, style));
 6544                runs.push((label.filter_range.end..range.end, muted_style));
 6545            }
 6546            prev_end = cmp::max(prev_end, range.end);
 6547
 6548            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6549                runs.push((prev_end..label.text.len(), fade_out));
 6550            }
 6551
 6552            runs
 6553        })
 6554}
 6555
 6556#[cfg(test)]
 6557mod tests {
 6558    use crate::test::{assert_text_with_selections, select_ranges};
 6559
 6560    use super::*;
 6561    use gpui::{
 6562        geometry::rect::RectF,
 6563        platform::{WindowBounds, WindowOptions},
 6564    };
 6565    use indoc::indoc;
 6566    use language::{FakeLspAdapter, LanguageConfig};
 6567    use lsp::FakeLanguageServer;
 6568    use project::FakeFs;
 6569    use settings::LanguageOverride;
 6570    use smol::stream::StreamExt;
 6571    use std::{cell::RefCell, rc::Rc, time::Instant};
 6572    use text::Point;
 6573    use unindent::Unindent;
 6574    use util::test::{marked_text_by, marked_text_ranges, sample_text};
 6575    use workspace::{FollowableItem, ItemHandle};
 6576
 6577    #[gpui::test]
 6578    fn test_edit_events(cx: &mut MutableAppContext) {
 6579        cx.set_global(Settings::test(cx));
 6580        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6581
 6582        let events = Rc::new(RefCell::new(Vec::new()));
 6583        let (_, editor1) = cx.add_window(Default::default(), {
 6584            let events = events.clone();
 6585            |cx| {
 6586                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6587                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6588                        events.borrow_mut().push(("editor1", *event));
 6589                    }
 6590                })
 6591                .detach();
 6592                Editor::for_buffer(buffer.clone(), None, cx)
 6593            }
 6594        });
 6595        let (_, editor2) = cx.add_window(Default::default(), {
 6596            let events = events.clone();
 6597            |cx| {
 6598                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6599                    if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
 6600                        events.borrow_mut().push(("editor2", *event));
 6601                    }
 6602                })
 6603                .detach();
 6604                Editor::for_buffer(buffer.clone(), None, cx)
 6605            }
 6606        });
 6607        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6608
 6609        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6610        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6611        assert_eq!(
 6612            mem::take(&mut *events.borrow_mut()),
 6613            [
 6614                ("editor1", Event::Edited),
 6615                ("editor1", Event::BufferEdited),
 6616                ("editor2", Event::BufferEdited),
 6617                ("editor1", Event::Dirtied),
 6618                ("editor2", Event::Dirtied)
 6619            ]
 6620        );
 6621
 6622        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6623        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6624        assert_eq!(
 6625            mem::take(&mut *events.borrow_mut()),
 6626            [
 6627                ("editor2", Event::Edited),
 6628                ("editor1", Event::BufferEdited),
 6629                ("editor2", Event::BufferEdited),
 6630            ]
 6631        );
 6632
 6633        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6634        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6635        assert_eq!(
 6636            mem::take(&mut *events.borrow_mut()),
 6637            [
 6638                ("editor1", Event::Edited),
 6639                ("editor1", Event::BufferEdited),
 6640                ("editor2", Event::BufferEdited),
 6641            ]
 6642        );
 6643
 6644        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6645        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6646        assert_eq!(
 6647            mem::take(&mut *events.borrow_mut()),
 6648            [
 6649                ("editor1", Event::Edited),
 6650                ("editor1", Event::BufferEdited),
 6651                ("editor2", Event::BufferEdited),
 6652            ]
 6653        );
 6654
 6655        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6656        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6657        assert_eq!(
 6658            mem::take(&mut *events.borrow_mut()),
 6659            [
 6660                ("editor2", Event::Edited),
 6661                ("editor1", Event::BufferEdited),
 6662                ("editor2", Event::BufferEdited),
 6663            ]
 6664        );
 6665
 6666        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6667        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6668        assert_eq!(
 6669            mem::take(&mut *events.borrow_mut()),
 6670            [
 6671                ("editor2", Event::Edited),
 6672                ("editor1", Event::BufferEdited),
 6673                ("editor2", Event::BufferEdited),
 6674            ]
 6675        );
 6676
 6677        // No event is emitted when the mutation is a no-op.
 6678        editor2.update(cx, |editor, cx| {
 6679            editor.select_ranges([0..0], None, cx);
 6680            editor.backspace(&Backspace, cx);
 6681        });
 6682        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6683    }
 6684
 6685    #[gpui::test]
 6686    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6687        cx.set_global(Settings::test(cx));
 6688        let mut now = Instant::now();
 6689        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6690        let group_interval = buffer.read(cx).transaction_group_interval();
 6691        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6692        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6693
 6694        editor.update(cx, |editor, cx| {
 6695            editor.start_transaction_at(now, cx);
 6696            editor.select_ranges([2..4], None, cx);
 6697            editor.insert("cd", cx);
 6698            editor.end_transaction_at(now, cx);
 6699            assert_eq!(editor.text(cx), "12cd56");
 6700            assert_eq!(editor.selected_ranges(cx), vec![4..4]);
 6701
 6702            editor.start_transaction_at(now, cx);
 6703            editor.select_ranges([4..5], None, cx);
 6704            editor.insert("e", cx);
 6705            editor.end_transaction_at(now, cx);
 6706            assert_eq!(editor.text(cx), "12cde6");
 6707            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6708
 6709            now += group_interval + Duration::from_millis(1);
 6710            editor.select_ranges([2..2], None, cx);
 6711
 6712            // Simulate an edit in another editor
 6713            buffer.update(cx, |buffer, cx| {
 6714                buffer.start_transaction_at(now, cx);
 6715                buffer.edit([(0..1, "a")], cx);
 6716                buffer.edit([(1..1, "b")], cx);
 6717                buffer.end_transaction_at(now, cx);
 6718            });
 6719
 6720            assert_eq!(editor.text(cx), "ab2cde6");
 6721            assert_eq!(editor.selected_ranges(cx), vec![3..3]);
 6722
 6723            // Last transaction happened past the group interval in a different editor.
 6724            // Undo it individually and don't restore selections.
 6725            editor.undo(&Undo, cx);
 6726            assert_eq!(editor.text(cx), "12cde6");
 6727            assert_eq!(editor.selected_ranges(cx), vec![2..2]);
 6728
 6729            // First two transactions happened within the group interval in this editor.
 6730            // Undo them together and restore selections.
 6731            editor.undo(&Undo, cx);
 6732            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6733            assert_eq!(editor.text(cx), "123456");
 6734            assert_eq!(editor.selected_ranges(cx), vec![0..0]);
 6735
 6736            // Redo the first two transactions together.
 6737            editor.redo(&Redo, cx);
 6738            assert_eq!(editor.text(cx), "12cde6");
 6739            assert_eq!(editor.selected_ranges(cx), vec![5..5]);
 6740
 6741            // Redo the last transaction on its own.
 6742            editor.redo(&Redo, cx);
 6743            assert_eq!(editor.text(cx), "ab2cde6");
 6744            assert_eq!(editor.selected_ranges(cx), vec![6..6]);
 6745
 6746            // Test empty transactions.
 6747            editor.start_transaction_at(now, cx);
 6748            editor.end_transaction_at(now, cx);
 6749            editor.undo(&Undo, cx);
 6750            assert_eq!(editor.text(cx), "12cde6");
 6751        });
 6752    }
 6753
 6754    #[gpui::test]
 6755    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6756        cx.set_global(Settings::test(cx));
 6757
 6758        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6759        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6760        editor.update(cx, |view, cx| {
 6761            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6762        });
 6763        assert_eq!(
 6764            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6765            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6766        );
 6767
 6768        editor.update(cx, |view, cx| {
 6769            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6770        });
 6771
 6772        assert_eq!(
 6773            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6774            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6775        );
 6776
 6777        editor.update(cx, |view, cx| {
 6778            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6779        });
 6780
 6781        assert_eq!(
 6782            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6783            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6784        );
 6785
 6786        editor.update(cx, |view, cx| {
 6787            view.end_selection(cx);
 6788            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6789        });
 6790
 6791        assert_eq!(
 6792            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6793            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6794        );
 6795
 6796        editor.update(cx, |view, cx| {
 6797            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6798            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6799        });
 6800
 6801        assert_eq!(
 6802            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6803            [
 6804                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6805                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6806            ]
 6807        );
 6808
 6809        editor.update(cx, |view, cx| {
 6810            view.end_selection(cx);
 6811        });
 6812
 6813        assert_eq!(
 6814            editor.update(cx, |view, cx| view.selected_display_ranges(cx)),
 6815            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6816        );
 6817    }
 6818
 6819    #[gpui::test]
 6820    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6821        cx.set_global(Settings::test(cx));
 6822        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6823        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6824
 6825        view.update(cx, |view, cx| {
 6826            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6827            assert_eq!(
 6828                view.selected_display_ranges(cx),
 6829                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6830            );
 6831        });
 6832
 6833        view.update(cx, |view, cx| {
 6834            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6835            assert_eq!(
 6836                view.selected_display_ranges(cx),
 6837                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6838            );
 6839        });
 6840
 6841        view.update(cx, |view, cx| {
 6842            view.cancel(&Cancel, cx);
 6843            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6844            assert_eq!(
 6845                view.selected_display_ranges(cx),
 6846                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6847            );
 6848        });
 6849    }
 6850
 6851    #[gpui::test]
 6852    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6853        cx.set_global(Settings::test(cx));
 6854        use workspace::Item;
 6855        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6856        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6857
 6858        cx.add_window(Default::default(), |cx| {
 6859            let mut editor = build_editor(buffer.clone(), cx);
 6860            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6861
 6862            // Move the cursor a small distance.
 6863            // Nothing is added to the navigation history.
 6864            editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
 6865            editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
 6866            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6867
 6868            // Move the cursor a large distance.
 6869            // The history can jump back to the previous position.
 6870            editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
 6871            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6872            editor.navigate(nav_entry.data.unwrap(), cx);
 6873            assert_eq!(nav_entry.item.id(), cx.view_id());
 6874            assert_eq!(
 6875                editor.selected_display_ranges(cx),
 6876                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6877            );
 6878            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6879
 6880            // Move the cursor a small distance via the mouse.
 6881            // Nothing is added to the navigation history.
 6882            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6883            editor.end_selection(cx);
 6884            assert_eq!(
 6885                editor.selected_display_ranges(cx),
 6886                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6887            );
 6888            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6889
 6890            // Move the cursor a large distance via the mouse.
 6891            // The history can jump back to the previous position.
 6892            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6893            editor.end_selection(cx);
 6894            assert_eq!(
 6895                editor.selected_display_ranges(cx),
 6896                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6897            );
 6898            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6899            editor.navigate(nav_entry.data.unwrap(), cx);
 6900            assert_eq!(nav_entry.item.id(), cx.view_id());
 6901            assert_eq!(
 6902                editor.selected_display_ranges(cx),
 6903                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6904            );
 6905            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6906
 6907            // Set scroll position to check later
 6908            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6909            let original_scroll_position = editor.scroll_position;
 6910            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6911
 6912            // Jump to the end of the document and adjust scroll
 6913            editor.move_to_end(&MoveToEnd, cx);
 6914            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6915            assert_ne!(editor.scroll_position, original_scroll_position);
 6916            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6917
 6918            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6919            editor.navigate(nav_entry.data.unwrap(), cx);
 6920            assert_eq!(editor.scroll_position, original_scroll_position);
 6921            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6922
 6923            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6924            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6925            invalid_anchor.text_anchor.buffer_id = Some(999);
 6926            let invalid_point = Point::new(9999, 0);
 6927            editor.navigate(
 6928                Box::new(NavigationData {
 6929                    cursor_anchor: invalid_anchor.clone(),
 6930                    cursor_position: invalid_point,
 6931                    scroll_top_anchor: invalid_anchor.clone(),
 6932                    scroll_top_row: invalid_point.row,
 6933                    scroll_position: Default::default(),
 6934                }),
 6935                cx,
 6936            );
 6937            assert_eq!(
 6938                editor.selected_display_ranges(cx),
 6939                &[editor.max_point(cx)..editor.max_point(cx)]
 6940            );
 6941            assert_eq!(
 6942                editor.scroll_position(cx),
 6943                vec2f(0., editor.max_point(cx).row() as f32)
 6944            );
 6945
 6946            editor
 6947        });
 6948    }
 6949
 6950    #[gpui::test]
 6951    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6952        cx.set_global(Settings::test(cx));
 6953        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6954        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6955
 6956        view.update(cx, |view, cx| {
 6957            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6958            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6959            view.end_selection(cx);
 6960
 6961            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6962            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6963            view.end_selection(cx);
 6964            assert_eq!(
 6965                view.selected_display_ranges(cx),
 6966                [
 6967                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6968                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6969                ]
 6970            );
 6971        });
 6972
 6973        view.update(cx, |view, cx| {
 6974            view.cancel(&Cancel, cx);
 6975            assert_eq!(
 6976                view.selected_display_ranges(cx),
 6977                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 6978            );
 6979        });
 6980
 6981        view.update(cx, |view, cx| {
 6982            view.cancel(&Cancel, cx);
 6983            assert_eq!(
 6984                view.selected_display_ranges(cx),
 6985                [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
 6986            );
 6987        });
 6988    }
 6989
 6990    #[gpui::test]
 6991    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6992        cx.set_global(Settings::test(cx));
 6993        let buffer = MultiBuffer::build_simple(
 6994            &"
 6995                impl Foo {
 6996                    // Hello!
 6997
 6998                    fn a() {
 6999                        1
 7000                    }
 7001
 7002                    fn b() {
 7003                        2
 7004                    }
 7005
 7006                    fn c() {
 7007                        3
 7008                    }
 7009                }
 7010            "
 7011            .unindent(),
 7012            cx,
 7013        );
 7014        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7015
 7016        view.update(cx, |view, cx| {
 7017            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], cx);
 7018            view.fold(&Fold, cx);
 7019            assert_eq!(
 7020                view.display_text(cx),
 7021                "
 7022                    impl Foo {
 7023                        // Hello!
 7024
 7025                        fn a() {
 7026                            1
 7027                        }
 7028
 7029                        fn b() {…
 7030                        }
 7031
 7032                        fn c() {…
 7033                        }
 7034                    }
 7035                "
 7036                .unindent(),
 7037            );
 7038
 7039            view.fold(&Fold, cx);
 7040            assert_eq!(
 7041                view.display_text(cx),
 7042                "
 7043                    impl Foo {…
 7044                    }
 7045                "
 7046                .unindent(),
 7047            );
 7048
 7049            view.unfold_lines(&UnfoldLines, cx);
 7050            assert_eq!(
 7051                view.display_text(cx),
 7052                "
 7053                    impl Foo {
 7054                        // Hello!
 7055
 7056                        fn a() {
 7057                            1
 7058                        }
 7059
 7060                        fn b() {…
 7061                        }
 7062
 7063                        fn c() {…
 7064                        }
 7065                    }
 7066                "
 7067                .unindent(),
 7068            );
 7069
 7070            view.unfold_lines(&UnfoldLines, cx);
 7071            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 7072        });
 7073    }
 7074
 7075    #[gpui::test]
 7076    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 7077        cx.set_global(Settings::test(cx));
 7078        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 7079        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7080
 7081        buffer.update(cx, |buffer, cx| {
 7082            buffer.edit(
 7083                vec![
 7084                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 7085                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 7086                ],
 7087                cx,
 7088            );
 7089        });
 7090
 7091        view.update(cx, |view, cx| {
 7092            assert_eq!(
 7093                view.selected_display_ranges(cx),
 7094                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7095            );
 7096
 7097            view.move_down(&MoveDown, cx);
 7098            assert_eq!(
 7099                view.selected_display_ranges(cx),
 7100                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7101            );
 7102
 7103            view.move_right(&MoveRight, cx);
 7104            assert_eq!(
 7105                view.selected_display_ranges(cx),
 7106                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 7107            );
 7108
 7109            view.move_left(&MoveLeft, cx);
 7110            assert_eq!(
 7111                view.selected_display_ranges(cx),
 7112                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 7113            );
 7114
 7115            view.move_up(&MoveUp, cx);
 7116            assert_eq!(
 7117                view.selected_display_ranges(cx),
 7118                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7119            );
 7120
 7121            view.move_to_end(&MoveToEnd, cx);
 7122            assert_eq!(
 7123                view.selected_display_ranges(cx),
 7124                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 7125            );
 7126
 7127            view.move_to_beginning(&MoveToBeginning, cx);
 7128            assert_eq!(
 7129                view.selected_display_ranges(cx),
 7130                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 7131            );
 7132
 7133            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], cx);
 7134            view.select_to_beginning(&SelectToBeginning, cx);
 7135            assert_eq!(
 7136                view.selected_display_ranges(cx),
 7137                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 7138            );
 7139
 7140            view.select_to_end(&SelectToEnd, cx);
 7141            assert_eq!(
 7142                view.selected_display_ranges(cx),
 7143                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 7144            );
 7145        });
 7146    }
 7147
 7148    #[gpui::test]
 7149    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 7150        cx.set_global(Settings::test(cx));
 7151        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 7152        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7153
 7154        assert_eq!('ⓐ'.len_utf8(), 3);
 7155        assert_eq!('α'.len_utf8(), 2);
 7156
 7157        view.update(cx, |view, cx| {
 7158            view.fold_ranges(
 7159                vec![
 7160                    Point::new(0, 6)..Point::new(0, 12),
 7161                    Point::new(1, 2)..Point::new(1, 4),
 7162                    Point::new(2, 4)..Point::new(2, 8),
 7163                ],
 7164                cx,
 7165            );
 7166            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 7167
 7168            view.move_right(&MoveRight, cx);
 7169            assert_eq!(
 7170                view.selected_display_ranges(cx),
 7171                &[empty_range(0, "".len())]
 7172            );
 7173            view.move_right(&MoveRight, cx);
 7174            assert_eq!(
 7175                view.selected_display_ranges(cx),
 7176                &[empty_range(0, "ⓐⓑ".len())]
 7177            );
 7178            view.move_right(&MoveRight, cx);
 7179            assert_eq!(
 7180                view.selected_display_ranges(cx),
 7181                &[empty_range(0, "ⓐⓑ…".len())]
 7182            );
 7183
 7184            view.move_down(&MoveDown, cx);
 7185            assert_eq!(
 7186                view.selected_display_ranges(cx),
 7187                &[empty_range(1, "ab…".len())]
 7188            );
 7189            view.move_left(&MoveLeft, cx);
 7190            assert_eq!(
 7191                view.selected_display_ranges(cx),
 7192                &[empty_range(1, "ab".len())]
 7193            );
 7194            view.move_left(&MoveLeft, cx);
 7195            assert_eq!(
 7196                view.selected_display_ranges(cx),
 7197                &[empty_range(1, "a".len())]
 7198            );
 7199
 7200            view.move_down(&MoveDown, cx);
 7201            assert_eq!(
 7202                view.selected_display_ranges(cx),
 7203                &[empty_range(2, "α".len())]
 7204            );
 7205            view.move_right(&MoveRight, cx);
 7206            assert_eq!(
 7207                view.selected_display_ranges(cx),
 7208                &[empty_range(2, "αβ".len())]
 7209            );
 7210            view.move_right(&MoveRight, cx);
 7211            assert_eq!(
 7212                view.selected_display_ranges(cx),
 7213                &[empty_range(2, "αβ…".len())]
 7214            );
 7215            view.move_right(&MoveRight, cx);
 7216            assert_eq!(
 7217                view.selected_display_ranges(cx),
 7218                &[empty_range(2, "αβ…ε".len())]
 7219            );
 7220
 7221            view.move_up(&MoveUp, cx);
 7222            assert_eq!(
 7223                view.selected_display_ranges(cx),
 7224                &[empty_range(1, "ab…e".len())]
 7225            );
 7226            view.move_up(&MoveUp, cx);
 7227            assert_eq!(
 7228                view.selected_display_ranges(cx),
 7229                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 7230            );
 7231            view.move_left(&MoveLeft, cx);
 7232            assert_eq!(
 7233                view.selected_display_ranges(cx),
 7234                &[empty_range(0, "ⓐⓑ…".len())]
 7235            );
 7236            view.move_left(&MoveLeft, cx);
 7237            assert_eq!(
 7238                view.selected_display_ranges(cx),
 7239                &[empty_range(0, "ⓐⓑ".len())]
 7240            );
 7241            view.move_left(&MoveLeft, cx);
 7242            assert_eq!(
 7243                view.selected_display_ranges(cx),
 7244                &[empty_range(0, "".len())]
 7245            );
 7246        });
 7247    }
 7248
 7249    #[gpui::test]
 7250    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 7251        cx.set_global(Settings::test(cx));
 7252        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 7253        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7254        view.update(cx, |view, cx| {
 7255            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], cx);
 7256            view.move_down(&MoveDown, cx);
 7257            assert_eq!(
 7258                view.selected_display_ranges(cx),
 7259                &[empty_range(1, "abcd".len())]
 7260            );
 7261
 7262            view.move_down(&MoveDown, cx);
 7263            assert_eq!(
 7264                view.selected_display_ranges(cx),
 7265                &[empty_range(2, "αβγ".len())]
 7266            );
 7267
 7268            view.move_down(&MoveDown, cx);
 7269            assert_eq!(
 7270                view.selected_display_ranges(cx),
 7271                &[empty_range(3, "abcd".len())]
 7272            );
 7273
 7274            view.move_down(&MoveDown, cx);
 7275            assert_eq!(
 7276                view.selected_display_ranges(cx),
 7277                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 7278            );
 7279
 7280            view.move_up(&MoveUp, cx);
 7281            assert_eq!(
 7282                view.selected_display_ranges(cx),
 7283                &[empty_range(3, "abcd".len())]
 7284            );
 7285
 7286            view.move_up(&MoveUp, cx);
 7287            assert_eq!(
 7288                view.selected_display_ranges(cx),
 7289                &[empty_range(2, "αβγ".len())]
 7290            );
 7291        });
 7292    }
 7293
 7294    #[gpui::test]
 7295    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 7296        cx.set_global(Settings::test(cx));
 7297        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 7298        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7299        view.update(cx, |view, cx| {
 7300            view.select_display_ranges(
 7301                &[
 7302                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7303                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7304                ],
 7305                cx,
 7306            );
 7307        });
 7308
 7309        view.update(cx, |view, cx| {
 7310            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7311            assert_eq!(
 7312                view.selected_display_ranges(cx),
 7313                &[
 7314                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7315                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7316                ]
 7317            );
 7318        });
 7319
 7320        view.update(cx, |view, cx| {
 7321            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7322            assert_eq!(
 7323                view.selected_display_ranges(cx),
 7324                &[
 7325                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7326                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7327                ]
 7328            );
 7329        });
 7330
 7331        view.update(cx, |view, cx| {
 7332            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7333            assert_eq!(
 7334                view.selected_display_ranges(cx),
 7335                &[
 7336                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7337                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7338                ]
 7339            );
 7340        });
 7341
 7342        view.update(cx, |view, cx| {
 7343            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7344            assert_eq!(
 7345                view.selected_display_ranges(cx),
 7346                &[
 7347                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7348                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7349                ]
 7350            );
 7351        });
 7352
 7353        // Moving to the end of line again is a no-op.
 7354        view.update(cx, |view, cx| {
 7355            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7356            assert_eq!(
 7357                view.selected_display_ranges(cx),
 7358                &[
 7359                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7360                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7361                ]
 7362            );
 7363        });
 7364
 7365        view.update(cx, |view, cx| {
 7366            view.move_left(&MoveLeft, cx);
 7367            view.select_to_beginning_of_line(
 7368                &SelectToBeginningOfLine {
 7369                    stop_at_soft_wraps: true,
 7370                },
 7371                cx,
 7372            );
 7373            assert_eq!(
 7374                view.selected_display_ranges(cx),
 7375                &[
 7376                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7377                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7378                ]
 7379            );
 7380        });
 7381
 7382        view.update(cx, |view, cx| {
 7383            view.select_to_beginning_of_line(
 7384                &SelectToBeginningOfLine {
 7385                    stop_at_soft_wraps: true,
 7386                },
 7387                cx,
 7388            );
 7389            assert_eq!(
 7390                view.selected_display_ranges(cx),
 7391                &[
 7392                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7393                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7394                ]
 7395            );
 7396        });
 7397
 7398        view.update(cx, |view, cx| {
 7399            view.select_to_beginning_of_line(
 7400                &SelectToBeginningOfLine {
 7401                    stop_at_soft_wraps: true,
 7402                },
 7403                cx,
 7404            );
 7405            assert_eq!(
 7406                view.selected_display_ranges(cx),
 7407                &[
 7408                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7409                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7410                ]
 7411            );
 7412        });
 7413
 7414        view.update(cx, |view, cx| {
 7415            view.select_to_end_of_line(
 7416                &SelectToEndOfLine {
 7417                    stop_at_soft_wraps: true,
 7418                },
 7419                cx,
 7420            );
 7421            assert_eq!(
 7422                view.selected_display_ranges(cx),
 7423                &[
 7424                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7425                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7426                ]
 7427            );
 7428        });
 7429
 7430        view.update(cx, |view, cx| {
 7431            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7432            assert_eq!(view.display_text(cx), "ab\n  de");
 7433            assert_eq!(
 7434                view.selected_display_ranges(cx),
 7435                &[
 7436                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7437                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7438                ]
 7439            );
 7440        });
 7441
 7442        view.update(cx, |view, cx| {
 7443            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7444            assert_eq!(view.display_text(cx), "\n");
 7445            assert_eq!(
 7446                view.selected_display_ranges(cx),
 7447                &[
 7448                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7449                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7450                ]
 7451            );
 7452        });
 7453    }
 7454
 7455    #[gpui::test]
 7456    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7457        cx.set_global(Settings::test(cx));
 7458        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7459        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7460        view.update(cx, |view, cx| {
 7461            view.select_display_ranges(
 7462                &[
 7463                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7464                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7465                ],
 7466                cx,
 7467            );
 7468
 7469            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7470            assert_selection_ranges(
 7471                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7472                vec![('<', '>'), ('[', ']')],
 7473                view,
 7474                cx,
 7475            );
 7476
 7477            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7478            assert_selection_ranges(
 7479                "use std<>::str::{foo, bar}\n\n  []{baz.qux()}",
 7480                vec![('<', '>'), ('[', ']')],
 7481                view,
 7482                cx,
 7483            );
 7484
 7485            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7486            assert_selection_ranges(
 7487                "use <>std::str::{foo, bar}\n\n[]  {baz.qux()}",
 7488                vec![('<', '>'), ('[', ']')],
 7489                view,
 7490                cx,
 7491            );
 7492
 7493            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7494            assert_selection_ranges(
 7495                "<>use std::str::{foo, bar}\n[]\n  {baz.qux()}",
 7496                vec![('<', '>'), ('[', ']')],
 7497                view,
 7498                cx,
 7499            );
 7500
 7501            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7502            assert_selection_ranges(
 7503                "<>use std::str::{foo, bar[]}\n\n  {baz.qux()}",
 7504                vec![('<', '>'), ('[', ']')],
 7505                view,
 7506                cx,
 7507            );
 7508
 7509            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7510            assert_selection_ranges(
 7511                "use<> std::str::{foo, bar}[]\n\n  {baz.qux()}",
 7512                vec![('<', '>'), ('[', ']')],
 7513                view,
 7514                cx,
 7515            );
 7516
 7517            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7518            assert_selection_ranges(
 7519                "use std<>::str::{foo, bar}\n[]\n  {baz.qux()}",
 7520                vec![('<', '>'), ('[', ']')],
 7521                view,
 7522                cx,
 7523            );
 7524
 7525            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7526            assert_selection_ranges(
 7527                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7528                vec![('<', '>'), ('[', ']')],
 7529                view,
 7530                cx,
 7531            );
 7532
 7533            view.move_right(&MoveRight, cx);
 7534            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7535            assert_selection_ranges(
 7536                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7537                vec![('<', '>'), ('[', ']')],
 7538                view,
 7539                cx,
 7540            );
 7541
 7542            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7543            assert_selection_ranges(
 7544                "use std>::s<tr::{foo, bar}\n\n  ]{b[az.qux()}",
 7545                vec![('<', '>'), ('[', ']')],
 7546                view,
 7547                cx,
 7548            );
 7549
 7550            view.select_to_next_word_end(&SelectToNextWordEnd, cx);
 7551            assert_selection_ranges(
 7552                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7553                vec![('<', '>'), ('[', ']')],
 7554                view,
 7555                cx,
 7556            );
 7557        });
 7558    }
 7559
 7560    #[gpui::test]
 7561    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7562        cx.set_global(Settings::test(cx));
 7563        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7564        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7565
 7566        view.update(cx, |view, cx| {
 7567            view.set_wrap_width(Some(140.), cx);
 7568            assert_eq!(
 7569                view.display_text(cx),
 7570                "use one::{\n    two::three::\n    four::five\n};"
 7571            );
 7572
 7573            view.select_display_ranges(&[DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)], cx);
 7574
 7575            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7576            assert_eq!(
 7577                view.selected_display_ranges(cx),
 7578                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7579            );
 7580
 7581            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7582            assert_eq!(
 7583                view.selected_display_ranges(cx),
 7584                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7585            );
 7586
 7587            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7588            assert_eq!(
 7589                view.selected_display_ranges(cx),
 7590                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7591            );
 7592
 7593            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7594            assert_eq!(
 7595                view.selected_display_ranges(cx),
 7596                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7597            );
 7598
 7599            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7600            assert_eq!(
 7601                view.selected_display_ranges(cx),
 7602                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7603            );
 7604
 7605            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7606            assert_eq!(
 7607                view.selected_display_ranges(cx),
 7608                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7609            );
 7610        });
 7611    }
 7612
 7613    #[gpui::test]
 7614    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7615        cx.set_global(Settings::test(cx));
 7616        let (text, ranges) = marked_text_ranges("one [two three] four");
 7617        let buffer = MultiBuffer::build_simple(&text, cx);
 7618
 7619        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7620
 7621        editor.update(cx, |editor, cx| {
 7622            editor.select_ranges(ranges, None, cx);
 7623            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7624            assert_eq!(editor.text(cx), " four");
 7625        });
 7626    }
 7627
 7628    #[gpui::test]
 7629    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7630        cx.set_global(Settings::test(cx));
 7631        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7632        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7633
 7634        view.update(cx, |view, cx| {
 7635            view.select_display_ranges(
 7636                &[
 7637                    // an empty selection - the preceding word fragment is deleted
 7638                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7639                    // characters selected - they are deleted
 7640                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7641                ],
 7642                cx,
 7643            );
 7644            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7645        });
 7646
 7647        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7648
 7649        view.update(cx, |view, cx| {
 7650            view.select_display_ranges(
 7651                &[
 7652                    // an empty selection - the following word fragment is deleted
 7653                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7654                    // characters selected - they are deleted
 7655                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7656                ],
 7657                cx,
 7658            );
 7659            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7660        });
 7661
 7662        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7663    }
 7664
 7665    #[gpui::test]
 7666    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7667        cx.set_global(Settings::test(cx));
 7668        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7669        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7670
 7671        view.update(cx, |view, cx| {
 7672            view.select_display_ranges(
 7673                &[
 7674                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7675                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7676                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7677                ],
 7678                cx,
 7679            );
 7680
 7681            view.newline(&Newline, cx);
 7682            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7683        });
 7684    }
 7685
 7686    #[gpui::test]
 7687    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7688        cx.set_global(Settings::test(cx));
 7689        let buffer = MultiBuffer::build_simple(
 7690            "
 7691                a
 7692                b(
 7693                    X
 7694                )
 7695                c(
 7696                    X
 7697                )
 7698            "
 7699            .unindent()
 7700            .as_str(),
 7701            cx,
 7702        );
 7703
 7704        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7705            let mut editor = build_editor(buffer.clone(), cx);
 7706            editor.select_ranges(
 7707                [
 7708                    Point::new(2, 4)..Point::new(2, 5),
 7709                    Point::new(5, 4)..Point::new(5, 5),
 7710                ],
 7711                None,
 7712                cx,
 7713            );
 7714            editor
 7715        });
 7716
 7717        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7718        buffer.update(cx, |buffer, cx| {
 7719            buffer.edit(
 7720                [
 7721                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7722                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7723                ],
 7724                cx,
 7725            );
 7726            assert_eq!(
 7727                buffer.read(cx).text(),
 7728                "
 7729                    a
 7730                    b()
 7731                    c()
 7732                "
 7733                .unindent()
 7734            );
 7735        });
 7736
 7737        editor.update(cx, |editor, cx| {
 7738            assert_eq!(
 7739                editor.selected_ranges(cx),
 7740                &[
 7741                    Point::new(1, 2)..Point::new(1, 2),
 7742                    Point::new(2, 2)..Point::new(2, 2),
 7743                ],
 7744            );
 7745
 7746            editor.newline(&Newline, cx);
 7747            assert_eq!(
 7748                editor.text(cx),
 7749                "
 7750                    a
 7751                    b(
 7752                    )
 7753                    c(
 7754                    )
 7755                "
 7756                .unindent()
 7757            );
 7758
 7759            // The selections are moved after the inserted newlines
 7760            assert_eq!(
 7761                editor.selected_ranges(cx),
 7762                &[
 7763                    Point::new(2, 0)..Point::new(2, 0),
 7764                    Point::new(4, 0)..Point::new(4, 0),
 7765                ],
 7766            );
 7767        });
 7768    }
 7769
 7770    #[gpui::test]
 7771    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7772        cx.set_global(Settings::test(cx));
 7773        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7774        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7775            let mut editor = build_editor(buffer.clone(), cx);
 7776            editor.select_ranges([3..4, 11..12, 19..20], None, cx);
 7777            editor
 7778        });
 7779
 7780        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7781        buffer.update(cx, |buffer, cx| {
 7782            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7783            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7784        });
 7785
 7786        editor.update(cx, |editor, cx| {
 7787            assert_eq!(editor.selected_ranges(cx), &[2..2, 7..7, 12..12],);
 7788
 7789            editor.insert("Z", cx);
 7790            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7791
 7792            // The selections are moved after the inserted characters
 7793            assert_eq!(editor.selected_ranges(cx), &[3..3, 9..9, 15..15],);
 7794        });
 7795    }
 7796
 7797    #[gpui::test]
 7798    fn test_indent_outdent(cx: &mut gpui::MutableAppContext) {
 7799        cx.set_global(Settings::test(cx));
 7800        let buffer = MultiBuffer::build_simple(
 7801            indoc! {"
 7802                  one two
 7803                three
 7804                 four"},
 7805            cx,
 7806        );
 7807        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7808
 7809        view.update(cx, |view, cx| {
 7810            // two selections on the same line
 7811            select_ranges(
 7812                view,
 7813                indoc! {"
 7814                      [one] [two]
 7815                    three
 7816                     four"},
 7817                cx,
 7818            );
 7819
 7820            // indent from mid-tabstop to full tabstop
 7821            view.tab(&Tab, cx);
 7822            assert_text_with_selections(
 7823                view,
 7824                indoc! {"
 7825                        [one] [two]
 7826                    three
 7827                     four"},
 7828                cx,
 7829            );
 7830
 7831            // outdent from 1 tabstop to 0 tabstops
 7832            view.tab_prev(&TabPrev, cx);
 7833            assert_text_with_selections(
 7834                view,
 7835                indoc! {"
 7836                    [one] [two]
 7837                    three
 7838                     four"},
 7839                cx,
 7840            );
 7841
 7842            // select across line ending
 7843            select_ranges(
 7844                view,
 7845                indoc! {"
 7846                    one two
 7847                    t[hree
 7848                    ] four"},
 7849                cx,
 7850            );
 7851
 7852            // indent and outdent affect only the preceding line
 7853            view.tab(&Tab, cx);
 7854            assert_text_with_selections(
 7855                view,
 7856                indoc! {"
 7857                    one two
 7858                        t[hree
 7859                    ] four"},
 7860                cx,
 7861            );
 7862            view.tab_prev(&TabPrev, cx);
 7863            assert_text_with_selections(
 7864                view,
 7865                indoc! {"
 7866                    one two
 7867                    t[hree
 7868                    ] four"},
 7869                cx,
 7870            );
 7871
 7872            // Ensure that indenting/outdenting works when the cursor is at column 0.
 7873            select_ranges(
 7874                view,
 7875                indoc! {"
 7876                    one two
 7877                    []three
 7878                     four"},
 7879                cx,
 7880            );
 7881            view.tab(&Tab, cx);
 7882            assert_text_with_selections(
 7883                view,
 7884                indoc! {"
 7885                    one two
 7886                        []three
 7887                     four"},
 7888                cx,
 7889            );
 7890
 7891            select_ranges(
 7892                view,
 7893                indoc! {"
 7894                    one two
 7895                    []    three
 7896                     four"},
 7897                cx,
 7898            );
 7899            view.tab_prev(&TabPrev, cx);
 7900            assert_text_with_selections(
 7901                view,
 7902                indoc! {"
 7903                    one two
 7904                    []three
 7905                     four"},
 7906                cx,
 7907            );
 7908        });
 7909    }
 7910
 7911    #[gpui::test]
 7912    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7913        cx.set_global(
 7914            Settings::test(cx)
 7915                .with_overrides(
 7916                    "TOML",
 7917                    LanguageOverride {
 7918                        tab_size: Some(2),
 7919                        ..Default::default()
 7920                    },
 7921                )
 7922                .with_overrides(
 7923                    "Rust",
 7924                    LanguageOverride {
 7925                        tab_size: Some(4),
 7926                        ..Default::default()
 7927                    },
 7928                ),
 7929        );
 7930        let toml_language = Arc::new(Language::new(
 7931            LanguageConfig {
 7932                name: "TOML".into(),
 7933                ..Default::default()
 7934            },
 7935            None,
 7936        ));
 7937        let rust_language = Arc::new(Language::new(
 7938            LanguageConfig {
 7939                name: "Rust".into(),
 7940                ..Default::default()
 7941            },
 7942            None,
 7943        ));
 7944
 7945        let toml_buffer = cx
 7946            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7947        let rust_buffer = cx.add_model(|cx| {
 7948            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7949        });
 7950        let multibuffer = cx.add_model(|cx| {
 7951            let mut multibuffer = MultiBuffer::new(0);
 7952            multibuffer.push_excerpts(
 7953                toml_buffer.clone(),
 7954                [Point::new(0, 0)..Point::new(2, 0)],
 7955                cx,
 7956            );
 7957            multibuffer.push_excerpts(
 7958                rust_buffer.clone(),
 7959                [Point::new(0, 0)..Point::new(1, 0)],
 7960                cx,
 7961            );
 7962            multibuffer
 7963        });
 7964
 7965        cx.add_window(Default::default(), |cx| {
 7966            let mut editor = build_editor(multibuffer, cx);
 7967
 7968            assert_eq!(
 7969                editor.text(cx),
 7970                indoc! {"
 7971                    a = 1
 7972                    b = 2
 7973
 7974                    const c: usize = 3;
 7975                "}
 7976            );
 7977
 7978            select_ranges(
 7979                &mut editor,
 7980                indoc! {"
 7981                    [a] = 1
 7982                    b = 2
 7983
 7984                    [const c:] usize = 3;
 7985                "},
 7986                cx,
 7987            );
 7988
 7989            editor.tab(&Tab, cx);
 7990            assert_text_with_selections(
 7991                &mut editor,
 7992                indoc! {"
 7993                      [a] = 1
 7994                    b = 2
 7995
 7996                        [const c:] usize = 3;
 7997                "},
 7998                cx,
 7999            );
 8000            editor.tab_prev(&TabPrev, cx);
 8001            assert_text_with_selections(
 8002                &mut editor,
 8003                indoc! {"
 8004                    [a] = 1
 8005                    b = 2
 8006
 8007                    [const c:] usize = 3;
 8008                "},
 8009                cx,
 8010            );
 8011
 8012            editor
 8013        });
 8014    }
 8015
 8016    #[gpui::test]
 8017    fn test_backspace(cx: &mut gpui::MutableAppContext) {
 8018        cx.set_global(Settings::test(cx));
 8019        let (_, view) = cx.add_window(Default::default(), |cx| {
 8020            build_editor(MultiBuffer::build_simple("", cx), cx)
 8021        });
 8022
 8023        view.update(cx, |view, cx| {
 8024            view.set_text("one two three\nfour five six\nseven eight nine\nten\n", cx);
 8025            view.select_display_ranges(
 8026                &[
 8027                    // an empty selection - the preceding character is deleted
 8028                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8029                    // one character selected - it is deleted
 8030                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8031                    // a line suffix selected - it is deleted
 8032                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 8033                ],
 8034                cx,
 8035            );
 8036            view.backspace(&Backspace, cx);
 8037            assert_eq!(view.text(cx), "oe two three\nfou five six\nseven ten\n");
 8038
 8039            view.set_text("    one\n        two\n        three\n   four", cx);
 8040            view.select_display_ranges(
 8041                &[
 8042                    // cursors at the the end of leading indent - last indent is deleted
 8043                    DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
 8044                    DisplayPoint::new(1, 8)..DisplayPoint::new(1, 8),
 8045                    // cursors inside leading indent - overlapping indent deletions are coalesced
 8046                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 8047                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8048                    DisplayPoint::new(2, 6)..DisplayPoint::new(2, 6),
 8049                    // cursor at the beginning of a line - preceding newline is deleted
 8050                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8051                    // selection inside leading indent - only the selected character is deleted
 8052                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 3),
 8053                ],
 8054                cx,
 8055            );
 8056            view.backspace(&Backspace, cx);
 8057            assert_eq!(view.text(cx), "one\n    two\n  three  four");
 8058        });
 8059    }
 8060
 8061    #[gpui::test]
 8062    fn test_delete(cx: &mut gpui::MutableAppContext) {
 8063        cx.set_global(Settings::test(cx));
 8064        let buffer =
 8065            MultiBuffer::build_simple("one two three\nfour five six\nseven eight nine\nten\n", cx);
 8066        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 8067
 8068        view.update(cx, |view, cx| {
 8069            view.select_display_ranges(
 8070                &[
 8071                    // an empty selection - the following character is deleted
 8072                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8073                    // one character selected - it is deleted
 8074                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8075                    // a line suffix selected - it is deleted
 8076                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
 8077                ],
 8078                cx,
 8079            );
 8080            view.delete(&Delete, cx);
 8081        });
 8082
 8083        assert_eq!(
 8084            buffer.read(cx).read(cx).text(),
 8085            "on two three\nfou five six\nseven ten\n"
 8086        );
 8087    }
 8088
 8089    #[gpui::test]
 8090    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 8091        cx.set_global(Settings::test(cx));
 8092        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8093        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8094        view.update(cx, |view, cx| {
 8095            view.select_display_ranges(
 8096                &[
 8097                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8098                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8099                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8100                ],
 8101                cx,
 8102            );
 8103            view.delete_line(&DeleteLine, cx);
 8104            assert_eq!(view.display_text(cx), "ghi");
 8105            assert_eq!(
 8106                view.selected_display_ranges(cx),
 8107                vec![
 8108                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 8109                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 8110                ]
 8111            );
 8112        });
 8113
 8114        cx.set_global(Settings::test(cx));
 8115        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8116        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8117        view.update(cx, |view, cx| {
 8118            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], cx);
 8119            view.delete_line(&DeleteLine, cx);
 8120            assert_eq!(view.display_text(cx), "ghi\n");
 8121            assert_eq!(
 8122                view.selected_display_ranges(cx),
 8123                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 8124            );
 8125        });
 8126    }
 8127
 8128    #[gpui::test]
 8129    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 8130        cx.set_global(Settings::test(cx));
 8131        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8132        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8133        view.update(cx, |view, cx| {
 8134            view.select_display_ranges(
 8135                &[
 8136                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8137                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8138                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8139                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8140                ],
 8141                cx,
 8142            );
 8143            view.duplicate_line(&DuplicateLine, cx);
 8144            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 8145            assert_eq!(
 8146                view.selected_display_ranges(cx),
 8147                vec![
 8148                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8149                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 8150                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8151                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 8152                ]
 8153            );
 8154        });
 8155
 8156        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 8157        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8158        view.update(cx, |view, cx| {
 8159            view.select_display_ranges(
 8160                &[
 8161                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 8162                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 8163                ],
 8164                cx,
 8165            );
 8166            view.duplicate_line(&DuplicateLine, cx);
 8167            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 8168            assert_eq!(
 8169                view.selected_display_ranges(cx),
 8170                vec![
 8171                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 8172                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 8173                ]
 8174            );
 8175        });
 8176    }
 8177
 8178    #[gpui::test]
 8179    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 8180        cx.set_global(Settings::test(cx));
 8181        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8182        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8183        view.update(cx, |view, cx| {
 8184            view.fold_ranges(
 8185                vec![
 8186                    Point::new(0, 2)..Point::new(1, 2),
 8187                    Point::new(2, 3)..Point::new(4, 1),
 8188                    Point::new(7, 0)..Point::new(8, 4),
 8189                ],
 8190                cx,
 8191            );
 8192            view.select_display_ranges(
 8193                &[
 8194                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8195                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8196                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8197                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 8198                ],
 8199                cx,
 8200            );
 8201            assert_eq!(
 8202                view.display_text(cx),
 8203                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 8204            );
 8205
 8206            view.move_line_up(&MoveLineUp, cx);
 8207            assert_eq!(
 8208                view.display_text(cx),
 8209                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 8210            );
 8211            assert_eq!(
 8212                view.selected_display_ranges(cx),
 8213                vec![
 8214                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8215                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8216                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8217                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8218                ]
 8219            );
 8220        });
 8221
 8222        view.update(cx, |view, cx| {
 8223            view.move_line_down(&MoveLineDown, cx);
 8224            assert_eq!(
 8225                view.display_text(cx),
 8226                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 8227            );
 8228            assert_eq!(
 8229                view.selected_display_ranges(cx),
 8230                vec![
 8231                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8232                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8233                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8234                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8235                ]
 8236            );
 8237        });
 8238
 8239        view.update(cx, |view, cx| {
 8240            view.move_line_down(&MoveLineDown, cx);
 8241            assert_eq!(
 8242                view.display_text(cx),
 8243                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 8244            );
 8245            assert_eq!(
 8246                view.selected_display_ranges(cx),
 8247                vec![
 8248                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8249                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 8250                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 8251                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 8252                ]
 8253            );
 8254        });
 8255
 8256        view.update(cx, |view, cx| {
 8257            view.move_line_up(&MoveLineUp, cx);
 8258            assert_eq!(
 8259                view.display_text(cx),
 8260                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 8261            );
 8262            assert_eq!(
 8263                view.selected_display_ranges(cx),
 8264                vec![
 8265                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8266                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8267                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 8268                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 8269                ]
 8270            );
 8271        });
 8272    }
 8273
 8274    #[gpui::test]
 8275    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 8276        cx.set_global(Settings::test(cx));
 8277        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 8278        let snapshot = buffer.read(cx).snapshot(cx);
 8279        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8280        editor.update(cx, |editor, cx| {
 8281            editor.insert_blocks(
 8282                [BlockProperties {
 8283                    position: snapshot.anchor_after(Point::new(2, 0)),
 8284                    disposition: BlockDisposition::Below,
 8285                    height: 1,
 8286                    render: Arc::new(|_| Empty::new().boxed()),
 8287                }],
 8288                cx,
 8289            );
 8290            editor.select_ranges([Point::new(2, 0)..Point::new(2, 0)], None, cx);
 8291            editor.move_line_down(&MoveLineDown, cx);
 8292        });
 8293    }
 8294
 8295    #[gpui::test]
 8296    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8297        cx.set_global(Settings::test(cx));
 8298
 8299        cx.add_window(Default::default(), |cx| {
 8300            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8301
 8302            editor.select_ranges([1..1], None, cx);
 8303            editor.transpose(&Default::default(), cx);
 8304            assert_eq!(editor.text(cx), "bac");
 8305            assert_eq!(editor.selected_ranges(cx), [2..2]);
 8306
 8307            editor.transpose(&Default::default(), cx);
 8308            assert_eq!(editor.text(cx), "bca");
 8309            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8310
 8311            editor.transpose(&Default::default(), cx);
 8312            assert_eq!(editor.text(cx), "bac");
 8313            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8314
 8315            editor
 8316        })
 8317        .1;
 8318
 8319        cx.add_window(Default::default(), |cx| {
 8320            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8321
 8322            editor.select_ranges([3..3], None, cx);
 8323            editor.transpose(&Default::default(), cx);
 8324            assert_eq!(editor.text(cx), "acb\nde");
 8325            assert_eq!(editor.selected_ranges(cx), [3..3]);
 8326
 8327            editor.select_ranges([4..4], None, cx);
 8328            editor.transpose(&Default::default(), cx);
 8329            assert_eq!(editor.text(cx), "acbd\ne");
 8330            assert_eq!(editor.selected_ranges(cx), [5..5]);
 8331
 8332            editor.transpose(&Default::default(), cx);
 8333            assert_eq!(editor.text(cx), "acbde\n");
 8334            assert_eq!(editor.selected_ranges(cx), [6..6]);
 8335
 8336            editor.transpose(&Default::default(), cx);
 8337            assert_eq!(editor.text(cx), "acbd\ne");
 8338            assert_eq!(editor.selected_ranges(cx), [6..6]);
 8339
 8340            editor
 8341        })
 8342        .1;
 8343
 8344        cx.add_window(Default::default(), |cx| {
 8345            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8346
 8347            editor.select_ranges([1..1, 2..2, 4..4], None, cx);
 8348            editor.transpose(&Default::default(), cx);
 8349            assert_eq!(editor.text(cx), "bacd\ne");
 8350            assert_eq!(editor.selected_ranges(cx), [2..2, 3..3, 5..5]);
 8351
 8352            editor.transpose(&Default::default(), cx);
 8353            assert_eq!(editor.text(cx), "bcade\n");
 8354            assert_eq!(editor.selected_ranges(cx), [3..3, 4..4, 6..6]);
 8355
 8356            editor.transpose(&Default::default(), cx);
 8357            assert_eq!(editor.text(cx), "bcda\ne");
 8358            assert_eq!(editor.selected_ranges(cx), [4..4, 6..6]);
 8359
 8360            editor.transpose(&Default::default(), cx);
 8361            assert_eq!(editor.text(cx), "bcade\n");
 8362            assert_eq!(editor.selected_ranges(cx), [4..4, 6..6]);
 8363
 8364            editor.transpose(&Default::default(), cx);
 8365            assert_eq!(editor.text(cx), "bcaed\n");
 8366            assert_eq!(editor.selected_ranges(cx), [5..5, 6..6]);
 8367
 8368            editor
 8369        })
 8370        .1;
 8371
 8372        cx.add_window(Default::default(), |cx| {
 8373            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8374
 8375            editor.select_ranges([4..4], None, cx);
 8376            editor.transpose(&Default::default(), cx);
 8377            assert_eq!(editor.text(cx), "🏀🍐✋");
 8378            assert_eq!(editor.selected_ranges(cx), [8..8]);
 8379
 8380            editor.transpose(&Default::default(), cx);
 8381            assert_eq!(editor.text(cx), "🏀✋🍐");
 8382            assert_eq!(editor.selected_ranges(cx), [11..11]);
 8383
 8384            editor.transpose(&Default::default(), cx);
 8385            assert_eq!(editor.text(cx), "🏀🍐✋");
 8386            assert_eq!(editor.selected_ranges(cx), [11..11]);
 8387
 8388            editor
 8389        })
 8390        .1;
 8391    }
 8392
 8393    #[gpui::test]
 8394    fn test_clipboard(cx: &mut gpui::MutableAppContext) {
 8395        cx.set_global(Settings::test(cx));
 8396        let buffer = MultiBuffer::build_simple("one✅ two three four five six ", cx);
 8397        let view = cx
 8398            .add_window(Default::default(), |cx| build_editor(buffer.clone(), cx))
 8399            .1;
 8400
 8401        // Cut with three selections. Clipboard text is divided into three slices.
 8402        view.update(cx, |view, cx| {
 8403            view.select_ranges(vec![0..7, 11..17, 22..27], None, cx);
 8404            view.cut(&Cut, cx);
 8405            assert_eq!(view.display_text(cx), "two four six ");
 8406        });
 8407
 8408        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8409        view.update(cx, |view, cx| {
 8410            view.select_ranges(vec![4..4, 9..9, 13..13], None, cx);
 8411            view.paste(&Paste, cx);
 8412            assert_eq!(view.display_text(cx), "two one✅ four three six five ");
 8413            assert_eq!(
 8414                view.selected_display_ranges(cx),
 8415                &[
 8416                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 8417                    DisplayPoint::new(0, 22)..DisplayPoint::new(0, 22),
 8418                    DisplayPoint::new(0, 31)..DisplayPoint::new(0, 31)
 8419                ]
 8420            );
 8421        });
 8422
 8423        // Paste again but with only two cursors. Since the number of cursors doesn't
 8424        // match the number of slices in the clipboard, the entire clipboard text
 8425        // is pasted at each cursor.
 8426        view.update(cx, |view, cx| {
 8427            view.select_ranges(vec![0..0, 31..31], None, cx);
 8428            view.handle_input(&Input("( ".into()), cx);
 8429            view.paste(&Paste, cx);
 8430            view.handle_input(&Input(") ".into()), cx);
 8431            assert_eq!(
 8432                view.display_text(cx),
 8433                "( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8434            );
 8435        });
 8436
 8437        view.update(cx, |view, cx| {
 8438            view.select_ranges(vec![0..0], None, cx);
 8439            view.handle_input(&Input("123\n4567\n89\n".into()), cx);
 8440            assert_eq!(
 8441                view.display_text(cx),
 8442                "123\n4567\n89\n( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8443            );
 8444        });
 8445
 8446        // Cut with three selections, one of which is full-line.
 8447        view.update(cx, |view, cx| {
 8448            view.select_display_ranges(
 8449                &[
 8450                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
 8451                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8452                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8453                ],
 8454                cx,
 8455            );
 8456            view.cut(&Cut, cx);
 8457            assert_eq!(
 8458                view.display_text(cx),
 8459                "13\n9\n( one✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8460            );
 8461        });
 8462
 8463        // Paste with three selections, noticing how the copied selection that was full-line
 8464        // gets inserted before the second cursor.
 8465        view.update(cx, |view, cx| {
 8466            view.select_display_ranges(
 8467                &[
 8468                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8469                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8470                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
 8471                ],
 8472                cx,
 8473            );
 8474            view.paste(&Paste, cx);
 8475            assert_eq!(
 8476                view.display_text(cx),
 8477                "123\n4567\n9\n( 8ne✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8478            );
 8479            assert_eq!(
 8480                view.selected_display_ranges(cx),
 8481                &[
 8482                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8483                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8484                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
 8485                ]
 8486            );
 8487        });
 8488
 8489        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8490        view.update(cx, |view, cx| {
 8491            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], cx);
 8492            view.copy(&Copy, cx);
 8493        });
 8494
 8495        // Paste with three selections, noticing how the copied full-line selection is inserted
 8496        // before the empty selections but replaces the selection that is non-empty.
 8497        view.update(cx, |view, cx| {
 8498            view.select_display_ranges(
 8499                &[
 8500                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8501                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
 8502                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8503                ],
 8504                cx,
 8505            );
 8506            view.paste(&Paste, cx);
 8507            assert_eq!(
 8508                view.display_text(cx),
 8509                "123\n123\n123\n67\n123\n9\n( 8ne✅ \nthree \nfive ) two one✅ four three six five ( one✅ \nthree \nfive ) "
 8510            );
 8511            assert_eq!(
 8512                view.selected_display_ranges(cx),
 8513                &[
 8514                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 8515                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8516                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
 8517                ]
 8518            );
 8519        });
 8520    }
 8521
 8522    #[gpui::test]
 8523    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8524        cx.set_global(Settings::test(cx));
 8525        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8526        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8527        view.update(cx, |view, cx| {
 8528            view.select_all(&SelectAll, cx);
 8529            assert_eq!(
 8530                view.selected_display_ranges(cx),
 8531                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8532            );
 8533        });
 8534    }
 8535
 8536    #[gpui::test]
 8537    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8538        cx.set_global(Settings::test(cx));
 8539        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8540        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8541        view.update(cx, |view, cx| {
 8542            view.select_display_ranges(
 8543                &[
 8544                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8545                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8546                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8547                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8548                ],
 8549                cx,
 8550            );
 8551            view.select_line(&SelectLine, cx);
 8552            assert_eq!(
 8553                view.selected_display_ranges(cx),
 8554                vec![
 8555                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8556                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8557                ]
 8558            );
 8559        });
 8560
 8561        view.update(cx, |view, cx| {
 8562            view.select_line(&SelectLine, cx);
 8563            assert_eq!(
 8564                view.selected_display_ranges(cx),
 8565                vec![
 8566                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8567                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8568                ]
 8569            );
 8570        });
 8571
 8572        view.update(cx, |view, cx| {
 8573            view.select_line(&SelectLine, cx);
 8574            assert_eq!(
 8575                view.selected_display_ranges(cx),
 8576                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8577            );
 8578        });
 8579    }
 8580
 8581    #[gpui::test]
 8582    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8583        cx.set_global(Settings::test(cx));
 8584        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8585        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8586        view.update(cx, |view, cx| {
 8587            view.fold_ranges(
 8588                vec![
 8589                    Point::new(0, 2)..Point::new(1, 2),
 8590                    Point::new(2, 3)..Point::new(4, 1),
 8591                    Point::new(7, 0)..Point::new(8, 4),
 8592                ],
 8593                cx,
 8594            );
 8595            view.select_display_ranges(
 8596                &[
 8597                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8598                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8599                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8600                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8601                ],
 8602                cx,
 8603            );
 8604            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8605        });
 8606
 8607        view.update(cx, |view, cx| {
 8608            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8609            assert_eq!(
 8610                view.display_text(cx),
 8611                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8612            );
 8613            assert_eq!(
 8614                view.selected_display_ranges(cx),
 8615                [
 8616                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8617                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8618                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8619                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8620                ]
 8621            );
 8622        });
 8623
 8624        view.update(cx, |view, cx| {
 8625            view.select_display_ranges(&[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)], cx);
 8626            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8627            assert_eq!(
 8628                view.display_text(cx),
 8629                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8630            );
 8631            assert_eq!(
 8632                view.selected_display_ranges(cx),
 8633                [
 8634                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8635                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8636                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8637                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8638                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8639                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8640                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8641                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8642                ]
 8643            );
 8644        });
 8645    }
 8646
 8647    #[gpui::test]
 8648    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8649        cx.set_global(Settings::test(cx));
 8650        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8651        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8652
 8653        view.update(cx, |view, cx| {
 8654            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], cx);
 8655        });
 8656        view.update(cx, |view, cx| {
 8657            view.add_selection_above(&AddSelectionAbove, cx);
 8658            assert_eq!(
 8659                view.selected_display_ranges(cx),
 8660                vec![
 8661                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8662                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8663                ]
 8664            );
 8665        });
 8666
 8667        view.update(cx, |view, cx| {
 8668            view.add_selection_above(&AddSelectionAbove, cx);
 8669            assert_eq!(
 8670                view.selected_display_ranges(cx),
 8671                vec![
 8672                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8673                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8674                ]
 8675            );
 8676        });
 8677
 8678        view.update(cx, |view, cx| {
 8679            view.add_selection_below(&AddSelectionBelow, cx);
 8680            assert_eq!(
 8681                view.selected_display_ranges(cx),
 8682                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8683            );
 8684
 8685            view.undo_selection(&UndoSelection, cx);
 8686            assert_eq!(
 8687                view.selected_display_ranges(cx),
 8688                vec![
 8689                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8690                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8691                ]
 8692            );
 8693
 8694            view.redo_selection(&RedoSelection, cx);
 8695            assert_eq!(
 8696                view.selected_display_ranges(cx),
 8697                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8698            );
 8699        });
 8700
 8701        view.update(cx, |view, cx| {
 8702            view.add_selection_below(&AddSelectionBelow, cx);
 8703            assert_eq!(
 8704                view.selected_display_ranges(cx),
 8705                vec![
 8706                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8707                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8708                ]
 8709            );
 8710        });
 8711
 8712        view.update(cx, |view, cx| {
 8713            view.add_selection_below(&AddSelectionBelow, cx);
 8714            assert_eq!(
 8715                view.selected_display_ranges(cx),
 8716                vec![
 8717                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8718                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8719                ]
 8720            );
 8721        });
 8722
 8723        view.update(cx, |view, cx| {
 8724            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], cx);
 8725        });
 8726        view.update(cx, |view, cx| {
 8727            view.add_selection_below(&AddSelectionBelow, cx);
 8728            assert_eq!(
 8729                view.selected_display_ranges(cx),
 8730                vec![
 8731                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8732                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8733                ]
 8734            );
 8735        });
 8736
 8737        view.update(cx, |view, cx| {
 8738            view.add_selection_below(&AddSelectionBelow, cx);
 8739            assert_eq!(
 8740                view.selected_display_ranges(cx),
 8741                vec![
 8742                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8743                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8744                ]
 8745            );
 8746        });
 8747
 8748        view.update(cx, |view, cx| {
 8749            view.add_selection_above(&AddSelectionAbove, cx);
 8750            assert_eq!(
 8751                view.selected_display_ranges(cx),
 8752                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8753            );
 8754        });
 8755
 8756        view.update(cx, |view, cx| {
 8757            view.add_selection_above(&AddSelectionAbove, cx);
 8758            assert_eq!(
 8759                view.selected_display_ranges(cx),
 8760                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 8761            );
 8762        });
 8763
 8764        view.update(cx, |view, cx| {
 8765            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], cx);
 8766            view.add_selection_below(&AddSelectionBelow, cx);
 8767            assert_eq!(
 8768                view.selected_display_ranges(cx),
 8769                vec![
 8770                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8771                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8772                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8773                ]
 8774            );
 8775        });
 8776
 8777        view.update(cx, |view, cx| {
 8778            view.add_selection_below(&AddSelectionBelow, cx);
 8779            assert_eq!(
 8780                view.selected_display_ranges(cx),
 8781                vec![
 8782                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8783                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8784                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8785                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8786                ]
 8787            );
 8788        });
 8789
 8790        view.update(cx, |view, cx| {
 8791            view.add_selection_above(&AddSelectionAbove, cx);
 8792            assert_eq!(
 8793                view.selected_display_ranges(cx),
 8794                vec![
 8795                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8796                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8797                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8798                ]
 8799            );
 8800        });
 8801
 8802        view.update(cx, |view, cx| {
 8803            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], cx);
 8804        });
 8805        view.update(cx, |view, cx| {
 8806            view.add_selection_above(&AddSelectionAbove, cx);
 8807            assert_eq!(
 8808                view.selected_display_ranges(cx),
 8809                vec![
 8810                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8811                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8812                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8813                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8814                ]
 8815            );
 8816        });
 8817
 8818        view.update(cx, |view, cx| {
 8819            view.add_selection_below(&AddSelectionBelow, cx);
 8820            assert_eq!(
 8821                view.selected_display_ranges(cx),
 8822                vec![
 8823                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8824                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8825                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8826                ]
 8827            );
 8828        });
 8829    }
 8830
 8831    #[gpui::test]
 8832    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8833        cx.set_global(Settings::test(cx));
 8834
 8835        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8836        let buffer = MultiBuffer::build_simple(&text, cx);
 8837        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8838
 8839        view.update(cx, |view, cx| {
 8840            view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx);
 8841            view.select_next(
 8842                &SelectNext {
 8843                    replace_newest: false,
 8844                },
 8845                cx,
 8846            );
 8847            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8848
 8849            view.select_next(
 8850                &SelectNext {
 8851                    replace_newest: false,
 8852                },
 8853                cx,
 8854            );
 8855            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8856
 8857            view.undo_selection(&UndoSelection, cx);
 8858            assert_eq!(view.selected_ranges(cx), &ranges[1..2]);
 8859
 8860            view.redo_selection(&RedoSelection, cx);
 8861            assert_eq!(view.selected_ranges(cx), &ranges[1..3]);
 8862
 8863            view.select_next(
 8864                &SelectNext {
 8865                    replace_newest: false,
 8866                },
 8867                cx,
 8868            );
 8869            assert_eq!(view.selected_ranges(cx), &ranges[1..4]);
 8870
 8871            view.select_next(
 8872                &SelectNext {
 8873                    replace_newest: false,
 8874                },
 8875                cx,
 8876            );
 8877            assert_eq!(view.selected_ranges(cx), &ranges[0..4]);
 8878        });
 8879    }
 8880
 8881    #[gpui::test]
 8882    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8883        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8884        let language = Arc::new(Language::new(
 8885            LanguageConfig::default(),
 8886            Some(tree_sitter_rust::language()),
 8887        ));
 8888
 8889        let text = r#"
 8890            use mod1::mod2::{mod3, mod4};
 8891
 8892            fn fn_1(param1: bool, param2: &str) {
 8893                let var1 = "text";
 8894            }
 8895        "#
 8896        .unindent();
 8897
 8898        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8899        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8900        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8901        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8902            .await;
 8903
 8904        view.update(cx, |view, cx| {
 8905            view.select_display_ranges(
 8906                &[
 8907                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8908                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8909                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8910                ],
 8911                cx,
 8912            );
 8913            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8914        });
 8915        assert_eq!(
 8916            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8917            &[
 8918                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8919                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8920                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8921            ]
 8922        );
 8923
 8924        view.update(cx, |view, cx| {
 8925            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8926        });
 8927        assert_eq!(
 8928            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8929            &[
 8930                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8931                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8932            ]
 8933        );
 8934
 8935        view.update(cx, |view, cx| {
 8936            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8937        });
 8938        assert_eq!(
 8939            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8940            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8941        );
 8942
 8943        // Trying to expand the selected syntax node one more time has no effect.
 8944        view.update(cx, |view, cx| {
 8945            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8946        });
 8947        assert_eq!(
 8948            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8949            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8950        );
 8951
 8952        view.update(cx, |view, cx| {
 8953            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8954        });
 8955        assert_eq!(
 8956            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8957            &[
 8958                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8959                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8960            ]
 8961        );
 8962
 8963        view.update(cx, |view, cx| {
 8964            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8965        });
 8966        assert_eq!(
 8967            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8968            &[
 8969                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8970                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8971                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8972            ]
 8973        );
 8974
 8975        view.update(cx, |view, cx| {
 8976            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8977        });
 8978        assert_eq!(
 8979            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8980            &[
 8981                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8982                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8983                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8984            ]
 8985        );
 8986
 8987        // Trying to shrink the selected syntax node one more time has no effect.
 8988        view.update(cx, |view, cx| {
 8989            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8990        });
 8991        assert_eq!(
 8992            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 8993            &[
 8994                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8995                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8996                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8997            ]
 8998        );
 8999
 9000        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 9001        // a fold.
 9002        view.update(cx, |view, cx| {
 9003            view.fold_ranges(
 9004                vec![
 9005                    Point::new(0, 21)..Point::new(0, 24),
 9006                    Point::new(3, 20)..Point::new(3, 22),
 9007                ],
 9008                cx,
 9009            );
 9010            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 9011        });
 9012        assert_eq!(
 9013            view.update(cx, |view, cx| view.selected_display_ranges(cx)),
 9014            &[
 9015                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 9016                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 9017                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 9018            ]
 9019        );
 9020    }
 9021
 9022    #[gpui::test]
 9023    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 9024        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9025        let language = Arc::new(
 9026            Language::new(
 9027                LanguageConfig {
 9028                    brackets: vec![
 9029                        BracketPair {
 9030                            start: "{".to_string(),
 9031                            end: "}".to_string(),
 9032                            close: false,
 9033                            newline: true,
 9034                        },
 9035                        BracketPair {
 9036                            start: "(".to_string(),
 9037                            end: ")".to_string(),
 9038                            close: false,
 9039                            newline: true,
 9040                        },
 9041                    ],
 9042                    ..Default::default()
 9043                },
 9044                Some(tree_sitter_rust::language()),
 9045            )
 9046            .with_indents_query(
 9047                r#"
 9048                (_ "(" ")" @end) @indent
 9049                (_ "{" "}" @end) @indent
 9050                "#,
 9051            )
 9052            .unwrap(),
 9053        );
 9054
 9055        let text = "fn a() {}";
 9056
 9057        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9058        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9059        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9060        editor
 9061            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 9062            .await;
 9063
 9064        editor.update(cx, |editor, cx| {
 9065            editor.select_ranges([5..5, 8..8, 9..9], None, cx);
 9066            editor.newline(&Newline, cx);
 9067            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 9068            assert_eq!(
 9069                editor.selected_ranges(cx),
 9070                &[
 9071                    Point::new(1, 4)..Point::new(1, 4),
 9072                    Point::new(3, 4)..Point::new(3, 4),
 9073                    Point::new(5, 0)..Point::new(5, 0)
 9074                ]
 9075            );
 9076        });
 9077    }
 9078
 9079    #[gpui::test]
 9080    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 9081        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9082        let language = Arc::new(Language::new(
 9083            LanguageConfig {
 9084                brackets: vec![
 9085                    BracketPair {
 9086                        start: "{".to_string(),
 9087                        end: "}".to_string(),
 9088                        close: true,
 9089                        newline: true,
 9090                    },
 9091                    BracketPair {
 9092                        start: "/*".to_string(),
 9093                        end: " */".to_string(),
 9094                        close: true,
 9095                        newline: true,
 9096                    },
 9097                ],
 9098                autoclose_before: "})]".to_string(),
 9099                ..Default::default()
 9100            },
 9101            Some(tree_sitter_rust::language()),
 9102        ));
 9103
 9104        let text = r#"
 9105            a
 9106
 9107            /
 9108
 9109        "#
 9110        .unindent();
 9111
 9112        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9113        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9114        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9115        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9116            .await;
 9117
 9118        view.update(cx, |view, cx| {
 9119            view.select_display_ranges(
 9120                &[
 9121                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9122                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 9123                ],
 9124                cx,
 9125            );
 9126
 9127            view.handle_input(&Input("{".to_string()), cx);
 9128            view.handle_input(&Input("{".to_string()), cx);
 9129            view.handle_input(&Input("{".to_string()), cx);
 9130            assert_eq!(
 9131                view.text(cx),
 9132                "
 9133                {{{}}}
 9134                {{{}}}
 9135                /
 9136
 9137                "
 9138                .unindent()
 9139            );
 9140
 9141            view.move_right(&MoveRight, cx);
 9142            view.handle_input(&Input("}".to_string()), cx);
 9143            view.handle_input(&Input("}".to_string()), cx);
 9144            view.handle_input(&Input("}".to_string()), cx);
 9145            assert_eq!(
 9146                view.text(cx),
 9147                "
 9148                {{{}}}}
 9149                {{{}}}}
 9150                /
 9151
 9152                "
 9153                .unindent()
 9154            );
 9155
 9156            view.undo(&Undo, cx);
 9157            view.handle_input(&Input("/".to_string()), cx);
 9158            view.handle_input(&Input("*".to_string()), cx);
 9159            assert_eq!(
 9160                view.text(cx),
 9161                "
 9162                /* */
 9163                /* */
 9164                /
 9165
 9166                "
 9167                .unindent()
 9168            );
 9169
 9170            view.undo(&Undo, cx);
 9171            view.select_display_ranges(
 9172                &[
 9173                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 9174                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 9175                ],
 9176                cx,
 9177            );
 9178            view.handle_input(&Input("*".to_string()), cx);
 9179            assert_eq!(
 9180                view.text(cx),
 9181                "
 9182                a
 9183
 9184                /*
 9185                *
 9186                "
 9187                .unindent()
 9188            );
 9189
 9190            // Don't autoclose if the next character isn't whitespace and isn't
 9191            // listed in the language's "autoclose_before" section.
 9192            view.finalize_last_transaction(cx);
 9193            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)], cx);
 9194            view.handle_input(&Input("{".to_string()), cx);
 9195            assert_eq!(
 9196                view.text(cx),
 9197                "
 9198                {a
 9199
 9200                /*
 9201                *
 9202                "
 9203                .unindent()
 9204            );
 9205
 9206            view.undo(&Undo, cx);
 9207            view.select_display_ranges(&[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)], cx);
 9208            view.handle_input(&Input("{".to_string()), cx);
 9209            assert_eq!(
 9210                view.text(cx),
 9211                "
 9212                {a}
 9213
 9214                /*
 9215                *
 9216                "
 9217                .unindent()
 9218            );
 9219            assert_eq!(
 9220                view.selected_display_ranges(cx),
 9221                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 9222            );
 9223        });
 9224    }
 9225
 9226    #[gpui::test]
 9227    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9228        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9229
 9230        let text = "
 9231            a. b
 9232            a. b
 9233            a. b
 9234        "
 9235        .unindent();
 9236        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9237        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9238
 9239        editor.update(cx, |editor, cx| {
 9240            let buffer = &editor.snapshot(cx).buffer_snapshot;
 9241            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9242            let insertion_ranges = [
 9243                Point::new(0, 2).to_offset(buffer)..Point::new(0, 2).to_offset(buffer),
 9244                Point::new(1, 2).to_offset(buffer)..Point::new(1, 2).to_offset(buffer),
 9245                Point::new(2, 2).to_offset(buffer)..Point::new(2, 2).to_offset(buffer),
 9246            ];
 9247
 9248            editor
 9249                .insert_snippet(&insertion_ranges, snippet, cx)
 9250                .unwrap();
 9251            assert_eq!(
 9252                editor.text(cx),
 9253                "
 9254                    a.f(one, two, three) b
 9255                    a.f(one, two, three) b
 9256                    a.f(one, two, three) b
 9257                "
 9258                .unindent()
 9259            );
 9260            assert_eq!(
 9261                editor.selected_ranges::<Point>(cx),
 9262                &[
 9263                    Point::new(0, 4)..Point::new(0, 7),
 9264                    Point::new(0, 14)..Point::new(0, 19),
 9265                    Point::new(1, 4)..Point::new(1, 7),
 9266                    Point::new(1, 14)..Point::new(1, 19),
 9267                    Point::new(2, 4)..Point::new(2, 7),
 9268                    Point::new(2, 14)..Point::new(2, 19),
 9269                ]
 9270            );
 9271
 9272            // Can't move earlier than the first tab stop
 9273            editor.move_to_prev_snippet_tabstop(cx);
 9274            assert_eq!(
 9275                editor.selected_ranges::<Point>(cx),
 9276                &[
 9277                    Point::new(0, 4)..Point::new(0, 7),
 9278                    Point::new(0, 14)..Point::new(0, 19),
 9279                    Point::new(1, 4)..Point::new(1, 7),
 9280                    Point::new(1, 14)..Point::new(1, 19),
 9281                    Point::new(2, 4)..Point::new(2, 7),
 9282                    Point::new(2, 14)..Point::new(2, 19),
 9283                ]
 9284            );
 9285
 9286            assert!(editor.move_to_next_snippet_tabstop(cx));
 9287            assert_eq!(
 9288                editor.selected_ranges::<Point>(cx),
 9289                &[
 9290                    Point::new(0, 9)..Point::new(0, 12),
 9291                    Point::new(1, 9)..Point::new(1, 12),
 9292                    Point::new(2, 9)..Point::new(2, 12)
 9293                ]
 9294            );
 9295
 9296            editor.move_to_prev_snippet_tabstop(cx);
 9297            assert_eq!(
 9298                editor.selected_ranges::<Point>(cx),
 9299                &[
 9300                    Point::new(0, 4)..Point::new(0, 7),
 9301                    Point::new(0, 14)..Point::new(0, 19),
 9302                    Point::new(1, 4)..Point::new(1, 7),
 9303                    Point::new(1, 14)..Point::new(1, 19),
 9304                    Point::new(2, 4)..Point::new(2, 7),
 9305                    Point::new(2, 14)..Point::new(2, 19),
 9306                ]
 9307            );
 9308
 9309            assert!(editor.move_to_next_snippet_tabstop(cx));
 9310            assert!(editor.move_to_next_snippet_tabstop(cx));
 9311            assert_eq!(
 9312                editor.selected_ranges::<Point>(cx),
 9313                &[
 9314                    Point::new(0, 20)..Point::new(0, 20),
 9315                    Point::new(1, 20)..Point::new(1, 20),
 9316                    Point::new(2, 20)..Point::new(2, 20)
 9317                ]
 9318            );
 9319
 9320            // As soon as the last tab stop is reached, snippet state is gone
 9321            editor.move_to_prev_snippet_tabstop(cx);
 9322            assert_eq!(
 9323                editor.selected_ranges::<Point>(cx),
 9324                &[
 9325                    Point::new(0, 20)..Point::new(0, 20),
 9326                    Point::new(1, 20)..Point::new(1, 20),
 9327                    Point::new(2, 20)..Point::new(2, 20)
 9328                ]
 9329            );
 9330        });
 9331    }
 9332
 9333    #[gpui::test]
 9334    async fn test_format_during_save(cx: &mut gpui::TestAppContext) {
 9335        cx.foreground().forbid_parking();
 9336        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9337
 9338        let mut language = Language::new(
 9339            LanguageConfig {
 9340                name: "Rust".into(),
 9341                path_suffixes: vec!["rs".to_string()],
 9342                ..Default::default()
 9343            },
 9344            Some(tree_sitter_rust::language()),
 9345        );
 9346        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9347            capabilities: lsp::ServerCapabilities {
 9348                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9349                ..Default::default()
 9350            },
 9351            ..Default::default()
 9352        });
 9353
 9354        let fs = FakeFs::new(cx.background().clone());
 9355        fs.insert_file("/file.rs", Default::default()).await;
 9356
 9357        let project = Project::test(fs, cx);
 9358        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9359
 9360        let worktree_id = project
 9361            .update(cx, |project, cx| {
 9362                project.find_or_create_local_worktree("/file.rs", true, cx)
 9363            })
 9364            .await
 9365            .unwrap()
 9366            .0
 9367            .read_with(cx, |tree, _| tree.id());
 9368        let buffer = project
 9369            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9370            .await
 9371            .unwrap();
 9372
 9373        cx.foreground().start_waiting();
 9374        let fake_server = fake_servers.next().await.unwrap();
 9375
 9376        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9377        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9378        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9379        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9380
 9381        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9382        fake_server
 9383            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9384                assert_eq!(
 9385                    params.text_document.uri,
 9386                    lsp::Url::from_file_path("/file.rs").unwrap()
 9387                );
 9388                assert_eq!(params.options.tab_size, 4);
 9389                Ok(Some(vec![lsp::TextEdit::new(
 9390                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9391                    ", ".to_string(),
 9392                )]))
 9393            })
 9394            .next()
 9395            .await;
 9396        cx.foreground().start_waiting();
 9397        save.await.unwrap();
 9398        assert_eq!(
 9399            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9400            "one, two\nthree\n"
 9401        );
 9402        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9403
 9404        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9405        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9406
 9407        // Ensure we can still save even if formatting hangs.
 9408        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9409            assert_eq!(
 9410                params.text_document.uri,
 9411                lsp::Url::from_file_path("/file.rs").unwrap()
 9412            );
 9413            futures::future::pending::<()>().await;
 9414            unreachable!()
 9415        });
 9416        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9417        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9418        cx.foreground().start_waiting();
 9419        save.await.unwrap();
 9420        assert_eq!(
 9421            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9422            "one\ntwo\nthree\n"
 9423        );
 9424        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9425
 9426        // Set rust language override and assert overriden tabsize is sent to language server
 9427        cx.update(|cx| {
 9428            cx.update_global::<Settings, _, _>(|settings, _| {
 9429                settings.language_overrides.insert(
 9430                    "Rust".into(),
 9431                    LanguageOverride {
 9432                        tab_size: Some(8),
 9433                        ..Default::default()
 9434                    },
 9435                );
 9436            })
 9437        });
 9438
 9439        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9440        fake_server
 9441            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9442                assert_eq!(
 9443                    params.text_document.uri,
 9444                    lsp::Url::from_file_path("/file.rs").unwrap()
 9445                );
 9446                assert_eq!(params.options.tab_size, 8);
 9447                Ok(Some(vec![]))
 9448            })
 9449            .next()
 9450            .await;
 9451        cx.foreground().start_waiting();
 9452        save.await.unwrap();
 9453    }
 9454
 9455    #[gpui::test]
 9456    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9457        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9458
 9459        let mut language = Language::new(
 9460            LanguageConfig {
 9461                name: "Rust".into(),
 9462                path_suffixes: vec!["rs".to_string()],
 9463                ..Default::default()
 9464            },
 9465            Some(tree_sitter_rust::language()),
 9466        );
 9467        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9468            capabilities: lsp::ServerCapabilities {
 9469                completion_provider: Some(lsp::CompletionOptions {
 9470                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9471                    ..Default::default()
 9472                }),
 9473                ..Default::default()
 9474            },
 9475            ..Default::default()
 9476        });
 9477
 9478        let text = "
 9479            one
 9480            two
 9481            three
 9482        "
 9483        .unindent();
 9484
 9485        let fs = FakeFs::new(cx.background().clone());
 9486        fs.insert_file("/file.rs", text).await;
 9487
 9488        let project = Project::test(fs, cx);
 9489        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9490
 9491        let worktree_id = project
 9492            .update(cx, |project, cx| {
 9493                project.find_or_create_local_worktree("/file.rs", true, cx)
 9494            })
 9495            .await
 9496            .unwrap()
 9497            .0
 9498            .read_with(cx, |tree, _| tree.id());
 9499        let buffer = project
 9500            .update(cx, |project, cx| project.open_buffer((worktree_id, ""), cx))
 9501            .await
 9502            .unwrap();
 9503        let mut fake_server = fake_servers.next().await.unwrap();
 9504
 9505        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9506        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9507
 9508        editor.update(cx, |editor, cx| {
 9509            editor.project = Some(project);
 9510            editor.select_ranges([Point::new(0, 3)..Point::new(0, 3)], None, cx);
 9511            editor.handle_input(&Input(".".to_string()), cx);
 9512        });
 9513
 9514        handle_completion_request(
 9515            &mut fake_server,
 9516            "/file.rs",
 9517            Point::new(0, 4),
 9518            vec![
 9519                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9520                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9521            ],
 9522        )
 9523        .await;
 9524        editor
 9525            .condition(&cx, |editor, _| editor.context_menu_visible())
 9526            .await;
 9527
 9528        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9529            editor.move_down(&MoveDown, cx);
 9530            let apply_additional_edits = editor
 9531                .confirm_completion(&ConfirmCompletion::default(), cx)
 9532                .unwrap();
 9533            assert_eq!(
 9534                editor.text(cx),
 9535                "
 9536                    one.second_completion
 9537                    two
 9538                    three
 9539                "
 9540                .unindent()
 9541            );
 9542            apply_additional_edits
 9543        });
 9544
 9545        handle_resolve_completion_request(
 9546            &mut fake_server,
 9547            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9548        )
 9549        .await;
 9550        apply_additional_edits.await.unwrap();
 9551        assert_eq!(
 9552            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9553            "
 9554                one.second_completion
 9555                two
 9556                three
 9557                additional edit
 9558            "
 9559            .unindent()
 9560        );
 9561
 9562        editor.update(cx, |editor, cx| {
 9563            editor.select_ranges(
 9564                [
 9565                    Point::new(1, 3)..Point::new(1, 3),
 9566                    Point::new(2, 5)..Point::new(2, 5),
 9567                ],
 9568                None,
 9569                cx,
 9570            );
 9571
 9572            editor.handle_input(&Input(" ".to_string()), cx);
 9573            assert!(editor.context_menu.is_none());
 9574            editor.handle_input(&Input("s".to_string()), cx);
 9575            assert!(editor.context_menu.is_none());
 9576        });
 9577
 9578        handle_completion_request(
 9579            &mut fake_server,
 9580            "/file.rs",
 9581            Point::new(2, 7),
 9582            vec![
 9583                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9584                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9585                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9586            ],
 9587        )
 9588        .await;
 9589        editor
 9590            .condition(&cx, |editor, _| editor.context_menu_visible())
 9591            .await;
 9592
 9593        editor.update(cx, |editor, cx| {
 9594            editor.handle_input(&Input("i".to_string()), cx);
 9595        });
 9596
 9597        handle_completion_request(
 9598            &mut fake_server,
 9599            "/file.rs",
 9600            Point::new(2, 8),
 9601            vec![
 9602                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9603                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9604                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9605            ],
 9606        )
 9607        .await;
 9608        editor
 9609            .condition(&cx, |editor, _| editor.context_menu_visible())
 9610            .await;
 9611
 9612        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9613            let apply_additional_edits = editor
 9614                .confirm_completion(&ConfirmCompletion::default(), cx)
 9615                .unwrap();
 9616            assert_eq!(
 9617                editor.text(cx),
 9618                "
 9619                    one.second_completion
 9620                    two sixth_completion
 9621                    three sixth_completion
 9622                    additional edit
 9623                "
 9624                .unindent()
 9625            );
 9626            apply_additional_edits
 9627        });
 9628        handle_resolve_completion_request(&mut fake_server, None).await;
 9629        apply_additional_edits.await.unwrap();
 9630
 9631        async fn handle_completion_request(
 9632            fake: &mut FakeLanguageServer,
 9633            path: &'static str,
 9634            position: Point,
 9635            completions: Vec<(Range<Point>, &'static str)>,
 9636        ) {
 9637            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9638                let completions = completions.clone();
 9639                async move {
 9640                    assert_eq!(
 9641                        params.text_document_position.text_document.uri,
 9642                        lsp::Url::from_file_path(path).unwrap()
 9643                    );
 9644                    assert_eq!(
 9645                        params.text_document_position.position,
 9646                        lsp::Position::new(position.row, position.column)
 9647                    );
 9648                    Ok(Some(lsp::CompletionResponse::Array(
 9649                        completions
 9650                            .iter()
 9651                            .map(|(range, new_text)| lsp::CompletionItem {
 9652                                label: new_text.to_string(),
 9653                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9654                                    range: lsp::Range::new(
 9655                                        lsp::Position::new(range.start.row, range.start.column),
 9656                                        lsp::Position::new(range.start.row, range.start.column),
 9657                                    ),
 9658                                    new_text: new_text.to_string(),
 9659                                })),
 9660                                ..Default::default()
 9661                            })
 9662                            .collect(),
 9663                    )))
 9664                }
 9665            })
 9666            .next()
 9667            .await;
 9668        }
 9669
 9670        async fn handle_resolve_completion_request(
 9671            fake: &mut FakeLanguageServer,
 9672            edit: Option<(Range<Point>, &'static str)>,
 9673        ) {
 9674            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9675                let edit = edit.clone();
 9676                async move {
 9677                    Ok(lsp::CompletionItem {
 9678                        additional_text_edits: edit.map(|(range, new_text)| {
 9679                            vec![lsp::TextEdit::new(
 9680                                lsp::Range::new(
 9681                                    lsp::Position::new(range.start.row, range.start.column),
 9682                                    lsp::Position::new(range.end.row, range.end.column),
 9683                                ),
 9684                                new_text.to_string(),
 9685                            )]
 9686                        }),
 9687                        ..Default::default()
 9688                    })
 9689                }
 9690            })
 9691            .next()
 9692            .await;
 9693        }
 9694    }
 9695
 9696    #[gpui::test]
 9697    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9698        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9699        let language = Arc::new(Language::new(
 9700            LanguageConfig {
 9701                line_comment: Some("// ".to_string()),
 9702                ..Default::default()
 9703            },
 9704            Some(tree_sitter_rust::language()),
 9705        ));
 9706
 9707        let text = "
 9708            fn a() {
 9709                //b();
 9710                // c();
 9711                //  d();
 9712            }
 9713        "
 9714        .unindent();
 9715
 9716        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9717        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9718        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9719
 9720        view.update(cx, |editor, cx| {
 9721            // If multiple selections intersect a line, the line is only
 9722            // toggled once.
 9723            editor.select_display_ranges(
 9724                &[
 9725                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9726                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9727                ],
 9728                cx,
 9729            );
 9730            editor.toggle_comments(&ToggleComments, cx);
 9731            assert_eq!(
 9732                editor.text(cx),
 9733                "
 9734                    fn a() {
 9735                        b();
 9736                        c();
 9737                         d();
 9738                    }
 9739                "
 9740                .unindent()
 9741            );
 9742
 9743            // The comment prefix is inserted at the same column for every line
 9744            // in a selection.
 9745            editor.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)], cx);
 9746            editor.toggle_comments(&ToggleComments, cx);
 9747            assert_eq!(
 9748                editor.text(cx),
 9749                "
 9750                    fn a() {
 9751                        // b();
 9752                        // c();
 9753                        //  d();
 9754                    }
 9755                "
 9756                .unindent()
 9757            );
 9758
 9759            // If a selection ends at the beginning of a line, that line is not toggled.
 9760            editor.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)], cx);
 9761            editor.toggle_comments(&ToggleComments, cx);
 9762            assert_eq!(
 9763                editor.text(cx),
 9764                "
 9765                        fn a() {
 9766                            // b();
 9767                            c();
 9768                            //  d();
 9769                        }
 9770                    "
 9771                .unindent()
 9772            );
 9773        });
 9774    }
 9775
 9776    #[gpui::test]
 9777    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9778        cx.set_global(Settings::test(cx));
 9779        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9780        let multibuffer = cx.add_model(|cx| {
 9781            let mut multibuffer = MultiBuffer::new(0);
 9782            multibuffer.push_excerpts(
 9783                buffer.clone(),
 9784                [
 9785                    Point::new(0, 0)..Point::new(0, 4),
 9786                    Point::new(1, 0)..Point::new(1, 4),
 9787                ],
 9788                cx,
 9789            );
 9790            multibuffer
 9791        });
 9792
 9793        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9794
 9795        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9796        view.update(cx, |view, cx| {
 9797            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9798            view.select_ranges(
 9799                [
 9800                    Point::new(0, 0)..Point::new(0, 0),
 9801                    Point::new(1, 0)..Point::new(1, 0),
 9802                ],
 9803                None,
 9804                cx,
 9805            );
 9806
 9807            view.handle_input(&Input("X".to_string()), cx);
 9808            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9809            assert_eq!(
 9810                view.selected_ranges(cx),
 9811                [
 9812                    Point::new(0, 1)..Point::new(0, 1),
 9813                    Point::new(1, 1)..Point::new(1, 1),
 9814                ]
 9815            )
 9816        });
 9817    }
 9818
 9819    #[gpui::test]
 9820    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9821        cx.set_global(Settings::test(cx));
 9822        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9823        let multibuffer = cx.add_model(|cx| {
 9824            let mut multibuffer = MultiBuffer::new(0);
 9825            multibuffer.push_excerpts(
 9826                buffer,
 9827                [
 9828                    Point::new(0, 0)..Point::new(1, 4),
 9829                    Point::new(1, 0)..Point::new(2, 4),
 9830                ],
 9831                cx,
 9832            );
 9833            multibuffer
 9834        });
 9835
 9836        assert_eq!(
 9837            multibuffer.read(cx).read(cx).text(),
 9838            "aaaa\nbbbb\nbbbb\ncccc"
 9839        );
 9840
 9841        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9842        view.update(cx, |view, cx| {
 9843            view.select_ranges(
 9844                [
 9845                    Point::new(1, 1)..Point::new(1, 1),
 9846                    Point::new(2, 3)..Point::new(2, 3),
 9847                ],
 9848                None,
 9849                cx,
 9850            );
 9851
 9852            view.handle_input(&Input("X".to_string()), cx);
 9853            assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
 9854            assert_eq!(
 9855                view.selected_ranges(cx),
 9856                [
 9857                    Point::new(1, 2)..Point::new(1, 2),
 9858                    Point::new(2, 5)..Point::new(2, 5),
 9859                ]
 9860            );
 9861
 9862            view.newline(&Newline, cx);
 9863            assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
 9864            assert_eq!(
 9865                view.selected_ranges(cx),
 9866                [
 9867                    Point::new(2, 0)..Point::new(2, 0),
 9868                    Point::new(6, 0)..Point::new(6, 0),
 9869                ]
 9870            );
 9871        });
 9872    }
 9873
 9874    #[gpui::test]
 9875    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9876        cx.set_global(Settings::test(cx));
 9877        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9878        let mut excerpt1_id = None;
 9879        let multibuffer = cx.add_model(|cx| {
 9880            let mut multibuffer = MultiBuffer::new(0);
 9881            excerpt1_id = multibuffer
 9882                .push_excerpts(
 9883                    buffer.clone(),
 9884                    [
 9885                        Point::new(0, 0)..Point::new(1, 4),
 9886                        Point::new(1, 0)..Point::new(2, 4),
 9887                    ],
 9888                    cx,
 9889                )
 9890                .into_iter()
 9891                .next();
 9892            multibuffer
 9893        });
 9894        assert_eq!(
 9895            multibuffer.read(cx).read(cx).text(),
 9896            "aaaa\nbbbb\nbbbb\ncccc"
 9897        );
 9898        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9899            let mut editor = build_editor(multibuffer.clone(), cx);
 9900            let snapshot = editor.snapshot(cx);
 9901            editor.select_ranges([Point::new(1, 3)..Point::new(1, 3)], None, cx);
 9902            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9903            assert_eq!(
 9904                editor.selected_ranges(cx),
 9905                [
 9906                    Point::new(1, 3)..Point::new(1, 3),
 9907                    Point::new(2, 1)..Point::new(2, 1),
 9908                ]
 9909            );
 9910            editor
 9911        });
 9912
 9913        // Refreshing selections is a no-op when excerpts haven't changed.
 9914        editor.update(cx, |editor, cx| {
 9915            editor.refresh_selections(cx);
 9916            assert_eq!(
 9917                editor.selected_ranges(cx),
 9918                [
 9919                    Point::new(1, 3)..Point::new(1, 3),
 9920                    Point::new(2, 1)..Point::new(2, 1),
 9921                ]
 9922            );
 9923        });
 9924
 9925        multibuffer.update(cx, |multibuffer, cx| {
 9926            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9927        });
 9928        editor.update(cx, |editor, cx| {
 9929            // Removing an excerpt causes the first selection to become degenerate.
 9930            assert_eq!(
 9931                editor.selected_ranges(cx),
 9932                [
 9933                    Point::new(0, 0)..Point::new(0, 0),
 9934                    Point::new(0, 1)..Point::new(0, 1)
 9935                ]
 9936            );
 9937
 9938            // Refreshing selections will relocate the first selection to the original buffer
 9939            // location.
 9940            editor.refresh_selections(cx);
 9941            assert_eq!(
 9942                editor.selected_ranges(cx),
 9943                [
 9944                    Point::new(0, 1)..Point::new(0, 1),
 9945                    Point::new(0, 3)..Point::new(0, 3)
 9946                ]
 9947            );
 9948            assert!(editor.pending_selection.is_some());
 9949        });
 9950    }
 9951
 9952    #[gpui::test]
 9953    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9954        cx.set_global(Settings::test(cx));
 9955        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9956        let mut excerpt1_id = None;
 9957        let multibuffer = cx.add_model(|cx| {
 9958            let mut multibuffer = MultiBuffer::new(0);
 9959            excerpt1_id = multibuffer
 9960                .push_excerpts(
 9961                    buffer.clone(),
 9962                    [
 9963                        Point::new(0, 0)..Point::new(1, 4),
 9964                        Point::new(1, 0)..Point::new(2, 4),
 9965                    ],
 9966                    cx,
 9967                )
 9968                .into_iter()
 9969                .next();
 9970            multibuffer
 9971        });
 9972        assert_eq!(
 9973            multibuffer.read(cx).read(cx).text(),
 9974            "aaaa\nbbbb\nbbbb\ncccc"
 9975        );
 9976        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9977            let mut editor = build_editor(multibuffer.clone(), cx);
 9978            let snapshot = editor.snapshot(cx);
 9979            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9980            assert_eq!(
 9981                editor.selected_ranges(cx),
 9982                [Point::new(1, 3)..Point::new(1, 3)]
 9983            );
 9984            editor
 9985        });
 9986
 9987        multibuffer.update(cx, |multibuffer, cx| {
 9988            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9989        });
 9990        editor.update(cx, |editor, cx| {
 9991            assert_eq!(
 9992                editor.selected_ranges(cx),
 9993                [Point::new(0, 0)..Point::new(0, 0)]
 9994            );
 9995
 9996            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9997            editor.refresh_selections(cx);
 9998            assert_eq!(
 9999                editor.selected_ranges(cx),
10000                [Point::new(0, 3)..Point::new(0, 3)]
10001            );
10002            assert!(editor.pending_selection.is_some());
10003        });
10004    }
10005
10006    #[gpui::test]
10007    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
10008        cx.update(|cx| cx.set_global(Settings::test(cx)));
10009        let language = Arc::new(Language::new(
10010            LanguageConfig {
10011                brackets: vec![
10012                    BracketPair {
10013                        start: "{".to_string(),
10014                        end: "}".to_string(),
10015                        close: true,
10016                        newline: true,
10017                    },
10018                    BracketPair {
10019                        start: "/* ".to_string(),
10020                        end: " */".to_string(),
10021                        close: true,
10022                        newline: true,
10023                    },
10024                ],
10025                ..Default::default()
10026            },
10027            Some(tree_sitter_rust::language()),
10028        ));
10029
10030        let text = concat!(
10031            "{   }\n",     // Suppress rustfmt
10032            "  x\n",       //
10033            "  /*   */\n", //
10034            "x\n",         //
10035            "{{} }\n",     //
10036        );
10037
10038        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
10039        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
10040        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
10041        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
10042            .await;
10043
10044        view.update(cx, |view, cx| {
10045            view.select_display_ranges(
10046                &[
10047                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
10048                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
10049                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
10050                ],
10051                cx,
10052            );
10053            view.newline(&Newline, cx);
10054
10055            assert_eq!(
10056                view.buffer().read(cx).read(cx).text(),
10057                concat!(
10058                    "{ \n",    // Suppress rustfmt
10059                    "\n",      //
10060                    "}\n",     //
10061                    "  x\n",   //
10062                    "  /* \n", //
10063                    "  \n",    //
10064                    "  */\n",  //
10065                    "x\n",     //
10066                    "{{} \n",  //
10067                    "}\n",     //
10068                )
10069            );
10070        });
10071    }
10072
10073    #[gpui::test]
10074    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
10075        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10076
10077        cx.set_global(Settings::test(cx));
10078        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10079
10080        editor.update(cx, |editor, cx| {
10081            struct Type1;
10082            struct Type2;
10083
10084            let buffer = buffer.read(cx).snapshot(cx);
10085
10086            let anchor_range = |range: Range<Point>| {
10087                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
10088            };
10089
10090            editor.highlight_background::<Type1>(
10091                vec![
10092                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10093                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10094                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10095                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10096                ],
10097                |_| Color::red(),
10098                cx,
10099            );
10100            editor.highlight_background::<Type2>(
10101                vec![
10102                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10103                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10104                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10105                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10106                ],
10107                |_| Color::green(),
10108                cx,
10109            );
10110
10111            let snapshot = editor.snapshot(cx);
10112            let mut highlighted_ranges = editor.background_highlights_in_range(
10113                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10114                &snapshot,
10115                cx.global::<Settings>().theme.as_ref(),
10116            );
10117            // Enforce a consistent ordering based on color without relying on the ordering of the
10118            // highlight's `TypeId` which is non-deterministic.
10119            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10120            assert_eq!(
10121                highlighted_ranges,
10122                &[
10123                    (
10124                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10125                        Color::green(),
10126                    ),
10127                    (
10128                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10129                        Color::green(),
10130                    ),
10131                    (
10132                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10133                        Color::red(),
10134                    ),
10135                    (
10136                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10137                        Color::red(),
10138                    ),
10139                ]
10140            );
10141            assert_eq!(
10142                editor.background_highlights_in_range(
10143                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10144                    &snapshot,
10145                    cx.global::<Settings>().theme.as_ref(),
10146                ),
10147                &[(
10148                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10149                    Color::red(),
10150                )]
10151            );
10152        });
10153    }
10154
10155    #[gpui::test]
10156    fn test_following(cx: &mut gpui::MutableAppContext) {
10157        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10158
10159        cx.set_global(Settings::test(cx));
10160
10161        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10162        let (_, follower) = cx.add_window(
10163            WindowOptions {
10164                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10165                ..Default::default()
10166            },
10167            |cx| build_editor(buffer.clone(), cx),
10168        );
10169
10170        let pending_update = Rc::new(RefCell::new(None));
10171        follower.update(cx, {
10172            let update = pending_update.clone();
10173            |_, cx| {
10174                cx.subscribe(&leader, move |_, leader, event, cx| {
10175                    leader
10176                        .read(cx)
10177                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10178                })
10179                .detach();
10180            }
10181        });
10182
10183        // Update the selections only
10184        leader.update(cx, |leader, cx| {
10185            leader.select_ranges([1..1], None, cx);
10186        });
10187        follower.update(cx, |follower, cx| {
10188            follower
10189                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10190                .unwrap();
10191        });
10192        assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
10193
10194        // Update the scroll position only
10195        leader.update(cx, |leader, cx| {
10196            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10197        });
10198        follower.update(cx, |follower, cx| {
10199            follower
10200                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10201                .unwrap();
10202        });
10203        assert_eq!(
10204            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10205            vec2f(1.5, 3.5)
10206        );
10207
10208        // Update the selections and scroll position
10209        leader.update(cx, |leader, cx| {
10210            leader.select_ranges([0..0], None, cx);
10211            leader.request_autoscroll(Autoscroll::Newest, cx);
10212            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10213        });
10214        follower.update(cx, |follower, cx| {
10215            let initial_scroll_position = follower.scroll_position(cx);
10216            follower
10217                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10218                .unwrap();
10219            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10220            assert!(follower.autoscroll_request.is_some());
10221        });
10222        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
10223
10224        // Creating a pending selection that precedes another selection
10225        leader.update(cx, |leader, cx| {
10226            leader.select_ranges([1..1], None, cx);
10227            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10228        });
10229        follower.update(cx, |follower, cx| {
10230            follower
10231                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10232                .unwrap();
10233        });
10234        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
10235
10236        // Extend the pending selection so that it surrounds another selection
10237        leader.update(cx, |leader, cx| {
10238            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10239        });
10240        follower.update(cx, |follower, cx| {
10241            follower
10242                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10243                .unwrap();
10244        });
10245        assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
10246    }
10247
10248    #[test]
10249    fn test_combine_syntax_and_fuzzy_match_highlights() {
10250        let string = "abcdefghijklmnop";
10251        let syntax_ranges = [
10252            (
10253                0..3,
10254                HighlightStyle {
10255                    color: Some(Color::red()),
10256                    ..Default::default()
10257                },
10258            ),
10259            (
10260                4..8,
10261                HighlightStyle {
10262                    color: Some(Color::green()),
10263                    ..Default::default()
10264                },
10265            ),
10266        ];
10267        let match_indices = [4, 6, 7, 8];
10268        assert_eq!(
10269            combine_syntax_and_fuzzy_match_highlights(
10270                &string,
10271                Default::default(),
10272                syntax_ranges.into_iter(),
10273                &match_indices,
10274            ),
10275            &[
10276                (
10277                    0..3,
10278                    HighlightStyle {
10279                        color: Some(Color::red()),
10280                        ..Default::default()
10281                    },
10282                ),
10283                (
10284                    4..5,
10285                    HighlightStyle {
10286                        color: Some(Color::green()),
10287                        weight: Some(fonts::Weight::BOLD),
10288                        ..Default::default()
10289                    },
10290                ),
10291                (
10292                    5..6,
10293                    HighlightStyle {
10294                        color: Some(Color::green()),
10295                        ..Default::default()
10296                    },
10297                ),
10298                (
10299                    6..8,
10300                    HighlightStyle {
10301                        color: Some(Color::green()),
10302                        weight: Some(fonts::Weight::BOLD),
10303                        ..Default::default()
10304                    },
10305                ),
10306                (
10307                    8..9,
10308                    HighlightStyle {
10309                        weight: Some(fonts::Weight::BOLD),
10310                        ..Default::default()
10311                    },
10312                ),
10313            ]
10314        );
10315    }
10316
10317    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10318        let point = DisplayPoint::new(row as u32, column as u32);
10319        point..point
10320    }
10321
10322    fn build_editor(buffer: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
10323        Editor::new(EditorMode::Full, buffer, None, None, cx)
10324    }
10325
10326    fn assert_selection_ranges(
10327        marked_text: &str,
10328        selection_marker_pairs: Vec<(char, char)>,
10329        view: &mut Editor,
10330        cx: &mut ViewContext<Editor>,
10331    ) {
10332        let snapshot = view.snapshot(cx).display_snapshot;
10333        let mut marker_chars = Vec::new();
10334        for (start, end) in selection_marker_pairs.iter() {
10335            marker_chars.push(*start);
10336            marker_chars.push(*end);
10337        }
10338        let (_, markers) = marked_text_by(marked_text, marker_chars);
10339        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10340            .iter()
10341            .map(|(start, end)| {
10342                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10343                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10344                start..end
10345            })
10346            .collect();
10347        assert_eq!(
10348            view.selected_display_ranges(cx),
10349            &asserted_ranges[..],
10350            "Assert selections are {}",
10351            marked_text
10352        );
10353    }
10354}
10355
10356trait RangeExt<T> {
10357    fn sorted(&self) -> Range<T>;
10358    fn to_inclusive(&self) -> RangeInclusive<T>;
10359}
10360
10361impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10362    fn sorted(&self) -> Self {
10363        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10364    }
10365
10366    fn to_inclusive(&self) -> RangeInclusive<T> {
10367        self.start.clone()..=self.end.clone()
10368    }
10369}