editor.rs

    1pub mod display_map;
    2mod element;
    3mod hover_popover;
    4pub mod items;
    5mod link_go_to_definition;
    6pub mod movement;
    7mod multi_buffer;
    8pub mod selections_collection;
    9
   10#[cfg(any(test, feature = "test-support"))]
   11pub mod test;
   12
   13use aho_corasick::AhoCorasick;
   14use anyhow::Result;
   15use clock::ReplicaId;
   16use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   17pub use display_map::DisplayPoint;
   18use display_map::*;
   19pub use element::*;
   20use fuzzy::{StringMatch, StringMatchCandidate};
   21use gpui::{
   22    actions,
   23    color::Color,
   24    elements::*,
   25    executor,
   26    fonts::{self, HighlightStyle, TextStyle},
   27    geometry::vector::{vec2f, Vector2F},
   28    impl_actions, impl_internal_actions,
   29    platform::CursorStyle,
   30    text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
   31    ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
   32    WeakViewHandle,
   33};
   34use hover_popover::{hide_hover, HoverState};
   35pub use language::{char_kind, CharKind};
   36use language::{
   37    BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticSeverity,
   38    IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection, SelectionGoal,
   39    TransactionId,
   40};
   41use link_go_to_definition::LinkGoToDefinitionState;
   42use multi_buffer::MultiBufferChunks;
   43pub use multi_buffer::{
   44    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   45    ToPoint,
   46};
   47use ordered_float::OrderedFloat;
   48use project::{Project, ProjectPath, ProjectTransaction};
   49use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   50use serde::{Deserialize, Serialize};
   51use settings::Settings;
   52use smallvec::SmallVec;
   53use smol::Timer;
   54use snippet::Snippet;
   55use std::{
   56    any::TypeId,
   57    borrow::Cow,
   58    cmp::{self, Ordering, Reverse},
   59    mem,
   60    num::NonZeroU32,
   61    ops::{Deref, DerefMut, Range, RangeInclusive},
   62    sync::Arc,
   63    time::{Duration, Instant},
   64};
   65pub use sum_tree::Bias;
   66use theme::{DiagnosticStyle, Theme};
   67use util::{post_inc, ResultExt, TryFutureExt};
   68use workspace::{ItemNavHistory, Workspace};
   69
   70const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
   71const MAX_LINE_LEN: usize = 1024;
   72const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
   73const MAX_SELECTION_HISTORY_LEN: usize = 1024;
   74
   75#[derive(Clone, Deserialize, PartialEq)]
   76pub struct SelectNext {
   77    #[serde(default)]
   78    pub replace_newest: bool,
   79}
   80
   81#[derive(Clone, PartialEq)]
   82pub struct GoToDiagnostic(pub Direction);
   83
   84#[derive(Clone, PartialEq)]
   85pub struct Scroll(pub Vector2F);
   86
   87#[derive(Clone, PartialEq)]
   88pub struct Select(pub SelectPhase);
   89
   90#[derive(Clone, Debug, PartialEq)]
   91pub struct Jump {
   92    path: ProjectPath,
   93    position: Point,
   94    anchor: language::Anchor,
   95}
   96
   97#[derive(Clone, Deserialize, PartialEq)]
   98pub struct Input(pub String);
   99
  100#[derive(Clone, Deserialize, PartialEq)]
  101pub struct SelectToBeginningOfLine {
  102    #[serde(default)]
  103    stop_at_soft_wraps: bool,
  104}
  105
  106#[derive(Clone, Deserialize, PartialEq)]
  107pub struct SelectToEndOfLine {
  108    #[serde(default)]
  109    stop_at_soft_wraps: bool,
  110}
  111
  112#[derive(Clone, Deserialize, PartialEq)]
  113pub struct ToggleCodeActions {
  114    #[serde(default)]
  115    pub deployed_from_indicator: bool,
  116}
  117
  118#[derive(Clone, Default, Deserialize, PartialEq)]
  119pub struct ConfirmCompletion {
  120    #[serde(default)]
  121    pub item_ix: Option<usize>,
  122}
  123
  124#[derive(Clone, Default, Deserialize, PartialEq)]
  125pub struct ConfirmCodeAction {
  126    #[serde(default)]
  127    pub item_ix: Option<usize>,
  128}
  129
  130actions!(
  131    editor,
  132    [
  133        Cancel,
  134        Backspace,
  135        Delete,
  136        Newline,
  137        GoToNextDiagnostic,
  138        GoToPrevDiagnostic,
  139        Indent,
  140        Outdent,
  141        DeleteLine,
  142        DeleteToPreviousWordStart,
  143        DeleteToPreviousSubwordStart,
  144        DeleteToNextWordEnd,
  145        DeleteToNextSubwordEnd,
  146        DeleteToBeginningOfLine,
  147        DeleteToEndOfLine,
  148        CutToEndOfLine,
  149        DuplicateLine,
  150        MoveLineUp,
  151        MoveLineDown,
  152        Transpose,
  153        Cut,
  154        Copy,
  155        Paste,
  156        Undo,
  157        Redo,
  158        MoveUp,
  159        MoveDown,
  160        MoveLeft,
  161        MoveRight,
  162        MoveToPreviousWordStart,
  163        MoveToPreviousSubwordStart,
  164        MoveToNextWordEnd,
  165        MoveToNextSubwordEnd,
  166        MoveToBeginningOfLine,
  167        MoveToEndOfLine,
  168        MoveToBeginning,
  169        MoveToEnd,
  170        SelectUp,
  171        SelectDown,
  172        SelectLeft,
  173        SelectRight,
  174        SelectToPreviousWordStart,
  175        SelectToPreviousSubwordStart,
  176        SelectToNextWordEnd,
  177        SelectToNextSubwordEnd,
  178        SelectToBeginning,
  179        SelectToEnd,
  180        SelectAll,
  181        SelectLine,
  182        SplitSelectionIntoLines,
  183        AddSelectionAbove,
  184        AddSelectionBelow,
  185        Tab,
  186        TabPrev,
  187        ToggleComments,
  188        SelectLargerSyntaxNode,
  189        SelectSmallerSyntaxNode,
  190        GoToDefinition,
  191        MoveToEnclosingBracket,
  192        UndoSelection,
  193        RedoSelection,
  194        FindAllReferences,
  195        Rename,
  196        ConfirmRename,
  197        PageUp,
  198        PageDown,
  199        Fold,
  200        UnfoldLines,
  201        FoldSelectedRanges,
  202        ShowCompletions,
  203        OpenExcerpts,
  204        RestartLanguageServer,
  205        Hover,
  206    ]
  207);
  208
  209impl_actions!(
  210    editor,
  211    [
  212        Input,
  213        SelectNext,
  214        SelectToBeginningOfLine,
  215        SelectToEndOfLine,
  216        ToggleCodeActions,
  217        ConfirmCompletion,
  218        ConfirmCodeAction,
  219    ]
  220);
  221
  222impl_internal_actions!(editor, [Scroll, Select, Jump]);
  223
  224enum DocumentHighlightRead {}
  225enum DocumentHighlightWrite {}
  226
  227#[derive(Copy, Clone, PartialEq, Eq)]
  228pub enum Direction {
  229    Prev,
  230    Next,
  231}
  232
  233pub fn init(cx: &mut MutableAppContext) {
  234    cx.add_action(Editor::new_file);
  235    cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx));
  236    cx.add_action(Editor::select);
  237    cx.add_action(Editor::cancel);
  238    cx.add_action(Editor::handle_input);
  239    cx.add_action(Editor::newline);
  240    cx.add_action(Editor::backspace);
  241    cx.add_action(Editor::delete);
  242    cx.add_action(Editor::tab);
  243    cx.add_action(Editor::tab_prev);
  244    cx.add_action(Editor::indent);
  245    cx.add_action(Editor::outdent);
  246    cx.add_action(Editor::delete_line);
  247    cx.add_action(Editor::delete_to_previous_word_start);
  248    cx.add_action(Editor::delete_to_previous_subword_start);
  249    cx.add_action(Editor::delete_to_next_word_end);
  250    cx.add_action(Editor::delete_to_next_subword_end);
  251    cx.add_action(Editor::delete_to_beginning_of_line);
  252    cx.add_action(Editor::delete_to_end_of_line);
  253    cx.add_action(Editor::cut_to_end_of_line);
  254    cx.add_action(Editor::duplicate_line);
  255    cx.add_action(Editor::move_line_up);
  256    cx.add_action(Editor::move_line_down);
  257    cx.add_action(Editor::transpose);
  258    cx.add_action(Editor::cut);
  259    cx.add_action(Editor::copy);
  260    cx.add_action(Editor::paste);
  261    cx.add_action(Editor::undo);
  262    cx.add_action(Editor::redo);
  263    cx.add_action(Editor::move_up);
  264    cx.add_action(Editor::move_down);
  265    cx.add_action(Editor::move_left);
  266    cx.add_action(Editor::move_right);
  267    cx.add_action(Editor::move_to_previous_word_start);
  268    cx.add_action(Editor::move_to_previous_subword_start);
  269    cx.add_action(Editor::move_to_next_word_end);
  270    cx.add_action(Editor::move_to_next_subword_end);
  271    cx.add_action(Editor::move_to_beginning_of_line);
  272    cx.add_action(Editor::move_to_end_of_line);
  273    cx.add_action(Editor::move_to_beginning);
  274    cx.add_action(Editor::move_to_end);
  275    cx.add_action(Editor::select_up);
  276    cx.add_action(Editor::select_down);
  277    cx.add_action(Editor::select_left);
  278    cx.add_action(Editor::select_right);
  279    cx.add_action(Editor::select_to_previous_word_start);
  280    cx.add_action(Editor::select_to_previous_subword_start);
  281    cx.add_action(Editor::select_to_next_word_end);
  282    cx.add_action(Editor::select_to_next_subword_end);
  283    cx.add_action(Editor::select_to_beginning_of_line);
  284    cx.add_action(Editor::select_to_end_of_line);
  285    cx.add_action(Editor::select_to_beginning);
  286    cx.add_action(Editor::select_to_end);
  287    cx.add_action(Editor::select_all);
  288    cx.add_action(Editor::select_line);
  289    cx.add_action(Editor::split_selection_into_lines);
  290    cx.add_action(Editor::add_selection_above);
  291    cx.add_action(Editor::add_selection_below);
  292    cx.add_action(Editor::select_next);
  293    cx.add_action(Editor::toggle_comments);
  294    cx.add_action(Editor::select_larger_syntax_node);
  295    cx.add_action(Editor::select_smaller_syntax_node);
  296    cx.add_action(Editor::move_to_enclosing_bracket);
  297    cx.add_action(Editor::undo_selection);
  298    cx.add_action(Editor::redo_selection);
  299    cx.add_action(Editor::go_to_next_diagnostic);
  300    cx.add_action(Editor::go_to_prev_diagnostic);
  301    cx.add_action(Editor::go_to_definition);
  302    cx.add_action(Editor::page_up);
  303    cx.add_action(Editor::page_down);
  304    cx.add_action(Editor::fold);
  305    cx.add_action(Editor::unfold_lines);
  306    cx.add_action(Editor::fold_selected_ranges);
  307    cx.add_action(Editor::show_completions);
  308    cx.add_action(Editor::toggle_code_actions);
  309    cx.add_action(Editor::open_excerpts);
  310    cx.add_action(Editor::jump);
  311    cx.add_action(Editor::restart_language_server);
  312    cx.add_async_action(Editor::confirm_completion);
  313    cx.add_async_action(Editor::confirm_code_action);
  314    cx.add_async_action(Editor::rename);
  315    cx.add_async_action(Editor::confirm_rename);
  316    cx.add_async_action(Editor::find_all_references);
  317
  318    hover_popover::init(cx);
  319    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                let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 4606                for definition in definitions {
 4607                    let range = definition
 4608                        .target
 4609                        .range
 4610                        .to_offset(definition.target.buffer.read(cx));
 4611
 4612                    let target_editor_handle =
 4613                        workspace.open_project_item(definition.target.buffer, cx);
 4614                    target_editor_handle.update(cx, |target_editor, cx| {
 4615                        // When selecting a definition in a different buffer, disable the nav history
 4616                        // to avoid creating a history entry at the previous cursor location.
 4617                        if editor_handle != target_editor_handle {
 4618                            nav_history.borrow_mut().disable();
 4619                        }
 4620                        target_editor.change_selections(Some(Autoscroll::Center), cx, |s| {
 4621                            s.select_ranges([range]);
 4622                        });
 4623
 4624                        nav_history.borrow_mut().enable();
 4625                    });
 4626                }
 4627            });
 4628
 4629            Ok::<(), anyhow::Error>(())
 4630        })
 4631        .detach_and_log_err(cx);
 4632    }
 4633
 4634    pub fn find_all_references(
 4635        workspace: &mut Workspace,
 4636        _: &FindAllReferences,
 4637        cx: &mut ViewContext<Workspace>,
 4638    ) -> Option<Task<Result<()>>> {
 4639        let active_item = workspace.active_item(cx)?;
 4640        let editor_handle = active_item.act_as::<Self>(cx)?;
 4641
 4642        let editor = editor_handle.read(cx);
 4643        let buffer = editor.buffer.read(cx);
 4644        let head = editor.selections.newest::<usize>(cx).head();
 4645        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 4646        let replica_id = editor.replica_id(cx);
 4647
 4648        let project = workspace.project().clone();
 4649        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 4650        Some(cx.spawn(|workspace, mut cx| async move {
 4651            let mut locations = references.await?;
 4652            if locations.is_empty() {
 4653                return Ok(());
 4654            }
 4655
 4656            locations.sort_by_key(|location| location.buffer.id());
 4657            let mut locations = locations.into_iter().peekable();
 4658            let mut ranges_to_highlight = Vec::new();
 4659
 4660            let excerpt_buffer = cx.add_model(|cx| {
 4661                let mut symbol_name = None;
 4662                let mut multibuffer = MultiBuffer::new(replica_id);
 4663                while let Some(location) = locations.next() {
 4664                    let buffer = location.buffer.read(cx);
 4665                    let mut ranges_for_buffer = Vec::new();
 4666                    let range = location.range.to_offset(buffer);
 4667                    ranges_for_buffer.push(range.clone());
 4668                    if symbol_name.is_none() {
 4669                        symbol_name = Some(buffer.text_for_range(range).collect::<String>());
 4670                    }
 4671
 4672                    while let Some(next_location) = locations.peek() {
 4673                        if next_location.buffer == location.buffer {
 4674                            ranges_for_buffer.push(next_location.range.to_offset(buffer));
 4675                            locations.next();
 4676                        } else {
 4677                            break;
 4678                        }
 4679                    }
 4680
 4681                    ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 4682                    ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 4683                        location.buffer.clone(),
 4684                        ranges_for_buffer,
 4685                        1,
 4686                        cx,
 4687                    ));
 4688                }
 4689                multibuffer.with_title(format!("References to `{}`", symbol_name.unwrap()))
 4690            });
 4691
 4692            workspace.update(&mut cx, |workspace, cx| {
 4693                let editor =
 4694                    cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 4695                editor.update(cx, |editor, cx| {
 4696                    editor.highlight_background::<Self>(
 4697                        ranges_to_highlight,
 4698                        |theme| theme.editor.highlighted_line_background,
 4699                        cx,
 4700                    );
 4701                });
 4702                workspace.add_item(Box::new(editor), cx);
 4703            });
 4704
 4705            Ok(())
 4706        }))
 4707    }
 4708
 4709    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 4710        use language::ToOffset as _;
 4711
 4712        let project = self.project.clone()?;
 4713        let selection = self.selections.newest_anchor().clone();
 4714        let (cursor_buffer, cursor_buffer_position) = self
 4715            .buffer
 4716            .read(cx)
 4717            .text_anchor_for_position(selection.head(), cx)?;
 4718        let (tail_buffer, _) = self
 4719            .buffer
 4720            .read(cx)
 4721            .text_anchor_for_position(selection.tail(), cx)?;
 4722        if tail_buffer != cursor_buffer {
 4723            return None;
 4724        }
 4725
 4726        let snapshot = cursor_buffer.read(cx).snapshot();
 4727        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 4728        let prepare_rename = project.update(cx, |project, cx| {
 4729            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 4730        });
 4731
 4732        Some(cx.spawn(|this, mut cx| async move {
 4733            let rename_range = if let Some(range) = prepare_rename.await? {
 4734                Some(range)
 4735            } else {
 4736                this.read_with(&cx, |this, cx| {
 4737                    let buffer = this.buffer.read(cx).snapshot(cx);
 4738                    let mut buffer_highlights = this
 4739                        .document_highlights_for_position(selection.head(), &buffer)
 4740                        .filter(|highlight| {
 4741                            highlight.start.excerpt_id() == selection.head().excerpt_id()
 4742                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
 4743                        });
 4744                    buffer_highlights
 4745                        .next()
 4746                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 4747                })
 4748            };
 4749            if let Some(rename_range) = rename_range {
 4750                let rename_buffer_range = rename_range.to_offset(&snapshot);
 4751                let cursor_offset_in_rename_range =
 4752                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 4753
 4754                this.update(&mut cx, |this, cx| {
 4755                    this.take_rename(false, cx);
 4756                    let style = this.style(cx);
 4757                    let buffer = this.buffer.read(cx).read(cx);
 4758                    let cursor_offset = selection.head().to_offset(&buffer);
 4759                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 4760                    let rename_end = rename_start + rename_buffer_range.len();
 4761                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 4762                    let mut old_highlight_id = None;
 4763                    let old_name: Arc<str> = buffer
 4764                        .chunks(rename_start..rename_end, true)
 4765                        .map(|chunk| {
 4766                            if old_highlight_id.is_none() {
 4767                                old_highlight_id = chunk.syntax_highlight_id;
 4768                            }
 4769                            chunk.text
 4770                        })
 4771                        .collect::<String>()
 4772                        .into();
 4773
 4774                    drop(buffer);
 4775
 4776                    // Position the selection in the rename editor so that it matches the current selection.
 4777                    this.show_local_selections = false;
 4778                    let rename_editor = cx.add_view(|cx| {
 4779                        let mut editor = Editor::single_line(None, cx);
 4780                        if let Some(old_highlight_id) = old_highlight_id {
 4781                            editor.override_text_style =
 4782                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 4783                        }
 4784                        editor
 4785                            .buffer
 4786                            .update(cx, |buffer, cx| buffer.edit([(0..0, old_name.clone())], cx));
 4787                        editor.select_all(&SelectAll, cx);
 4788                        editor
 4789                    });
 4790
 4791                    let ranges = this
 4792                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 4793                        .into_iter()
 4794                        .flat_map(|(_, ranges)| ranges)
 4795                        .chain(
 4796                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 4797                                .into_iter()
 4798                                .flat_map(|(_, ranges)| ranges),
 4799                        )
 4800                        .collect();
 4801
 4802                    this.highlight_text::<Rename>(
 4803                        ranges,
 4804                        HighlightStyle {
 4805                            fade_out: Some(style.rename_fade),
 4806                            ..Default::default()
 4807                        },
 4808                        cx,
 4809                    );
 4810                    cx.focus(&rename_editor);
 4811                    let block_id = this.insert_blocks(
 4812                        [BlockProperties {
 4813                            style: BlockStyle::Flex,
 4814                            position: range.start.clone(),
 4815                            height: 1,
 4816                            render: Arc::new({
 4817                                let editor = rename_editor.clone();
 4818                                move |cx: &mut BlockContext| {
 4819                                    ChildView::new(editor.clone())
 4820                                        .contained()
 4821                                        .with_padding_left(cx.anchor_x)
 4822                                        .boxed()
 4823                                }
 4824                            }),
 4825                            disposition: BlockDisposition::Below,
 4826                        }],
 4827                        cx,
 4828                    )[0];
 4829                    this.pending_rename = Some(RenameState {
 4830                        range,
 4831                        old_name,
 4832                        editor: rename_editor,
 4833                        block_id,
 4834                    });
 4835                });
 4836            }
 4837
 4838            Ok(())
 4839        }))
 4840    }
 4841
 4842    pub fn confirm_rename(
 4843        workspace: &mut Workspace,
 4844        _: &ConfirmRename,
 4845        cx: &mut ViewContext<Workspace>,
 4846    ) -> Option<Task<Result<()>>> {
 4847        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 4848
 4849        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 4850            let rename = editor.take_rename(false, cx)?;
 4851            let buffer = editor.buffer.read(cx);
 4852            let (start_buffer, start) =
 4853                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 4854            let (end_buffer, end) =
 4855                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 4856            if start_buffer == end_buffer {
 4857                let new_name = rename.editor.read(cx).text(cx);
 4858                Some((start_buffer, start..end, rename.old_name, new_name))
 4859            } else {
 4860                None
 4861            }
 4862        })?;
 4863
 4864        let rename = workspace.project().clone().update(cx, |project, cx| {
 4865            project.perform_rename(
 4866                buffer.clone(),
 4867                range.start.clone(),
 4868                new_name.clone(),
 4869                true,
 4870                cx,
 4871            )
 4872        });
 4873
 4874        Some(cx.spawn(|workspace, mut cx| async move {
 4875            let project_transaction = rename.await?;
 4876            Self::open_project_transaction(
 4877                editor.clone(),
 4878                workspace,
 4879                project_transaction,
 4880                format!("Rename: {}{}", old_name, new_name),
 4881                cx.clone(),
 4882            )
 4883            .await?;
 4884
 4885            editor.update(&mut cx, |editor, cx| {
 4886                editor.refresh_document_highlights(cx);
 4887            });
 4888            Ok(())
 4889        }))
 4890    }
 4891
 4892    fn take_rename(
 4893        &mut self,
 4894        moving_cursor: bool,
 4895        cx: &mut ViewContext<Self>,
 4896    ) -> Option<RenameState> {
 4897        let rename = self.pending_rename.take()?;
 4898        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
 4899        self.clear_text_highlights::<Rename>(cx);
 4900        self.show_local_selections = true;
 4901
 4902        if moving_cursor {
 4903            let rename_editor = rename.editor.read(cx);
 4904            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 4905
 4906            // Update the selection to match the position of the selection inside
 4907            // the rename editor.
 4908            let snapshot = self.buffer.read(cx).read(cx);
 4909            let rename_range = rename.range.to_offset(&snapshot);
 4910            let cursor_in_editor = snapshot
 4911                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 4912                .min(rename_range.end);
 4913            drop(snapshot);
 4914
 4915            self.change_selections(None, cx, |s| {
 4916                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 4917            });
 4918        }
 4919
 4920        Some(rename)
 4921    }
 4922
 4923    #[cfg(any(test, feature = "test-support"))]
 4924    pub fn pending_rename(&self) -> Option<&RenameState> {
 4925        self.pending_rename.as_ref()
 4926    }
 4927
 4928    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 4929        if let Some(project) = self.project.clone() {
 4930            self.buffer.update(cx, |multi_buffer, cx| {
 4931                project.update(cx, |project, cx| {
 4932                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 4933                });
 4934            })
 4935        }
 4936    }
 4937
 4938    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 4939        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 4940            let buffer = self.buffer.read(cx).snapshot(cx);
 4941            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 4942            let is_valid = buffer
 4943                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 4944                .any(|entry| {
 4945                    entry.diagnostic.is_primary
 4946                        && !entry.range.is_empty()
 4947                        && entry.range.start == primary_range_start
 4948                        && entry.diagnostic.message == active_diagnostics.primary_message
 4949                });
 4950
 4951            if is_valid != active_diagnostics.is_valid {
 4952                active_diagnostics.is_valid = is_valid;
 4953                let mut new_styles = HashMap::default();
 4954                for (block_id, diagnostic) in &active_diagnostics.blocks {
 4955                    new_styles.insert(
 4956                        *block_id,
 4957                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 4958                    );
 4959                }
 4960                self.display_map
 4961                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 4962            }
 4963        }
 4964    }
 4965
 4966    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
 4967        self.dismiss_diagnostics(cx);
 4968        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 4969            let buffer = self.buffer.read(cx).snapshot(cx);
 4970
 4971            let mut primary_range = None;
 4972            let mut primary_message = None;
 4973            let mut group_end = Point::zero();
 4974            let diagnostic_group = buffer
 4975                .diagnostic_group::<Point>(group_id)
 4976                .map(|entry| {
 4977                    if entry.range.end > group_end {
 4978                        group_end = entry.range.end;
 4979                    }
 4980                    if entry.diagnostic.is_primary {
 4981                        primary_range = Some(entry.range.clone());
 4982                        primary_message = Some(entry.diagnostic.message.clone());
 4983                    }
 4984                    entry
 4985                })
 4986                .collect::<Vec<_>>();
 4987            let primary_range = primary_range.unwrap();
 4988            let primary_message = primary_message.unwrap();
 4989            let primary_range =
 4990                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 4991
 4992            let blocks = display_map
 4993                .insert_blocks(
 4994                    diagnostic_group.iter().map(|entry| {
 4995                        let diagnostic = entry.diagnostic.clone();
 4996                        let message_height = diagnostic.message.lines().count() as u8;
 4997                        BlockProperties {
 4998                            style: BlockStyle::Fixed,
 4999                            position: buffer.anchor_after(entry.range.start),
 5000                            height: message_height,
 5001                            render: diagnostic_block_renderer(diagnostic, true),
 5002                            disposition: BlockDisposition::Below,
 5003                        }
 5004                    }),
 5005                    cx,
 5006                )
 5007                .into_iter()
 5008                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 5009                .collect();
 5010
 5011            Some(ActiveDiagnosticGroup {
 5012                primary_range,
 5013                primary_message,
 5014                blocks,
 5015                is_valid: true,
 5016            })
 5017        });
 5018    }
 5019
 5020    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 5021        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 5022            self.display_map.update(cx, |display_map, cx| {
 5023                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 5024            });
 5025            cx.notify();
 5026        }
 5027    }
 5028
 5029    pub fn set_selections_from_remote(
 5030        &mut self,
 5031        selections: Vec<Selection<Anchor>>,
 5032        cx: &mut ViewContext<Self>,
 5033    ) {
 5034        let old_cursor_position = self.selections.newest_anchor().head();
 5035        self.selections.change_with(cx, |s| {
 5036            s.select_anchors(selections);
 5037        });
 5038        self.selections_did_change(false, &old_cursor_position, cx);
 5039    }
 5040
 5041    fn push_to_selection_history(&mut self) {
 5042        self.selection_history.push(SelectionHistoryEntry {
 5043            selections: self.selections.disjoint_anchors().clone(),
 5044            select_next_state: self.select_next_state.clone(),
 5045            add_selections_state: self.add_selections_state.clone(),
 5046        });
 5047    }
 5048
 5049    pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5050        self.autoscroll_request = Some((autoscroll, true));
 5051        cx.notify();
 5052    }
 5053
 5054    fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
 5055        self.autoscroll_request = Some((autoscroll, false));
 5056        cx.notify();
 5057    }
 5058
 5059    pub fn transact(
 5060        &mut self,
 5061        cx: &mut ViewContext<Self>,
 5062        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 5063    ) {
 5064        self.start_transaction_at(Instant::now(), cx);
 5065        update(self, cx);
 5066        self.end_transaction_at(Instant::now(), cx);
 5067    }
 5068
 5069    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5070        self.end_selection(cx);
 5071        if let Some(tx_id) = self
 5072            .buffer
 5073            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 5074        {
 5075            self.selection_history
 5076                .insert_transaction(tx_id, self.selections.disjoint_anchors().clone());
 5077        }
 5078    }
 5079
 5080    fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 5081        if let Some(tx_id) = self
 5082            .buffer
 5083            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 5084        {
 5085            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 5086                *end_selections = Some(self.selections.disjoint_anchors().clone());
 5087            } else {
 5088                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 5089            }
 5090
 5091            cx.emit(Event::Edited);
 5092        }
 5093    }
 5094
 5095    pub fn page_up(&mut self, _: &PageUp, _: &mut ViewContext<Self>) {
 5096        log::info!("Editor::page_up");
 5097    }
 5098
 5099    pub fn page_down(&mut self, _: &PageDown, _: &mut ViewContext<Self>) {
 5100        log::info!("Editor::page_down");
 5101    }
 5102
 5103    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 5104        let mut fold_ranges = Vec::new();
 5105
 5106        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5107        let selections = self.selections.all::<Point>(cx);
 5108        for selection in selections {
 5109            let range = selection.display_range(&display_map).sorted();
 5110            let buffer_start_row = range.start.to_point(&display_map).row;
 5111
 5112            for row in (0..=range.end.row()).rev() {
 5113                if self.is_line_foldable(&display_map, row) && !display_map.is_line_folded(row) {
 5114                    let fold_range = self.foldable_range_for_line(&display_map, row);
 5115                    if fold_range.end.row >= buffer_start_row {
 5116                        fold_ranges.push(fold_range);
 5117                        if row <= range.start.row() {
 5118                            break;
 5119                        }
 5120                    }
 5121                }
 5122            }
 5123        }
 5124
 5125        self.fold_ranges(fold_ranges, cx);
 5126    }
 5127
 5128    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 5129        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5130        let buffer = &display_map.buffer_snapshot;
 5131        let selections = self.selections.all::<Point>(cx);
 5132        let ranges = selections
 5133            .iter()
 5134            .map(|s| {
 5135                let range = s.display_range(&display_map).sorted();
 5136                let mut start = range.start.to_point(&display_map);
 5137                let mut end = range.end.to_point(&display_map);
 5138                start.column = 0;
 5139                end.column = buffer.line_len(end.row);
 5140                start..end
 5141            })
 5142            .collect::<Vec<_>>();
 5143        self.unfold_ranges(ranges, true, cx);
 5144    }
 5145
 5146    fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool {
 5147        let max_point = display_map.max_point();
 5148        if display_row >= max_point.row() {
 5149            false
 5150        } else {
 5151            let (start_indent, is_blank) = display_map.line_indent(display_row);
 5152            if is_blank {
 5153                false
 5154            } else {
 5155                for display_row in display_row + 1..=max_point.row() {
 5156                    let (indent, is_blank) = display_map.line_indent(display_row);
 5157                    if !is_blank {
 5158                        return indent > start_indent;
 5159                    }
 5160                }
 5161                false
 5162            }
 5163        }
 5164    }
 5165
 5166    fn foldable_range_for_line(
 5167        &self,
 5168        display_map: &DisplaySnapshot,
 5169        start_row: u32,
 5170    ) -> Range<Point> {
 5171        let max_point = display_map.max_point();
 5172
 5173        let (start_indent, _) = display_map.line_indent(start_row);
 5174        let start = DisplayPoint::new(start_row, display_map.line_len(start_row));
 5175        let mut end = None;
 5176        for row in start_row + 1..=max_point.row() {
 5177            let (indent, is_blank) = display_map.line_indent(row);
 5178            if !is_blank && indent <= start_indent {
 5179                end = Some(DisplayPoint::new(row - 1, display_map.line_len(row - 1)));
 5180                break;
 5181            }
 5182        }
 5183
 5184        let end = end.unwrap_or(max_point);
 5185        return start.to_point(display_map)..end.to_point(display_map);
 5186    }
 5187
 5188    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 5189        let selections = self.selections.all::<Point>(cx);
 5190        let ranges = selections.into_iter().map(|s| s.start..s.end);
 5191        self.fold_ranges(ranges, cx);
 5192    }
 5193
 5194    pub fn fold_ranges<T: ToOffset>(
 5195        &mut self,
 5196        ranges: impl IntoIterator<Item = Range<T>>,
 5197        cx: &mut ViewContext<Self>,
 5198    ) {
 5199        let mut ranges = ranges.into_iter().peekable();
 5200        if ranges.peek().is_some() {
 5201            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 5202            self.request_autoscroll(Autoscroll::Fit, cx);
 5203            cx.notify();
 5204        }
 5205    }
 5206
 5207    pub fn unfold_ranges<T: ToOffset>(
 5208        &mut self,
 5209        ranges: impl IntoIterator<Item = Range<T>>,
 5210        inclusive: bool,
 5211        cx: &mut ViewContext<Self>,
 5212    ) {
 5213        let mut ranges = ranges.into_iter().peekable();
 5214        if ranges.peek().is_some() {
 5215            self.display_map
 5216                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 5217            self.request_autoscroll(Autoscroll::Fit, cx);
 5218            cx.notify();
 5219        }
 5220    }
 5221
 5222    pub fn insert_blocks(
 5223        &mut self,
 5224        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 5225        cx: &mut ViewContext<Self>,
 5226    ) -> Vec<BlockId> {
 5227        let blocks = self
 5228            .display_map
 5229            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 5230        self.request_autoscroll(Autoscroll::Fit, cx);
 5231        blocks
 5232    }
 5233
 5234    pub fn replace_blocks(
 5235        &mut self,
 5236        blocks: HashMap<BlockId, RenderBlock>,
 5237        cx: &mut ViewContext<Self>,
 5238    ) {
 5239        self.display_map
 5240            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 5241        self.request_autoscroll(Autoscroll::Fit, cx);
 5242    }
 5243
 5244    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
 5245        self.display_map.update(cx, |display_map, cx| {
 5246            display_map.remove_blocks(block_ids, cx)
 5247        });
 5248    }
 5249
 5250    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
 5251        self.display_map
 5252            .update(cx, |map, cx| map.snapshot(cx))
 5253            .longest_row()
 5254    }
 5255
 5256    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
 5257        self.display_map
 5258            .update(cx, |map, cx| map.snapshot(cx))
 5259            .max_point()
 5260    }
 5261
 5262    pub fn text(&self, cx: &AppContext) -> String {
 5263        self.buffer.read(cx).read(cx).text()
 5264    }
 5265
 5266    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 5267        self.transact(cx, |this, cx| {
 5268            this.buffer
 5269                .read(cx)
 5270                .as_singleton()
 5271                .expect("you can only call set_text on editors for singleton buffers")
 5272                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 5273        });
 5274    }
 5275
 5276    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
 5277        self.display_map
 5278            .update(cx, |map, cx| map.snapshot(cx))
 5279            .text()
 5280    }
 5281
 5282    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 5283        let language_name = self
 5284            .buffer
 5285            .read(cx)
 5286            .as_singleton()
 5287            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
 5288            .map(|l| l.name());
 5289
 5290        let settings = cx.global::<Settings>();
 5291        let mode = self
 5292            .soft_wrap_mode_override
 5293            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
 5294        match mode {
 5295            settings::SoftWrap::None => SoftWrap::None,
 5296            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 5297            settings::SoftWrap::PreferredLineLength => {
 5298                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
 5299            }
 5300        }
 5301    }
 5302
 5303    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
 5304        self.soft_wrap_mode_override = Some(mode);
 5305        cx.notify();
 5306    }
 5307
 5308    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
 5309        self.display_map
 5310            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 5311    }
 5312
 5313    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 5314        self.highlighted_rows = rows;
 5315    }
 5316
 5317    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 5318        self.highlighted_rows.clone()
 5319    }
 5320
 5321    pub fn highlight_background<T: 'static>(
 5322        &mut self,
 5323        ranges: Vec<Range<Anchor>>,
 5324        color_fetcher: fn(&Theme) -> Color,
 5325        cx: &mut ViewContext<Self>,
 5326    ) {
 5327        self.background_highlights
 5328            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 5329        cx.notify();
 5330    }
 5331
 5332    pub fn clear_background_highlights<T: 'static>(
 5333        &mut self,
 5334        cx: &mut ViewContext<Self>,
 5335    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
 5336        cx.notify();
 5337        self.background_highlights.remove(&TypeId::of::<T>())
 5338    }
 5339
 5340    #[cfg(feature = "test-support")]
 5341    pub fn all_background_highlights(
 5342        &mut self,
 5343        cx: &mut ViewContext<Self>,
 5344    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5345        let snapshot = self.snapshot(cx);
 5346        let buffer = &snapshot.buffer_snapshot;
 5347        let start = buffer.anchor_before(0);
 5348        let end = buffer.anchor_after(buffer.len());
 5349        let theme = cx.global::<Settings>().theme.as_ref();
 5350        self.background_highlights_in_range(start..end, &snapshot, theme)
 5351    }
 5352
 5353    fn document_highlights_for_position<'a>(
 5354        &'a self,
 5355        position: Anchor,
 5356        buffer: &'a MultiBufferSnapshot,
 5357    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 5358        let read_highlights = self
 5359            .background_highlights
 5360            .get(&TypeId::of::<DocumentHighlightRead>())
 5361            .map(|h| &h.1);
 5362        let write_highlights = self
 5363            .background_highlights
 5364            .get(&TypeId::of::<DocumentHighlightRead>())
 5365            .map(|h| &h.1);
 5366        let left_position = position.bias_left(buffer);
 5367        let right_position = position.bias_right(buffer);
 5368        read_highlights
 5369            .into_iter()
 5370            .chain(write_highlights)
 5371            .flat_map(move |ranges| {
 5372                let start_ix = match ranges.binary_search_by(|probe| {
 5373                    let cmp = probe.end.cmp(&left_position, &buffer);
 5374                    if cmp.is_ge() {
 5375                        Ordering::Greater
 5376                    } else {
 5377                        Ordering::Less
 5378                    }
 5379                }) {
 5380                    Ok(i) | Err(i) => i,
 5381                };
 5382
 5383                let right_position = right_position.clone();
 5384                ranges[start_ix..]
 5385                    .iter()
 5386                    .take_while(move |range| range.start.cmp(&right_position, &buffer).is_le())
 5387            })
 5388    }
 5389
 5390    pub fn background_highlights_in_range(
 5391        &self,
 5392        search_range: Range<Anchor>,
 5393        display_snapshot: &DisplaySnapshot,
 5394        theme: &Theme,
 5395    ) -> Vec<(Range<DisplayPoint>, Color)> {
 5396        let mut results = Vec::new();
 5397        let buffer = &display_snapshot.buffer_snapshot;
 5398        for (color_fetcher, ranges) in self.background_highlights.values() {
 5399            let color = color_fetcher(theme);
 5400            let start_ix = match ranges.binary_search_by(|probe| {
 5401                let cmp = probe.end.cmp(&search_range.start, &buffer);
 5402                if cmp.is_gt() {
 5403                    Ordering::Greater
 5404                } else {
 5405                    Ordering::Less
 5406                }
 5407            }) {
 5408                Ok(i) | Err(i) => i,
 5409            };
 5410            for range in &ranges[start_ix..] {
 5411                if range.start.cmp(&search_range.end, &buffer).is_ge() {
 5412                    break;
 5413                }
 5414                let start = range
 5415                    .start
 5416                    .to_point(buffer)
 5417                    .to_display_point(display_snapshot);
 5418                let end = range
 5419                    .end
 5420                    .to_point(buffer)
 5421                    .to_display_point(display_snapshot);
 5422                results.push((start..end, color))
 5423            }
 5424        }
 5425        results
 5426    }
 5427
 5428    pub fn highlight_text<T: 'static>(
 5429        &mut self,
 5430        ranges: Vec<Range<Anchor>>,
 5431        style: HighlightStyle,
 5432        cx: &mut ViewContext<Self>,
 5433    ) {
 5434        self.display_map.update(cx, |map, _| {
 5435            map.highlight_text(TypeId::of::<T>(), ranges, style)
 5436        });
 5437        cx.notify();
 5438    }
 5439
 5440    pub fn clear_text_highlights<T: 'static>(
 5441        &mut self,
 5442        cx: &mut ViewContext<Self>,
 5443    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
 5444        cx.notify();
 5445        self.display_map
 5446            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()))
 5447    }
 5448
 5449    fn next_blink_epoch(&mut self) -> usize {
 5450        self.blink_epoch += 1;
 5451        self.blink_epoch
 5452    }
 5453
 5454    fn pause_cursor_blinking(&mut self, cx: &mut ViewContext<Self>) {
 5455        if !self.focused {
 5456            return;
 5457        }
 5458
 5459        self.show_local_cursors = true;
 5460        cx.notify();
 5461
 5462        let epoch = self.next_blink_epoch();
 5463        cx.spawn(|this, mut cx| {
 5464            let this = this.downgrade();
 5465            async move {
 5466                Timer::after(CURSOR_BLINK_INTERVAL).await;
 5467                if let Some(this) = this.upgrade(&cx) {
 5468                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
 5469                }
 5470            }
 5471        })
 5472        .detach();
 5473    }
 5474
 5475    fn resume_cursor_blinking(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5476        if epoch == self.blink_epoch {
 5477            self.blinking_paused = false;
 5478            self.blink_cursors(epoch, cx);
 5479        }
 5480    }
 5481
 5482    fn blink_cursors(&mut self, epoch: usize, cx: &mut ViewContext<Self>) {
 5483        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
 5484            self.show_local_cursors = !self.show_local_cursors;
 5485            cx.notify();
 5486
 5487            let epoch = self.next_blink_epoch();
 5488            cx.spawn(|this, mut cx| {
 5489                let this = this.downgrade();
 5490                async move {
 5491                    Timer::after(CURSOR_BLINK_INTERVAL).await;
 5492                    if let Some(this) = this.upgrade(&cx) {
 5493                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
 5494                    }
 5495                }
 5496            })
 5497            .detach();
 5498        }
 5499    }
 5500
 5501    pub fn show_local_cursors(&self) -> bool {
 5502        self.show_local_cursors && self.focused
 5503    }
 5504
 5505    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 5506        cx.notify();
 5507    }
 5508
 5509    fn on_buffer_event(
 5510        &mut self,
 5511        _: ModelHandle<MultiBuffer>,
 5512        event: &language::Event,
 5513        cx: &mut ViewContext<Self>,
 5514    ) {
 5515        match event {
 5516            language::Event::Edited => {
 5517                self.refresh_active_diagnostics(cx);
 5518                self.refresh_code_actions(cx);
 5519                cx.emit(Event::BufferEdited);
 5520            }
 5521            language::Event::Reparsed => cx.emit(Event::Reparsed),
 5522            language::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 5523            language::Event::Saved => cx.emit(Event::Saved),
 5524            language::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 5525            language::Event::Reloaded => cx.emit(Event::TitleChanged),
 5526            language::Event::Closed => cx.emit(Event::Closed),
 5527            language::Event::DiagnosticsUpdated => {
 5528                self.refresh_active_diagnostics(cx);
 5529            }
 5530            _ => {}
 5531        }
 5532    }
 5533
 5534    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 5535        cx.notify();
 5536    }
 5537
 5538    pub fn set_searchable(&mut self, searchable: bool) {
 5539        self.searchable = searchable;
 5540    }
 5541
 5542    pub fn searchable(&self) -> bool {
 5543        self.searchable
 5544    }
 5545
 5546    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 5547        let active_item = workspace.active_item(cx);
 5548        let editor_handle = if let Some(editor) = active_item
 5549            .as_ref()
 5550            .and_then(|item| item.act_as::<Self>(cx))
 5551        {
 5552            editor
 5553        } else {
 5554            cx.propagate_action();
 5555            return;
 5556        };
 5557
 5558        let editor = editor_handle.read(cx);
 5559        let buffer = editor.buffer.read(cx);
 5560        if buffer.is_singleton() {
 5561            cx.propagate_action();
 5562            return;
 5563        }
 5564
 5565        let mut new_selections_by_buffer = HashMap::default();
 5566        for selection in editor.selections.all::<usize>(cx) {
 5567            for (buffer, mut range) in
 5568                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 5569            {
 5570                if selection.reversed {
 5571                    mem::swap(&mut range.start, &mut range.end);
 5572                }
 5573                new_selections_by_buffer
 5574                    .entry(buffer)
 5575                    .or_insert(Vec::new())
 5576                    .push(range)
 5577            }
 5578        }
 5579
 5580        editor_handle.update(cx, |editor, cx| {
 5581            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 5582        });
 5583        let nav_history = workspace.active_pane().read(cx).nav_history().clone();
 5584        nav_history.borrow_mut().disable();
 5585
 5586        // We defer the pane interaction because we ourselves are a workspace item
 5587        // and activating a new item causes the pane to call a method on us reentrantly,
 5588        // which panics if we're on the stack.
 5589        cx.defer(move |workspace, cx| {
 5590            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 5591                let editor = workspace.open_project_item::<Self>(buffer, cx);
 5592                editor.update(cx, |editor, cx| {
 5593                    editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5594                        s.select_ranges(ranges);
 5595                    });
 5596                });
 5597            }
 5598
 5599            nav_history.borrow_mut().enable();
 5600        });
 5601    }
 5602
 5603    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
 5604        let editor = workspace.open_path(action.path.clone(), true, cx);
 5605        let position = action.position;
 5606        let anchor = action.anchor;
 5607        cx.spawn_weak(|_, mut cx| async move {
 5608            let editor = editor.await.log_err()?.downcast::<Editor>()?;
 5609            editor.update(&mut cx, |editor, cx| {
 5610                let buffer = editor.buffer().read(cx).as_singleton()?;
 5611                let buffer = buffer.read(cx);
 5612                let cursor = if buffer.can_resolve(&anchor) {
 5613                    language::ToPoint::to_point(&anchor, buffer)
 5614                } else {
 5615                    buffer.clip_point(position, Bias::Left)
 5616                };
 5617
 5618                let nav_history = editor.nav_history.take();
 5619                editor.change_selections(Some(Autoscroll::Newest), cx, |s| {
 5620                    s.select_ranges([cursor..cursor]);
 5621                });
 5622                editor.nav_history = nav_history;
 5623
 5624                Some(())
 5625            })?;
 5626            Some(())
 5627        })
 5628        .detach()
 5629    }
 5630}
 5631
 5632impl EditorSnapshot {
 5633    pub fn is_focused(&self) -> bool {
 5634        self.is_focused
 5635    }
 5636
 5637    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 5638        self.placeholder_text.as_ref()
 5639    }
 5640
 5641    pub fn scroll_position(&self) -> Vector2F {
 5642        compute_scroll_position(
 5643            &self.display_snapshot,
 5644            self.scroll_position,
 5645            &self.scroll_top_anchor,
 5646        )
 5647    }
 5648}
 5649
 5650impl Deref for EditorSnapshot {
 5651    type Target = DisplaySnapshot;
 5652
 5653    fn deref(&self) -> &Self::Target {
 5654        &self.display_snapshot
 5655    }
 5656}
 5657
 5658fn compute_scroll_position(
 5659    snapshot: &DisplaySnapshot,
 5660    mut scroll_position: Vector2F,
 5661    scroll_top_anchor: &Anchor,
 5662) -> Vector2F {
 5663    if *scroll_top_anchor != Anchor::min() {
 5664        let scroll_top = scroll_top_anchor.to_display_point(snapshot).row() as f32;
 5665        scroll_position.set_y(scroll_top + scroll_position.y());
 5666    } else {
 5667        scroll_position.set_y(0.);
 5668    }
 5669    scroll_position
 5670}
 5671
 5672#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 5673pub enum Event {
 5674    Activate,
 5675    BufferEdited,
 5676    Edited,
 5677    Reparsed,
 5678    Blurred,
 5679    DirtyChanged,
 5680    Saved,
 5681    TitleChanged,
 5682    SelectionsChanged { local: bool },
 5683    ScrollPositionChanged { local: bool },
 5684    Closed,
 5685}
 5686
 5687pub struct EditorFocused(pub ViewHandle<Editor>);
 5688pub struct EditorBlurred(pub ViewHandle<Editor>);
 5689pub struct EditorReleased(pub WeakViewHandle<Editor>);
 5690
 5691impl Entity for Editor {
 5692    type Event = Event;
 5693
 5694    fn release(&mut self, cx: &mut MutableAppContext) {
 5695        cx.emit_global(EditorReleased(self.handle.clone()));
 5696    }
 5697}
 5698
 5699impl View for Editor {
 5700    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 5701        let style = self.style(cx);
 5702        let font_changed = self.display_map.update(cx, |map, cx| {
 5703            map.set_font(style.text.font_id, style.text.font_size, cx)
 5704        });
 5705
 5706        if font_changed {
 5707            let handle = self.handle.clone();
 5708            cx.defer(move |cx| {
 5709                if let Some(editor) = handle.upgrade(cx) {
 5710                    editor.update(cx, |editor, cx| {
 5711                        hide_hover(editor, cx);
 5712                    })
 5713                }
 5714            });
 5715        }
 5716
 5717        EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
 5718    }
 5719
 5720    fn ui_name() -> &'static str {
 5721        "Editor"
 5722    }
 5723
 5724    fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
 5725        let focused_event = EditorFocused(cx.handle());
 5726        cx.emit_global(focused_event);
 5727        if let Some(rename) = self.pending_rename.as_ref() {
 5728            cx.focus(&rename.editor);
 5729        } else {
 5730            self.focused = true;
 5731            self.blink_cursors(self.blink_epoch, cx);
 5732            self.buffer.update(cx, |buffer, cx| {
 5733                buffer.finalize_last_transaction(cx);
 5734                if self.leader_replica_id.is_none() {
 5735                    buffer.set_active_selections(
 5736                        &self.selections.disjoint_anchors(),
 5737                        self.selections.line_mode,
 5738                        cx,
 5739                    );
 5740                }
 5741            });
 5742        }
 5743    }
 5744
 5745    fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
 5746        let blurred_event = EditorBlurred(cx.handle());
 5747        cx.emit_global(blurred_event);
 5748        self.focused = false;
 5749        self.buffer
 5750            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 5751        self.hide_context_menu(cx);
 5752        hide_hover(self, cx);
 5753        cx.emit(Event::Blurred);
 5754        cx.notify();
 5755    }
 5756
 5757    fn keymap_context(&self, _: &AppContext) -> gpui::keymap::Context {
 5758        let mut context = Self::default_keymap_context();
 5759        let mode = match self.mode {
 5760            EditorMode::SingleLine => "single_line",
 5761            EditorMode::AutoHeight { .. } => "auto_height",
 5762            EditorMode::Full => "full",
 5763        };
 5764        context.map.insert("mode".into(), mode.into());
 5765        if self.pending_rename.is_some() {
 5766            context.set.insert("renaming".into());
 5767        }
 5768        match self.context_menu.as_ref() {
 5769            Some(ContextMenu::Completions(_)) => {
 5770                context.set.insert("showing_completions".into());
 5771            }
 5772            Some(ContextMenu::CodeActions(_)) => {
 5773                context.set.insert("showing_code_actions".into());
 5774            }
 5775            None => {}
 5776        }
 5777
 5778        for layer in self.keymap_context_layers.values() {
 5779            context.extend(layer);
 5780        }
 5781
 5782        context
 5783    }
 5784}
 5785
 5786fn build_style(
 5787    settings: &Settings,
 5788    get_field_editor_theme: Option<GetFieldEditorTheme>,
 5789    override_text_style: Option<&OverrideTextStyle>,
 5790    cx: &AppContext,
 5791) -> EditorStyle {
 5792    let font_cache = cx.font_cache();
 5793
 5794    let mut theme = settings.theme.editor.clone();
 5795    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 5796        let field_editor_theme = get_field_editor_theme(&settings.theme);
 5797        theme.text_color = field_editor_theme.text.color;
 5798        theme.selection = field_editor_theme.selection;
 5799        theme.background = field_editor_theme
 5800            .container
 5801            .background_color
 5802            .unwrap_or_default();
 5803        EditorStyle {
 5804            text: field_editor_theme.text,
 5805            placeholder_text: field_editor_theme.placeholder_text,
 5806            theme,
 5807        }
 5808    } else {
 5809        let font_family_id = settings.buffer_font_family;
 5810        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 5811        let font_properties = Default::default();
 5812        let font_id = font_cache
 5813            .select_font(font_family_id, &font_properties)
 5814            .unwrap();
 5815        let font_size = settings.buffer_font_size;
 5816        EditorStyle {
 5817            text: TextStyle {
 5818                color: settings.theme.editor.text_color,
 5819                font_family_name,
 5820                font_family_id,
 5821                font_id,
 5822                font_size,
 5823                font_properties,
 5824                underline: Default::default(),
 5825            },
 5826            placeholder_text: None,
 5827            theme,
 5828        }
 5829    };
 5830
 5831    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 5832        if let Some(highlighted) = style
 5833            .text
 5834            .clone()
 5835            .highlight(highlight_style, font_cache)
 5836            .log_err()
 5837        {
 5838            style.text = highlighted;
 5839        }
 5840    }
 5841
 5842    style
 5843}
 5844
 5845trait SelectionExt {
 5846    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 5847    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 5848    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 5849    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 5850        -> Range<u32>;
 5851}
 5852
 5853impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 5854    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 5855        let start = self.start.to_point(buffer);
 5856        let end = self.end.to_point(buffer);
 5857        if self.reversed {
 5858            end..start
 5859        } else {
 5860            start..end
 5861        }
 5862    }
 5863
 5864    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 5865        let start = self.start.to_offset(buffer);
 5866        let end = self.end.to_offset(buffer);
 5867        if self.reversed {
 5868            end..start
 5869        } else {
 5870            start..end
 5871        }
 5872    }
 5873
 5874    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 5875        let start = self
 5876            .start
 5877            .to_point(&map.buffer_snapshot)
 5878            .to_display_point(map);
 5879        let end = self
 5880            .end
 5881            .to_point(&map.buffer_snapshot)
 5882            .to_display_point(map);
 5883        if self.reversed {
 5884            end..start
 5885        } else {
 5886            start..end
 5887        }
 5888    }
 5889
 5890    fn spanned_rows(
 5891        &self,
 5892        include_end_if_at_line_start: bool,
 5893        map: &DisplaySnapshot,
 5894    ) -> Range<u32> {
 5895        let start = self.start.to_point(&map.buffer_snapshot);
 5896        let mut end = self.end.to_point(&map.buffer_snapshot);
 5897        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 5898            end.row -= 1;
 5899        }
 5900
 5901        let buffer_start = map.prev_line_boundary(start).0;
 5902        let buffer_end = map.next_line_boundary(end).0;
 5903        buffer_start.row..buffer_end.row + 1
 5904    }
 5905}
 5906
 5907impl<T: InvalidationRegion> InvalidationStack<T> {
 5908    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 5909    where
 5910        S: Clone + ToOffset,
 5911    {
 5912        while let Some(region) = self.last() {
 5913            let all_selections_inside_invalidation_ranges =
 5914                if selections.len() == region.ranges().len() {
 5915                    selections
 5916                        .iter()
 5917                        .zip(region.ranges().iter().map(|r| r.to_offset(&buffer)))
 5918                        .all(|(selection, invalidation_range)| {
 5919                            let head = selection.head().to_offset(&buffer);
 5920                            invalidation_range.start <= head && invalidation_range.end >= head
 5921                        })
 5922                } else {
 5923                    false
 5924                };
 5925
 5926            if all_selections_inside_invalidation_ranges {
 5927                break;
 5928            } else {
 5929                self.pop();
 5930            }
 5931        }
 5932    }
 5933}
 5934
 5935impl<T> Default for InvalidationStack<T> {
 5936    fn default() -> Self {
 5937        Self(Default::default())
 5938    }
 5939}
 5940
 5941impl<T> Deref for InvalidationStack<T> {
 5942    type Target = Vec<T>;
 5943
 5944    fn deref(&self) -> &Self::Target {
 5945        &self.0
 5946    }
 5947}
 5948
 5949impl<T> DerefMut for InvalidationStack<T> {
 5950    fn deref_mut(&mut self) -> &mut Self::Target {
 5951        &mut self.0
 5952    }
 5953}
 5954
 5955impl InvalidationRegion for BracketPairState {
 5956    fn ranges(&self) -> &[Range<Anchor>] {
 5957        &self.ranges
 5958    }
 5959}
 5960
 5961impl InvalidationRegion for SnippetState {
 5962    fn ranges(&self) -> &[Range<Anchor>] {
 5963        &self.ranges[self.active_index]
 5964    }
 5965}
 5966
 5967impl Deref for EditorStyle {
 5968    type Target = theme::Editor;
 5969
 5970    fn deref(&self) -> &Self::Target {
 5971        &self.theme
 5972    }
 5973}
 5974
 5975pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 5976    let mut highlighted_lines = Vec::new();
 5977    for line in diagnostic.message.lines() {
 5978        highlighted_lines.push(highlight_diagnostic_message(line));
 5979    }
 5980
 5981    Arc::new(move |cx: &mut BlockContext| {
 5982        let settings = cx.global::<Settings>();
 5983        let theme = &settings.theme.editor;
 5984        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 5985        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
 5986        Flex::column()
 5987            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 5988                Label::new(
 5989                    line.clone(),
 5990                    style.message.clone().with_font_size(font_size),
 5991                )
 5992                .with_highlights(highlights.clone())
 5993                .contained()
 5994                .with_margin_left(cx.anchor_x)
 5995                .boxed()
 5996            }))
 5997            .aligned()
 5998            .left()
 5999            .boxed()
 6000    })
 6001}
 6002
 6003pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
 6004    let mut message_without_backticks = String::new();
 6005    let mut prev_offset = 0;
 6006    let mut inside_block = false;
 6007    let mut highlights = Vec::new();
 6008    for (match_ix, (offset, _)) in message
 6009        .match_indices('`')
 6010        .chain([(message.len(), "")])
 6011        .enumerate()
 6012    {
 6013        message_without_backticks.push_str(&message[prev_offset..offset]);
 6014        if inside_block {
 6015            highlights.extend(prev_offset - match_ix..offset - match_ix);
 6016        }
 6017
 6018        inside_block = !inside_block;
 6019        prev_offset = offset + 1;
 6020    }
 6021
 6022    (message_without_backticks, highlights)
 6023}
 6024
 6025pub fn diagnostic_style(
 6026    severity: DiagnosticSeverity,
 6027    valid: bool,
 6028    theme: &theme::Editor,
 6029) -> DiagnosticStyle {
 6030    match (severity, valid) {
 6031        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 6032        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 6033        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 6034        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 6035        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 6036        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 6037        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 6038        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 6039        _ => theme.invalid_hint_diagnostic.clone(),
 6040    }
 6041}
 6042
 6043pub fn combine_syntax_and_fuzzy_match_highlights(
 6044    text: &str,
 6045    default_style: HighlightStyle,
 6046    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 6047    match_indices: &[usize],
 6048) -> Vec<(Range<usize>, HighlightStyle)> {
 6049    let mut result = Vec::new();
 6050    let mut match_indices = match_indices.iter().copied().peekable();
 6051
 6052    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 6053    {
 6054        syntax_highlight.weight = None;
 6055
 6056        // Add highlights for any fuzzy match characters before the next
 6057        // syntax highlight range.
 6058        while let Some(&match_index) = match_indices.peek() {
 6059            if match_index >= range.start {
 6060                break;
 6061            }
 6062            match_indices.next();
 6063            let end_index = char_ix_after(match_index, text);
 6064            let mut match_style = default_style;
 6065            match_style.weight = Some(fonts::Weight::BOLD);
 6066            result.push((match_index..end_index, match_style));
 6067        }
 6068
 6069        if range.start == usize::MAX {
 6070            break;
 6071        }
 6072
 6073        // Add highlights for any fuzzy match characters within the
 6074        // syntax highlight range.
 6075        let mut offset = range.start;
 6076        while let Some(&match_index) = match_indices.peek() {
 6077            if match_index >= range.end {
 6078                break;
 6079            }
 6080
 6081            match_indices.next();
 6082            if match_index > offset {
 6083                result.push((offset..match_index, syntax_highlight));
 6084            }
 6085
 6086            let mut end_index = char_ix_after(match_index, text);
 6087            while let Some(&next_match_index) = match_indices.peek() {
 6088                if next_match_index == end_index && next_match_index < range.end {
 6089                    end_index = char_ix_after(next_match_index, text);
 6090                    match_indices.next();
 6091                } else {
 6092                    break;
 6093                }
 6094            }
 6095
 6096            let mut match_style = syntax_highlight;
 6097            match_style.weight = Some(fonts::Weight::BOLD);
 6098            result.push((match_index..end_index, match_style));
 6099            offset = end_index;
 6100        }
 6101
 6102        if offset < range.end {
 6103            result.push((offset..range.end, syntax_highlight));
 6104        }
 6105    }
 6106
 6107    fn char_ix_after(ix: usize, text: &str) -> usize {
 6108        ix + text[ix..].chars().next().unwrap().len_utf8()
 6109    }
 6110
 6111    result
 6112}
 6113
 6114pub fn styled_runs_for_code_label<'a>(
 6115    label: &'a CodeLabel,
 6116    syntax_theme: &'a theme::SyntaxTheme,
 6117) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
 6118    let fade_out = HighlightStyle {
 6119        fade_out: Some(0.35),
 6120        ..Default::default()
 6121    };
 6122
 6123    let mut prev_end = label.filter_range.end;
 6124    label
 6125        .runs
 6126        .iter()
 6127        .enumerate()
 6128        .flat_map(move |(ix, (range, highlight_id))| {
 6129            let style = if let Some(style) = highlight_id.style(syntax_theme) {
 6130                style
 6131            } else {
 6132                return Default::default();
 6133            };
 6134            let mut muted_style = style.clone();
 6135            muted_style.highlight(fade_out);
 6136
 6137            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
 6138            if range.start >= label.filter_range.end {
 6139                if range.start > prev_end {
 6140                    runs.push((prev_end..range.start, fade_out));
 6141                }
 6142                runs.push((range.clone(), muted_style));
 6143            } else if range.end <= label.filter_range.end {
 6144                runs.push((range.clone(), style));
 6145            } else {
 6146                runs.push((range.start..label.filter_range.end, style));
 6147                runs.push((label.filter_range.end..range.end, muted_style));
 6148            }
 6149            prev_end = cmp::max(prev_end, range.end);
 6150
 6151            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
 6152                runs.push((prev_end..label.text.len(), fade_out));
 6153            }
 6154
 6155            runs
 6156        })
 6157}
 6158
 6159#[cfg(test)]
 6160mod tests {
 6161    use crate::test::{
 6162        assert_text_with_selections, build_editor, select_ranges, EditorTestContext,
 6163    };
 6164
 6165    use super::*;
 6166    use futures::StreamExt;
 6167    use gpui::{
 6168        geometry::rect::RectF,
 6169        platform::{WindowBounds, WindowOptions},
 6170    };
 6171    use indoc::indoc;
 6172    use language::{FakeLspAdapter, LanguageConfig};
 6173    use lsp::FakeLanguageServer;
 6174    use project::FakeFs;
 6175    use settings::LanguageSettings;
 6176    use std::{cell::RefCell, rc::Rc, time::Instant};
 6177    use text::Point;
 6178    use unindent::Unindent;
 6179    use util::{
 6180        assert_set_eq,
 6181        test::{marked_text_by, marked_text_ranges, marked_text_ranges_by, sample_text},
 6182    };
 6183    use workspace::{FollowableItem, ItemHandle};
 6184
 6185    #[gpui::test]
 6186    fn test_edit_events(cx: &mut MutableAppContext) {
 6187        cx.set_global(Settings::test(cx));
 6188        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6189
 6190        let events = Rc::new(RefCell::new(Vec::new()));
 6191        let (_, editor1) = cx.add_window(Default::default(), {
 6192            let events = events.clone();
 6193            |cx| {
 6194                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6195                    if matches!(
 6196                        event,
 6197                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6198                    ) {
 6199                        events.borrow_mut().push(("editor1", *event));
 6200                    }
 6201                })
 6202                .detach();
 6203                Editor::for_buffer(buffer.clone(), None, cx)
 6204            }
 6205        });
 6206        let (_, editor2) = cx.add_window(Default::default(), {
 6207            let events = events.clone();
 6208            |cx| {
 6209                cx.subscribe(&cx.handle(), move |_, _, event, _| {
 6210                    if matches!(
 6211                        event,
 6212                        Event::Edited | Event::BufferEdited | Event::DirtyChanged
 6213                    ) {
 6214                        events.borrow_mut().push(("editor2", *event));
 6215                    }
 6216                })
 6217                .detach();
 6218                Editor::for_buffer(buffer.clone(), None, cx)
 6219            }
 6220        });
 6221        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6222
 6223        // Mutating editor 1 will emit an `Edited` event only for that editor.
 6224        editor1.update(cx, |editor, cx| editor.insert("X", cx));
 6225        assert_eq!(
 6226            mem::take(&mut *events.borrow_mut()),
 6227            [
 6228                ("editor1", Event::Edited),
 6229                ("editor1", Event::BufferEdited),
 6230                ("editor2", Event::BufferEdited),
 6231                ("editor1", Event::DirtyChanged),
 6232                ("editor2", Event::DirtyChanged)
 6233            ]
 6234        );
 6235
 6236        // Mutating editor 2 will emit an `Edited` event only for that editor.
 6237        editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
 6238        assert_eq!(
 6239            mem::take(&mut *events.borrow_mut()),
 6240            [
 6241                ("editor2", Event::Edited),
 6242                ("editor1", Event::BufferEdited),
 6243                ("editor2", Event::BufferEdited),
 6244            ]
 6245        );
 6246
 6247        // Undoing on editor 1 will emit an `Edited` event only for that editor.
 6248        editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6249        assert_eq!(
 6250            mem::take(&mut *events.borrow_mut()),
 6251            [
 6252                ("editor1", Event::Edited),
 6253                ("editor1", Event::BufferEdited),
 6254                ("editor2", Event::BufferEdited),
 6255                ("editor1", Event::DirtyChanged),
 6256                ("editor2", Event::DirtyChanged),
 6257            ]
 6258        );
 6259
 6260        // Redoing on editor 1 will emit an `Edited` event only for that editor.
 6261        editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6262        assert_eq!(
 6263            mem::take(&mut *events.borrow_mut()),
 6264            [
 6265                ("editor1", Event::Edited),
 6266                ("editor1", Event::BufferEdited),
 6267                ("editor2", Event::BufferEdited),
 6268                ("editor1", Event::DirtyChanged),
 6269                ("editor2", Event::DirtyChanged),
 6270            ]
 6271        );
 6272
 6273        // Undoing on editor 2 will emit an `Edited` event only for that editor.
 6274        editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
 6275        assert_eq!(
 6276            mem::take(&mut *events.borrow_mut()),
 6277            [
 6278                ("editor2", Event::Edited),
 6279                ("editor1", Event::BufferEdited),
 6280                ("editor2", Event::BufferEdited),
 6281                ("editor1", Event::DirtyChanged),
 6282                ("editor2", Event::DirtyChanged),
 6283            ]
 6284        );
 6285
 6286        // Redoing on editor 2 will emit an `Edited` event only for that editor.
 6287        editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
 6288        assert_eq!(
 6289            mem::take(&mut *events.borrow_mut()),
 6290            [
 6291                ("editor2", Event::Edited),
 6292                ("editor1", Event::BufferEdited),
 6293                ("editor2", Event::BufferEdited),
 6294                ("editor1", Event::DirtyChanged),
 6295                ("editor2", Event::DirtyChanged),
 6296            ]
 6297        );
 6298
 6299        // No event is emitted when the mutation is a no-op.
 6300        editor2.update(cx, |editor, cx| {
 6301            editor.change_selections(None, cx, |s| s.select_ranges([0..0]));
 6302
 6303            editor.backspace(&Backspace, cx);
 6304        });
 6305        assert_eq!(mem::take(&mut *events.borrow_mut()), []);
 6306    }
 6307
 6308    #[gpui::test]
 6309    fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
 6310        cx.set_global(Settings::test(cx));
 6311        let mut now = Instant::now();
 6312        let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
 6313        let group_interval = buffer.read(cx).transaction_group_interval();
 6314        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 6315        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6316
 6317        editor.update(cx, |editor, cx| {
 6318            editor.start_transaction_at(now, cx);
 6319            editor.change_selections(None, cx, |s| s.select_ranges([2..4]));
 6320
 6321            editor.insert("cd", cx);
 6322            editor.end_transaction_at(now, cx);
 6323            assert_eq!(editor.text(cx), "12cd56");
 6324            assert_eq!(editor.selections.ranges(cx), vec![4..4]);
 6325
 6326            editor.start_transaction_at(now, cx);
 6327            editor.change_selections(None, cx, |s| s.select_ranges([4..5]));
 6328            editor.insert("e", cx);
 6329            editor.end_transaction_at(now, cx);
 6330            assert_eq!(editor.text(cx), "12cde6");
 6331            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6332
 6333            now += group_interval + Duration::from_millis(1);
 6334            editor.change_selections(None, cx, |s| s.select_ranges([2..2]));
 6335
 6336            // Simulate an edit in another editor
 6337            buffer.update(cx, |buffer, cx| {
 6338                buffer.start_transaction_at(now, cx);
 6339                buffer.edit([(0..1, "a")], cx);
 6340                buffer.edit([(1..1, "b")], cx);
 6341                buffer.end_transaction_at(now, cx);
 6342            });
 6343
 6344            assert_eq!(editor.text(cx), "ab2cde6");
 6345            assert_eq!(editor.selections.ranges(cx), vec![3..3]);
 6346
 6347            // Last transaction happened past the group interval in a different editor.
 6348            // Undo it individually and don't restore selections.
 6349            editor.undo(&Undo, cx);
 6350            assert_eq!(editor.text(cx), "12cde6");
 6351            assert_eq!(editor.selections.ranges(cx), vec![2..2]);
 6352
 6353            // First two transactions happened within the group interval in this editor.
 6354            // Undo them together and restore selections.
 6355            editor.undo(&Undo, cx);
 6356            editor.undo(&Undo, cx); // Undo stack is empty here, so this is a no-op.
 6357            assert_eq!(editor.text(cx), "123456");
 6358            assert_eq!(editor.selections.ranges(cx), vec![0..0]);
 6359
 6360            // Redo the first two transactions together.
 6361            editor.redo(&Redo, cx);
 6362            assert_eq!(editor.text(cx), "12cde6");
 6363            assert_eq!(editor.selections.ranges(cx), vec![5..5]);
 6364
 6365            // Redo the last transaction on its own.
 6366            editor.redo(&Redo, cx);
 6367            assert_eq!(editor.text(cx), "ab2cde6");
 6368            assert_eq!(editor.selections.ranges(cx), vec![6..6]);
 6369
 6370            // Test empty transactions.
 6371            editor.start_transaction_at(now, cx);
 6372            editor.end_transaction_at(now, cx);
 6373            editor.undo(&Undo, cx);
 6374            assert_eq!(editor.text(cx), "12cde6");
 6375        });
 6376    }
 6377
 6378    #[gpui::test]
 6379    fn test_selection_with_mouse(cx: &mut gpui::MutableAppContext) {
 6380        cx.set_global(Settings::test(cx));
 6381
 6382        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
 6383        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6384        editor.update(cx, |view, cx| {
 6385            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6386        });
 6387        assert_eq!(
 6388            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6389            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6390        );
 6391
 6392        editor.update(cx, |view, cx| {
 6393            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6394        });
 6395
 6396        assert_eq!(
 6397            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6398            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6399        );
 6400
 6401        editor.update(cx, |view, cx| {
 6402            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6403        });
 6404
 6405        assert_eq!(
 6406            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6407            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6408        );
 6409
 6410        editor.update(cx, |view, cx| {
 6411            view.end_selection(cx);
 6412            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6413        });
 6414
 6415        assert_eq!(
 6416            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6417            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
 6418        );
 6419
 6420        editor.update(cx, |view, cx| {
 6421            view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
 6422            view.update_selection(DisplayPoint::new(0, 0), 0, Vector2F::zero(), cx);
 6423        });
 6424
 6425        assert_eq!(
 6426            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6427            [
 6428                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
 6429                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
 6430            ]
 6431        );
 6432
 6433        editor.update(cx, |view, cx| {
 6434            view.end_selection(cx);
 6435        });
 6436
 6437        assert_eq!(
 6438            editor.update(cx, |view, cx| view.selections.display_ranges(cx)),
 6439            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
 6440        );
 6441    }
 6442
 6443    #[gpui::test]
 6444    fn test_canceling_pending_selection(cx: &mut gpui::MutableAppContext) {
 6445        cx.set_global(Settings::test(cx));
 6446        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6447        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6448
 6449        view.update(cx, |view, cx| {
 6450            view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
 6451            assert_eq!(
 6452                view.selections.display_ranges(cx),
 6453                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
 6454            );
 6455        });
 6456
 6457        view.update(cx, |view, cx| {
 6458            view.update_selection(DisplayPoint::new(3, 3), 0, Vector2F::zero(), cx);
 6459            assert_eq!(
 6460                view.selections.display_ranges(cx),
 6461                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6462            );
 6463        });
 6464
 6465        view.update(cx, |view, cx| {
 6466            view.cancel(&Cancel, cx);
 6467            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6468            assert_eq!(
 6469                view.selections.display_ranges(cx),
 6470                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
 6471            );
 6472        });
 6473    }
 6474
 6475    #[gpui::test]
 6476    fn test_clone(cx: &mut gpui::MutableAppContext) {
 6477        let (text, selection_ranges) = marked_text_ranges(indoc! {"
 6478            one
 6479            two
 6480            three[]
 6481            four
 6482            five[]
 6483        "});
 6484        cx.set_global(Settings::test(cx));
 6485        let buffer = MultiBuffer::build_simple(&text, cx);
 6486
 6487        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6488
 6489        editor.update(cx, |editor, cx| {
 6490            editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
 6491            editor.fold_ranges(
 6492                [
 6493                    Point::new(1, 0)..Point::new(2, 0),
 6494                    Point::new(3, 0)..Point::new(4, 0),
 6495                ],
 6496                cx,
 6497            );
 6498        });
 6499
 6500        let (_, cloned_editor) = editor.update(cx, |editor, cx| {
 6501            cx.add_window(Default::default(), |cx| editor.clone(cx))
 6502        });
 6503
 6504        let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
 6505        let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
 6506
 6507        assert_eq!(
 6508            cloned_editor.update(cx, |e, cx| e.display_text(cx)),
 6509            editor.update(cx, |e, cx| e.display_text(cx))
 6510        );
 6511        assert_eq!(
 6512            cloned_snapshot
 6513                .folds_in_range(0..text.len())
 6514                .collect::<Vec<_>>(),
 6515            snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
 6516        );
 6517        assert_set_eq!(
 6518            cloned_editor.read(cx).selections.ranges::<Point>(cx),
 6519            editor.read(cx).selections.ranges(cx)
 6520        );
 6521        assert_set_eq!(
 6522            cloned_editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx))),
 6523            editor.update(cx, |e, cx| dbg!(e.selections.display_ranges(cx)))
 6524        );
 6525    }
 6526
 6527    #[gpui::test]
 6528    fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
 6529        cx.set_global(Settings::test(cx));
 6530        use workspace::Item;
 6531        let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
 6532        let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
 6533
 6534        cx.add_window(Default::default(), |cx| {
 6535            let mut editor = build_editor(buffer.clone(), cx);
 6536            editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
 6537
 6538            // Move the cursor a small distance.
 6539            // Nothing is added to the navigation history.
 6540            editor.change_selections(None, cx, |s| {
 6541                s.select_display_ranges([DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)])
 6542            });
 6543            editor.change_selections(None, cx, |s| {
 6544                s.select_display_ranges([DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)])
 6545            });
 6546            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6547
 6548            // Move the cursor a large distance.
 6549            // The history can jump back to the previous position.
 6550            editor.change_selections(None, cx, |s| {
 6551                s.select_display_ranges([DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)])
 6552            });
 6553            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6554            editor.navigate(nav_entry.data.unwrap(), cx);
 6555            assert_eq!(nav_entry.item.id(), cx.view_id());
 6556            assert_eq!(
 6557                editor.selections.display_ranges(cx),
 6558                &[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)]
 6559            );
 6560            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6561
 6562            // Move the cursor a small distance via the mouse.
 6563            // Nothing is added to the navigation history.
 6564            editor.begin_selection(DisplayPoint::new(5, 0), false, 1, cx);
 6565            editor.end_selection(cx);
 6566            assert_eq!(
 6567                editor.selections.display_ranges(cx),
 6568                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6569            );
 6570            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6571
 6572            // Move the cursor a large distance via the mouse.
 6573            // The history can jump back to the previous position.
 6574            editor.begin_selection(DisplayPoint::new(15, 0), false, 1, cx);
 6575            editor.end_selection(cx);
 6576            assert_eq!(
 6577                editor.selections.display_ranges(cx),
 6578                &[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
 6579            );
 6580            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6581            editor.navigate(nav_entry.data.unwrap(), cx);
 6582            assert_eq!(nav_entry.item.id(), cx.view_id());
 6583            assert_eq!(
 6584                editor.selections.display_ranges(cx),
 6585                &[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
 6586            );
 6587            assert!(nav_history.borrow_mut().pop_backward().is_none());
 6588
 6589            // Set scroll position to check later
 6590            editor.set_scroll_position(Vector2F::new(5.5, 5.5), cx);
 6591            let original_scroll_position = editor.scroll_position;
 6592            let original_scroll_top_anchor = editor.scroll_top_anchor.clone();
 6593
 6594            // Jump to the end of the document and adjust scroll
 6595            editor.move_to_end(&MoveToEnd, cx);
 6596            editor.set_scroll_position(Vector2F::new(-2.5, -0.5), cx);
 6597            assert_ne!(editor.scroll_position, original_scroll_position);
 6598            assert_ne!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6599
 6600            let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
 6601            editor.navigate(nav_entry.data.unwrap(), cx);
 6602            assert_eq!(editor.scroll_position, original_scroll_position);
 6603            assert_eq!(editor.scroll_top_anchor, original_scroll_top_anchor);
 6604
 6605            // Ensure we don't panic when navigation data contains invalid anchors *and* points.
 6606            let mut invalid_anchor = editor.scroll_top_anchor.clone();
 6607            invalid_anchor.text_anchor.buffer_id = Some(999);
 6608            let invalid_point = Point::new(9999, 0);
 6609            editor.navigate(
 6610                Box::new(NavigationData {
 6611                    cursor_anchor: invalid_anchor.clone(),
 6612                    cursor_position: invalid_point,
 6613                    scroll_top_anchor: invalid_anchor.clone(),
 6614                    scroll_top_row: invalid_point.row,
 6615                    scroll_position: Default::default(),
 6616                }),
 6617                cx,
 6618            );
 6619            assert_eq!(
 6620                editor.selections.display_ranges(cx),
 6621                &[editor.max_point(cx)..editor.max_point(cx)]
 6622            );
 6623            assert_eq!(
 6624                editor.scroll_position(cx),
 6625                vec2f(0., editor.max_point(cx).row() as f32)
 6626            );
 6627
 6628            editor
 6629        });
 6630    }
 6631
 6632    #[gpui::test]
 6633    fn test_cancel(cx: &mut gpui::MutableAppContext) {
 6634        cx.set_global(Settings::test(cx));
 6635        let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
 6636        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6637
 6638        view.update(cx, |view, cx| {
 6639            view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
 6640            view.update_selection(DisplayPoint::new(1, 1), 0, Vector2F::zero(), cx);
 6641            view.end_selection(cx);
 6642
 6643            view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
 6644            view.update_selection(DisplayPoint::new(0, 3), 0, Vector2F::zero(), cx);
 6645            view.end_selection(cx);
 6646            assert_eq!(
 6647                view.selections.display_ranges(cx),
 6648                [
 6649                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 6650                    DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
 6651                ]
 6652            );
 6653        });
 6654
 6655        view.update(cx, |view, cx| {
 6656            view.cancel(&Cancel, cx);
 6657            assert_eq!(
 6658                view.selections.display_ranges(cx),
 6659                [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
 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(1, 1)..DisplayPoint::new(1, 1)]
 6668            );
 6669        });
 6670    }
 6671
 6672    #[gpui::test]
 6673    fn test_fold(cx: &mut gpui::MutableAppContext) {
 6674        cx.set_global(Settings::test(cx));
 6675        let buffer = MultiBuffer::build_simple(
 6676            &"
 6677                impl Foo {
 6678                    // Hello!
 6679
 6680                    fn a() {
 6681                        1
 6682                    }
 6683
 6684                    fn b() {
 6685                        2
 6686                    }
 6687
 6688                    fn c() {
 6689                        3
 6690                    }
 6691                }
 6692            "
 6693            .unindent(),
 6694            cx,
 6695        );
 6696        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6697
 6698        view.update(cx, |view, cx| {
 6699            view.change_selections(None, cx, |s| {
 6700                s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]);
 6701            });
 6702            view.fold(&Fold, cx);
 6703            assert_eq!(
 6704                view.display_text(cx),
 6705                "
 6706                    impl Foo {
 6707                        // Hello!
 6708
 6709                        fn a() {
 6710                            1
 6711                        }
 6712
 6713                        fn b() {…
 6714                        }
 6715
 6716                        fn c() {…
 6717                        }
 6718                    }
 6719                "
 6720                .unindent(),
 6721            );
 6722
 6723            view.fold(&Fold, cx);
 6724            assert_eq!(
 6725                view.display_text(cx),
 6726                "
 6727                    impl Foo {…
 6728                    }
 6729                "
 6730                .unindent(),
 6731            );
 6732
 6733            view.unfold_lines(&UnfoldLines, cx);
 6734            assert_eq!(
 6735                view.display_text(cx),
 6736                "
 6737                    impl Foo {
 6738                        // Hello!
 6739
 6740                        fn a() {
 6741                            1
 6742                        }
 6743
 6744                        fn b() {…
 6745                        }
 6746
 6747                        fn c() {…
 6748                        }
 6749                    }
 6750                "
 6751                .unindent(),
 6752            );
 6753
 6754            view.unfold_lines(&UnfoldLines, cx);
 6755            assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text());
 6756        });
 6757    }
 6758
 6759    #[gpui::test]
 6760    fn test_move_cursor(cx: &mut gpui::MutableAppContext) {
 6761        cx.set_global(Settings::test(cx));
 6762        let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
 6763        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6764
 6765        buffer.update(cx, |buffer, cx| {
 6766            buffer.edit(
 6767                vec![
 6768                    (Point::new(1, 0)..Point::new(1, 0), "\t"),
 6769                    (Point::new(1, 1)..Point::new(1, 1), "\t"),
 6770                ],
 6771                cx,
 6772            );
 6773        });
 6774
 6775        view.update(cx, |view, cx| {
 6776            assert_eq!(
 6777                view.selections.display_ranges(cx),
 6778                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6779            );
 6780
 6781            view.move_down(&MoveDown, cx);
 6782            assert_eq!(
 6783                view.selections.display_ranges(cx),
 6784                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6785            );
 6786
 6787            view.move_right(&MoveRight, cx);
 6788            assert_eq!(
 6789                view.selections.display_ranges(cx),
 6790                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
 6791            );
 6792
 6793            view.move_left(&MoveLeft, cx);
 6794            assert_eq!(
 6795                view.selections.display_ranges(cx),
 6796                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
 6797            );
 6798
 6799            view.move_up(&MoveUp, cx);
 6800            assert_eq!(
 6801                view.selections.display_ranges(cx),
 6802                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6803            );
 6804
 6805            view.move_to_end(&MoveToEnd, cx);
 6806            assert_eq!(
 6807                view.selections.display_ranges(cx),
 6808                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
 6809            );
 6810
 6811            view.move_to_beginning(&MoveToBeginning, cx);
 6812            assert_eq!(
 6813                view.selections.display_ranges(cx),
 6814                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
 6815            );
 6816
 6817            view.change_selections(None, cx, |s| {
 6818                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]);
 6819            });
 6820            view.select_to_beginning(&SelectToBeginning, cx);
 6821            assert_eq!(
 6822                view.selections.display_ranges(cx),
 6823                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
 6824            );
 6825
 6826            view.select_to_end(&SelectToEnd, cx);
 6827            assert_eq!(
 6828                view.selections.display_ranges(cx),
 6829                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
 6830            );
 6831        });
 6832    }
 6833
 6834    #[gpui::test]
 6835    fn test_move_cursor_multibyte(cx: &mut gpui::MutableAppContext) {
 6836        cx.set_global(Settings::test(cx));
 6837        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
 6838        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6839
 6840        assert_eq!('ⓐ'.len_utf8(), 3);
 6841        assert_eq!('α'.len_utf8(), 2);
 6842
 6843        view.update(cx, |view, cx| {
 6844            view.fold_ranges(
 6845                vec![
 6846                    Point::new(0, 6)..Point::new(0, 12),
 6847                    Point::new(1, 2)..Point::new(1, 4),
 6848                    Point::new(2, 4)..Point::new(2, 8),
 6849                ],
 6850                cx,
 6851            );
 6852            assert_eq!(view.display_text(cx), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
 6853
 6854            view.move_right(&MoveRight, cx);
 6855            assert_eq!(
 6856                view.selections.display_ranges(cx),
 6857                &[empty_range(0, "".len())]
 6858            );
 6859            view.move_right(&MoveRight, cx);
 6860            assert_eq!(
 6861                view.selections.display_ranges(cx),
 6862                &[empty_range(0, "ⓐⓑ".len())]
 6863            );
 6864            view.move_right(&MoveRight, cx);
 6865            assert_eq!(
 6866                view.selections.display_ranges(cx),
 6867                &[empty_range(0, "ⓐⓑ…".len())]
 6868            );
 6869
 6870            view.move_down(&MoveDown, cx);
 6871            assert_eq!(
 6872                view.selections.display_ranges(cx),
 6873                &[empty_range(1, "ab…".len())]
 6874            );
 6875            view.move_left(&MoveLeft, cx);
 6876            assert_eq!(
 6877                view.selections.display_ranges(cx),
 6878                &[empty_range(1, "ab".len())]
 6879            );
 6880            view.move_left(&MoveLeft, cx);
 6881            assert_eq!(
 6882                view.selections.display_ranges(cx),
 6883                &[empty_range(1, "a".len())]
 6884            );
 6885
 6886            view.move_down(&MoveDown, cx);
 6887            assert_eq!(
 6888                view.selections.display_ranges(cx),
 6889                &[empty_range(2, "α".len())]
 6890            );
 6891            view.move_right(&MoveRight, cx);
 6892            assert_eq!(
 6893                view.selections.display_ranges(cx),
 6894                &[empty_range(2, "αβ".len())]
 6895            );
 6896            view.move_right(&MoveRight, cx);
 6897            assert_eq!(
 6898                view.selections.display_ranges(cx),
 6899                &[empty_range(2, "αβ…".len())]
 6900            );
 6901            view.move_right(&MoveRight, cx);
 6902            assert_eq!(
 6903                view.selections.display_ranges(cx),
 6904                &[empty_range(2, "αβ…ε".len())]
 6905            );
 6906
 6907            view.move_up(&MoveUp, cx);
 6908            assert_eq!(
 6909                view.selections.display_ranges(cx),
 6910                &[empty_range(1, "ab…e".len())]
 6911            );
 6912            view.move_up(&MoveUp, cx);
 6913            assert_eq!(
 6914                view.selections.display_ranges(cx),
 6915                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
 6916            );
 6917            view.move_left(&MoveLeft, cx);
 6918            assert_eq!(
 6919                view.selections.display_ranges(cx),
 6920                &[empty_range(0, "ⓐⓑ…".len())]
 6921            );
 6922            view.move_left(&MoveLeft, cx);
 6923            assert_eq!(
 6924                view.selections.display_ranges(cx),
 6925                &[empty_range(0, "ⓐⓑ".len())]
 6926            );
 6927            view.move_left(&MoveLeft, cx);
 6928            assert_eq!(
 6929                view.selections.display_ranges(cx),
 6930                &[empty_range(0, "".len())]
 6931            );
 6932        });
 6933    }
 6934
 6935    #[gpui::test]
 6936    fn test_move_cursor_different_line_lengths(cx: &mut gpui::MutableAppContext) {
 6937        cx.set_global(Settings::test(cx));
 6938        let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
 6939        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 6940        view.update(cx, |view, cx| {
 6941            view.change_selections(None, cx, |s| {
 6942                s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
 6943            });
 6944            view.move_down(&MoveDown, cx);
 6945            assert_eq!(
 6946                view.selections.display_ranges(cx),
 6947                &[empty_range(1, "abcd".len())]
 6948            );
 6949
 6950            view.move_down(&MoveDown, cx);
 6951            assert_eq!(
 6952                view.selections.display_ranges(cx),
 6953                &[empty_range(2, "αβγ".len())]
 6954            );
 6955
 6956            view.move_down(&MoveDown, cx);
 6957            assert_eq!(
 6958                view.selections.display_ranges(cx),
 6959                &[empty_range(3, "abcd".len())]
 6960            );
 6961
 6962            view.move_down(&MoveDown, cx);
 6963            assert_eq!(
 6964                view.selections.display_ranges(cx),
 6965                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
 6966            );
 6967
 6968            view.move_up(&MoveUp, cx);
 6969            assert_eq!(
 6970                view.selections.display_ranges(cx),
 6971                &[empty_range(3, "abcd".len())]
 6972            );
 6973
 6974            view.move_up(&MoveUp, cx);
 6975            assert_eq!(
 6976                view.selections.display_ranges(cx),
 6977                &[empty_range(2, "αβγ".len())]
 6978            );
 6979        });
 6980    }
 6981
 6982    #[gpui::test]
 6983    fn test_beginning_end_of_line(cx: &mut gpui::MutableAppContext) {
 6984        cx.set_global(Settings::test(cx));
 6985        let buffer = MultiBuffer::build_simple("abc\n  def", cx);
 6986        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 6987        view.update(cx, |view, cx| {
 6988            view.change_selections(None, cx, |s| {
 6989                s.select_display_ranges([
 6990                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 6991                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 6992                ]);
 6993            });
 6994        });
 6995
 6996        view.update(cx, |view, cx| {
 6997            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 6998            assert_eq!(
 6999                view.selections.display_ranges(cx),
 7000                &[
 7001                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7002                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7003                ]
 7004            );
 7005        });
 7006
 7007        view.update(cx, |view, cx| {
 7008            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7009            assert_eq!(
 7010                view.selections.display_ranges(cx),
 7011                &[
 7012                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7013                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7014                ]
 7015            );
 7016        });
 7017
 7018        view.update(cx, |view, cx| {
 7019            view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx);
 7020            assert_eq!(
 7021                view.selections.display_ranges(cx),
 7022                &[
 7023                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7024                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7025                ]
 7026            );
 7027        });
 7028
 7029        view.update(cx, |view, cx| {
 7030            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7031            assert_eq!(
 7032                view.selections.display_ranges(cx),
 7033                &[
 7034                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7035                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7036                ]
 7037            );
 7038        });
 7039
 7040        // Moving to the end of line again is a no-op.
 7041        view.update(cx, |view, cx| {
 7042            view.move_to_end_of_line(&MoveToEndOfLine, cx);
 7043            assert_eq!(
 7044                view.selections.display_ranges(cx),
 7045                &[
 7046                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7047                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 7048                ]
 7049            );
 7050        });
 7051
 7052        view.update(cx, |view, cx| {
 7053            view.move_left(&MoveLeft, cx);
 7054            view.select_to_beginning_of_line(
 7055                &SelectToBeginningOfLine {
 7056                    stop_at_soft_wraps: true,
 7057                },
 7058                cx,
 7059            );
 7060            assert_eq!(
 7061                view.selections.display_ranges(cx),
 7062                &[
 7063                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7064                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7065                ]
 7066            );
 7067        });
 7068
 7069        view.update(cx, |view, cx| {
 7070            view.select_to_beginning_of_line(
 7071                &SelectToBeginningOfLine {
 7072                    stop_at_soft_wraps: true,
 7073                },
 7074                cx,
 7075            );
 7076            assert_eq!(
 7077                view.selections.display_ranges(cx),
 7078                &[
 7079                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7080                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
 7081                ]
 7082            );
 7083        });
 7084
 7085        view.update(cx, |view, cx| {
 7086            view.select_to_beginning_of_line(
 7087                &SelectToBeginningOfLine {
 7088                    stop_at_soft_wraps: true,
 7089                },
 7090                cx,
 7091            );
 7092            assert_eq!(
 7093                view.selections.display_ranges(cx),
 7094                &[
 7095                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
 7096                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
 7097                ]
 7098            );
 7099        });
 7100
 7101        view.update(cx, |view, cx| {
 7102            view.select_to_end_of_line(
 7103                &SelectToEndOfLine {
 7104                    stop_at_soft_wraps: true,
 7105                },
 7106                cx,
 7107            );
 7108            assert_eq!(
 7109                view.selections.display_ranges(cx),
 7110                &[
 7111                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 7112                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
 7113                ]
 7114            );
 7115        });
 7116
 7117        view.update(cx, |view, cx| {
 7118            view.delete_to_end_of_line(&DeleteToEndOfLine, cx);
 7119            assert_eq!(view.display_text(cx), "ab\n  de");
 7120            assert_eq!(
 7121                view.selections.display_ranges(cx),
 7122                &[
 7123                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7124                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
 7125                ]
 7126            );
 7127        });
 7128
 7129        view.update(cx, |view, cx| {
 7130            view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7131            assert_eq!(view.display_text(cx), "\n");
 7132            assert_eq!(
 7133                view.selections.display_ranges(cx),
 7134                &[
 7135                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7136                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7137                ]
 7138            );
 7139        });
 7140    }
 7141
 7142    #[gpui::test]
 7143    fn test_prev_next_word_boundary(cx: &mut gpui::MutableAppContext) {
 7144        cx.set_global(Settings::test(cx));
 7145        let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n  {baz.qux()}", cx);
 7146        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7147        view.update(cx, |view, cx| {
 7148            view.change_selections(None, cx, |s| {
 7149                s.select_display_ranges([
 7150                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
 7151                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
 7152                ])
 7153            });
 7154
 7155            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7156            assert_selection_ranges(
 7157                "use std::<>str::{foo, bar}\n\n  {[]baz.qux()}",
 7158                vec![('<', '>'), ('[', ']')],
 7159                view,
 7160                cx,
 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_next_word_end(&MoveToNextWordEnd, 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_right(&MoveRight, cx);
 7220            view.select_to_previous_word_start(&SelectToPreviousWordStart, cx);
 7221            assert_selection_ranges(
 7222                "use std::>s<tr::{foo, bar}\n\n  {]b[az.qux()}",
 7223                vec![('<', '>'), ('[', ']')],
 7224                view,
 7225                cx,
 7226            );
 7227
 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_next_word_end(&SelectToNextWordEnd, 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    }
 7245
 7246    #[gpui::test]
 7247    fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut gpui::MutableAppContext) {
 7248        cx.set_global(Settings::test(cx));
 7249        let buffer = MultiBuffer::build_simple("use one::{\n    two::three::four::five\n};", cx);
 7250        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7251
 7252        view.update(cx, |view, cx| {
 7253            view.set_wrap_width(Some(140.), cx);
 7254            assert_eq!(
 7255                view.display_text(cx),
 7256                "use one::{\n    two::three::\n    four::five\n};"
 7257            );
 7258
 7259            view.change_selections(None, cx, |s| {
 7260                s.select_display_ranges([DisplayPoint::new(1, 7)..DisplayPoint::new(1, 7)]);
 7261            });
 7262
 7263            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7264            assert_eq!(
 7265                view.selections.display_ranges(cx),
 7266                &[DisplayPoint::new(1, 9)..DisplayPoint::new(1, 9)]
 7267            );
 7268
 7269            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7270            assert_eq!(
 7271                view.selections.display_ranges(cx),
 7272                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7273            );
 7274
 7275            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7276            assert_eq!(
 7277                view.selections.display_ranges(cx),
 7278                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7279            );
 7280
 7281            view.move_to_next_word_end(&MoveToNextWordEnd, cx);
 7282            assert_eq!(
 7283                view.selections.display_ranges(cx),
 7284                &[DisplayPoint::new(2, 8)..DisplayPoint::new(2, 8)]
 7285            );
 7286
 7287            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7288            assert_eq!(
 7289                view.selections.display_ranges(cx),
 7290                &[DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4)]
 7291            );
 7292
 7293            view.move_to_previous_word_start(&MoveToPreviousWordStart, cx);
 7294            assert_eq!(
 7295                view.selections.display_ranges(cx),
 7296                &[DisplayPoint::new(1, 14)..DisplayPoint::new(1, 14)]
 7297            );
 7298        });
 7299    }
 7300
 7301    #[gpui::test]
 7302    fn test_delete_to_beginning_of_line(cx: &mut gpui::MutableAppContext) {
 7303        cx.set_global(Settings::test(cx));
 7304        let (text, ranges) = marked_text_ranges("one [two three] four");
 7305        let buffer = MultiBuffer::build_simple(&text, cx);
 7306
 7307        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7308
 7309        editor.update(cx, |editor, cx| {
 7310            editor.change_selections(None, cx, |s| s.select_ranges(ranges));
 7311            editor.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx);
 7312            assert_eq!(editor.text(cx), " four");
 7313        });
 7314    }
 7315
 7316    #[gpui::test]
 7317    fn test_delete_to_word_boundary(cx: &mut gpui::MutableAppContext) {
 7318        cx.set_global(Settings::test(cx));
 7319        let buffer = MultiBuffer::build_simple("one two three four", cx);
 7320        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7321
 7322        view.update(cx, |view, cx| {
 7323            view.change_selections(None, cx, |s| {
 7324                s.select_display_ranges([
 7325                    // an empty selection - the preceding word fragment is deleted
 7326                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7327                    // characters selected - they are deleted
 7328                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 12),
 7329                ])
 7330            });
 7331            view.delete_to_previous_word_start(&DeleteToPreviousWordStart, cx);
 7332        });
 7333
 7334        assert_eq!(buffer.read(cx).read(cx).text(), "e two te four");
 7335
 7336        view.update(cx, |view, cx| {
 7337            view.change_selections(None, cx, |s| {
 7338                s.select_display_ranges([
 7339                    // an empty selection - the following word fragment is deleted
 7340                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 7341                    // characters selected - they are deleted
 7342                    DisplayPoint::new(0, 9)..DisplayPoint::new(0, 10),
 7343                ])
 7344            });
 7345            view.delete_to_next_word_end(&DeleteToNextWordEnd, cx);
 7346        });
 7347
 7348        assert_eq!(buffer.read(cx).read(cx).text(), "e t te our");
 7349    }
 7350
 7351    #[gpui::test]
 7352    fn test_newline(cx: &mut gpui::MutableAppContext) {
 7353        cx.set_global(Settings::test(cx));
 7354        let buffer = MultiBuffer::build_simple("aaaa\n    bbbb\n", cx);
 7355        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 7356
 7357        view.update(cx, |view, cx| {
 7358            view.change_selections(None, cx, |s| {
 7359                s.select_display_ranges([
 7360                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7361                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7362                    DisplayPoint::new(1, 6)..DisplayPoint::new(1, 6),
 7363                ])
 7364            });
 7365
 7366            view.newline(&Newline, cx);
 7367            assert_eq!(view.text(cx), "aa\naa\n  \n    bb\n    bb\n");
 7368        });
 7369    }
 7370
 7371    #[gpui::test]
 7372    fn test_newline_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7373        cx.set_global(Settings::test(cx));
 7374        let buffer = MultiBuffer::build_simple(
 7375            "
 7376                a
 7377                b(
 7378                    X
 7379                )
 7380                c(
 7381                    X
 7382                )
 7383            "
 7384            .unindent()
 7385            .as_str(),
 7386            cx,
 7387        );
 7388
 7389        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7390            let mut editor = build_editor(buffer.clone(), cx);
 7391            editor.change_selections(None, cx, |s| {
 7392                s.select_ranges([
 7393                    Point::new(2, 4)..Point::new(2, 5),
 7394                    Point::new(5, 4)..Point::new(5, 5),
 7395                ])
 7396            });
 7397            editor
 7398        });
 7399
 7400        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7401        buffer.update(cx, |buffer, cx| {
 7402            buffer.edit(
 7403                [
 7404                    (Point::new(1, 2)..Point::new(3, 0), ""),
 7405                    (Point::new(4, 2)..Point::new(6, 0), ""),
 7406                ],
 7407                cx,
 7408            );
 7409            assert_eq!(
 7410                buffer.read(cx).text(),
 7411                "
 7412                    a
 7413                    b()
 7414                    c()
 7415                "
 7416                .unindent()
 7417            );
 7418        });
 7419
 7420        editor.update(cx, |editor, cx| {
 7421            assert_eq!(
 7422                editor.selections.ranges(cx),
 7423                &[
 7424                    Point::new(1, 2)..Point::new(1, 2),
 7425                    Point::new(2, 2)..Point::new(2, 2),
 7426                ],
 7427            );
 7428
 7429            editor.newline(&Newline, cx);
 7430            assert_eq!(
 7431                editor.text(cx),
 7432                "
 7433                    a
 7434                    b(
 7435                    )
 7436                    c(
 7437                    )
 7438                "
 7439                .unindent()
 7440            );
 7441
 7442            // The selections are moved after the inserted newlines
 7443            assert_eq!(
 7444                editor.selections.ranges(cx),
 7445                &[
 7446                    Point::new(2, 0)..Point::new(2, 0),
 7447                    Point::new(4, 0)..Point::new(4, 0),
 7448                ],
 7449            );
 7450        });
 7451    }
 7452
 7453    #[gpui::test]
 7454    fn test_insert_with_old_selections(cx: &mut gpui::MutableAppContext) {
 7455        cx.set_global(Settings::test(cx));
 7456        let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
 7457        let (_, editor) = cx.add_window(Default::default(), |cx| {
 7458            let mut editor = build_editor(buffer.clone(), cx);
 7459            editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
 7460            editor
 7461        });
 7462
 7463        // Edit the buffer directly, deleting ranges surrounding the editor's selections
 7464        buffer.update(cx, |buffer, cx| {
 7465            buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], cx);
 7466            assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
 7467        });
 7468
 7469        editor.update(cx, |editor, cx| {
 7470            assert_eq!(editor.selections.ranges(cx), &[2..2, 7..7, 12..12],);
 7471
 7472            editor.insert("Z", cx);
 7473            assert_eq!(editor.text(cx), "a(Z), b(Z), c(Z)");
 7474
 7475            // The selections are moved after the inserted characters
 7476            assert_eq!(editor.selections.ranges(cx), &[3..3, 9..9, 15..15],);
 7477        });
 7478    }
 7479
 7480    #[gpui::test]
 7481    async fn test_indent_outdent(cx: &mut gpui::TestAppContext) {
 7482        let mut cx = EditorTestContext::new(cx).await;
 7483
 7484        cx.set_state(indoc! {"
 7485              [one} [two}
 7486            three
 7487             four"});
 7488        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7489        cx.assert_editor_state(indoc! {"
 7490                [one} [two}
 7491            three
 7492             four"});
 7493
 7494        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7495        cx.assert_editor_state(indoc! {"
 7496            [one} [two}
 7497            three
 7498             four"});
 7499
 7500        // select across line ending
 7501        cx.set_state(indoc! {"
 7502            one two
 7503            t[hree
 7504            } four"});
 7505        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7506        cx.assert_editor_state(indoc! {"
 7507            one two
 7508                t[hree
 7509            } four"});
 7510
 7511        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7512        cx.assert_editor_state(indoc! {"
 7513            one two
 7514            t[hree
 7515            } four"});
 7516
 7517        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7518        cx.set_state(indoc! {"
 7519            one two
 7520            |three
 7521                four"});
 7522        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7523        cx.assert_editor_state(indoc! {"
 7524            one two
 7525                |three
 7526                four"});
 7527
 7528        cx.set_state(indoc! {"
 7529            one two
 7530            |    three
 7531             four"});
 7532        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7533        cx.assert_editor_state(indoc! {"
 7534            one two
 7535            |three
 7536             four"});
 7537    }
 7538
 7539    #[gpui::test]
 7540    async fn test_indent_outdent_with_hard_tabs(cx: &mut gpui::TestAppContext) {
 7541        let mut cx = EditorTestContext::new(cx).await;
 7542        cx.update(|cx| {
 7543            cx.update_global::<Settings, _, _>(|settings, _| {
 7544                settings.language_settings.hard_tabs = Some(true);
 7545            });
 7546        });
 7547
 7548        // select two ranges on one line
 7549        cx.set_state(indoc! {"
 7550            [one} [two}
 7551            three
 7552            four"});
 7553        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7554        cx.assert_editor_state(indoc! {"
 7555            \t[one} [two}
 7556            three
 7557            four"});
 7558        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7559        cx.assert_editor_state(indoc! {"
 7560            \t\t[one} [two}
 7561            three
 7562            four"});
 7563        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7564        cx.assert_editor_state(indoc! {"
 7565            \t[one} [two}
 7566            three
 7567            four"});
 7568        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7569        cx.assert_editor_state(indoc! {"
 7570            [one} [two}
 7571            three
 7572            four"});
 7573
 7574        // select across a line ending
 7575        cx.set_state(indoc! {"
 7576            one two
 7577            t[hree
 7578            }four"});
 7579        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7580        cx.assert_editor_state(indoc! {"
 7581            one two
 7582            \tt[hree
 7583            }four"});
 7584        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7585        cx.assert_editor_state(indoc! {"
 7586            one two
 7587            \t\tt[hree
 7588            }four"});
 7589        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7590        cx.assert_editor_state(indoc! {"
 7591            one two
 7592            \tt[hree
 7593            }four"});
 7594        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7595        cx.assert_editor_state(indoc! {"
 7596            one two
 7597            t[hree
 7598            }four"});
 7599
 7600        // Ensure that indenting/outdenting works when the cursor is at column 0.
 7601        cx.set_state(indoc! {"
 7602            one two
 7603            |three
 7604            four"});
 7605        cx.assert_editor_state(indoc! {"
 7606            one two
 7607            |three
 7608            four"});
 7609        cx.update_editor(|e, cx| e.tab(&Tab, cx));
 7610        cx.assert_editor_state(indoc! {"
 7611            one two
 7612            \t|three
 7613            four"});
 7614        cx.update_editor(|e, cx| e.tab_prev(&TabPrev, cx));
 7615        cx.assert_editor_state(indoc! {"
 7616            one two
 7617            |three
 7618            four"});
 7619    }
 7620
 7621    #[gpui::test]
 7622    fn test_indent_outdent_with_excerpts(cx: &mut gpui::MutableAppContext) {
 7623        cx.set_global(
 7624            Settings::test(cx)
 7625                .with_language_defaults(
 7626                    "TOML",
 7627                    LanguageSettings {
 7628                        tab_size: Some(2.try_into().unwrap()),
 7629                        ..Default::default()
 7630                    },
 7631                )
 7632                .with_language_defaults(
 7633                    "Rust",
 7634                    LanguageSettings {
 7635                        tab_size: Some(4.try_into().unwrap()),
 7636                        ..Default::default()
 7637                    },
 7638                ),
 7639        );
 7640        let toml_language = Arc::new(Language::new(
 7641            LanguageConfig {
 7642                name: "TOML".into(),
 7643                ..Default::default()
 7644            },
 7645            None,
 7646        ));
 7647        let rust_language = Arc::new(Language::new(
 7648            LanguageConfig {
 7649                name: "Rust".into(),
 7650                ..Default::default()
 7651            },
 7652            None,
 7653        ));
 7654
 7655        let toml_buffer = cx
 7656            .add_model(|cx| Buffer::new(0, "a = 1\nb = 2\n", cx).with_language(toml_language, cx));
 7657        let rust_buffer = cx.add_model(|cx| {
 7658            Buffer::new(0, "const c: usize = 3;\n", cx).with_language(rust_language, cx)
 7659        });
 7660        let multibuffer = cx.add_model(|cx| {
 7661            let mut multibuffer = MultiBuffer::new(0);
 7662            multibuffer.push_excerpts(
 7663                toml_buffer.clone(),
 7664                [ExcerptRange {
 7665                    context: Point::new(0, 0)..Point::new(2, 0),
 7666                    primary: None,
 7667                }],
 7668                cx,
 7669            );
 7670            multibuffer.push_excerpts(
 7671                rust_buffer.clone(),
 7672                [ExcerptRange {
 7673                    context: Point::new(0, 0)..Point::new(1, 0),
 7674                    primary: None,
 7675                }],
 7676                cx,
 7677            );
 7678            multibuffer
 7679        });
 7680
 7681        cx.add_window(Default::default(), |cx| {
 7682            let mut editor = build_editor(multibuffer, cx);
 7683
 7684            assert_eq!(
 7685                editor.text(cx),
 7686                indoc! {"
 7687                    a = 1
 7688                    b = 2
 7689
 7690                    const c: usize = 3;
 7691                "}
 7692            );
 7693
 7694            select_ranges(
 7695                &mut editor,
 7696                indoc! {"
 7697                    [a] = 1
 7698                    b = 2
 7699
 7700                    [const c:] usize = 3;
 7701                "},
 7702                cx,
 7703            );
 7704
 7705            editor.tab(&Tab, cx);
 7706            assert_text_with_selections(
 7707                &mut editor,
 7708                indoc! {"
 7709                      [a] = 1
 7710                    b = 2
 7711
 7712                        [const c:] usize = 3;
 7713                "},
 7714                cx,
 7715            );
 7716            editor.tab_prev(&TabPrev, cx);
 7717            assert_text_with_selections(
 7718                &mut editor,
 7719                indoc! {"
 7720                    [a] = 1
 7721                    b = 2
 7722
 7723                    [const c:] usize = 3;
 7724                "},
 7725                cx,
 7726            );
 7727
 7728            editor
 7729        });
 7730    }
 7731
 7732    #[gpui::test]
 7733    async fn test_backspace(cx: &mut gpui::TestAppContext) {
 7734        let mut cx = EditorTestContext::new(cx).await;
 7735        // Basic backspace
 7736        cx.set_state(indoc! {"
 7737            on|e two three
 7738            fou[r} five six
 7739            seven {eight nine
 7740            ]ten"});
 7741        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7742        cx.assert_editor_state(indoc! {"
 7743            o|e two three
 7744            fou| five six
 7745            seven |ten"});
 7746
 7747        // Test backspace inside and around indents
 7748        cx.set_state(indoc! {"
 7749            zero
 7750                |one
 7751                    |two
 7752                | | |  three
 7753            |  |  four"});
 7754        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7755        cx.assert_editor_state(indoc! {"
 7756            zero
 7757            |one
 7758                |two
 7759            |  three|  four"});
 7760
 7761        // Test backspace with line_mode set to true
 7762        cx.update_editor(|e, _| e.selections.line_mode = true);
 7763        cx.set_state(indoc! {"
 7764            The |quick |brown
 7765            fox jumps over
 7766            the lazy dog
 7767            |The qu[ick b}rown"});
 7768        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7769        cx.assert_editor_state(indoc! {"
 7770            |fox jumps over
 7771            the lazy dog|"});
 7772    }
 7773
 7774    #[gpui::test]
 7775    async fn test_delete(cx: &mut gpui::TestAppContext) {
 7776        let mut cx = EditorTestContext::new(cx).await;
 7777
 7778        cx.set_state(indoc! {"
 7779            on|e two three
 7780            fou[r} five six
 7781            seven {eight nine
 7782            ]ten"});
 7783        cx.update_editor(|e, cx| e.delete(&Delete, cx));
 7784        cx.assert_editor_state(indoc! {"
 7785            on| two three
 7786            fou| five six
 7787            seven |ten"});
 7788
 7789        // Test backspace with line_mode set to true
 7790        cx.update_editor(|e, _| e.selections.line_mode = true);
 7791        cx.set_state(indoc! {"
 7792            The |quick |brown
 7793            fox {jum]ps over
 7794            the lazy dog
 7795            |The qu[ick b}rown"});
 7796        cx.update_editor(|e, cx| e.backspace(&Backspace, cx));
 7797        cx.assert_editor_state("|the lazy dog|");
 7798    }
 7799
 7800    #[gpui::test]
 7801    fn test_delete_line(cx: &mut gpui::MutableAppContext) {
 7802        cx.set_global(Settings::test(cx));
 7803        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7804        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7805        view.update(cx, |view, cx| {
 7806            view.change_selections(None, cx, |s| {
 7807                s.select_display_ranges([
 7808                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7809                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7810                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7811                ])
 7812            });
 7813            view.delete_line(&DeleteLine, cx);
 7814            assert_eq!(view.display_text(cx), "ghi");
 7815            assert_eq!(
 7816                view.selections.display_ranges(cx),
 7817                vec![
 7818                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
 7819                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
 7820                ]
 7821            );
 7822        });
 7823
 7824        cx.set_global(Settings::test(cx));
 7825        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7826        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7827        view.update(cx, |view, cx| {
 7828            view.change_selections(None, cx, |s| {
 7829                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
 7830            });
 7831            view.delete_line(&DeleteLine, cx);
 7832            assert_eq!(view.display_text(cx), "ghi\n");
 7833            assert_eq!(
 7834                view.selections.display_ranges(cx),
 7835                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
 7836            );
 7837        });
 7838    }
 7839
 7840    #[gpui::test]
 7841    fn test_duplicate_line(cx: &mut gpui::MutableAppContext) {
 7842        cx.set_global(Settings::test(cx));
 7843        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7844        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7845        view.update(cx, |view, cx| {
 7846            view.change_selections(None, cx, |s| {
 7847                s.select_display_ranges([
 7848                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 7849                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 7850                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 7851                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7852                ])
 7853            });
 7854            view.duplicate_line(&DuplicateLine, cx);
 7855            assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
 7856            assert_eq!(
 7857                view.selections.display_ranges(cx),
 7858                vec![
 7859                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 7860                    DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
 7861                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 7862                    DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
 7863                ]
 7864            );
 7865        });
 7866
 7867        let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
 7868        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7869        view.update(cx, |view, cx| {
 7870            view.change_selections(None, cx, |s| {
 7871                s.select_display_ranges([
 7872                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
 7873                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
 7874                ])
 7875            });
 7876            view.duplicate_line(&DuplicateLine, cx);
 7877            assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
 7878            assert_eq!(
 7879                view.selections.display_ranges(cx),
 7880                vec![
 7881                    DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
 7882                    DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
 7883                ]
 7884            );
 7885        });
 7886    }
 7887
 7888    #[gpui::test]
 7889    fn test_move_line_up_down(cx: &mut gpui::MutableAppContext) {
 7890        cx.set_global(Settings::test(cx));
 7891        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 7892        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7893        view.update(cx, |view, cx| {
 7894            view.fold_ranges(
 7895                vec![
 7896                    Point::new(0, 2)..Point::new(1, 2),
 7897                    Point::new(2, 3)..Point::new(4, 1),
 7898                    Point::new(7, 0)..Point::new(8, 4),
 7899                ],
 7900                cx,
 7901            );
 7902            view.change_selections(None, cx, |s| {
 7903                s.select_display_ranges([
 7904                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7905                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7906                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7907                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
 7908                ])
 7909            });
 7910            assert_eq!(
 7911                view.display_text(cx),
 7912                "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
 7913            );
 7914
 7915            view.move_line_up(&MoveLineUp, cx);
 7916            assert_eq!(
 7917                view.display_text(cx),
 7918                "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
 7919            );
 7920            assert_eq!(
 7921                view.selections.display_ranges(cx),
 7922                vec![
 7923                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 7924                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 7925                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 7926                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 7927                ]
 7928            );
 7929        });
 7930
 7931        view.update(cx, |view, cx| {
 7932            view.move_line_down(&MoveLineDown, cx);
 7933            assert_eq!(
 7934                view.display_text(cx),
 7935                "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
 7936            );
 7937            assert_eq!(
 7938                view.selections.display_ranges(cx),
 7939                vec![
 7940                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 7941                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7942                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7943                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 7944                ]
 7945            );
 7946        });
 7947
 7948        view.update(cx, |view, cx| {
 7949            view.move_line_down(&MoveLineDown, cx);
 7950            assert_eq!(
 7951                view.display_text(cx),
 7952                "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
 7953            );
 7954            assert_eq!(
 7955                view.selections.display_ranges(cx),
 7956                vec![
 7957                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 7958                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
 7959                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
 7960                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
 7961                ]
 7962            );
 7963        });
 7964
 7965        view.update(cx, |view, cx| {
 7966            view.move_line_up(&MoveLineUp, cx);
 7967            assert_eq!(
 7968                view.display_text(cx),
 7969                "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
 7970            );
 7971            assert_eq!(
 7972                view.selections.display_ranges(cx),
 7973                vec![
 7974                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
 7975                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 7976                    DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
 7977                    DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
 7978                ]
 7979            );
 7980        });
 7981    }
 7982
 7983    #[gpui::test]
 7984    fn test_move_line_up_down_with_blocks(cx: &mut gpui::MutableAppContext) {
 7985        cx.set_global(Settings::test(cx));
 7986        let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
 7987        let snapshot = buffer.read(cx).snapshot(cx);
 7988        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 7989        editor.update(cx, |editor, cx| {
 7990            editor.insert_blocks(
 7991                [BlockProperties {
 7992                    style: BlockStyle::Fixed,
 7993                    position: snapshot.anchor_after(Point::new(2, 0)),
 7994                    disposition: BlockDisposition::Below,
 7995                    height: 1,
 7996                    render: Arc::new(|_| Empty::new().boxed()),
 7997                }],
 7998                cx,
 7999            );
 8000            editor.change_selections(None, cx, |s| {
 8001                s.select_ranges([Point::new(2, 0)..Point::new(2, 0)])
 8002            });
 8003            editor.move_line_down(&MoveLineDown, cx);
 8004        });
 8005    }
 8006
 8007    #[gpui::test]
 8008    fn test_transpose(cx: &mut gpui::MutableAppContext) {
 8009        cx.set_global(Settings::test(cx));
 8010
 8011        cx.add_window(Default::default(), |cx| {
 8012            let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), cx);
 8013
 8014            editor.change_selections(None, cx, |s| s.select_ranges([1..1]));
 8015            editor.transpose(&Default::default(), cx);
 8016            assert_eq!(editor.text(cx), "bac");
 8017            assert_eq!(editor.selections.ranges(cx), [2..2]);
 8018
 8019            editor.transpose(&Default::default(), cx);
 8020            assert_eq!(editor.text(cx), "bca");
 8021            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8022
 8023            editor.transpose(&Default::default(), cx);
 8024            assert_eq!(editor.text(cx), "bac");
 8025            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8026
 8027            editor
 8028        })
 8029        .1;
 8030
 8031        cx.add_window(Default::default(), |cx| {
 8032            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8033
 8034            editor.change_selections(None, cx, |s| s.select_ranges([3..3]));
 8035            editor.transpose(&Default::default(), cx);
 8036            assert_eq!(editor.text(cx), "acb\nde");
 8037            assert_eq!(editor.selections.ranges(cx), [3..3]);
 8038
 8039            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8040            editor.transpose(&Default::default(), cx);
 8041            assert_eq!(editor.text(cx), "acbd\ne");
 8042            assert_eq!(editor.selections.ranges(cx), [5..5]);
 8043
 8044            editor.transpose(&Default::default(), cx);
 8045            assert_eq!(editor.text(cx), "acbde\n");
 8046            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8047
 8048            editor.transpose(&Default::default(), cx);
 8049            assert_eq!(editor.text(cx), "acbd\ne");
 8050            assert_eq!(editor.selections.ranges(cx), [6..6]);
 8051
 8052            editor
 8053        })
 8054        .1;
 8055
 8056        cx.add_window(Default::default(), |cx| {
 8057            let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), cx);
 8058
 8059            editor.change_selections(None, cx, |s| s.select_ranges([1..1, 2..2, 4..4]));
 8060            editor.transpose(&Default::default(), cx);
 8061            assert_eq!(editor.text(cx), "bacd\ne");
 8062            assert_eq!(editor.selections.ranges(cx), [2..2, 3..3, 5..5]);
 8063
 8064            editor.transpose(&Default::default(), cx);
 8065            assert_eq!(editor.text(cx), "bcade\n");
 8066            assert_eq!(editor.selections.ranges(cx), [3..3, 4..4, 6..6]);
 8067
 8068            editor.transpose(&Default::default(), cx);
 8069            assert_eq!(editor.text(cx), "bcda\ne");
 8070            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8071
 8072            editor.transpose(&Default::default(), cx);
 8073            assert_eq!(editor.text(cx), "bcade\n");
 8074            assert_eq!(editor.selections.ranges(cx), [4..4, 6..6]);
 8075
 8076            editor.transpose(&Default::default(), cx);
 8077            assert_eq!(editor.text(cx), "bcaed\n");
 8078            assert_eq!(editor.selections.ranges(cx), [5..5, 6..6]);
 8079
 8080            editor
 8081        })
 8082        .1;
 8083
 8084        cx.add_window(Default::default(), |cx| {
 8085            let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), cx);
 8086
 8087            editor.change_selections(None, cx, |s| s.select_ranges([4..4]));
 8088            editor.transpose(&Default::default(), cx);
 8089            assert_eq!(editor.text(cx), "🏀🍐✋");
 8090            assert_eq!(editor.selections.ranges(cx), [8..8]);
 8091
 8092            editor.transpose(&Default::default(), cx);
 8093            assert_eq!(editor.text(cx), "🏀✋🍐");
 8094            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8095
 8096            editor.transpose(&Default::default(), cx);
 8097            assert_eq!(editor.text(cx), "🏀🍐✋");
 8098            assert_eq!(editor.selections.ranges(cx), [11..11]);
 8099
 8100            editor
 8101        })
 8102        .1;
 8103    }
 8104
 8105    #[gpui::test]
 8106    async fn test_clipboard(cx: &mut gpui::TestAppContext) {
 8107        let mut cx = EditorTestContext::new(cx).await;
 8108
 8109        cx.set_state("[one✅ }two [three }four [five }six ");
 8110        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8111        cx.assert_editor_state("|two |four |six ");
 8112
 8113        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
 8114        cx.set_state("two |four |six |");
 8115        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8116        cx.assert_editor_state("two one✅ |four three |six five |");
 8117
 8118        // Paste again but with only two cursors. Since the number of cursors doesn't
 8119        // match the number of slices in the clipboard, the entire clipboard text
 8120        // is pasted at each cursor.
 8121        cx.set_state("|two one✅ four three six five |");
 8122        cx.update_editor(|e, cx| {
 8123            e.handle_input(&Input("( ".into()), cx);
 8124            e.paste(&Paste, cx);
 8125            e.handle_input(&Input(") ".into()), cx);
 8126        });
 8127        cx.assert_editor_state(indoc! {"
 8128            ( one✅ 
 8129            three 
 8130            five ) |two one✅ four three six five ( one✅ 
 8131            three 
 8132            five ) |"});
 8133
 8134        // Cut with three selections, one of which is full-line.
 8135        cx.set_state(indoc! {"
 8136            1[2}3
 8137            4|567
 8138            [8}9"});
 8139        cx.update_editor(|e, cx| e.cut(&Cut, cx));
 8140        cx.assert_editor_state(indoc! {"
 8141            1|3
 8142            |9"});
 8143
 8144        // Paste with three selections, noticing how the copied selection that was full-line
 8145        // gets inserted before the second cursor.
 8146        cx.set_state(indoc! {"
 8147            1|3
 8148            9|
 8149            [o}ne"});
 8150        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8151        cx.assert_editor_state(indoc! {"
 8152            12|3
 8153            4567
 8154            9|
 8155            8|ne"});
 8156
 8157        // Copy with a single cursor only, which writes the whole line into the clipboard.
 8158        cx.set_state(indoc! {"
 8159            The quick brown
 8160            fox ju|mps over
 8161            the lazy dog"});
 8162        cx.update_editor(|e, cx| e.copy(&Copy, cx));
 8163        cx.assert_clipboard_content(Some("fox jumps over\n"));
 8164
 8165        // Paste with three selections, noticing how the copied full-line selection is inserted
 8166        // before the empty selections but replaces the selection that is non-empty.
 8167        cx.set_state(indoc! {"
 8168            T|he quick brown
 8169            [fo}x jumps over
 8170            t|he lazy dog"});
 8171        cx.update_editor(|e, cx| e.paste(&Paste, cx));
 8172        cx.assert_editor_state(indoc! {"
 8173            fox jumps over
 8174            T|he quick brown
 8175            fox jumps over
 8176            |x jumps over
 8177            fox jumps over
 8178            t|he lazy dog"});
 8179    }
 8180
 8181    #[gpui::test]
 8182    fn test_select_all(cx: &mut gpui::MutableAppContext) {
 8183        cx.set_global(Settings::test(cx));
 8184        let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
 8185        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8186        view.update(cx, |view, cx| {
 8187            view.select_all(&SelectAll, cx);
 8188            assert_eq!(
 8189                view.selections.display_ranges(cx),
 8190                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
 8191            );
 8192        });
 8193    }
 8194
 8195    #[gpui::test]
 8196    fn test_select_line(cx: &mut gpui::MutableAppContext) {
 8197        cx.set_global(Settings::test(cx));
 8198        let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
 8199        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8200        view.update(cx, |view, cx| {
 8201            view.change_selections(None, cx, |s| {
 8202                s.select_display_ranges([
 8203                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8204                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8205                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8206                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
 8207                ])
 8208            });
 8209            view.select_line(&SelectLine, cx);
 8210            assert_eq!(
 8211                view.selections.display_ranges(cx),
 8212                vec![
 8213                    DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
 8214                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
 8215                ]
 8216            );
 8217        });
 8218
 8219        view.update(cx, |view, cx| {
 8220            view.select_line(&SelectLine, cx);
 8221            assert_eq!(
 8222                view.selections.display_ranges(cx),
 8223                vec![
 8224                    DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
 8225                    DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
 8226                ]
 8227            );
 8228        });
 8229
 8230        view.update(cx, |view, cx| {
 8231            view.select_line(&SelectLine, cx);
 8232            assert_eq!(
 8233                view.selections.display_ranges(cx),
 8234                vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
 8235            );
 8236        });
 8237    }
 8238
 8239    #[gpui::test]
 8240    fn test_split_selection_into_lines(cx: &mut gpui::MutableAppContext) {
 8241        cx.set_global(Settings::test(cx));
 8242        let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
 8243        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8244        view.update(cx, |view, cx| {
 8245            view.fold_ranges(
 8246                vec![
 8247                    Point::new(0, 2)..Point::new(1, 2),
 8248                    Point::new(2, 3)..Point::new(4, 1),
 8249                    Point::new(7, 0)..Point::new(8, 4),
 8250                ],
 8251                cx,
 8252            );
 8253            view.change_selections(None, cx, |s| {
 8254                s.select_display_ranges([
 8255                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8256                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8257                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8258                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 8259                ])
 8260            });
 8261            assert_eq!(view.display_text(cx), "aa…bbb\nccc…eeee\nfffff\nggggg\n…i");
 8262        });
 8263
 8264        view.update(cx, |view, cx| {
 8265            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8266            assert_eq!(
 8267                view.display_text(cx),
 8268                "aaaaa\nbbbbb\nccc…eeee\nfffff\nggggg\n…i"
 8269            );
 8270            assert_eq!(
 8271                view.selections.display_ranges(cx),
 8272                [
 8273                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
 8274                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
 8275                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
 8276                    DisplayPoint::new(5, 4)..DisplayPoint::new(5, 4)
 8277                ]
 8278            );
 8279        });
 8280
 8281        view.update(cx, |view, cx| {
 8282            view.change_selections(None, cx, |s| {
 8283                s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)])
 8284            });
 8285            view.split_selection_into_lines(&SplitSelectionIntoLines, cx);
 8286            assert_eq!(
 8287                view.display_text(cx),
 8288                "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\nhhhhh\niiiii"
 8289            );
 8290            assert_eq!(
 8291                view.selections.display_ranges(cx),
 8292                [
 8293                    DisplayPoint::new(0, 5)..DisplayPoint::new(0, 5),
 8294                    DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
 8295                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 8296                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
 8297                    DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
 8298                    DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
 8299                    DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
 8300                    DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
 8301                ]
 8302            );
 8303        });
 8304    }
 8305
 8306    #[gpui::test]
 8307    fn test_add_selection_above_below(cx: &mut gpui::MutableAppContext) {
 8308        cx.set_global(Settings::test(cx));
 8309        let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
 8310        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8311
 8312        view.update(cx, |view, cx| {
 8313            view.change_selections(None, cx, |s| {
 8314                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
 8315            });
 8316        });
 8317        view.update(cx, |view, cx| {
 8318            view.add_selection_above(&AddSelectionAbove, cx);
 8319            assert_eq!(
 8320                view.selections.display_ranges(cx),
 8321                vec![
 8322                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8323                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8324                ]
 8325            );
 8326        });
 8327
 8328        view.update(cx, |view, cx| {
 8329            view.add_selection_above(&AddSelectionAbove, cx);
 8330            assert_eq!(
 8331                view.selections.display_ranges(cx),
 8332                vec![
 8333                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8334                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8335                ]
 8336            );
 8337        });
 8338
 8339        view.update(cx, |view, cx| {
 8340            view.add_selection_below(&AddSelectionBelow, cx);
 8341            assert_eq!(
 8342                view.selections.display_ranges(cx),
 8343                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8344            );
 8345
 8346            view.undo_selection(&UndoSelection, cx);
 8347            assert_eq!(
 8348                view.selections.display_ranges(cx),
 8349                vec![
 8350                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
 8351                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
 8352                ]
 8353            );
 8354
 8355            view.redo_selection(&RedoSelection, cx);
 8356            assert_eq!(
 8357                view.selections.display_ranges(cx),
 8358                vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
 8359            );
 8360        });
 8361
 8362        view.update(cx, |view, cx| {
 8363            view.add_selection_below(&AddSelectionBelow, cx);
 8364            assert_eq!(
 8365                view.selections.display_ranges(cx),
 8366                vec![
 8367                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8368                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8369                ]
 8370            );
 8371        });
 8372
 8373        view.update(cx, |view, cx| {
 8374            view.add_selection_below(&AddSelectionBelow, cx);
 8375            assert_eq!(
 8376                view.selections.display_ranges(cx),
 8377                vec![
 8378                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
 8379                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
 8380                ]
 8381            );
 8382        });
 8383
 8384        view.update(cx, |view, cx| {
 8385            view.change_selections(None, cx, |s| {
 8386                s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
 8387            });
 8388        });
 8389        view.update(cx, |view, cx| {
 8390            view.add_selection_below(&AddSelectionBelow, cx);
 8391            assert_eq!(
 8392                view.selections.display_ranges(cx),
 8393                vec![
 8394                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8395                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8396                ]
 8397            );
 8398        });
 8399
 8400        view.update(cx, |view, cx| {
 8401            view.add_selection_below(&AddSelectionBelow, cx);
 8402            assert_eq!(
 8403                view.selections.display_ranges(cx),
 8404                vec![
 8405                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
 8406                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
 8407                ]
 8408            );
 8409        });
 8410
 8411        view.update(cx, |view, cx| {
 8412            view.add_selection_above(&AddSelectionAbove, cx);
 8413            assert_eq!(
 8414                view.selections.display_ranges(cx),
 8415                vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
 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.change_selections(None, cx, |s| {
 8429                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
 8430            });
 8431            view.add_selection_below(&AddSelectionBelow, cx);
 8432            assert_eq!(
 8433                view.selections.display_ranges(cx),
 8434                vec![
 8435                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8436                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8437                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8438                ]
 8439            );
 8440        });
 8441
 8442        view.update(cx, |view, cx| {
 8443            view.add_selection_below(&AddSelectionBelow, cx);
 8444            assert_eq!(
 8445                view.selections.display_ranges(cx),
 8446                vec![
 8447                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8448                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8449                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8450                    DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
 8451                ]
 8452            );
 8453        });
 8454
 8455        view.update(cx, |view, cx| {
 8456            view.add_selection_above(&AddSelectionAbove, cx);
 8457            assert_eq!(
 8458                view.selections.display_ranges(cx),
 8459                vec![
 8460                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
 8461                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
 8462                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
 8463                ]
 8464            );
 8465        });
 8466
 8467        view.update(cx, |view, cx| {
 8468            view.change_selections(None, cx, |s| {
 8469                s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
 8470            });
 8471        });
 8472        view.update(cx, |view, cx| {
 8473            view.add_selection_above(&AddSelectionAbove, cx);
 8474            assert_eq!(
 8475                view.selections.display_ranges(cx),
 8476                vec![
 8477                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
 8478                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8479                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8480                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8481                ]
 8482            );
 8483        });
 8484
 8485        view.update(cx, |view, cx| {
 8486            view.add_selection_below(&AddSelectionBelow, cx);
 8487            assert_eq!(
 8488                view.selections.display_ranges(cx),
 8489                vec![
 8490                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
 8491                    DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
 8492                    DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
 8493                ]
 8494            );
 8495        });
 8496    }
 8497
 8498    #[gpui::test]
 8499    fn test_select_next(cx: &mut gpui::MutableAppContext) {
 8500        cx.set_global(Settings::test(cx));
 8501
 8502        let (text, ranges) = marked_text_ranges("[abc]\n[abc] [abc]\ndefabc\n[abc]");
 8503        let buffer = MultiBuffer::build_simple(&text, cx);
 8504        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, cx));
 8505
 8506        view.update(cx, |view, cx| {
 8507            view.change_selections(None, cx, |s| {
 8508                s.select_ranges([ranges[1].start + 1..ranges[1].start + 1])
 8509            });
 8510            view.select_next(
 8511                &SelectNext {
 8512                    replace_newest: false,
 8513                },
 8514                cx,
 8515            );
 8516            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8517
 8518            view.select_next(
 8519                &SelectNext {
 8520                    replace_newest: false,
 8521                },
 8522                cx,
 8523            );
 8524            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8525
 8526            view.undo_selection(&UndoSelection, cx);
 8527            assert_eq!(view.selections.ranges(cx), &ranges[1..2]);
 8528
 8529            view.redo_selection(&RedoSelection, cx);
 8530            assert_eq!(view.selections.ranges(cx), &ranges[1..3]);
 8531
 8532            view.select_next(
 8533                &SelectNext {
 8534                    replace_newest: false,
 8535                },
 8536                cx,
 8537            );
 8538            assert_eq!(view.selections.ranges(cx), &ranges[1..4]);
 8539
 8540            view.select_next(
 8541                &SelectNext {
 8542                    replace_newest: false,
 8543                },
 8544                cx,
 8545            );
 8546            assert_eq!(view.selections.ranges(cx), &ranges[0..4]);
 8547        });
 8548    }
 8549
 8550    #[gpui::test]
 8551    async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
 8552        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8553        let language = Arc::new(Language::new(
 8554            LanguageConfig::default(),
 8555            Some(tree_sitter_rust::language()),
 8556        ));
 8557
 8558        let text = r#"
 8559            use mod1::mod2::{mod3, mod4};
 8560
 8561            fn fn_1(param1: bool, param2: &str) {
 8562                let var1 = "text";
 8563            }
 8564        "#
 8565        .unindent();
 8566
 8567        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8568        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8569        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8570        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8571            .await;
 8572
 8573        view.update(cx, |view, cx| {
 8574            view.change_selections(None, cx, |s| {
 8575                s.select_display_ranges([
 8576                    DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8577                    DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8578                    DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8579                ]);
 8580            });
 8581            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8582        });
 8583        assert_eq!(
 8584            view.update(cx, |view, cx| { view.selections.display_ranges(cx) }),
 8585            &[
 8586                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8587                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8588                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8589            ]
 8590        );
 8591
 8592        view.update(cx, |view, cx| {
 8593            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8594        });
 8595        assert_eq!(
 8596            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8597            &[
 8598                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8599                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8600            ]
 8601        );
 8602
 8603        view.update(cx, |view, cx| {
 8604            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8605        });
 8606        assert_eq!(
 8607            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8608            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8609        );
 8610
 8611        // Trying to expand the selected syntax node one more time has no effect.
 8612        view.update(cx, |view, cx| {
 8613            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8614        });
 8615        assert_eq!(
 8616            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8617            &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)]
 8618        );
 8619
 8620        view.update(cx, |view, cx| {
 8621            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8622        });
 8623        assert_eq!(
 8624            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8625            &[
 8626                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8627                DisplayPoint::new(4, 1)..DisplayPoint::new(2, 0),
 8628            ]
 8629        );
 8630
 8631        view.update(cx, |view, cx| {
 8632            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8633        });
 8634        assert_eq!(
 8635            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8636            &[
 8637                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 27),
 8638                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8639                DisplayPoint::new(3, 15)..DisplayPoint::new(3, 21),
 8640            ]
 8641        );
 8642
 8643        view.update(cx, |view, cx| {
 8644            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8645        });
 8646        assert_eq!(
 8647            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8648            &[
 8649                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8650                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8651                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8652            ]
 8653        );
 8654
 8655        // Trying to shrink the selected syntax node one more time has no effect.
 8656        view.update(cx, |view, cx| {
 8657            view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx);
 8658        });
 8659        assert_eq!(
 8660            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8661            &[
 8662                DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25),
 8663                DisplayPoint::new(2, 24)..DisplayPoint::new(2, 12),
 8664                DisplayPoint::new(3, 18)..DisplayPoint::new(3, 18),
 8665            ]
 8666        );
 8667
 8668        // Ensure that we keep expanding the selection if the larger selection starts or ends within
 8669        // a fold.
 8670        view.update(cx, |view, cx| {
 8671            view.fold_ranges(
 8672                vec![
 8673                    Point::new(0, 21)..Point::new(0, 24),
 8674                    Point::new(3, 20)..Point::new(3, 22),
 8675                ],
 8676                cx,
 8677            );
 8678            view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx);
 8679        });
 8680        assert_eq!(
 8681            view.update(cx, |view, cx| view.selections.display_ranges(cx)),
 8682            &[
 8683                DisplayPoint::new(0, 16)..DisplayPoint::new(0, 28),
 8684                DisplayPoint::new(2, 35)..DisplayPoint::new(2, 7),
 8685                DisplayPoint::new(3, 4)..DisplayPoint::new(3, 23),
 8686            ]
 8687        );
 8688    }
 8689
 8690    #[gpui::test]
 8691    async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
 8692        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8693        let language = Arc::new(
 8694            Language::new(
 8695                LanguageConfig {
 8696                    brackets: vec![
 8697                        BracketPair {
 8698                            start: "{".to_string(),
 8699                            end: "}".to_string(),
 8700                            close: false,
 8701                            newline: true,
 8702                        },
 8703                        BracketPair {
 8704                            start: "(".to_string(),
 8705                            end: ")".to_string(),
 8706                            close: false,
 8707                            newline: true,
 8708                        },
 8709                    ],
 8710                    ..Default::default()
 8711                },
 8712                Some(tree_sitter_rust::language()),
 8713            )
 8714            .with_indents_query(
 8715                r#"
 8716                (_ "(" ")" @end) @indent
 8717                (_ "{" "}" @end) @indent
 8718                "#,
 8719            )
 8720            .unwrap(),
 8721        );
 8722
 8723        let text = "fn a() {}";
 8724
 8725        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8726        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8727        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 8728        editor
 8729            .condition(&cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
 8730            .await;
 8731
 8732        editor.update(cx, |editor, cx| {
 8733            editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9]));
 8734            editor.newline(&Newline, cx);
 8735            assert_eq!(editor.text(cx), "fn a(\n    \n) {\n    \n}\n");
 8736            assert_eq!(
 8737                editor.selections.ranges(cx),
 8738                &[
 8739                    Point::new(1, 4)..Point::new(1, 4),
 8740                    Point::new(3, 4)..Point::new(3, 4),
 8741                    Point::new(5, 0)..Point::new(5, 0)
 8742                ]
 8743            );
 8744        });
 8745    }
 8746
 8747    #[gpui::test]
 8748    async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) {
 8749        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8750        let language = Arc::new(Language::new(
 8751            LanguageConfig {
 8752                brackets: vec![
 8753                    BracketPair {
 8754                        start: "{".to_string(),
 8755                        end: "}".to_string(),
 8756                        close: true,
 8757                        newline: true,
 8758                    },
 8759                    BracketPair {
 8760                        start: "/*".to_string(),
 8761                        end: " */".to_string(),
 8762                        close: true,
 8763                        newline: true,
 8764                    },
 8765                    BracketPair {
 8766                        start: "[".to_string(),
 8767                        end: "]".to_string(),
 8768                        close: false,
 8769                        newline: true,
 8770                    },
 8771                ],
 8772                autoclose_before: "})]".to_string(),
 8773                ..Default::default()
 8774            },
 8775            Some(tree_sitter_rust::language()),
 8776        ));
 8777
 8778        let text = r#"
 8779            a
 8780
 8781            /
 8782
 8783        "#
 8784        .unindent();
 8785
 8786        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8787        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8788        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8789        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8790            .await;
 8791
 8792        view.update(cx, |view, cx| {
 8793            view.change_selections(None, cx, |s| {
 8794                s.select_display_ranges([
 8795                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8796                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
 8797                ])
 8798            });
 8799
 8800            view.handle_input(&Input("{".to_string()), cx);
 8801            view.handle_input(&Input("{".to_string()), cx);
 8802            view.handle_input(&Input("{".to_string()), cx);
 8803            assert_eq!(
 8804                view.text(cx),
 8805                "
 8806                {{{}}}
 8807                {{{}}}
 8808                /
 8809
 8810                "
 8811                .unindent()
 8812            );
 8813
 8814            view.move_right(&MoveRight, cx);
 8815            view.handle_input(&Input("}".to_string()), cx);
 8816            view.handle_input(&Input("}".to_string()), cx);
 8817            view.handle_input(&Input("}".to_string()), cx);
 8818            assert_eq!(
 8819                view.text(cx),
 8820                "
 8821                {{{}}}}
 8822                {{{}}}}
 8823                /
 8824
 8825                "
 8826                .unindent()
 8827            );
 8828
 8829            view.undo(&Undo, cx);
 8830            view.handle_input(&Input("/".to_string()), cx);
 8831            view.handle_input(&Input("*".to_string()), cx);
 8832            assert_eq!(
 8833                view.text(cx),
 8834                "
 8835                /* */
 8836                /* */
 8837                /
 8838
 8839                "
 8840                .unindent()
 8841            );
 8842
 8843            view.undo(&Undo, cx);
 8844            view.change_selections(None, cx, |s| {
 8845                s.select_display_ranges([
 8846                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
 8847                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
 8848                ])
 8849            });
 8850            view.handle_input(&Input("*".to_string()), cx);
 8851            assert_eq!(
 8852                view.text(cx),
 8853                "
 8854                a
 8855
 8856                /*
 8857                *
 8858                "
 8859                .unindent()
 8860            );
 8861
 8862            // Don't autoclose if the next character isn't whitespace and isn't
 8863            // listed in the language's "autoclose_before" section.
 8864            view.finalize_last_transaction(cx);
 8865            view.change_selections(None, cx, |s| {
 8866                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)])
 8867            });
 8868            view.handle_input(&Input("{".to_string()), cx);
 8869            assert_eq!(
 8870                view.text(cx),
 8871                "
 8872                {a
 8873
 8874                /*
 8875                *
 8876                "
 8877                .unindent()
 8878            );
 8879
 8880            view.undo(&Undo, cx);
 8881            view.change_selections(None, cx, |s| {
 8882                s.select_display_ranges([DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1)])
 8883            });
 8884            view.handle_input(&Input("{".to_string()), cx);
 8885            assert_eq!(
 8886                view.text(cx),
 8887                "
 8888                {a}
 8889
 8890                /*
 8891                *
 8892                "
 8893                .unindent()
 8894            );
 8895            assert_eq!(
 8896                view.selections.display_ranges(cx),
 8897                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8898            );
 8899
 8900            view.undo(&Undo, cx);
 8901            view.handle_input(&Input("[".to_string()), cx);
 8902            assert_eq!(
 8903                view.text(cx),
 8904                "
 8905                [a]
 8906                
 8907                /*
 8908                *
 8909                "
 8910                .unindent()
 8911            );
 8912            assert_eq!(
 8913                view.selections.display_ranges(cx),
 8914                [DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)]
 8915            );
 8916
 8917            view.undo(&Undo, cx);
 8918            view.change_selections(None, cx, |s| {
 8919                s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)])
 8920            });
 8921            view.handle_input(&Input("[".to_string()), cx);
 8922            assert_eq!(
 8923                view.text(cx),
 8924                "
 8925                a[
 8926                
 8927                /*
 8928                *
 8929                "
 8930                .unindent()
 8931            );
 8932            assert_eq!(
 8933                view.selections.display_ranges(cx),
 8934                [DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2)]
 8935            );
 8936        });
 8937    }
 8938
 8939    #[gpui::test]
 8940    async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
 8941        cx.update(|cx| cx.set_global(Settings::test(cx)));
 8942        let language = Arc::new(Language::new(
 8943            LanguageConfig {
 8944                brackets: vec![BracketPair {
 8945                    start: "{".to_string(),
 8946                    end: "}".to_string(),
 8947                    close: true,
 8948                    newline: true,
 8949                }],
 8950                ..Default::default()
 8951            },
 8952            Some(tree_sitter_rust::language()),
 8953        ));
 8954
 8955        let text = r#"
 8956            a
 8957            b
 8958            c
 8959            "#
 8960        .unindent();
 8961
 8962        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 8963        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 8964        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 8965        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 8966            .await;
 8967
 8968        view.update(cx, |view, cx| {
 8969            view.change_selections(None, cx, |s| {
 8970                s.select_display_ranges([
 8971                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 8972                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 8973                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
 8974                ])
 8975            });
 8976
 8977            view.handle_input(&Input("{".to_string()), cx);
 8978            view.handle_input(&Input("{".to_string()), cx);
 8979            view.handle_input(&Input("{".to_string()), cx);
 8980            assert_eq!(
 8981                view.text(cx),
 8982                "
 8983                {{{a}}}
 8984                {{{b}}}
 8985                {{{c}}}
 8986                "
 8987                .unindent()
 8988            );
 8989            assert_eq!(
 8990                view.selections.display_ranges(cx),
 8991                [
 8992                    DisplayPoint::new(0, 3)..DisplayPoint::new(0, 4),
 8993                    DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
 8994                    DisplayPoint::new(2, 3)..DisplayPoint::new(2, 4)
 8995                ]
 8996            );
 8997
 8998            view.undo(&Undo, cx);
 8999            assert_eq!(
 9000                view.text(cx),
 9001                "
 9002                a
 9003                b
 9004                c
 9005                "
 9006                .unindent()
 9007            );
 9008            assert_eq!(
 9009                view.selections.display_ranges(cx),
 9010                [
 9011                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
 9012                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
 9013                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1)
 9014                ]
 9015            );
 9016        });
 9017    }
 9018
 9019    #[gpui::test]
 9020    async fn test_snippets(cx: &mut gpui::TestAppContext) {
 9021        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9022
 9023        let (text, insertion_ranges) = marked_text_ranges(indoc! {"
 9024            a.| b
 9025            a.| b
 9026            a.| b"});
 9027        let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
 9028        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9029
 9030        editor.update(cx, |editor, cx| {
 9031            let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
 9032
 9033            editor
 9034                .insert_snippet(&insertion_ranges, snippet, cx)
 9035                .unwrap();
 9036
 9037            fn assert(editor: &mut Editor, cx: &mut ViewContext<Editor>, marked_text_ranges: &str) {
 9038                let range_markers = ('<', '>');
 9039                let (expected_text, mut selection_ranges_lookup) =
 9040                    marked_text_ranges_by(marked_text_ranges, vec![range_markers.clone().into()]);
 9041                let selection_ranges = selection_ranges_lookup
 9042                    .remove(&range_markers.into())
 9043                    .unwrap();
 9044                assert_eq!(editor.text(cx), expected_text);
 9045                assert_eq!(editor.selections.ranges::<usize>(cx), selection_ranges);
 9046            }
 9047            assert(
 9048                editor,
 9049                cx,
 9050                indoc! {"
 9051                    a.f(<one>, two, <three>) b
 9052                    a.f(<one>, two, <three>) b
 9053                    a.f(<one>, two, <three>) b"},
 9054            );
 9055
 9056            // Can't move earlier than the first tab stop
 9057            assert!(!editor.move_to_prev_snippet_tabstop(cx));
 9058            assert(
 9059                editor,
 9060                cx,
 9061                indoc! {"
 9062                    a.f(<one>, two, <three>) b
 9063                    a.f(<one>, two, <three>) b
 9064                    a.f(<one>, two, <three>) b"},
 9065            );
 9066
 9067            assert!(editor.move_to_next_snippet_tabstop(cx));
 9068            assert(
 9069                editor,
 9070                cx,
 9071                indoc! {"
 9072                    a.f(one, <two>, three) b
 9073                    a.f(one, <two>, three) b
 9074                    a.f(one, <two>, three) b"},
 9075            );
 9076
 9077            editor.move_to_prev_snippet_tabstop(cx);
 9078            assert(
 9079                editor,
 9080                cx,
 9081                indoc! {"
 9082                    a.f(<one>, two, <three>) b
 9083                    a.f(<one>, two, <three>) b
 9084                    a.f(<one>, two, <three>) b"},
 9085            );
 9086
 9087            assert!(editor.move_to_next_snippet_tabstop(cx));
 9088            assert(
 9089                editor,
 9090                cx,
 9091                indoc! {"
 9092                    a.f(one, <two>, three) b
 9093                    a.f(one, <two>, three) b
 9094                    a.f(one, <two>, three) b"},
 9095            );
 9096            assert!(editor.move_to_next_snippet_tabstop(cx));
 9097            assert(
 9098                editor,
 9099                cx,
 9100                indoc! {"
 9101                    a.f(one, two, three)<> b
 9102                    a.f(one, two, three)<> b
 9103                    a.f(one, two, three)<> b"},
 9104            );
 9105
 9106            // As soon as the last tab stop is reached, snippet state is gone
 9107            editor.move_to_prev_snippet_tabstop(cx);
 9108            assert(
 9109                editor,
 9110                cx,
 9111                indoc! {"
 9112                    a.f(one, two, three)<> b
 9113                    a.f(one, two, three)<> b
 9114                    a.f(one, two, three)<> b"},
 9115            );
 9116        });
 9117    }
 9118
 9119    #[gpui::test]
 9120    async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
 9121        cx.foreground().forbid_parking();
 9122
 9123        let mut language = Language::new(
 9124            LanguageConfig {
 9125                name: "Rust".into(),
 9126                path_suffixes: vec!["rs".to_string()],
 9127                ..Default::default()
 9128            },
 9129            Some(tree_sitter_rust::language()),
 9130        );
 9131        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9132            capabilities: lsp::ServerCapabilities {
 9133                document_formatting_provider: Some(lsp::OneOf::Left(true)),
 9134                ..Default::default()
 9135            },
 9136            ..Default::default()
 9137        });
 9138
 9139        let fs = FakeFs::new(cx.background().clone());
 9140        fs.insert_file("/file.rs", Default::default()).await;
 9141
 9142        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9143        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9144        let buffer = project
 9145            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9146            .await
 9147            .unwrap();
 9148
 9149        cx.foreground().start_waiting();
 9150        let fake_server = fake_servers.next().await.unwrap();
 9151
 9152        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9153        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9154        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9155        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9156
 9157        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9158        fake_server
 9159            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9160                assert_eq!(
 9161                    params.text_document.uri,
 9162                    lsp::Url::from_file_path("/file.rs").unwrap()
 9163                );
 9164                assert_eq!(params.options.tab_size, 4);
 9165                Ok(Some(vec![lsp::TextEdit::new(
 9166                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9167                    ", ".to_string(),
 9168                )]))
 9169            })
 9170            .next()
 9171            .await;
 9172        cx.foreground().start_waiting();
 9173        save.await.unwrap();
 9174        assert_eq!(
 9175            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9176            "one, two\nthree\n"
 9177        );
 9178        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9179
 9180        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9181        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9182
 9183        // Ensure we can still save even if formatting hangs.
 9184        fake_server.handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9185            assert_eq!(
 9186                params.text_document.uri,
 9187                lsp::Url::from_file_path("/file.rs").unwrap()
 9188            );
 9189            futures::future::pending::<()>().await;
 9190            unreachable!()
 9191        });
 9192        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9193        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9194        cx.foreground().start_waiting();
 9195        save.await.unwrap();
 9196        assert_eq!(
 9197            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9198            "one\ntwo\nthree\n"
 9199        );
 9200        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9201
 9202        // Set rust language override and assert overriden tabsize is sent to language server
 9203        cx.update(|cx| {
 9204            cx.update_global::<Settings, _, _>(|settings, _| {
 9205                settings.language_overrides.insert(
 9206                    "Rust".into(),
 9207                    LanguageSettings {
 9208                        tab_size: Some(8.try_into().unwrap()),
 9209                        ..Default::default()
 9210                    },
 9211                );
 9212            })
 9213        });
 9214
 9215        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9216        fake_server
 9217            .handle_request::<lsp::request::Formatting, _, _>(move |params, _| async move {
 9218                assert_eq!(
 9219                    params.text_document.uri,
 9220                    lsp::Url::from_file_path("/file.rs").unwrap()
 9221                );
 9222                assert_eq!(params.options.tab_size, 8);
 9223                Ok(Some(vec![]))
 9224            })
 9225            .next()
 9226            .await;
 9227        cx.foreground().start_waiting();
 9228        save.await.unwrap();
 9229    }
 9230
 9231    #[gpui::test]
 9232    async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
 9233        cx.foreground().forbid_parking();
 9234
 9235        let mut language = Language::new(
 9236            LanguageConfig {
 9237                name: "Rust".into(),
 9238                path_suffixes: vec!["rs".to_string()],
 9239                ..Default::default()
 9240            },
 9241            Some(tree_sitter_rust::language()),
 9242        );
 9243        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9244            capabilities: lsp::ServerCapabilities {
 9245                document_range_formatting_provider: Some(lsp::OneOf::Left(true)),
 9246                ..Default::default()
 9247            },
 9248            ..Default::default()
 9249        });
 9250
 9251        let fs = FakeFs::new(cx.background().clone());
 9252        fs.insert_file("/file.rs", Default::default()).await;
 9253
 9254        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9255        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9256        let buffer = project
 9257            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9258            .await
 9259            .unwrap();
 9260
 9261        cx.foreground().start_waiting();
 9262        let fake_server = fake_servers.next().await.unwrap();
 9263
 9264        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9265        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9266        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9267        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9268
 9269        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9270        fake_server
 9271            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9272                assert_eq!(
 9273                    params.text_document.uri,
 9274                    lsp::Url::from_file_path("/file.rs").unwrap()
 9275                );
 9276                assert_eq!(params.options.tab_size, 4);
 9277                Ok(Some(vec![lsp::TextEdit::new(
 9278                    lsp::Range::new(lsp::Position::new(0, 3), lsp::Position::new(1, 0)),
 9279                    ", ".to_string(),
 9280                )]))
 9281            })
 9282            .next()
 9283            .await;
 9284        cx.foreground().start_waiting();
 9285        save.await.unwrap();
 9286        assert_eq!(
 9287            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9288            "one, two\nthree\n"
 9289        );
 9290        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9291
 9292        editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
 9293        assert!(cx.read(|cx| editor.is_dirty(cx)));
 9294
 9295        // Ensure we can still save even if formatting hangs.
 9296        fake_server.handle_request::<lsp::request::RangeFormatting, _, _>(
 9297            move |params, _| async move {
 9298                assert_eq!(
 9299                    params.text_document.uri,
 9300                    lsp::Url::from_file_path("/file.rs").unwrap()
 9301                );
 9302                futures::future::pending::<()>().await;
 9303                unreachable!()
 9304            },
 9305        );
 9306        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9307        cx.foreground().advance_clock(items::FORMAT_TIMEOUT);
 9308        cx.foreground().start_waiting();
 9309        save.await.unwrap();
 9310        assert_eq!(
 9311            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9312            "one\ntwo\nthree\n"
 9313        );
 9314        assert!(!cx.read(|cx| editor.is_dirty(cx)));
 9315
 9316        // Set rust language override and assert overriden tabsize is sent to language server
 9317        cx.update(|cx| {
 9318            cx.update_global::<Settings, _, _>(|settings, _| {
 9319                settings.language_overrides.insert(
 9320                    "Rust".into(),
 9321                    LanguageSettings {
 9322                        tab_size: Some(8.try_into().unwrap()),
 9323                        ..Default::default()
 9324                    },
 9325                );
 9326            })
 9327        });
 9328
 9329        let save = cx.update(|cx| editor.save(project.clone(), cx));
 9330        fake_server
 9331            .handle_request::<lsp::request::RangeFormatting, _, _>(move |params, _| async move {
 9332                assert_eq!(
 9333                    params.text_document.uri,
 9334                    lsp::Url::from_file_path("/file.rs").unwrap()
 9335                );
 9336                assert_eq!(params.options.tab_size, 8);
 9337                Ok(Some(vec![]))
 9338            })
 9339            .next()
 9340            .await;
 9341        cx.foreground().start_waiting();
 9342        save.await.unwrap();
 9343    }
 9344
 9345    #[gpui::test]
 9346    async fn test_completion(cx: &mut gpui::TestAppContext) {
 9347        let mut language = Language::new(
 9348            LanguageConfig {
 9349                name: "Rust".into(),
 9350                path_suffixes: vec!["rs".to_string()],
 9351                ..Default::default()
 9352            },
 9353            Some(tree_sitter_rust::language()),
 9354        );
 9355        let mut fake_servers = language.set_fake_lsp_adapter(FakeLspAdapter {
 9356            capabilities: lsp::ServerCapabilities {
 9357                completion_provider: Some(lsp::CompletionOptions {
 9358                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
 9359                    ..Default::default()
 9360                }),
 9361                ..Default::default()
 9362            },
 9363            ..Default::default()
 9364        });
 9365
 9366        let text = "
 9367            one
 9368            two
 9369            three
 9370        "
 9371        .unindent();
 9372
 9373        let fs = FakeFs::new(cx.background().clone());
 9374        fs.insert_file("/file.rs", text).await;
 9375
 9376        let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
 9377        project.update(cx, |project, _| project.languages().add(Arc::new(language)));
 9378        let buffer = project
 9379            .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx))
 9380            .await
 9381            .unwrap();
 9382        let mut fake_server = fake_servers.next().await.unwrap();
 9383
 9384        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9385        let (_, editor) = cx.add_window(|cx| build_editor(buffer, cx));
 9386
 9387        editor.update(cx, |editor, cx| {
 9388            editor.project = Some(project);
 9389            editor.change_selections(None, cx, |s| {
 9390                s.select_ranges([Point::new(0, 3)..Point::new(0, 3)])
 9391            });
 9392            editor.handle_input(&Input(".".to_string()), cx);
 9393        });
 9394
 9395        handle_completion_request(
 9396            &mut fake_server,
 9397            "/file.rs",
 9398            Point::new(0, 4),
 9399            vec![
 9400                (Point::new(0, 4)..Point::new(0, 4), "first_completion"),
 9401                (Point::new(0, 4)..Point::new(0, 4), "second_completion"),
 9402            ],
 9403        )
 9404        .await;
 9405        editor
 9406            .condition(&cx, |editor, _| editor.context_menu_visible())
 9407            .await;
 9408
 9409        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9410            editor.move_down(&MoveDown, cx);
 9411            let apply_additional_edits = editor
 9412                .confirm_completion(&ConfirmCompletion::default(), cx)
 9413                .unwrap();
 9414            assert_eq!(
 9415                editor.text(cx),
 9416                "
 9417                    one.second_completion
 9418                    two
 9419                    three
 9420                "
 9421                .unindent()
 9422            );
 9423            apply_additional_edits
 9424        });
 9425
 9426        handle_resolve_completion_request(
 9427            &mut fake_server,
 9428            Some((Point::new(2, 5)..Point::new(2, 5), "\nadditional edit")),
 9429        )
 9430        .await;
 9431        apply_additional_edits.await.unwrap();
 9432        assert_eq!(
 9433            editor.read_with(cx, |editor, cx| editor.text(cx)),
 9434            "
 9435                one.second_completion
 9436                two
 9437                three
 9438                additional edit
 9439            "
 9440            .unindent()
 9441        );
 9442
 9443        editor.update(cx, |editor, cx| {
 9444            editor.change_selections(None, cx, |s| {
 9445                s.select_ranges([
 9446                    Point::new(1, 3)..Point::new(1, 3),
 9447                    Point::new(2, 5)..Point::new(2, 5),
 9448                ])
 9449            });
 9450
 9451            editor.handle_input(&Input(" ".to_string()), cx);
 9452            assert!(editor.context_menu.is_none());
 9453            editor.handle_input(&Input("s".to_string()), cx);
 9454            assert!(editor.context_menu.is_none());
 9455        });
 9456
 9457        handle_completion_request(
 9458            &mut fake_server,
 9459            "/file.rs",
 9460            Point::new(2, 7),
 9461            vec![
 9462                (Point::new(2, 6)..Point::new(2, 7), "fourth_completion"),
 9463                (Point::new(2, 6)..Point::new(2, 7), "fifth_completion"),
 9464                (Point::new(2, 6)..Point::new(2, 7), "sixth_completion"),
 9465            ],
 9466        )
 9467        .await;
 9468        editor
 9469            .condition(&cx, |editor, _| editor.context_menu_visible())
 9470            .await;
 9471
 9472        editor.update(cx, |editor, cx| {
 9473            editor.handle_input(&Input("i".to_string()), cx);
 9474        });
 9475
 9476        handle_completion_request(
 9477            &mut fake_server,
 9478            "/file.rs",
 9479            Point::new(2, 8),
 9480            vec![
 9481                (Point::new(2, 6)..Point::new(2, 8), "fourth_completion"),
 9482                (Point::new(2, 6)..Point::new(2, 8), "fifth_completion"),
 9483                (Point::new(2, 6)..Point::new(2, 8), "sixth_completion"),
 9484            ],
 9485        )
 9486        .await;
 9487        editor
 9488            .condition(&cx, |editor, _| editor.context_menu_visible())
 9489            .await;
 9490
 9491        let apply_additional_edits = editor.update(cx, |editor, cx| {
 9492            let apply_additional_edits = editor
 9493                .confirm_completion(&ConfirmCompletion::default(), cx)
 9494                .unwrap();
 9495            assert_eq!(
 9496                editor.text(cx),
 9497                "
 9498                    one.second_completion
 9499                    two sixth_completion
 9500                    three sixth_completion
 9501                    additional edit
 9502                "
 9503                .unindent()
 9504            );
 9505            apply_additional_edits
 9506        });
 9507        handle_resolve_completion_request(&mut fake_server, None).await;
 9508        apply_additional_edits.await.unwrap();
 9509
 9510        async fn handle_completion_request(
 9511            fake: &mut FakeLanguageServer,
 9512            path: &'static str,
 9513            position: Point,
 9514            completions: Vec<(Range<Point>, &'static str)>,
 9515        ) {
 9516            fake.handle_request::<lsp::request::Completion, _, _>(move |params, _| {
 9517                let completions = completions.clone();
 9518                async move {
 9519                    assert_eq!(
 9520                        params.text_document_position.text_document.uri,
 9521                        lsp::Url::from_file_path(path).unwrap()
 9522                    );
 9523                    assert_eq!(
 9524                        params.text_document_position.position,
 9525                        lsp::Position::new(position.row, position.column)
 9526                    );
 9527                    Ok(Some(lsp::CompletionResponse::Array(
 9528                        completions
 9529                            .iter()
 9530                            .map(|(range, new_text)| lsp::CompletionItem {
 9531                                label: new_text.to_string(),
 9532                                text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
 9533                                    range: lsp::Range::new(
 9534                                        lsp::Position::new(range.start.row, range.start.column),
 9535                                        lsp::Position::new(range.start.row, range.start.column),
 9536                                    ),
 9537                                    new_text: new_text.to_string(),
 9538                                })),
 9539                                ..Default::default()
 9540                            })
 9541                            .collect(),
 9542                    )))
 9543                }
 9544            })
 9545            .next()
 9546            .await;
 9547        }
 9548
 9549        async fn handle_resolve_completion_request(
 9550            fake: &mut FakeLanguageServer,
 9551            edit: Option<(Range<Point>, &'static str)>,
 9552        ) {
 9553            fake.handle_request::<lsp::request::ResolveCompletionItem, _, _>(move |_, _| {
 9554                let edit = edit.clone();
 9555                async move {
 9556                    Ok(lsp::CompletionItem {
 9557                        additional_text_edits: edit.map(|(range, new_text)| {
 9558                            vec![lsp::TextEdit::new(
 9559                                lsp::Range::new(
 9560                                    lsp::Position::new(range.start.row, range.start.column),
 9561                                    lsp::Position::new(range.end.row, range.end.column),
 9562                                ),
 9563                                new_text.to_string(),
 9564                            )]
 9565                        }),
 9566                        ..Default::default()
 9567                    })
 9568                }
 9569            })
 9570            .next()
 9571            .await;
 9572        }
 9573    }
 9574
 9575    #[gpui::test]
 9576    async fn test_toggle_comment(cx: &mut gpui::TestAppContext) {
 9577        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9578        let language = Arc::new(Language::new(
 9579            LanguageConfig {
 9580                line_comment: Some("// ".to_string()),
 9581                ..Default::default()
 9582            },
 9583            Some(tree_sitter_rust::language()),
 9584        ));
 9585
 9586        let text = "
 9587            fn a() {
 9588                //b();
 9589                // c();
 9590                //  d();
 9591            }
 9592        "
 9593        .unindent();
 9594
 9595        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9596        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9597        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9598
 9599        view.update(cx, |editor, cx| {
 9600            // If multiple selections intersect a line, the line is only
 9601            // toggled once.
 9602            editor.change_selections(None, cx, |s| {
 9603                s.select_display_ranges([
 9604                    DisplayPoint::new(1, 3)..DisplayPoint::new(2, 3),
 9605                    DisplayPoint::new(3, 5)..DisplayPoint::new(3, 6),
 9606                ])
 9607            });
 9608            editor.toggle_comments(&ToggleComments, cx);
 9609            assert_eq!(
 9610                editor.text(cx),
 9611                "
 9612                    fn a() {
 9613                        b();
 9614                        c();
 9615                         d();
 9616                    }
 9617                "
 9618                .unindent()
 9619            );
 9620
 9621            // The comment prefix is inserted at the same column for every line
 9622            // in a selection.
 9623            editor.change_selections(None, cx, |s| {
 9624                s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(3, 6)])
 9625            });
 9626            editor.toggle_comments(&ToggleComments, cx);
 9627            assert_eq!(
 9628                editor.text(cx),
 9629                "
 9630                    fn a() {
 9631                        // b();
 9632                        // c();
 9633                        //  d();
 9634                    }
 9635                "
 9636                .unindent()
 9637            );
 9638
 9639            // If a selection ends at the beginning of a line, that line is not toggled.
 9640            editor.change_selections(None, cx, |s| {
 9641                s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(3, 0)])
 9642            });
 9643            editor.toggle_comments(&ToggleComments, cx);
 9644            assert_eq!(
 9645                editor.text(cx),
 9646                "
 9647                        fn a() {
 9648                            // b();
 9649                            c();
 9650                            //  d();
 9651                        }
 9652                    "
 9653                .unindent()
 9654            );
 9655        });
 9656    }
 9657
 9658    #[gpui::test]
 9659    fn test_editing_disjoint_excerpts(cx: &mut gpui::MutableAppContext) {
 9660        cx.set_global(Settings::test(cx));
 9661        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9662        let multibuffer = cx.add_model(|cx| {
 9663            let mut multibuffer = MultiBuffer::new(0);
 9664            multibuffer.push_excerpts(
 9665                buffer.clone(),
 9666                [
 9667                    ExcerptRange {
 9668                        context: Point::new(0, 0)..Point::new(0, 4),
 9669                        primary: None,
 9670                    },
 9671                    ExcerptRange {
 9672                        context: Point::new(1, 0)..Point::new(1, 4),
 9673                        primary: None,
 9674                    },
 9675                ],
 9676                cx,
 9677            );
 9678            multibuffer
 9679        });
 9680
 9681        assert_eq!(multibuffer.read(cx).read(cx).text(), "aaaa\nbbbb");
 9682
 9683        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9684        view.update(cx, |view, cx| {
 9685            assert_eq!(view.text(cx), "aaaa\nbbbb");
 9686            view.change_selections(None, cx, |s| {
 9687                s.select_ranges([
 9688                    Point::new(0, 0)..Point::new(0, 0),
 9689                    Point::new(1, 0)..Point::new(1, 0),
 9690                ])
 9691            });
 9692
 9693            view.handle_input(&Input("X".to_string()), cx);
 9694            assert_eq!(view.text(cx), "Xaaaa\nXbbbb");
 9695            assert_eq!(
 9696                view.selections.ranges(cx),
 9697                [
 9698                    Point::new(0, 1)..Point::new(0, 1),
 9699                    Point::new(1, 1)..Point::new(1, 1),
 9700                ]
 9701            )
 9702        });
 9703    }
 9704
 9705    #[gpui::test]
 9706    fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
 9707        cx.set_global(Settings::test(cx));
 9708        let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
 9709                [aaaa
 9710                (bbbb]
 9711                cccc)"});
 9712        let excerpt_ranges = excerpt_ranges.into_iter().map(|context| ExcerptRange {
 9713            context,
 9714            primary: None,
 9715        });
 9716        let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
 9717        let multibuffer = cx.add_model(|cx| {
 9718            let mut multibuffer = MultiBuffer::new(0);
 9719            multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
 9720            multibuffer
 9721        });
 9722
 9723        let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
 9724        view.update(cx, |view, cx| {
 9725            let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
 9726                aaaa
 9727                b|bbb
 9728                b|bb|b
 9729                cccc"});
 9730            assert_eq!(view.text(cx), expected_text);
 9731            view.change_selections(None, cx, |s| s.select_ranges(selection_ranges));
 9732
 9733            view.handle_input(&Input("X".to_string()), cx);
 9734
 9735            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9736                aaaa
 9737                bX|bbXb
 9738                bX|bbX|b
 9739                cccc"});
 9740            assert_eq!(view.text(cx), expected_text);
 9741            assert_eq!(view.selections.ranges(cx), expected_selections);
 9742
 9743            view.newline(&Newline, cx);
 9744            let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
 9745                aaaa
 9746                bX
 9747                |bbX
 9748                b
 9749                bX
 9750                |bbX
 9751                |b
 9752                cccc"});
 9753            assert_eq!(view.text(cx), expected_text);
 9754            assert_eq!(view.selections.ranges(cx), expected_selections);
 9755        });
 9756    }
 9757
 9758    #[gpui::test]
 9759    fn test_refresh_selections(cx: &mut gpui::MutableAppContext) {
 9760        cx.set_global(Settings::test(cx));
 9761        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9762        let mut excerpt1_id = None;
 9763        let multibuffer = cx.add_model(|cx| {
 9764            let mut multibuffer = MultiBuffer::new(0);
 9765            excerpt1_id = multibuffer
 9766                .push_excerpts(
 9767                    buffer.clone(),
 9768                    [
 9769                        ExcerptRange {
 9770                            context: Point::new(0, 0)..Point::new(1, 4),
 9771                            primary: None,
 9772                        },
 9773                        ExcerptRange {
 9774                            context: Point::new(1, 0)..Point::new(2, 4),
 9775                            primary: None,
 9776                        },
 9777                    ],
 9778                    cx,
 9779                )
 9780                .into_iter()
 9781                .next();
 9782            multibuffer
 9783        });
 9784        assert_eq!(
 9785            multibuffer.read(cx).read(cx).text(),
 9786            "aaaa\nbbbb\nbbbb\ncccc"
 9787        );
 9788        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9789            let mut editor = build_editor(multibuffer.clone(), cx);
 9790            let snapshot = editor.snapshot(cx);
 9791            editor.change_selections(None, cx, |s| {
 9792                s.select_ranges([Point::new(1, 3)..Point::new(1, 3)])
 9793            });
 9794            editor.begin_selection(Point::new(2, 1).to_display_point(&snapshot), true, 1, cx);
 9795            assert_eq!(
 9796                editor.selections.ranges(cx),
 9797                [
 9798                    Point::new(1, 3)..Point::new(1, 3),
 9799                    Point::new(2, 1)..Point::new(2, 1),
 9800                ]
 9801            );
 9802            editor
 9803        });
 9804
 9805        // Refreshing selections is a no-op when excerpts haven't changed.
 9806        editor.update(cx, |editor, cx| {
 9807            editor.change_selections(None, cx, |s| {
 9808                s.refresh();
 9809            });
 9810            assert_eq!(
 9811                editor.selections.ranges(cx),
 9812                [
 9813                    Point::new(1, 3)..Point::new(1, 3),
 9814                    Point::new(2, 1)..Point::new(2, 1),
 9815                ]
 9816            );
 9817        });
 9818
 9819        multibuffer.update(cx, |multibuffer, cx| {
 9820            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9821        });
 9822        editor.update(cx, |editor, cx| {
 9823            // Removing an excerpt causes the first selection to become degenerate.
 9824            assert_eq!(
 9825                editor.selections.ranges(cx),
 9826                [
 9827                    Point::new(0, 0)..Point::new(0, 0),
 9828                    Point::new(0, 1)..Point::new(0, 1)
 9829                ]
 9830            );
 9831
 9832            // Refreshing selections will relocate the first selection to the original buffer
 9833            // location.
 9834            editor.change_selections(None, cx, |s| {
 9835                s.refresh();
 9836            });
 9837            assert_eq!(
 9838                editor.selections.ranges(cx),
 9839                [
 9840                    Point::new(0, 1)..Point::new(0, 1),
 9841                    Point::new(0, 3)..Point::new(0, 3)
 9842                ]
 9843            );
 9844            assert!(editor.selections.pending_anchor().is_some());
 9845        });
 9846    }
 9847
 9848    #[gpui::test]
 9849    fn test_refresh_selections_while_selecting_with_mouse(cx: &mut gpui::MutableAppContext) {
 9850        cx.set_global(Settings::test(cx));
 9851        let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
 9852        let mut excerpt1_id = None;
 9853        let multibuffer = cx.add_model(|cx| {
 9854            let mut multibuffer = MultiBuffer::new(0);
 9855            excerpt1_id = multibuffer
 9856                .push_excerpts(
 9857                    buffer.clone(),
 9858                    [
 9859                        ExcerptRange {
 9860                            context: Point::new(0, 0)..Point::new(1, 4),
 9861                            primary: None,
 9862                        },
 9863                        ExcerptRange {
 9864                            context: Point::new(1, 0)..Point::new(2, 4),
 9865                            primary: None,
 9866                        },
 9867                    ],
 9868                    cx,
 9869                )
 9870                .into_iter()
 9871                .next();
 9872            multibuffer
 9873        });
 9874        assert_eq!(
 9875            multibuffer.read(cx).read(cx).text(),
 9876            "aaaa\nbbbb\nbbbb\ncccc"
 9877        );
 9878        let (_, editor) = cx.add_window(Default::default(), |cx| {
 9879            let mut editor = build_editor(multibuffer.clone(), cx);
 9880            let snapshot = editor.snapshot(cx);
 9881            editor.begin_selection(Point::new(1, 3).to_display_point(&snapshot), false, 1, cx);
 9882            assert_eq!(
 9883                editor.selections.ranges(cx),
 9884                [Point::new(1, 3)..Point::new(1, 3)]
 9885            );
 9886            editor
 9887        });
 9888
 9889        multibuffer.update(cx, |multibuffer, cx| {
 9890            multibuffer.remove_excerpts([&excerpt1_id.unwrap()], cx);
 9891        });
 9892        editor.update(cx, |editor, cx| {
 9893            assert_eq!(
 9894                editor.selections.ranges(cx),
 9895                [Point::new(0, 0)..Point::new(0, 0)]
 9896            );
 9897
 9898            // Ensure we don't panic when selections are refreshed and that the pending selection is finalized.
 9899            editor.change_selections(None, cx, |s| {
 9900                s.refresh();
 9901            });
 9902            assert_eq!(
 9903                editor.selections.ranges(cx),
 9904                [Point::new(0, 3)..Point::new(0, 3)]
 9905            );
 9906            assert!(editor.selections.pending_anchor().is_some());
 9907        });
 9908    }
 9909
 9910    #[gpui::test]
 9911    async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
 9912        cx.update(|cx| cx.set_global(Settings::test(cx)));
 9913        let language = Arc::new(
 9914            Language::new(
 9915                LanguageConfig {
 9916                    brackets: vec![
 9917                        BracketPair {
 9918                            start: "{".to_string(),
 9919                            end: "}".to_string(),
 9920                            close: true,
 9921                            newline: true,
 9922                        },
 9923                        BracketPair {
 9924                            start: "/* ".to_string(),
 9925                            end: " */".to_string(),
 9926                            close: true,
 9927                            newline: true,
 9928                        },
 9929                    ],
 9930                    ..Default::default()
 9931                },
 9932                Some(tree_sitter_rust::language()),
 9933            )
 9934            .with_indents_query("")
 9935            .unwrap(),
 9936        );
 9937
 9938        let text = concat!(
 9939            "{   }\n",     // Suppress rustfmt
 9940            "  x\n",       //
 9941            "  /*   */\n", //
 9942            "x\n",         //
 9943            "{{} }\n",     //
 9944        );
 9945
 9946        let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
 9947        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
 9948        let (_, view) = cx.add_window(|cx| build_editor(buffer, cx));
 9949        view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
 9950            .await;
 9951
 9952        view.update(cx, |view, cx| {
 9953            view.change_selections(None, cx, |s| {
 9954                s.select_display_ranges([
 9955                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
 9956                    DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
 9957                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
 9958                ])
 9959            });
 9960            view.newline(&Newline, cx);
 9961
 9962            assert_eq!(
 9963                view.buffer().read(cx).read(cx).text(),
 9964                concat!(
 9965                    "{ \n",    // Suppress rustfmt
 9966                    "\n",      //
 9967                    "}\n",     //
 9968                    "  x\n",   //
 9969                    "  /* \n", //
 9970                    "  \n",    //
 9971                    "  */\n",  //
 9972                    "x\n",     //
 9973                    "{{} \n",  //
 9974                    "}\n",     //
 9975                )
 9976            );
 9977        });
 9978    }
 9979
 9980    #[gpui::test]
 9981    fn test_highlighted_ranges(cx: &mut gpui::MutableAppContext) {
 9982        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
 9983
 9984        cx.set_global(Settings::test(cx));
 9985        let (_, editor) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
 9986
 9987        editor.update(cx, |editor, cx| {
 9988            struct Type1;
 9989            struct Type2;
 9990
 9991            let buffer = buffer.read(cx).snapshot(cx);
 9992
 9993            let anchor_range = |range: Range<Point>| {
 9994                buffer.anchor_after(range.start)..buffer.anchor_after(range.end)
 9995            };
 9996
 9997            editor.highlight_background::<Type1>(
 9998                vec![
 9999                    anchor_range(Point::new(2, 1)..Point::new(2, 3)),
10000                    anchor_range(Point::new(4, 2)..Point::new(4, 4)),
10001                    anchor_range(Point::new(6, 3)..Point::new(6, 5)),
10002                    anchor_range(Point::new(8, 4)..Point::new(8, 6)),
10003                ],
10004                |_| Color::red(),
10005                cx,
10006            );
10007            editor.highlight_background::<Type2>(
10008                vec![
10009                    anchor_range(Point::new(3, 2)..Point::new(3, 5)),
10010                    anchor_range(Point::new(5, 3)..Point::new(5, 6)),
10011                    anchor_range(Point::new(7, 4)..Point::new(7, 7)),
10012                    anchor_range(Point::new(9, 5)..Point::new(9, 8)),
10013                ],
10014                |_| Color::green(),
10015                cx,
10016            );
10017
10018            let snapshot = editor.snapshot(cx);
10019            let mut highlighted_ranges = editor.background_highlights_in_range(
10020                anchor_range(Point::new(3, 4)..Point::new(7, 4)),
10021                &snapshot,
10022                cx.global::<Settings>().theme.as_ref(),
10023            );
10024            // Enforce a consistent ordering based on color without relying on the ordering of the
10025            // highlight's `TypeId` which is non-deterministic.
10026            highlighted_ranges.sort_unstable_by_key(|(_, color)| *color);
10027            assert_eq!(
10028                highlighted_ranges,
10029                &[
10030                    (
10031                        DisplayPoint::new(3, 2)..DisplayPoint::new(3, 5),
10032                        Color::green(),
10033                    ),
10034                    (
10035                        DisplayPoint::new(5, 3)..DisplayPoint::new(5, 6),
10036                        Color::green(),
10037                    ),
10038                    (
10039                        DisplayPoint::new(4, 2)..DisplayPoint::new(4, 4),
10040                        Color::red(),
10041                    ),
10042                    (
10043                        DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10044                        Color::red(),
10045                    ),
10046                ]
10047            );
10048            assert_eq!(
10049                editor.background_highlights_in_range(
10050                    anchor_range(Point::new(5, 6)..Point::new(6, 4)),
10051                    &snapshot,
10052                    cx.global::<Settings>().theme.as_ref(),
10053                ),
10054                &[(
10055                    DisplayPoint::new(6, 3)..DisplayPoint::new(6, 5),
10056                    Color::red(),
10057                )]
10058            );
10059        });
10060    }
10061
10062    #[gpui::test]
10063    fn test_following(cx: &mut gpui::MutableAppContext) {
10064        let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
10065
10066        cx.set_global(Settings::test(cx));
10067
10068        let (_, leader) = cx.add_window(Default::default(), |cx| build_editor(buffer.clone(), cx));
10069        let (_, follower) = cx.add_window(
10070            WindowOptions {
10071                bounds: WindowBounds::Fixed(RectF::from_points(vec2f(0., 0.), vec2f(10., 80.))),
10072                ..Default::default()
10073            },
10074            |cx| build_editor(buffer.clone(), cx),
10075        );
10076
10077        let pending_update = Rc::new(RefCell::new(None));
10078        follower.update(cx, {
10079            let update = pending_update.clone();
10080            |_, cx| {
10081                cx.subscribe(&leader, move |_, leader, event, cx| {
10082                    leader
10083                        .read(cx)
10084                        .add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
10085                })
10086                .detach();
10087            }
10088        });
10089
10090        // Update the selections only
10091        leader.update(cx, |leader, cx| {
10092            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10093        });
10094        follower.update(cx, |follower, cx| {
10095            follower
10096                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10097                .unwrap();
10098        });
10099        assert_eq!(follower.read(cx).selections.ranges(cx), vec![1..1]);
10100
10101        // Update the scroll position only
10102        leader.update(cx, |leader, cx| {
10103            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10104        });
10105        follower.update(cx, |follower, cx| {
10106            follower
10107                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10108                .unwrap();
10109        });
10110        assert_eq!(
10111            follower.update(cx, |follower, cx| follower.scroll_position(cx)),
10112            vec2f(1.5, 3.5)
10113        );
10114
10115        // Update the selections and scroll position
10116        leader.update(cx, |leader, cx| {
10117            leader.change_selections(None, cx, |s| s.select_ranges([0..0]));
10118            leader.request_autoscroll(Autoscroll::Newest, cx);
10119            leader.set_scroll_position(vec2f(1.5, 3.5), cx);
10120        });
10121        follower.update(cx, |follower, cx| {
10122            let initial_scroll_position = follower.scroll_position(cx);
10123            follower
10124                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10125                .unwrap();
10126            assert_eq!(follower.scroll_position(cx), initial_scroll_position);
10127            assert!(follower.autoscroll_request.is_some());
10128        });
10129        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0]);
10130
10131        // Creating a pending selection that precedes another selection
10132        leader.update(cx, |leader, cx| {
10133            leader.change_selections(None, cx, |s| s.select_ranges([1..1]));
10134            leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
10135        });
10136        follower.update(cx, |follower, cx| {
10137            follower
10138                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10139                .unwrap();
10140        });
10141        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..0, 1..1]);
10142
10143        // Extend the pending selection so that it surrounds another selection
10144        leader.update(cx, |leader, cx| {
10145            leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
10146        });
10147        follower.update(cx, |follower, cx| {
10148            follower
10149                .apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
10150                .unwrap();
10151        });
10152        assert_eq!(follower.read(cx).selections.ranges(cx), vec![0..2]);
10153    }
10154
10155    #[test]
10156    fn test_combine_syntax_and_fuzzy_match_highlights() {
10157        let string = "abcdefghijklmnop";
10158        let syntax_ranges = [
10159            (
10160                0..3,
10161                HighlightStyle {
10162                    color: Some(Color::red()),
10163                    ..Default::default()
10164                },
10165            ),
10166            (
10167                4..8,
10168                HighlightStyle {
10169                    color: Some(Color::green()),
10170                    ..Default::default()
10171                },
10172            ),
10173        ];
10174        let match_indices = [4, 6, 7, 8];
10175        assert_eq!(
10176            combine_syntax_and_fuzzy_match_highlights(
10177                &string,
10178                Default::default(),
10179                syntax_ranges.into_iter(),
10180                &match_indices,
10181            ),
10182            &[
10183                (
10184                    0..3,
10185                    HighlightStyle {
10186                        color: Some(Color::red()),
10187                        ..Default::default()
10188                    },
10189                ),
10190                (
10191                    4..5,
10192                    HighlightStyle {
10193                        color: Some(Color::green()),
10194                        weight: Some(fonts::Weight::BOLD),
10195                        ..Default::default()
10196                    },
10197                ),
10198                (
10199                    5..6,
10200                    HighlightStyle {
10201                        color: Some(Color::green()),
10202                        ..Default::default()
10203                    },
10204                ),
10205                (
10206                    6..8,
10207                    HighlightStyle {
10208                        color: Some(Color::green()),
10209                        weight: Some(fonts::Weight::BOLD),
10210                        ..Default::default()
10211                    },
10212                ),
10213                (
10214                    8..9,
10215                    HighlightStyle {
10216                        weight: Some(fonts::Weight::BOLD),
10217                        ..Default::default()
10218                    },
10219                ),
10220            ]
10221        );
10222    }
10223
10224    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
10225        let point = DisplayPoint::new(row as u32, column as u32);
10226        point..point
10227    }
10228
10229    fn assert_selection_ranges(
10230        marked_text: &str,
10231        selection_marker_pairs: Vec<(char, char)>,
10232        view: &mut Editor,
10233        cx: &mut ViewContext<Editor>,
10234    ) {
10235        let snapshot = view.snapshot(cx).display_snapshot;
10236        let mut marker_chars = Vec::new();
10237        for (start, end) in selection_marker_pairs.iter() {
10238            marker_chars.push(*start);
10239            marker_chars.push(*end);
10240        }
10241        let (_, markers) = marked_text_by(marked_text, marker_chars);
10242        let asserted_ranges: Vec<Range<DisplayPoint>> = selection_marker_pairs
10243            .iter()
10244            .map(|(start, end)| {
10245                let start = markers.get(start).unwrap()[0].to_display_point(&snapshot);
10246                let end = markers.get(end).unwrap()[0].to_display_point(&snapshot);
10247                start..end
10248            })
10249            .collect();
10250        assert_eq!(
10251            view.selections.display_ranges(cx),
10252            &asserted_ranges[..],
10253            "Assert selections are {}",
10254            marked_text
10255        );
10256    }
10257}
10258
10259trait RangeExt<T> {
10260    fn sorted(&self) -> Range<T>;
10261    fn to_inclusive(&self) -> RangeInclusive<T>;
10262}
10263
10264impl<T: Ord + Clone> RangeExt<T> for Range<T> {
10265    fn sorted(&self) -> Self {
10266        cmp::min(&self.start, &self.end).clone()..cmp::max(&self.start, &self.end).clone()
10267    }
10268
10269    fn to_inclusive(&self) -> RangeInclusive<T> {
10270        self.start.clone()..=self.end.clone()
10271    }
10272}