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