editor.rs

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