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