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