editor.rs

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