editor.rs

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