editor.rs

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