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