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