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