editor.rs

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