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