editor.rs

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